mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 22:11:34 +00:00
Merge branch 'raii' into 'master'
Make all physics object manage their own resources. See merge request OpenMW/openmw!527
This commit is contained in:
commit
6863c5a68f
8 changed files with 39 additions and 53 deletions
|
@ -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…
Reference in a new issue