1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-06 00:40:04 +00:00

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
This commit is contained in:
fredzio 2020-12-25 18:20:42 +01:00
parent dc82cb61f4
commit d015f17a6c
8 changed files with 39 additions and 53 deletions

View File

@ -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)

View File

@ -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();
} }
} }

View File

@ -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&);
}; };

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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()