Physics: Create actor shapes outside of BulletNifLoader

This will allow to create a specialised shape instead, such as a capsule, which tends to work better for character controllers.
deque
scrawl 11 years ago
parent 98329a94b4
commit e002acdeae

@ -175,7 +175,7 @@ namespace MWWorld
const int maxHeight = 200.f; const int maxHeight = 200.f;
OEngine::Physic::ActorTracer tracer; OEngine::Physic::ActorTracer tracer;
tracer.findGround(physicActor->getCollisionBody(), position, position-Ogre::Vector3(0,0,maxHeight), engine); tracer.findGround(physicActor, position, position-Ogre::Vector3(0,0,maxHeight), engine);
if(tracer.mFraction >= 1.0f) if(tracer.mFraction >= 1.0f)
{ {
physicActor->setOnGround(false); physicActor->setOnGround(false);
@ -607,9 +607,10 @@ namespace MWWorld
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
const std::string &handle = node->getName(); const std::string &handle = node->getName();
const Ogre::Quaternion &rotation = node->getOrientation(); const Ogre::Quaternion &rotation = node->getOrientation();
// TODO: map to MWWorld::Ptr for faster access
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
{ {
//Needs to be changed
act->setRotation(rotation); act->setRotation(rotation);
} }
if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle))
@ -740,8 +741,9 @@ namespace MWWorld
btCollisionObject object; btCollisionObject object;
object.setCollisionShape(&planeShape); object.setCollisionShape(&planeShape);
// TODO: this seems to have a slight performance impact
if (waterCollision) if (waterCollision)
mEngine->dynamicsWorld->addCollisionObject(&object); mEngine->mDynamicsWorld->addCollisionObject(&object);
// 100 points of slowfall reduce gravity by 90% (this is just a guess) // 100 points of slowfall reduce gravity by 90% (this is just a guess)
float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).mMagnitude / 100.f) * 0.9f), 0.9f); float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).mMagnitude / 100.f) * 0.9f), 0.9f);
@ -751,7 +753,7 @@ namespace MWWorld
waterlevel, slowFall, mEngine); waterlevel, slowFall, mEngine);
if (waterCollision) if (waterCollision)
mEngine->dynamicsWorld->removeCollisionObject(&object); mEngine->mDynamicsWorld->removeCollisionObject(&object);
float heightDiff = newpos.z - oldHeight; float heightDiff = newpos.z - oldHeight;

@ -1847,7 +1847,7 @@ namespace MWWorld
Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos);
OEngine::Physic::ActorTracer tracer; OEngine::Physic::ActorTracer tracer;
// a small distance above collision object is considered "on ground" // a small distance above collision object is considered "on ground"
tracer.findGround(physactor->getCollisionBody(), tracer.findGround(physactor,
pos, pos,
pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down
mPhysEngine); mPhysEngine);

@ -304,4 +304,53 @@ void ManualBulletShapeLoader::load(const std::string &name,const std::string &gr
OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this); OEngine::Physic::BulletShapeManager::getSingleton().create(name,group,true,this);
} }
bool findBoundingBox (const Nif::Node* node, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation)
{
if(node->hasBounds)
{
if (!(node->flags & Nif::NiNode::Flag_Hidden))
{
translation = node->boundPos;
orientation = node->boundRot;
halfExtents = node->boundXYZ;
return true;
}
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
{
if(!list[i].empty())
if (findBoundingBox(list[i].getPtr(), halfExtents, translation, orientation))
return true;
}
}
return false;
}
bool getBoundingBox(const std::string& nifFile, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation)
{
Nif::NIFFile::ptr pnif (Nif::NIFFile::create (nifFile));
Nif::NIFFile & nif = *pnif.get ();
if (nif.numRoots() < 1)
{
return false;
}
Nif::Record *r = nif.getRoot(0);
assert(r != NULL);
Nif::Node *node = dynamic_cast<Nif::Node*>(r);
if (node == NULL)
{
return false;
}
return findBoundingBox(node, halfExtents, translation, orientation);
}
} // namespace NifBullet } // namespace NifBullet

@ -108,6 +108,11 @@ private:
bool mHasShape; bool mHasShape;
}; };
bool getBoundingBox(const std::string& nifFile, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation);
bool findBoundingBox(const Nif::Node* node, Ogre::Vector3& halfExtents, Ogre::Vector3& translation, Ogre::Quaternion& orientation);
} }
#endif #endif

@ -16,115 +16,93 @@ namespace Physic
{ {
PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale)
: mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) : mName(name), mEngine(engine), mMesh(mesh)
, mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0) , mBody(0), mOnGround(false), mInternalCollisionMode(true)
, mCollisionBody(true) , mExternalCollisionMode(true)
, mForce(0.0f) , mForce(0.0f)
, mScale(scale)
{ {
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation))
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true); {
Ogre::Quaternion inverse = mBoxRotation.Inverse(); mHalfExtents = Ogre::Vector3(0.f);
mBoxRotationInverse = Ogre::Quaternion(inverse.w, inverse.x, inverse.y,inverse.z); mMeshTranslation = Ogre::Vector3(0.f);
mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map mMeshOrientation = Ogre::Quaternion::IDENTITY;
}
mShape.reset(new btBoxShape(BtOgre::Convert::toBullet(mHalfExtents)));
mShape->setLocalScaling(btVector3(scale,scale,scale));
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo
(0,0, mShape.get());
mBody = new RigidBody(CI, name);
mBody->mPlaceable = false;
setPosition(position);
setRotation(rotation);
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
CollisionType_Actor|CollisionType_World|CollisionType_HeightMap);
} }
PhysicActor::~PhysicActor() PhysicActor::~PhysicActor()
{ {
if(mBody) if(mBody)
{ {
mEngine->dynamicsWorld->removeRigidBody(mBody); mEngine->mDynamicsWorld->removeRigidBody(mBody);
delete mBody; delete mBody;
} }
if(mRaycastingBody)
{
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
delete mRaycastingBody;
}
} }
void PhysicActor::enableCollisionMode(bool collision) void PhysicActor::enableCollisionMode(bool collision)
{ {
mCollisionMode = collision; mInternalCollisionMode = collision;
} }
void PhysicActor::enableCollisionBody(bool collision) void PhysicActor::enableCollisionBody(bool collision)
{ {
assert(mBody); assert(mBody);
if(collision && !mCollisionBody) enableCollisionBody(); if(collision && !mExternalCollisionMode) enableCollisionBody();
if(!collision && mCollisionBody) disableCollisionBody(); if(!collision && mExternalCollisionMode) disableCollisionBody();
mCollisionBody = collision; mExternalCollisionMode = collision;
} }
void PhysicActor::setPosition(const Ogre::Vector3 &pos) const Ogre::Vector3& PhysicActor::getPosition() const
{ {
assert(mBody); return mPosition;
if(pos != getPosition())
{
mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
mEngine->adjustRigidBody(mRaycastingBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation);
}
} }
void PhysicActor::setRotation(const Ogre::Quaternion &quat) void PhysicActor::setPosition(const Ogre::Vector3 &position)
{ {
assert(mBody); assert(mBody);
if(!quat.equals(getRotation(), Ogre::Radian(0))){
mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
mEngine->adjustRigidBody(mRaycastingBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation);
} mPosition = position;
}
btTransform tr = mBody->getWorldTransform();
Ogre::Quaternion meshrot = mMeshOrientation;
Ogre::Vector3 transrot = meshrot * (mMeshTranslation * mScale);
Ogre::Vector3 newPosition = transrot + position;
Ogre::Vector3 PhysicActor::getPosition() tr.setOrigin(BtOgre::Convert::toBullet(newPosition));
{ mBody->setWorldTransform(tr);
assert(mBody);
btVector3 vec = mBody->getWorldTransform().getOrigin();
Ogre::Quaternion rotation = Ogre::Quaternion(mBody->getWorldTransform().getRotation().getW(), mBody->getWorldTransform().getRotation().getX(),
mBody->getWorldTransform().getRotation().getY(), mBody->getWorldTransform().getRotation().getZ());
Ogre::Vector3 transrot = rotation * mBoxScaledTranslation;
Ogre::Vector3 visualPosition = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ()) - transrot;
return visualPosition;
} }
Ogre::Quaternion PhysicActor::getRotation() void PhysicActor::setRotation (const Ogre::Quaternion& rotation)
{ {
assert(mBody); btTransform tr = mBody->getWorldTransform();
btQuaternion quat = mBody->getWorldTransform().getRotation(); tr.setRotation(BtOgre::Convert::toBullet(mMeshOrientation * rotation));
return Ogre::Quaternion(quat.getW(), quat.getX(), quat.getY(), quat.getZ()) * mBoxRotationInverse; mBody->setWorldTransform(tr);
} }
void PhysicActor::setScale(float scale){ void PhysicActor::setScale(float scale)
//We only need to change the scaled box translation, box rotations remain the same. {
assert(mBody); mScale = scale;
mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX(); mShape->setLocalScaling(btVector3(scale,scale,scale));
mBoxScaledTranslation *= scale; setPosition(mPosition);
Ogre::Vector3 pos = getPosition();
Ogre::Quaternion rot = getRotation();
if(mBody){
mEngine->dynamicsWorld->removeRigidBody(mBody);
mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody);
delete mBody;
delete mRaycastingBody;
}
//Create the newly scaled rigid body
mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot);
mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, pos, rot, 0, 0, true);
mEngine->addRigidBody(mCollisionBody ? mBody : 0, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map
} }
Ogre::Vector3 PhysicActor::getHalfExtents() const Ogre::Vector3 PhysicActor::getHalfExtents() const
{ {
if(mBody) return mHalfExtents;
{
btBoxShape *box = static_cast<btBoxShape*>(mBody->getCollisionShape());
if(box != NULL)
{
btVector3 size = box->getHalfExtentsWithMargin();
return Ogre::Vector3(size.getX(), size.getY(), size.getZ());
}
}
return Ogre::Vector3(0.0f);
} }
void PhysicActor::setInertialForce(const Ogre::Vector3 &force) void PhysicActor::setInertialForce(const Ogre::Vector3 &force)
@ -139,12 +117,16 @@ namespace Physic
void PhysicActor::disableCollisionBody() void PhysicActor::disableCollisionBody()
{ {
mEngine->dynamicsWorld->removeRigidBody(mBody); mEngine->mDynamicsWorld->removeRigidBody(mBody);
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
CollisionType_Raycasting);
} }
void PhysicActor::enableCollisionBody() void PhysicActor::enableCollisionBody()
{ {
mEngine->dynamicsWorld->addRigidBody(mBody,CollisionType_Actor,CollisionType_World|CollisionType_HeightMap); mEngine->mDynamicsWorld->removeRigidBody(mBody);
mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor,
CollisionType_Actor|CollisionType_World|CollisionType_HeightMap);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -189,8 +171,8 @@ namespace Physic
broadphase = new btDbvtBroadphase(); broadphase = new btDbvtBroadphase();
// The world. // The world.
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); mDynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0,0,-10)); mDynamicsWorld->setGravity(btVector3(0,0,-10));
if(BulletShapeManager::getSingletonPtr() == NULL) if(BulletShapeManager::getSingletonPtr() == NULL)
{ {
@ -208,10 +190,10 @@ namespace Physic
if(!isDebugCreated) if(!isDebugCreated)
{ {
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld); mDebugDrawer = new BtOgre::DebugDrawer(node, mDynamicsWorld);
dynamicsWorld->setDebugDrawer(mDebugDrawer); mDynamicsWorld->setDebugDrawer(mDebugDrawer);
isDebugCreated = true; isDebugCreated = true;
dynamicsWorld->debugDrawWorld(); mDynamicsWorld->debugDrawWorld();
} }
} }
@ -241,7 +223,7 @@ namespace Physic
HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin(); HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin();
for (; hf_it != mHeightFieldMap.end(); ++hf_it) for (; hf_it != mHeightFieldMap.end(); ++hf_it)
{ {
dynamicsWorld->removeRigidBody(hf_it->second.mBody); mDynamicsWorld->removeRigidBody(hf_it->second.mBody);
delete hf_it->second.mShape; delete hf_it->second.mShape;
delete hf_it->second.mBody; delete hf_it->second.mBody;
} }
@ -251,7 +233,7 @@ namespace Physic
{ {
if (rb_it->second != NULL) if (rb_it->second != NULL)
{ {
dynamicsWorld->removeRigidBody(rb_it->second); mDynamicsWorld->removeRigidBody(rb_it->second);
delete rb_it->second; delete rb_it->second;
rb_it->second = NULL; rb_it->second = NULL;
@ -262,7 +244,7 @@ namespace Physic
{ {
if (rb_it->second != NULL) if (rb_it->second != NULL)
{ {
dynamicsWorld->removeRigidBody(rb_it->second); mDynamicsWorld->removeRigidBody(rb_it->second);
delete rb_it->second; delete rb_it->second;
rb_it->second = NULL; rb_it->second = NULL;
@ -281,7 +263,7 @@ namespace Physic
delete mDebugDrawer; delete mDebugDrawer;
delete dynamicsWorld; delete mDynamicsWorld;
delete solver; delete solver;
delete collisionConfiguration; delete collisionConfiguration;
delete dispatcher; delete dispatcher;
@ -331,7 +313,7 @@ namespace Physic
mHeightFieldMap [name] = hf; mHeightFieldMap [name] = hf;
dynamicsWorld->addRigidBody(body,CollisionType_HeightMap|CollisionType_Raycasting, mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap,
CollisionType_World|CollisionType_Actor|CollisionType_Raycasting); CollisionType_World|CollisionType_Actor|CollisionType_Raycasting);
} }
@ -343,7 +325,7 @@ namespace Physic
HeightField hf = mHeightFieldMap [name]; HeightField hf = mHeightFieldMap [name];
dynamicsWorld->removeRigidBody(hf.mBody); mDynamicsWorld->removeRigidBody(hf.mBody);
delete hf.mShape; delete hf.mShape;
delete hf.mBody; delete hf.mBody;
@ -367,7 +349,6 @@ namespace Physic
{ {
std::string sid = (boost::format("%07.3f") % scale).str(); std::string sid = (boost::format("%07.3f") % scale).str();
std::string outputstring = mesh + sid; std::string outputstring = mesh + sid;
//std::cout << "The string" << outputstring << "\n";
//get the shape from the .nif //get the shape from the .nif
mShapeLoader->load(outputstring,"General"); mShapeLoader->load(outputstring,"General");
@ -419,7 +400,7 @@ namespace Physic
} }
void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody,bool actor) void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody)
{ {
if(!body && !raycastingBody) if(!body && !raycastingBody)
return; // nothing to do return; // nothing to do
@ -427,12 +408,11 @@ namespace Physic
const std::string& name = (body ? body->mName : raycastingBody->mName); const std::string& name = (body ? body->mName : raycastingBody->mName);
if (body){ if (body){
if(actor) dynamicsWorld->addRigidBody(body,CollisionType_Actor,CollisionType_World|CollisionType_HeightMap); mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap);
else dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap);
} }
if (raycastingBody) if (raycastingBody)
dynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World); mDynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting);
if(addToMap){ if(addToMap){
removeRigidBody(name); removeRigidBody(name);
@ -453,7 +433,7 @@ namespace Physic
RigidBody* body = it->second; RigidBody* body = it->second;
if(body != NULL) if(body != NULL)
{ {
dynamicsWorld->removeRigidBody(body); mDynamicsWorld->removeRigidBody(body);
} }
} }
it = mRaycastingObjectMap.find(name); it = mRaycastingObjectMap.find(name);
@ -462,7 +442,7 @@ namespace Physic
RigidBody* body = it->second; RigidBody* body = it->second;
if(body != NULL) if(body != NULL)
{ {
dynamicsWorld->removeRigidBody(body); mDynamicsWorld->removeRigidBody(body);
} }
} }
} }
@ -605,7 +585,7 @@ namespace Physic
if (!body) // fall back to raycasting body if there is no collision body if (!body) // fall back to raycasting body if there is no collision body
body = getRigidBody(name, true); body = getRigidBody(name, true);
ContactTestResultCallback callback; ContactTestResultCallback callback;
dynamicsWorld->contactTest(body, callback); mDynamicsWorld->contactTest(body, callback);
return callback.mResult; return callback.mResult;
} }
@ -615,8 +595,9 @@ namespace Physic
btCollisionObject *object) btCollisionObject *object)
{ {
DeepestNotMeContactTestResultCallback callback(filter, origin); DeepestNotMeContactTestResultCallback callback(filter, origin);
callback.m_collisionFilterGroup = 0xff;
callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor; callback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
dynamicsWorld->contactTest(object, callback); mDynamicsWorld->contactTest(object, callback);
return std::make_pair(callback.mObject, callback.mContactPoint); return std::make_pair(callback.mObject, callback.mContactPoint);
} }
@ -624,7 +605,7 @@ namespace Physic
void PhysicEngine::stepSimulation(double deltaT) void PhysicEngine::stepSimulation(double deltaT)
{ {
// This seems to be needed for character controller objects // This seems to be needed for character controller objects
dynamicsWorld->stepSimulation(deltaT,10, 1/60.0); mDynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
if(isDebugCreated) if(isDebugCreated)
{ {
mDebugDrawer->step(); mDebugDrawer->step();
@ -684,14 +665,15 @@ namespace Physic
float d = -1; float d = -1;
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
resultCallback1.m_collisionFilterGroup = 0xff;
if(raycastingObjectOnly) if(raycastingObjectOnly)
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor;
else else
resultCallback1.m_collisionFilterMask = CollisionType_World; resultCallback1.m_collisionFilterMask = CollisionType_World;
if(!ignoreHeightMap) if(!ignoreHeightMap)
resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap; resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap;
dynamicsWorld->rayTest(from, to, resultCallback1); mDynamicsWorld->rayTest(from, to, resultCallback1);
if (resultCallback1.hasHit()) if (resultCallback1.hasHit())
{ {
name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName; name = static_cast<const RigidBody&>(*resultCallback1.m_collisionObject).mName;
@ -724,6 +706,7 @@ namespace Physic
std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to) std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to)
{ {
OurClosestConvexResultCallback callback(from, to); OurClosestConvexResultCallback callback(from, to);
callback.m_collisionFilterGroup = 0xff;
callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap; callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap;
btSphereShape shape(radius); btSphereShape shape(radius);
@ -732,7 +715,7 @@ namespace Physic
btTransform from_ (btrot, from); btTransform from_ (btrot, from);
btTransform to_ (btrot, to); btTransform to_ (btrot, to);
dynamicsWorld->convexSweepTest(&shape, from_, to_, callback); mDynamicsWorld->convexSweepTest(&shape, from_, to_, callback);
if (callback.hasHit()) if (callback.hasHit())
return std::make_pair(true, callback.m_closestHitFraction); return std::make_pair(true, callback.m_closestHitFraction);
@ -743,8 +726,9 @@ namespace Physic
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to) std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
{ {
MyRayResultCallback resultCallback1; MyRayResultCallback resultCallback1;
resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; resultCallback1.m_collisionFilterGroup = 0xff;
dynamicsWorld->rayTest(from, to, resultCallback1); resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor;
mDynamicsWorld->rayTest(from, to, resultCallback1);
std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results; std::vector< std::pair<float, const btCollisionObject*> > results = resultCallback1.results;
std::vector< std::pair<float, std::string> > results2; std::vector< std::pair<float, std::string> > results2;

@ -76,6 +76,9 @@ namespace Physic
RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name);
virtual ~RigidBody(); virtual ~RigidBody();
std::string mName; std::string mName;
// Hack: placeable objects (that can be picked up by the player) have different collision behaviour.
// This variable needs to be passed to BulletNifLoader.
bool mPlaceable; bool mPlaceable;
}; };
@ -92,13 +95,6 @@ namespace Physic
void setPosition(const Ogre::Vector3 &pos); void setPosition(const Ogre::Vector3 &pos);
/**
* This adjusts the rotation of a PhysicActor
* If we have any problems with this (getting stuck in pmove) we should change it
* from setting the visual orientation to setting the orientation of the rigid body directly.
*/
void setRotation(const Ogre::Quaternion &quat);
/** /**
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry. * Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
*/ */
@ -111,26 +107,18 @@ namespace Physic
bool getCollisionMode() const bool getCollisionMode() const
{ {
return mCollisionMode; return mInternalCollisionMode;
} }
/**
* This returns the visual position of the PhysicActor (used to position a scenenode).
* Note - this is different from the position of the contained mBody.
*/
Ogre::Vector3 getPosition();
/**
* Returns the visual orientation of the PhysicActor
*/
Ogre::Quaternion getRotation();
/** /**
* Sets the scale of the PhysicActor * Sets the scale of the PhysicActor
*/ */
void setScale(float scale); void setScale(float scale);
void setRotation (const Ogre::Quaternion& rotation);
const Ogre::Vector3& getPosition() const;
/** /**
* Returns the half extents for this PhysiActor * Returns the half extents for this PhysiActor
*/ */
@ -153,7 +141,7 @@ namespace Physic
bool getOnGround() const bool getOnGround() const
{ {
return mCollisionMode && mOnGround; return mInternalCollisionMode && mOnGround;
} }
btCollisionObject *getCollisionBody() const btCollisionObject *getCollisionBody() const
@ -165,17 +153,21 @@ namespace Physic
void disableCollisionBody(); void disableCollisionBody();
void enableCollisionBody(); void enableCollisionBody();
boost::shared_ptr<btCollisionShape> mShape;
OEngine::Physic::RigidBody* mBody; OEngine::Physic::RigidBody* mBody;
OEngine::Physic::RigidBody* mRaycastingBody;
Ogre::Vector3 mBoxScaledTranslation; Ogre::Quaternion mMeshOrientation;
Ogre::Quaternion mBoxRotation; Ogre::Vector3 mMeshTranslation;
Ogre::Quaternion mBoxRotationInverse; Ogre::Vector3 mHalfExtents;
float mScale;
Ogre::Vector3 mPosition;
Ogre::Vector3 mForce; Ogre::Vector3 mForce;
bool mOnGround; bool mOnGround;
bool mCollisionMode; bool mInternalCollisionMode;
bool mCollisionBody; bool mExternalCollisionMode;
std::string mMesh; std::string mMesh;
std::string mName; std::string mName;
@ -242,7 +234,7 @@ namespace Physic
/** /**
* Add a RigidBody to the simulation * Add a RigidBody to the simulation
*/ */
void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL,bool actor = false); 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. * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap.
@ -335,7 +327,7 @@ namespace Physic
btDefaultCollisionConfiguration* collisionConfiguration; btDefaultCollisionConfiguration* collisionConfiguration;
btSequentialImpulseConstraintSolver* solver; btSequentialImpulseConstraintSolver* solver;
btCollisionDispatcher* dispatcher; btCollisionDispatcher* dispatcher;
btDiscreteDynamicsWorld* dynamicsWorld; btDiscreteDynamicsWorld* mDynamicsWorld;
//the NIF file loader. //the NIF file loader.
BulletShapeLoader* mShapeLoader; BulletShapeLoader* mShapeLoader;

@ -65,12 +65,13 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start,
to.setOrigin(btend); to.setOrigin(btend);
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0));
newTraceCallback.m_collisionFilterGroup = CollisionType_Actor;
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
CollisionType_Actor; CollisionType_Actor;
btCollisionShape *shape = actor->getCollisionShape(); btCollisionShape *shape = actor->getCollisionShape();
assert(shape->isConvex()); assert(shape->isConvex());
enginePass->dynamicsWorld->convexSweepTest(static_cast<btConvexShape*>(shape), enginePass->mDynamicsWorld->convexSweepTest(static_cast<btConvexShape*>(shape),
from, to, newTraceCallback); from, to, newTraceCallback);
// Copy the hit data over to our trace results struct: // Copy the hit data over to our trace results struct:
@ -89,27 +90,26 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start,
} }
} }
void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass) void ActorTracer::findGround(const OEngine::Physic::PhysicActor* actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass)
{ {
const btVector3 btstart(start.x, start.y, start.z+1.0f); const btVector3 btstart(start.x, start.y, start.z+1.0f);
const btVector3 btend(end.x, end.y, end.z+1.0f); const btVector3 btend(end.x, end.y, end.z+1.0f);
const btTransform &trans = actor->getWorldTransform(); const btTransform &trans = actor->getCollisionBody()->getWorldTransform();
btTransform from(trans.getBasis(), btstart); btTransform from(trans.getBasis(), btstart);
btTransform to(trans.getBasis(), btend); btTransform to(trans.getBasis(), btend);
ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); ClosestNotMeConvexResultCallback newTraceCallback(actor->getCollisionBody(), btstart-btend, btScalar(0.0));
newTraceCallback.m_collisionFilterGroup = CollisionType_Actor;
newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap |
CollisionType_Actor; CollisionType_Actor;
const btBoxShape *shape = dynamic_cast<btBoxShape*>(actor->getCollisionShape()); btVector3 halfExtents(actor->getHalfExtents().x, actor->getHalfExtents().y, actor->getHalfExtents().z);
assert(shape);
btVector3 halfExtents = shape->getHalfExtentsWithMargin();
halfExtents[2] = 1.0f; halfExtents[2] = 1.0f;
btBoxShape box(halfExtents); btBoxShape base(halfExtents);
enginePass->dynamicsWorld->convexSweepTest(&box, from, to, newTraceCallback); enginePass->mDynamicsWorld->convexSweepTest(&base, from, to, newTraceCallback);
if(newTraceCallback.hasHit()) if(newTraceCallback.hasHit())
{ {
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;

@ -12,6 +12,7 @@ namespace OEngine
namespace Physic namespace Physic
{ {
class PhysicEngine; class PhysicEngine;
class PhysicActor;
struct ActorTracer struct ActorTracer
{ {
@ -22,7 +23,7 @@ namespace Physic
void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
const PhysicEngine *enginePass); const PhysicEngine *enginePass);
void findGround(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, void findGround(const OEngine::Physic::PhysicActor* actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end,
const PhysicEngine *enginePass); const PhysicEngine *enginePass);
}; };
} }

Loading…
Cancel
Save