Move BulletShapeManager and BulletShape to resource/

openmw-38
scrawl 9 years ago
parent eb2f16d682
commit 8cf57ef6ac

@ -6,7 +6,7 @@
#include <BulletCollision/CollisionShapes/btBoxShape.h> #include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h> #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <components/nifbullet/bulletnifloader.hpp> #include <components/resource/bulletshape.hpp>
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
@ -17,7 +17,7 @@ namespace MWPhysics
{ {
Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<NifBullet::BulletShapeInstance> shape, btCollisionWorld* world) Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shape, btCollisionWorld* world)
: mCanWaterWalk(false), mWalkingOnWater(false) : mCanWaterWalk(false), mWalkingOnWater(false)
, mCollisionObject(0), mForce(0.f, 0.f, 0.f), mOnGround(false) , mCollisionObject(0), mForce(0.f, 0.f, 0.f), mOnGround(false)
, mInternalCollisionMode(true) , mInternalCollisionMode(true)

@ -13,7 +13,7 @@ class btCollisionWorld;
class btCollisionShape; class btCollisionShape;
class btCollisionObject; class btCollisionObject;
namespace NifBullet namespace Resource
{ {
class BulletShapeInstance; class BulletShapeInstance;
} }
@ -43,7 +43,7 @@ namespace MWPhysics
class Actor : public PtrHolder class Actor : public PtrHolder
{ {
public: public:
Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<NifBullet::BulletShapeInstance> shape, btCollisionWorld* world); Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shape, btCollisionWorld* world);
~Actor(); ~Actor();
/** /**

@ -17,9 +17,9 @@
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h> #include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
#include <LinearMath/btQuickprof.h> #include <LinearMath/btQuickprof.h>
#include <components/nifbullet/bulletshapemanager.hpp>
#include <components/nifbullet/bulletnifloader.hpp> #include <components/nifbullet/bulletnifloader.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
@ -520,7 +520,7 @@ namespace MWPhysics
class Object : public PtrHolder class Object : public PtrHolder
{ {
public: public:
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<NifBullet::BulletShapeInstance> shapeInstance) Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance)
: mShapeInstance(shapeInstance) : mShapeInstance(shapeInstance)
{ {
mPtr = ptr; mPtr = ptr;
@ -599,13 +599,13 @@ namespace MWPhysics
private: private:
std::auto_ptr<btCollisionObject> mCollisionObject; std::auto_ptr<btCollisionObject> mCollisionObject;
osg::ref_ptr<NifBullet::BulletShapeInstance> mShapeInstance; osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
}; };
// --------------------------------------------------------------- // ---------------------------------------------------------------
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode) PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
: mShapeManager(new NifBullet::BulletShapeManager(resourceSystem->getVFS())) : mShapeManager(new Resource::BulletShapeManager(resourceSystem->getVFS()))
, mDebugDrawEnabled(false) , mDebugDrawEnabled(false)
, mTimeAccum(0.0f) , mTimeAccum(0.0f)
, mWaterHeight(0) , mWaterHeight(0)
@ -974,7 +974,7 @@ namespace MWPhysics
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh) void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh)
{ {
osg::ref_ptr<NifBullet::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh); osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh);
if (!shapeInstance || !shapeInstance->getCollisionShape()) if (!shapeInstance || !shapeInstance->getCollisionShape())
return; return;
@ -1115,7 +1115,7 @@ namespace MWPhysics
} }
void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh) { void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh) {
osg::ref_ptr<NifBullet::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh); osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->createInstance(mesh);
if (!shapeInstance) if (!shapeInstance)
return; return;

@ -21,7 +21,7 @@ namespace MWRender
class DebugDrawer; class DebugDrawer;
} }
namespace NifBullet namespace Resource
{ {
class BulletShapeManager; class BulletShapeManager;
} }
@ -154,7 +154,7 @@ namespace MWPhysics
btCollisionDispatcher* mDispatcher; btCollisionDispatcher* mDispatcher;
btCollisionWorld* mCollisionWorld; btCollisionWorld* mCollisionWorld;
std::auto_ptr<NifBullet::BulletShapeManager> mShapeManager; std::auto_ptr<Resource::BulletShapeManager> mShapeManager;
typedef std::map<MWWorld::Ptr, Object*> ObjectMap; typedef std::map<MWWorld::Ptr, Object*> ObjectMap;
ObjectMap mObjects; ObjectMap mObjects;

@ -37,7 +37,7 @@ add_component_dir (vfs
) )
add_component_dir (resource add_component_dir (resource
scenemanager texturemanager resourcesystem scenemanager texturemanager resourcesystem bulletshapemanager bulletshape
) )
add_component_dir (sceneutil add_component_dir (sceneutil
@ -55,7 +55,7 @@ add_component_dir (nifosg
) )
add_component_dir (nifbullet add_component_dir (nifbullet
bulletnifloader bulletshapemanager bulletnifloader
) )
add_component_dir (to_utf8 add_component_dir (to_utf8

@ -40,21 +40,6 @@ btVector3 getbtVector(const osg::Vec3f &v)
namespace NifBullet namespace NifBullet
{ {
// Subclass btBhvTriangleMeshShape to auto-delete the meshInterface
struct TriangleMeshShape : public btBvhTriangleMeshShape
{
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
{
}
virtual ~TriangleMeshShape()
{
delete getTriangleInfoMap();
delete m_meshInterface;
}
};
BulletNifLoader::BulletNifLoader() BulletNifLoader::BulletNifLoader()
: mCompoundShape(NULL) : mCompoundShape(NULL)
, mStaticMesh(NULL) , mStaticMesh(NULL)
@ -65,9 +50,9 @@ BulletNifLoader::~BulletNifLoader()
{ {
} }
osg::ref_ptr<BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif) osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif)
{ {
mShape = new BulletShape; mShape = new Resource::BulletShape;
mCompoundShape = NULL; mCompoundShape = NULL;
mStaticMesh = NULL; mStaticMesh = NULL;
@ -126,11 +111,11 @@ osg::ref_ptr<BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr nif)
{ {
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
mCompoundShape->addChildShape(trans, new TriangleMeshShape(mStaticMesh,true)); mCompoundShape->addChildShape(trans, new Resource::TriangleMeshShape(mStaticMesh,true));
} }
} }
else if (mStaticMesh) else if (mStaticMesh)
mShape->mCollisionShape = new TriangleMeshShape(mStaticMesh,true); mShape->mCollisionShape = new Resource::TriangleMeshShape(mStaticMesh,true);
return mShape; return mShape;
} }
@ -306,7 +291,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
childMesh->addTriangle(getbtVector(b1), getbtVector(b2), getbtVector(b3)); childMesh->addTriangle(getbtVector(b1), getbtVector(b2), getbtVector(b3));
} }
TriangleMeshShape* childShape = new TriangleMeshShape(childMesh,true); Resource::TriangleMeshShape* childShape = new Resource::TriangleMeshShape(childMesh,true);
float scale = shape->trafo.scale; float scale = shape->trafo.scale;
const Nif::Node* parent = shape; const Nif::Node* parent = shape;
@ -346,93 +331,4 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
} }
} }
BulletShape::BulletShape()
: mCollisionShape(NULL)
{
}
BulletShape::~BulletShape()
{
deleteShape(mCollisionShape);
}
void BulletShape::deleteShape(btCollisionShape* shape)
{
if(shape!=NULL)
{
if(shape->isCompound())
{
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
int a = ms->getNumChildShapes();
for(int i=0; i <a;i++)
deleteShape(ms->getChildShape(i));
}
delete shape;
}
}
btCollisionShape* BulletShape::duplicateCollisionShape(btCollisionShape *shape) const
{
if(shape->isCompound())
{
btCompoundShape *comp = static_cast<btCompoundShape*>(shape);
btCompoundShape *newShape = new btCompoundShape;
int numShapes = comp->getNumChildShapes();
for(int i = 0;i < numShapes;++i)
{
btCollisionShape *child = duplicateCollisionShape(comp->getChildShape(i));
btTransform trans = comp->getChildTransform(i);
newShape->addChildShape(trans, child);
}
return newShape;
}
if(btBvhTriangleMeshShape* trishape = dynamic_cast<btBvhTriangleMeshShape*>(shape))
{
#if BT_BULLET_VERSION >= 283
btScaledBvhTriangleMeshShape* newShape = new btScaledBvhTriangleMeshShape(trishape, btVector3(1.f, 1.f, 1.f));
#else
// work around btScaledBvhTriangleMeshShape bug ( https://code.google.com/p/bullet/issues/detail?id=371 ) in older bullet versions
btTriangleMesh* oldMesh = static_cast<btTriangleMesh*>(trishape->getMeshInterface());
btTriangleMesh* newMesh = new btTriangleMesh(*oldMesh);
NifBullet::TriangleMeshShape* newShape = new NifBullet::TriangleMeshShape(newMesh, true);
#endif
return newShape;
}
if (btBoxShape* boxshape = dynamic_cast<btBoxShape*>(shape))
{
return new btBoxShape(*boxshape);
}
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
}
btCollisionShape *BulletShape::getCollisionShape()
{
return mCollisionShape;
}
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance()
{
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
return instance;
}
BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<BulletShape> source)
: BulletShape()
, mSource(source)
{
mCollisionBoxHalfExtents = source->mCollisionBoxHalfExtents;
mCollisionBoxTranslate = source->mCollisionBoxTranslate;
mAnimatedShapes = source->mAnimatedShapes;
if (source->mCollisionShape)
mCollisionShape = duplicateCollisionShape(source->mCollisionShape);
}
} // namespace NifBullet } // namespace NifBullet

@ -13,6 +13,7 @@
#include <osg/Referenced> #include <osg/Referenced>
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
#include <components/resource/bulletshape.hpp>
class btTriangleMesh; class btTriangleMesh;
class btCompoundShape; class btCompoundShape;
@ -28,48 +29,6 @@ namespace Nif
namespace NifBullet namespace NifBullet
{ {
class BulletShapeInstance;
class BulletShape : public osg::Referenced
{
public:
BulletShape();
virtual ~BulletShape();
btCollisionShape* mCollisionShape;
// Used for actors. Note, ideally actors would use a separate loader - as it is
// we have to keep a redundant copy of the actor model around in mCollisionShape, which isn't used.
// For now, use one file <-> one resource for simplicity.
osg::Vec3f mCollisionBoxHalfExtents;
osg::Vec3f mCollisionBoxTranslate;
// Stores animated collision shapes. If any collision nodes in the NIF are animated, then mCollisionShape
// will be a btCompoundShape (which consists of one or more child shapes).
// In this map, for each animated collision shape,
// we store the node's record index mapped to the child index of the shape in the btCompoundShape.
std::map<int, int> mAnimatedShapes;
osg::ref_ptr<BulletShapeInstance> makeInstance();
btCollisionShape* duplicateCollisionShape(btCollisionShape* shape) const;
btCollisionShape* getCollisionShape();
private:
void deleteShape(btCollisionShape* shape);
};
// An instance of a BulletShape that may have its own unique scaling set on the mCollisionShape.
// Vertex data is shallow-copied where possible. A ref_ptr to the original shape needs to be held to keep vertex pointers intact.
class BulletShapeInstance : public BulletShape
{
public:
BulletShapeInstance(osg::ref_ptr<BulletShape> source);
private:
osg::ref_ptr<BulletShape> mSource;
};
/** /**
*Load bulletShape from NIF files. *Load bulletShape from NIF files.
*/ */
@ -91,7 +50,7 @@ public:
abort(); abort();
} }
osg::ref_ptr<BulletShape> load(const Nif::NIFFilePtr file); osg::ref_ptr<Resource::BulletShape> load(const Nif::NIFFilePtr file);
private: private:
bool findBoundingBox(const Nif::Node* node, int flags = 0); bool findBoundingBox(const Nif::Node* node, int flags = 0);
@ -106,7 +65,7 @@ private:
btTriangleMesh* mStaticMesh; btTriangleMesh* mStaticMesh;
osg::ref_ptr<BulletShape> mShape; osg::ref_ptr<Resource::BulletShape> mShape;
}; };
} }

@ -0,0 +1,102 @@
#include "bulletshape.hpp"
#include <stdexcept>
#include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/CollisionShapes/btTriangleMesh.h>
#include <BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h>
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
namespace Resource
{
BulletShape::BulletShape()
: mCollisionShape(NULL)
{
}
BulletShape::~BulletShape()
{
deleteShape(mCollisionShape);
}
void BulletShape::deleteShape(btCollisionShape* shape)
{
if(shape!=NULL)
{
if(shape->isCompound())
{
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
int a = ms->getNumChildShapes();
for(int i=0; i <a;i++)
deleteShape(ms->getChildShape(i));
}
delete shape;
}
}
btCollisionShape* BulletShape::duplicateCollisionShape(btCollisionShape *shape) const
{
if(shape->isCompound())
{
btCompoundShape *comp = static_cast<btCompoundShape*>(shape);
btCompoundShape *newShape = new btCompoundShape;
int numShapes = comp->getNumChildShapes();
for(int i = 0;i < numShapes;++i)
{
btCollisionShape *child = duplicateCollisionShape(comp->getChildShape(i));
btTransform trans = comp->getChildTransform(i);
newShape->addChildShape(trans, child);
}
return newShape;
}
if(btBvhTriangleMeshShape* trishape = dynamic_cast<btBvhTriangleMeshShape*>(shape))
{
#if BT_BULLET_VERSION >= 283
btScaledBvhTriangleMeshShape* newShape = new btScaledBvhTriangleMeshShape(trishape, btVector3(1.f, 1.f, 1.f));
#else
// work around btScaledBvhTriangleMeshShape bug ( https://code.google.com/p/bullet/issues/detail?id=371 ) in older bullet versions
btTriangleMesh* oldMesh = static_cast<btTriangleMesh*>(trishape->getMeshInterface());
btTriangleMesh* newMesh = new btTriangleMesh(*oldMesh);
TriangleMeshShape* newShape = new TriangleMeshShape(newMesh, true);
#endif
return newShape;
}
if (btBoxShape* boxshape = dynamic_cast<btBoxShape*>(shape))
{
return new btBoxShape(*boxshape);
}
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
}
btCollisionShape *BulletShape::getCollisionShape()
{
return mCollisionShape;
}
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance()
{
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
return instance;
}
BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<BulletShape> source)
: BulletShape()
, mSource(source)
{
mCollisionBoxHalfExtents = source->mCollisionBoxHalfExtents;
mCollisionBoxTranslate = source->mCollisionBoxTranslate;
mAnimatedShapes = source->mAnimatedShapes;
if (source->mCollisionShape)
mCollisionShape = duplicateCollisionShape(source->mCollisionShape);
}
}

@ -0,0 +1,78 @@
#ifndef OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H
#define OPENMW_COMPONENTS_RESOURCE_BULLETSHAPE_H
#include <map>
#include <osg/Referenced>
#include <osg/ref_ptr>
#include <osg/Vec3f>
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
class btCollisionShape;
namespace Resource
{
class BulletShapeInstance;
class BulletShape : public osg::Referenced
{
public:
BulletShape();
virtual ~BulletShape();
btCollisionShape* mCollisionShape;
// Used for actors. Note, ideally actors would use a separate loader - as it is
// we have to keep a redundant copy of the actor model around in mCollisionShape, which isn't used.
// For now, use one file <-> one resource for simplicity.
osg::Vec3f mCollisionBoxHalfExtents;
osg::Vec3f mCollisionBoxTranslate;
// Stores animated collision shapes. If any collision nodes in the NIF are animated, then mCollisionShape
// will be a btCompoundShape (which consists of one or more child shapes).
// In this map, for each animated collision shape,
// we store the node's record index mapped to the child index of the shape in the btCompoundShape.
std::map<int, int> mAnimatedShapes;
osg::ref_ptr<BulletShapeInstance> makeInstance();
btCollisionShape* duplicateCollisionShape(btCollisionShape* shape) const;
btCollisionShape* getCollisionShape();
private:
void deleteShape(btCollisionShape* shape);
};
// An instance of a BulletShape that may have its own unique scaling set on the mCollisionShape.
// Vertex data is shallow-copied where possible. A ref_ptr to the original shape is held to keep vertex pointers intact.
class BulletShapeInstance : public BulletShape
{
public:
BulletShapeInstance(osg::ref_ptr<BulletShape> source);
private:
osg::ref_ptr<BulletShape> mSource;
};
// Subclass btBhvTriangleMeshShape to auto-delete the meshInterface
struct TriangleMeshShape : public btBvhTriangleMeshShape
{
TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
: btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression)
{
}
virtual ~TriangleMeshShape()
{
delete getTriangleInfoMap();
delete m_meshInterface;
}
};
}
#endif

@ -4,7 +4,9 @@
#include <components/nifbullet/bulletnifloader.hpp> #include <components/nifbullet/bulletnifloader.hpp>
namespace NifBullet #include "bulletshape.hpp"
namespace Resource
{ {
BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs) BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs)
@ -38,7 +40,7 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::createInstance(const std::
if (ext != "nif") if (ext != "nif")
return NULL; return NULL;
BulletNifLoader loader; NifBullet::BulletNifLoader loader;
// might be worth sharing NIFFiles with SceneManager in some way // might be worth sharing NIFFiles with SceneManager in some way
shape = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized))); shape = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)));

@ -6,6 +6,8 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include "bulletshape.hpp"
namespace VFS namespace VFS
{ {
class Manager; class Manager;
@ -14,10 +16,6 @@ namespace VFS
namespace Resource namespace Resource
{ {
class SceneManager; class SceneManager;
}
namespace NifBullet
{
class BulletShape; class BulletShape;
class BulletShapeInstance; class BulletShapeInstance;
Loading…
Cancel
Save