forked from mirror/openmw-tes3mp
Add support for animated collision shapes (Fixes #1549)
This commit is contained in:
parent
64a4c2785e
commit
0b34d8d2fd
9 changed files with 312 additions and 97 deletions
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <openengine/bullet/trace.h>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
#include <openengine/bullet/BtOgreExtras.h>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
@ -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<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>& map)
|
||||
{
|
||||
for (std::map<OEngine::Physic::RigidBody*, OEngine::Physic::AnimatedShapeInstance>::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<std::string, int>& shapes = instance.mAnimatedShapes;
|
||||
for (std::map<std::string, int>::iterator shapeIt = shapes.begin();
|
||||
shapeIt != shapes.end(); ++shapeIt)
|
||||
{
|
||||
Ogre::Node* bone = animation->getNode(shapeIt->first);
|
||||
|
||||
btCompoundShape* compound = dynamic_cast<btCompoundShape*>(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ namespace MWWorld
|
|||
|
||||
bool toggleCollisionMode();
|
||||
|
||||
void stepSimulation(float dt);
|
||||
|
||||
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with
|
||||
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
else if (mHasShape && mShape->mCollide)
|
||||
delete mStaticMesh;
|
||||
if (mCompoundShape)
|
||||
{
|
||||
mShape->mCollisionShape = new TriangleMeshShape(mesh1,true);
|
||||
int n = mCompoundShape->getNumChildShapes();
|
||||
for(int i=0; i <n;i++)
|
||||
delete (mCompoundShape->getChildShape(i));
|
||||
delete mCompoundShape;
|
||||
}
|
||||
}
|
||||
else
|
||||
delete mesh1;
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//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;
|
||||
mStaticMesh = NULL;
|
||||
mCompoundShape = NULL;
|
||||
|
||||
btTriangleMesh* mesh2 = new btTriangleMesh();
|
||||
handleNode(node,0,true,true,false);
|
||||
|
||||
handleNode(mesh2, 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<const Nif::NiTriShape*>(node), flags, node->getWorldTransform(), raycasting);
|
||||
handleNiTriShape(static_cast<const Nif::NiTriShape*>(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;
|
||||
|
||||
if (isAnimated)
|
||||
{
|
||||
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<Ogre::Vector3> &vertices = data->vertices;
|
||||
const short *triangles = &data->triangles[0];
|
||||
const std::vector<short> &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<Ogre::Vector3> &vertices = data->vertices;
|
||||
const std::vector<short> &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]];
|
||||
mesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
|
||||
mStaticMesh->addTriangle(btVector3(b1.x,b1.y,b1.z),btVector3(b2.x,b2.y,b2.z),btVector3(b3.x,b3.y,b3.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <string>
|
||||
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <openengine/bullet/BulletShapeLoader.h>
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void BulletShape::deleteShape(btCollisionShape* shape)
|
|||
{
|
||||
if(shape->isCompound())
|
||||
{
|
||||
btCompoundShape* ms = static_cast<btCompoundShape*>(mCollisionShape);
|
||||
btCompoundShape* ms = static_cast<btCompoundShape*>(shape);
|
||||
int a = ms->getNumChildShapes();
|
||||
for(int i=0; i <a;i++)
|
||||
{
|
||||
|
@ -51,13 +51,14 @@ void BulletShape::deleteShape(btCollisionShape* shape)
|
|||
}
|
||||
delete shape;
|
||||
}
|
||||
shape = NULL;
|
||||
}
|
||||
|
||||
void BulletShape::unloadImpl()
|
||||
{
|
||||
deleteShape(mCollisionShape);
|
||||
deleteShape(mRaycastingShape);
|
||||
mCollisionShape = NULL;
|
||||
mRaycastingShape = NULL;
|
||||
}
|
||||
|
||||
//TODO:change this?
|
||||
|
|
|
@ -30,6 +30,14 @@ public:
|
|||
|
||||
virtual ~BulletShape();
|
||||
|
||||
// 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 bone name mapped to the child index of the shape in the btCompoundShape.
|
||||
std::map<std::string, int> mAnimatedShapes;
|
||||
|
||||
std::map<std::string, int> mAnimatedRaycastingShapes;
|
||||
|
||||
btCollisionShape* mCollisionShape;
|
||||
btCollisionShape* mRaycastingShape;
|
||||
|
||||
|
|
|
@ -11,6 +11,59 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
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<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))
|
||||
{
|
||||
btTriangleMesh* oldMesh = dynamic_cast<btTriangleMesh*>(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<btCompoundShape*>(shape);
|
||||
int a = ms->getNumChildShapes();
|
||||
for(int i=0; i <a;i++)
|
||||
{
|
||||
deleteShape(ms->getChildShape(i));
|
||||
}
|
||||
}
|
||||
delete shape;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace OEngine {
|
||||
namespace Physic
|
||||
{
|
||||
|
@ -228,6 +281,11 @@ namespace Physic
|
|||
|
||||
PhysicEngine::~PhysicEngine()
|
||||
{
|
||||
for (std::map<RigidBody*, AnimatedShapeInstance>::iterator it = mAnimatedShapes.begin(); it != mAnimatedShapes.end(); ++it)
|
||||
deleteShape(it->second.mCompound);
|
||||
for (std::map<RigidBody*, AnimatedShapeInstance>::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 (!raycasting)
|
||||
{
|
||||
if(!body && !raycastingBody)
|
||||
return; // nothing to do
|
||||
|
||||
const std::string& name = (body ? body->mName : raycastingBody->mName);
|
||||
|
||||
if (body){
|
||||
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);
|
||||
|
|
|
@ -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<std::string, int> 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<std::string,RigidBody*> 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<RigidBody*, AnimatedShapeInstance > mAnimatedShapes;
|
||||
|
||||
RigidBodyContainer mRaycastingObjectMap;
|
||||
|
||||
std::map<RigidBody*, AnimatedShapeInstance > mAnimatedRaycastingShapes;
|
||||
|
||||
typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
|
||||
PhysicActorContainer mActorMap;
|
||||
|
||||
|
|
Loading…
Reference in a new issue