1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 21:23:52 +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());
mCollisionObject.reset(new btCollisionObject);
mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
mCollisionObject->setActivationState(DISABLE_DEACTIVATION);
mCollisionObject->setCollisionShape(mShape.get());
@ -76,8 +76,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic
Actor::~Actor()
{
if (mCollisionObject)
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
}
void Actor::enableCollisionMode(bool collision)

View file

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

View file

@ -5,6 +5,7 @@
#include <LinearMath/btScalar.h>
#include <memory>
#include <vector>
class btCollisionObject;
@ -17,10 +18,12 @@ namespace osg
namespace MWPhysics
{
class PhysicsTaskScheduler;
class HeightField
{
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();
btCollisionObject* getCollisionObject();
@ -28,11 +31,13 @@ namespace MWPhysics
const btHeightfieldTerrainShape* getShape() const;
private:
btHeightfieldTerrainShape* mShape;
btCollisionObject* mCollisionObject;
std::unique_ptr<btHeightfieldTerrainShape> mShape;
std::unique_ptr<btCollisionObject> mCollisionObject;
osg::ref_ptr<const osg::Object> mHoldObject;
std::vector<btScalar> mHeights;
PhysicsTaskScheduler* mTaskScheduler;
void operator=(const HeightField&);
HeightField(const HeightField&);
};

View file

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

View file

@ -26,7 +26,7 @@ namespace MWPhysics
class Object final : public PtrHolder
{
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;
const Resource::BulletShapeInstance* getShapeInstance() const;

View file

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

View file

@ -274,7 +274,7 @@ namespace MWPhysics
using ProjectileMap = std::map<int, std::shared_ptr<Projectile>>;
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;
bool mDebugDrawEnabled;

View file

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