From 0b34d8d2fddacc6e99435a7ab2ed11446a9796c2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 23 Jun 2014 20:43:24 +0200 Subject: [PATCH] Add support for animated collision shapes (Fixes #1549) --- apps/openmw/mwworld/physicssystem.cpp | 53 ++++++- apps/openmw/mwworld/physicssystem.hpp | 2 + apps/openmw/mwworld/worldimp.cpp | 2 +- components/nifbullet/bulletnifloader.cpp | 148 +++++++++++++------ components/nifbullet/bulletnifloader.hpp | 32 +++- libs/openengine/bullet/BulletShapeLoader.cpp | 5 +- libs/openengine/bullet/BulletShapeLoader.h | 8 + libs/openengine/bullet/physic.cpp | 136 ++++++++++++----- libs/openengine/bullet/physic.hpp | 21 ++- 9 files changed, 311 insertions(+), 96 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index ad4300b1f..7f26fa75a 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -26,10 +27,49 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" +#include "../apps/openmw/mwrender/animation.hpp" +#include "../apps/openmw/mwbase/world.hpp" +#include "../apps/openmw/mwbase/environment.hpp" + #include "ptr.hpp" #include "class.hpp" using namespace Ogre; + +namespace +{ + +void animateCollisionShapes (std::map& map) +{ + for (std::map::iterator it = map.begin(); + it != map.end(); ++it) + { + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle(it->first->mName); + MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr); + + OEngine::Physic::AnimatedShapeInstance& instance = it->second; + + std::map& shapes = instance.mAnimatedShapes; + for (std::map::iterator shapeIt = shapes.begin(); + shapeIt != shapes.end(); ++shapeIt) + { + Ogre::Node* bone = animation->getNode(shapeIt->first); + + btCompoundShape* compound = dynamic_cast(instance.mCompound); + + btTransform trans; + trans.setOrigin(BtOgre::Convert::toBullet(bone->_getDerivedPosition())); + trans.setRotation(BtOgre::Convert::toBullet(bone->_getDerivedOrientation())); + + compound->getChildShape(shapeIt->second)->setLocalScaling(BtOgre::Convert::toBullet(bone->_getDerivedScale())); + compound->updateChildTransform(shapeIt->second, trans); + } + } +} + +} + + namespace MWWorld { @@ -564,11 +604,10 @@ namespace MWWorld std::string mesh = ptr.getClass().getModel(ptr); Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); handleToMesh[node->getName()] = mesh; - OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody( + mEngine->createAndAdjustRigidBody( mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, false, placeable); - OEngine::Physic::RigidBody* raycastingBody = mEngine->createAndAdjustRigidBody( + mEngine->createAndAdjustRigidBody( mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true, placeable); - mEngine->addRigidBody(body, true, raycastingBody); } void PhysicsSystem::addActor (const Ptr& ptr) @@ -770,4 +809,12 @@ namespace MWWorld return mMovementResults; } + + void PhysicsSystem::stepSimulation(float dt) + { + animateCollisionShapes(mEngine->mAnimatedShapes); + animateCollisionShapes(mEngine->mAnimatedRaycastingShapes); + + mEngine->stepSimulation(dt); + } } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index c590b40c8..df9718669 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -53,6 +53,8 @@ namespace MWWorld bool toggleCollisionMode(); + void stepSimulation(float dt); + std::vector getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index be334646b..b4957abfd 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1231,7 +1231,7 @@ namespace MWWorld if(player != results.end()) moveObjectImp(player->first, player->second.x, player->second.y, player->second.z); - mPhysEngine->stepSimulation(duration); + mPhysics->stepSimulation(duration); } bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index bed3e8869..64febc3c2 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -49,20 +49,6 @@ typedef unsigned char ubyte; namespace NifBullet { -struct TriangleMeshShape : public btBvhTriangleMeshShape -{ - TriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression) - : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression) - { - } - - virtual ~TriangleMeshShape() - { - delete getTriangleInfoMap(); - delete m_meshInterface; - } -}; - ManualBulletShapeLoader::~ManualBulletShapeLoader() { } @@ -81,9 +67,8 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mBoundingBox = NULL; mShape->mBoxTranslation = Ogre::Vector3(0,0,0); mShape->mBoxRotation = Ogre::Quaternion::IDENTITY; - mHasShape = false; - - btTriangleMesh* mesh1 = new btTriangleMesh(); + mCompoundShape = NULL; + mStaticMesh = NULL; // Load the NIF. TODO: Wrap this in a try-catch block once we're out // of the early stages of development. Right now we WANT to catch @@ -111,19 +96,35 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mShape->mHasCollisionNode = hasRootCollisionNode(node); //do a first pass - handleNode(mesh1, node,0,false,false,false); + handleNode(node,0,false,false,false); if(mBoundingBox != NULL) { mShape->mCollisionShape = mBoundingBox; - delete mesh1; + delete mStaticMesh; + if (mCompoundShape) + { + int n = mCompoundShape->getNumChildShapes(); + for(int i=0; i getChildShape(i)); + delete mCompoundShape; + } } - else if (mHasShape && mShape->mCollide) + else { - mShape->mCollisionShape = new TriangleMeshShape(mesh1,true); + if (mCompoundShape) + { + mShape->mCollisionShape = mCompoundShape; + if (mStaticMesh) + { + btTransform trans; + trans.setIdentity(); + mCompoundShape->addChildShape(trans, new TriangleMeshShape(mStaticMesh,true)); + } + } + else if (mStaticMesh) + mShape->mCollisionShape = new TriangleMeshShape(mStaticMesh,true); } - else - delete mesh1; //second pass which create a shape for raycasting. mResourceName = mShape->getName(); @@ -131,18 +132,23 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mBoundingBox = NULL; mShape->mBoxTranslation = Ogre::Vector3(0,0,0); mShape->mBoxRotation = Ogre::Quaternion::IDENTITY; - mHasShape = false; - - btTriangleMesh* mesh2 = new btTriangleMesh(); + mStaticMesh = NULL; + mCompoundShape = NULL; - handleNode(mesh2, node,0,true,true,false); + handleNode(node,0,true,true,false); - if (mHasShape) + if (mCompoundShape) { - mShape->mRaycastingShape = new TriangleMeshShape(mesh2,true); + mShape->mRaycastingShape = mCompoundShape; + if (mStaticMesh) + { + btTransform trans; + trans.setIdentity(); + mCompoundShape->addChildShape(trans, new TriangleMeshShape(mStaticMesh,true)); + } } - else - delete mesh2; + else if (mStaticMesh) + mShape->mRaycastingShape = new TriangleMeshShape(mStaticMesh,true); } bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node) @@ -167,14 +173,17 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node const * node) return false; } -void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node *node, int flags, +void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, bool isCollisionNode, - bool raycasting, bool isMarker) + bool raycasting, bool isMarker, bool isAnimated) { // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; + if (!node->controller.empty() && node->controller->recType == Nif::RC_NiKeyframeController) + isAnimated = true; + if (!raycasting) isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode); else @@ -237,7 +246,7 @@ void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node * else if(node->recType == Nif::RC_NiTriShape) { mShape->mCollide = !(flags&0x800); - handleNiTriShape(mesh, static_cast(node), flags, node->getWorldTransform(), raycasting); + handleNiTriShape(static_cast(node), flags, node->getWorldTransform(), raycasting, isAnimated); } } @@ -249,13 +258,13 @@ void ManualBulletShapeLoader::handleNode(btTriangleMesh* mesh, const Nif::Node * for(size_t i = 0;i < list.length();i++) { if(!list[i].empty()) - handleNode(mesh, list[i].getPtr(), flags, isCollisionNode, raycasting, isMarker); + handleNode(list[i].getPtr(), flags, isCollisionNode, raycasting, isMarker, isAnimated); } } } -void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, - bool raycasting) +void ManualBulletShapeLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, + bool raycasting, bool isAnimated) { assert(shape != NULL); @@ -278,17 +287,64 @@ void ManualBulletShapeLoader::handleNiTriShape(btTriangleMesh* mesh, const Nif:: // bother setting it up. return; - mHasShape = true; + if (!shape->skin.empty()) + isAnimated = false; - const Nif::NiTriShapeData *data = shape->data.getPtr(); - const std::vector &vertices = data->vertices; - const short *triangles = &data->triangles[0]; - for(size_t i = 0;i < data->triangles.size();i+=3) + if (isAnimated) { - Ogre::Vector3 b1 = transform*vertices[triangles[i+0]]; - Ogre::Vector3 b2 = transform*vertices[triangles[i+1]]; - Ogre::Vector3 b3 = transform*vertices[triangles[i+2]]; - mesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); + if (!mCompoundShape) + mCompoundShape = new btCompoundShape(); + + btTriangleMesh* childMesh = new btTriangleMesh(); + + const Nif::NiTriShapeData *data = shape->data.getPtr(); + + childMesh->preallocateVertices(data->vertices.size()); + childMesh->preallocateIndices(data->triangles.size()); + + const std::vector &vertices = data->vertices; + const std::vector &triangles = data->triangles; + + for(size_t i = 0;i < data->triangles.size();i+=3) + { + Ogre::Vector3 b1 = vertices[triangles[i+0]]; + Ogre::Vector3 b2 = vertices[triangles[i+1]]; + Ogre::Vector3 b3 = vertices[triangles[i+2]]; + childMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); + } + + TriangleMeshShape* childShape = new TriangleMeshShape(childMesh,true); + + childShape->setLocalScaling(btVector3(transform[0][0], transform[1][1], transform[2][2])); + + Ogre::Quaternion q = transform.extractQuaternion(); + Ogre::Vector3 v = transform.getTrans(); + btTransform trans(btQuaternion(q.x, q.y, q.z, q.w), btVector3(v.x, v.y, v.z)); + + if (raycasting) + mShape->mAnimatedRaycastingShapes.insert(std::make_pair(shape->name, mCompoundShape->getNumChildShapes())); + else + mShape->mAnimatedShapes.insert(std::make_pair(shape->name, mCompoundShape->getNumChildShapes())); + + mCompoundShape->addChildShape(trans, childShape); + } + else + { + if (!mStaticMesh) + mStaticMesh = new btTriangleMesh(); + + // Static shape, just transform all vertices into position + const Nif::NiTriShapeData *data = shape->data.getPtr(); + const std::vector &vertices = data->vertices; + const std::vector &triangles = data->triangles; + + for(size_t i = 0;i < data->triangles.size();i+=3) + { + Ogre::Vector3 b1 = transform*vertices[triangles[i+0]]; + Ogre::Vector3 b2 = transform*vertices[triangles[i+1]]; + Ogre::Vector3 b3 = transform*vertices[triangles[i+2]]; + mStaticMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z)); + } } } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index fb7d3d70a..a9ee968b9 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,22 @@ namespace Nif 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; + } +}; + + /** *Load bulletShape from NIF files. */ @@ -52,8 +69,9 @@ class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader public: ManualBulletShapeLoader() : mShape(NULL) + , mStaticMesh(NULL) + , mCompoundShape(NULL) , mBoundingBox(NULL) - , mHasShape(false) { } @@ -88,7 +106,8 @@ private: /** *Parse a node. */ - void handleNode(btTriangleMesh* mesh, Nif::Node const *node, int flags, bool isCollisionNode, bool raycasting, bool isMarker); + void handleNode(Nif::Node const *node, int flags, bool isCollisionNode, + bool raycasting, bool isMarker, bool isAnimated=false); /** *Helper function @@ -98,14 +117,17 @@ private: /** *convert a NiTriShape to a bullet trishape. */ - void handleNiTriShape(btTriangleMesh* mesh, const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, bool raycasting); + void handleNiTriShape(const Nif::NiTriShape *shape, int flags, const Ogre::Matrix4 &transform, bool raycasting, bool isAnimated); std::string mResourceName; OEngine::Physic::BulletShape* mShape;//current shape - btBoxShape *mBoundingBox; - bool mHasShape; + btCompoundShape* mCompoundShape; + + btTriangleMesh* mStaticMesh; + + btBoxShape *mBoundingBox; }; diff --git a/libs/openengine/bullet/BulletShapeLoader.cpp b/libs/openengine/bullet/BulletShapeLoader.cpp index 5528924a9..bcb2ba6b2 100644 --- a/libs/openengine/bullet/BulletShapeLoader.cpp +++ b/libs/openengine/bullet/BulletShapeLoader.cpp @@ -42,7 +42,7 @@ void BulletShape::deleteShape(btCollisionShape* shape) { if(shape->isCompound()) { - btCompoundShape* ms = static_cast(mCollisionShape); + btCompoundShape* ms = static_cast(shape); int a = ms->getNumChildShapes(); for(int i=0; i mAnimatedShapes; + + std::map mAnimatedRaycastingShapes; + btCollisionShape* mCollisionShape; btCollisionShape* mRaycastingShape; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 31cb67a58..469e33f25 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -11,6 +11,59 @@ #include #include +namespace +{ + +// Create a copy of the given collision shape (responsibility of user to delete the returned shape). +btCollisionShape *duplicateCollisionShape(btCollisionShape *shape) +{ + if(shape->isCompound()) + { + btCompoundShape *comp = static_cast(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(shape)) + { + btTriangleMesh* oldMesh = dynamic_cast(trishape->getMeshInterface()); + btTriangleMesh* newMesh = new btTriangleMesh(*oldMesh); + NifBullet::TriangleMeshShape *newShape = new NifBullet::TriangleMeshShape(newMesh, true); + + return newShape; + } + + throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName()); +} + +void deleteShape(btCollisionShape* shape) +{ + if(shape!=NULL) + { + if(shape->isCompound()) + { + btCompoundShape* ms = static_cast(shape); + int a = ms->getNumChildShapes(); + for(int i=0; i getChildShape(i)); + } + } + delete shape; + } +} + +} + namespace OEngine { namespace Physic { @@ -228,6 +281,11 @@ namespace Physic PhysicEngine::~PhysicEngine() { + for (std::map::iterator it = mAnimatedShapes.begin(); it != mAnimatedShapes.end(); ++it) + deleteShape(it->second.mCompound); + for (std::map::iterator it = mAnimatedRaycastingShapes.begin(); it != mAnimatedRaycastingShapes.end(); ++it) + deleteShape(it->second.mCompound); + HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin(); for (; hf_it != mHeightFieldMap.end(); ++hf_it) { @@ -386,17 +444,38 @@ namespace Physic if (!shape->mRaycastingShape && raycasting) return NULL; - if (!raycasting) - shape->mCollisionShape->setLocalScaling( btVector3(scale,scale,scale)); - else - shape->mRaycastingShape->setLocalScaling( btVector3(scale,scale,scale)); + btCollisionShape* collisionShape = raycasting ? shape->mRaycastingShape : shape->mCollisionShape; + + // If this is an animated compound shape, we must duplicate it so we can animate + // multiple instances independently. + if (!raycasting && !shape->mAnimatedShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); + if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); + + collisionShape->setLocalScaling( btVector3(scale,scale,scale)); //create the real body btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo - (0,0, raycasting ? shape->mRaycastingShape : shape->mCollisionShape); + (0,0, collisionShape); RigidBody* body = new RigidBody(CI,name); body->mPlaceable = placeable; + if (!raycasting && !shape->mAnimatedShapes.empty()) + { + AnimatedShapeInstance instance; + instance.mAnimatedShapes = shape->mAnimatedShapes; + instance.mCompound = collisionShape; + mAnimatedShapes[body] = instance; + } + if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) + { + AnimatedShapeInstance instance; + instance.mAnimatedShapes = shape->mAnimatedRaycastingShapes; + instance.mCompound = collisionShape; + mAnimatedRaycastingShapes[body] = instance; + } + if(scaledBoxTranslation != 0) *scaledBoxTranslation = shape->mBoxTranslation * scale; if(boxRotation != 0) @@ -404,33 +483,20 @@ namespace Physic adjustRigidBody(body, position, rotation, shape->mBoxTranslation * scale, shape->mBoxRotation); - return body; - - } - - void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody) - { - if(!body && !raycastingBody) - return; // nothing to do - - const std::string& name = (body ? body->mName : raycastingBody->mName); - - if (body){ + if (!raycasting) + { + assert (mCollisionObjectMap.find(name) == mCollisionObjectMap.end()); + mCollisionObjectMap[name] = body; mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap); } - - if (raycastingBody) - mDynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting); - - if(addToMap){ - removeRigidBody(name); - deleteRigidBody(name); - - if (body) - mCollisionObjectMap[name] = body; - if (raycastingBody) - mRaycastingObjectMap[name] = raycastingBody; + else + { + assert (mRaycastingObjectMap.find(name) == mRaycastingObjectMap.end()); + mRaycastingObjectMap[name] = body; + mDynamicsWorld->addRigidBody(body,CollisionType_Raycasting,CollisionType_Raycasting); } + + return body; } void PhysicEngine::removeRigidBody(const std::string &name) @@ -464,6 +530,10 @@ namespace Physic if(body != NULL) { + if (mAnimatedShapes.find(body) != mAnimatedShapes.end()) + deleteShape(mAnimatedShapes[body].mCompound); + mAnimatedShapes.erase(body); + delete body; } mCollisionObjectMap.erase(it); @@ -475,6 +545,10 @@ namespace Physic if(body != NULL) { + if (mAnimatedRaycastingShapes.find(body) != mAnimatedRaycastingShapes.end()) + deleteShape(mAnimatedRaycastingShapes[body].mCompound); + mAnimatedRaycastingShapes.erase(body); + delete body; } mRaycastingObjectMap.erase(it); @@ -609,7 +683,6 @@ namespace Physic return std::make_pair(callback.mObject, callback.mContactPoint); } - void PhysicEngine::stepSimulation(double deltaT) { // This seems to be needed for character controller objects @@ -629,8 +702,6 @@ namespace Physic PhysicActor* newActor = new PhysicActor(name, mesh, this, position, rotation, scale); - - //dynamicsWorld->addAction( newActor->mCharacter ); mActorMap[name] = newActor; } @@ -642,7 +713,6 @@ namespace Physic PhysicActor* act = it->second; if(act != NULL) { - delete act; } mActorMap.erase(it); diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index deef21443..e37caee38 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -117,7 +117,7 @@ namespace Physic const Ogre::Vector3& getPosition() const; /** - * Returns the half extents for this PhysiActor + * Returns the (scaled) half extents */ Ogre::Vector3 getHalfExtents() const; @@ -178,6 +178,14 @@ namespace Physic RigidBody* mBody; }; + struct AnimatedShapeInstance + { + btCollisionShape* mCompound; + + // Maps bone name to child index in the compound shape + std::map mAnimatedShapes; + }; + /** * The PhysicEngine class contain everything which is needed for Physic. * It's needed that Ogre Resources are set up before the PhysicEngine is created. @@ -228,11 +236,6 @@ namespace Physic */ void removeHeightField(int x, int y); - /** - * Add a RigidBody to the simulation - */ - void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL); - /** * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. */ @@ -335,8 +338,14 @@ namespace Physic typedef std::map RigidBodyContainer; RigidBodyContainer mCollisionObjectMap; + // Compound shapes that must be animated each frame based on bone positions + // the index refers to an element in mCollisionObjectMap + std::map mAnimatedShapes; + RigidBodyContainer mRaycastingObjectMap; + std::map mAnimatedRaycastingShapes; + typedef std::map PhysicActorContainer; PhysicActorContainer mActorMap;