Make all physics object manage their own resources

Use smart pointer for heightfields and their members.
Move collision object addition inside of Object's ctor, as for Actors and HeightFields
pull/593/head
fredzio 4 years ago
parent dc82cb61f4
commit d015f17a6c

@ -58,7 +58,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic
mConvexShape = static_cast<btConvexShape*>(mShape.get()); mConvexShape = static_cast<btConvexShape*>(mShape.get());
mCollisionObject.reset(new btCollisionObject); mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
mCollisionObject->setActivationState(DISABLE_DEACTIVATION); mCollisionObject->setActivationState(DISABLE_DEACTIVATION);
mCollisionObject->setCollisionShape(mShape.get()); mCollisionObject->setCollisionShape(mShape.get());
@ -76,8 +76,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic
Actor::~Actor() Actor::~Actor()
{ {
if (mCollisionObject) mTaskScheduler->removeCollisionObject(mCollisionObject.get());
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
} }
void Actor::enableCollisionMode(bool collision) void Actor::enableCollisionMode(bool collision)

@ -1,4 +1,5 @@
#include "heightfield.hpp" #include "heightfield.hpp"
#include "mtphysics.hpp"
#include <osg/Object> #include <osg/Object>
@ -42,10 +43,12 @@ namespace
namespace MWPhysics namespace MWPhysics
{ {
HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject) HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler)
: mHeights(makeHeights(heights, sqrtVerts)) : mHoldObject(holdObject)
, mHeights(makeHeights(heights, sqrtVerts))
, mTaskScheduler(scheduler)
{ {
mShape = new btHeightfieldTerrainShape( mShape = std::make_unique<btHeightfieldTerrainShape>(
sqrtVerts, sqrtVerts, sqrtVerts, sqrtVerts,
getHeights(heights, mHeights), getHeights(heights, mHeights),
1, 1,
@ -60,31 +63,29 @@ namespace MWPhysics
(y+0.5f) * triSize * (sqrtVerts-1), (y+0.5f) * triSize * (sqrtVerts-1),
(maxH+minH)*0.5f)); (maxH+minH)*0.5f));
mCollisionObject = new btCollisionObject; mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionShape(mShape); mCollisionObject->setCollisionShape(mShape.get());
mCollisionObject->setWorldTransform(transform); mCollisionObject->setWorldTransform(transform);
mTaskScheduler->addCollisionObject(mCollisionObject.get(), CollisionType_HeightMap, CollisionType_Actor|CollisionType_Projectile);
mHoldObject = holdObject;
} }
HeightField::~HeightField() HeightField::~HeightField()
{ {
delete mCollisionObject; mTaskScheduler->removeCollisionObject(mCollisionObject.get());
delete mShape;
} }
btCollisionObject* HeightField::getCollisionObject() btCollisionObject* HeightField::getCollisionObject()
{ {
return mCollisionObject; return mCollisionObject.get();
} }
const btCollisionObject* HeightField::getCollisionObject() const const btCollisionObject* HeightField::getCollisionObject() const
{ {
return mCollisionObject; return mCollisionObject.get();
} }
const btHeightfieldTerrainShape* HeightField::getShape() const const btHeightfieldTerrainShape* HeightField::getShape() const
{ {
return mShape; return mShape.get();
} }
} }

@ -5,6 +5,7 @@
#include <LinearMath/btScalar.h> #include <LinearMath/btScalar.h>
#include <memory>
#include <vector> #include <vector>
class btCollisionObject; class btCollisionObject;
@ -17,10 +18,12 @@ namespace osg
namespace MWPhysics namespace MWPhysics
{ {
class PhysicsTaskScheduler;
class HeightField class HeightField
{ {
public: public:
HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject); HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler);
~HeightField(); ~HeightField();
btCollisionObject* getCollisionObject(); btCollisionObject* getCollisionObject();
@ -28,11 +31,13 @@ namespace MWPhysics
const btHeightfieldTerrainShape* getShape() const; const btHeightfieldTerrainShape* getShape() const;
private: private:
btHeightfieldTerrainShape* mShape; std::unique_ptr<btHeightfieldTerrainShape> mShape;
btCollisionObject* mCollisionObject; std::unique_ptr<btCollisionObject> mCollisionObject;
osg::ref_ptr<const osg::Object> mHoldObject; osg::ref_ptr<const osg::Object> mHoldObject;
std::vector<btScalar> mHeights; std::vector<btScalar> mHeights;
PhysicsTaskScheduler* mTaskScheduler;
void operator=(const HeightField&); void operator=(const HeightField&);
HeightField(const HeightField&); HeightField(const HeightField&);
}; };

@ -14,29 +14,29 @@
namespace MWPhysics namespace MWPhysics
{ {
Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, PhysicsTaskScheduler* scheduler) Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler)
: mShapeInstance(shapeInstance) : mShapeInstance(shapeInstance)
, mSolid(true) , mSolid(true)
, mTaskScheduler(scheduler) , mTaskScheduler(scheduler)
{ {
mPtr = ptr; mPtr = ptr;
mCollisionObject.reset(new btCollisionObject); mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionShape(shapeInstance->getCollisionShape()); mCollisionObject->setCollisionShape(shapeInstance->getCollisionShape());
mCollisionObject->setUserPointer(this); mCollisionObject->setUserPointer(this);
setScale(ptr.getCellRef().getScale()); setScale(ptr.getCellRef().getScale());
setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude()));
const float* pos = ptr.getRefData().getPosition().pos; setOrigin(Misc::Convert::toBullet(ptr.getRefData().getPosition().asVec3()));
setOrigin(btVector3(pos[0], pos[1], pos[2]));
commitPositionChange(); commitPositionChange();
mTaskScheduler->addCollisionObject(mCollisionObject.get(), collisionType, CollisionType_Actor|CollisionType_HeightMap|CollisionType_Projectile);
} }
Object::~Object() Object::~Object()
{ {
if (mCollisionObject) mTaskScheduler->removeCollisionObject(mCollisionObject.get());
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
} }
const Resource::BulletShapeInstance* Object::getShapeInstance() const const Resource::BulletShapeInstance* Object::getShapeInstance() const

@ -26,7 +26,7 @@ namespace MWPhysics
class Object final : public PtrHolder class Object final : public PtrHolder
{ {
public: public:
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, PhysicsTaskScheduler* scheduler); Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler);
~Object() override; ~Object() override;
const Resource::BulletShapeInstance* getShapeInstance() const; const Resource::BulletShapeInstance* getShapeInstance() const;

@ -107,12 +107,7 @@ namespace MWPhysics
if (mWaterCollisionObject) if (mWaterCollisionObject)
mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get()); mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get());
for (auto& heightField : mHeightFields) mHeightFields.clear();
{
mTaskScheduler->removeCollisionObject(heightField.second->getCollisionObject());
delete heightField.second;
}
mObjects.clear(); mObjects.clear();
mActors.clear(); mActors.clear();
mProjectiles.clear(); mProjectiles.clear();
@ -442,22 +437,14 @@ namespace MWPhysics
void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject) void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
{ {
HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject); mHeightFields[std::make_pair(x,y)] = std::make_unique<HeightField>(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get());
mHeightFields[std::make_pair(x,y)] = heightfield;
mTaskScheduler->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap,
CollisionType_Actor|CollisionType_Projectile);
} }
void PhysicsSystem::removeHeightField (int x, int y) void PhysicsSystem::removeHeightField (int x, int y)
{ {
HeightFieldMap::iterator heightfield = mHeightFields.find(std::make_pair(x,y)); HeightFieldMap::iterator heightfield = mHeightFields.find(std::make_pair(x,y));
if(heightfield != mHeightFields.end()) if(heightfield != mHeightFields.end())
{
mTaskScheduler->removeCollisionObject(heightfield->second->getCollisionObject());
delete heightfield->second;
mHeightFields.erase(heightfield); mHeightFields.erase(heightfield);
}
} }
const HeightField* PhysicsSystem::getHeightField(int x, int y) const const HeightField* PhysicsSystem::getHeightField(int x, int y) const
@ -465,7 +452,7 @@ namespace MWPhysics
const auto heightField = mHeightFields.find(std::make_pair(x, y)); const auto heightField = mHeightFields.find(std::make_pair(x, y));
if (heightField == mHeightFields.end()) if (heightField == mHeightFields.end())
return nullptr; return nullptr;
return heightField->second; return heightField->second.get();
} }
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType) void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType)
@ -474,14 +461,11 @@ namespace MWPhysics
if (!shapeInstance || !shapeInstance->getCollisionShape()) if (!shapeInstance || !shapeInstance->getCollisionShape())
return; return;
auto obj = std::make_shared<Object>(ptr, shapeInstance, mTaskScheduler.get()); auto obj = std::make_shared<Object>(ptr, shapeInstance, collisionType, mTaskScheduler.get());
mObjects.emplace(ptr, obj); mObjects.emplace(ptr, obj);
if (obj->isAnimated()) if (obj->isAnimated())
mAnimatedObjects.insert(obj.get()); mAnimatedObjects.insert(obj.get());
mTaskScheduler->addCollisionObject(obj->getCollisionObject(), collisionType,
CollisionType_Actor|CollisionType_HeightMap|CollisionType_Projectile);
} }
void PhysicsSystem::remove(const MWWorld::Ptr &ptr) void PhysicsSystem::remove(const MWWorld::Ptr &ptr)

@ -274,7 +274,7 @@ namespace MWPhysics
using ProjectileMap = std::map<int, std::shared_ptr<Projectile>>; using ProjectileMap = std::map<int, std::shared_ptr<Projectile>>;
ProjectileMap mProjectiles; ProjectileMap mProjectiles;
using HeightFieldMap = std::map<std::pair<int, int>, HeightField *>; using HeightFieldMap = std::map<std::pair<int, int>, std::unique_ptr<HeightField>>;
HeightFieldMap mHeightFields; HeightFieldMap mHeightFields;
bool mDebugDrawEnabled; bool mDebugDrawEnabled;

@ -28,7 +28,7 @@ Projectile::Projectile(int projectileId, const MWWorld::Ptr& caster, const osg::
mShape.reset(new btSphereShape(1.f)); mShape.reset(new btSphereShape(1.f));
mConvexShape = static_cast<btConvexShape*>(mShape.get()); mConvexShape = static_cast<btConvexShape*>(mShape.get());
mCollisionObject.reset(new btCollisionObject); mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
mCollisionObject->setActivationState(DISABLE_DEACTIVATION); mCollisionObject->setActivationState(DISABLE_DEACTIVATION);
mCollisionObject->setCollisionShape(mShape.get()); mCollisionObject->setCollisionShape(mShape.get());
@ -45,12 +45,9 @@ Projectile::Projectile(int projectileId, const MWWorld::Ptr& caster, const osg::
Projectile::~Projectile() Projectile::~Projectile()
{ {
if (mCollisionObject) if (!mActive)
{ mPhysics->reportCollision(mHitPosition, mHitNormal);
if (!mActive) mTaskScheduler->removeCollisionObject(mCollisionObject.get());
mPhysics->reportCollision(mHitPosition, mHitNormal);
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
}
} }
void Projectile::commitPositionChange() void Projectile::commitPositionChange()

Loading…
Cancel
Save