From e002acdeaeb3c2559f36b7c9f0ee4ac6abeb7748 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 21 Jun 2014 23:32:58 +0200 Subject: [PATCH] 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. --- apps/openmw/mwworld/physicssystem.cpp | 10 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/nifbullet/bulletnifloader.cpp | 49 ++++++ components/nifbullet/bulletnifloader.hpp | 5 + libs/openengine/bullet/physic.cpp | 184 +++++++++++------------ libs/openengine/bullet/physic.hpp | 50 +++--- libs/openengine/bullet/trace.cpp | 18 +-- libs/openengine/bullet/trace.h | 3 +- 8 files changed, 177 insertions(+), 144 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 73a704c88..8aca591e8 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -175,7 +175,7 @@ namespace MWWorld const int maxHeight = 200.f; 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) { physicActor->setOnGround(false); @@ -607,9 +607,10 @@ namespace MWWorld Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); const std::string &handle = node->getName(); const Ogre::Quaternion &rotation = node->getOrientation(); + + // TODO: map to MWWorld::Ptr for faster access if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) { - //Needs to be changed act->setRotation(rotation); } if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) @@ -740,8 +741,9 @@ namespace MWWorld btCollisionObject object; object.setCollisionShape(&planeShape); + // TODO: this seems to have a slight performance impact if (waterCollision) - mEngine->dynamicsWorld->addCollisionObject(&object); + mEngine->mDynamicsWorld->addCollisionObject(&object); // 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); @@ -751,7 +753,7 @@ namespace MWWorld waterlevel, slowFall, mEngine); if (waterCollision) - mEngine->dynamicsWorld->removeCollisionObject(&object); + mEngine->mDynamicsWorld->removeCollisionObject(&object); float heightDiff = newpos.z - oldHeight; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bcae8c070..be334646b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1847,7 +1847,7 @@ namespace MWWorld Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); OEngine::Physic::ActorTracer tracer; // a small distance above collision object is considered "on ground" - tracer.findGround(physactor->getCollisionBody(), + tracer.findGround(physactor, pos, pos - Ogre::Vector3(0, 0, 1.5f), // trace a small amount down mPhysEngine); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index cdddb94d0..3e753dd37 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -304,4 +304,53 @@ void ManualBulletShapeLoader::load(const std::string &name,const std::string &gr 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(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(r); + if (node == NULL) + { + return false; + } + + return findBoundingBox(node, halfExtents, translation, orientation); +} + } // namespace NifBullet diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index d1e876305..fb7d3d70a 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -108,6 +108,11 @@ private: 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 diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 8d9ac3c22..bc34f2f51 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -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) - : mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0) - , mBody(0), mRaycastingBody(0), mOnGround(false), mCollisionMode(true), mBoxRotation(0,0,0,0) - , mCollisionBody(true) + : mName(name), mEngine(engine), mMesh(mesh) + , mBody(0), mOnGround(false), mInternalCollisionMode(true) + , mExternalCollisionMode(true) , mForce(0.0f) + , mScale(scale) { - mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); - mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true); - Ogre::Quaternion inverse = mBoxRotation.Inverse(); - mBoxRotationInverse = Ogre::Quaternion(inverse.w, inverse.x, inverse.y,inverse.z); - mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map + if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation)) + { + mHalfExtents = Ogre::Vector3(0.f); + mMeshTranslation = Ogre::Vector3(0.f); + 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() { if(mBody) { - mEngine->dynamicsWorld->removeRigidBody(mBody); + mEngine->mDynamicsWorld->removeRigidBody(mBody); delete mBody; - } - if(mRaycastingBody) - { - mEngine->dynamicsWorld->removeRigidBody(mRaycastingBody); - delete mRaycastingBody; - } + } } void PhysicActor::enableCollisionMode(bool collision) { - mCollisionMode = collision; + mInternalCollisionMode = collision; } void PhysicActor::enableCollisionBody(bool collision) { assert(mBody); - if(collision && !mCollisionBody) enableCollisionBody(); - if(!collision && mCollisionBody) disableCollisionBody(); - mCollisionBody = collision; + if(collision && !mExternalCollisionMode) enableCollisionBody(); + if(!collision && mExternalCollisionMode) disableCollisionBody(); + mExternalCollisionMode = collision; } - void PhysicActor::setPosition(const Ogre::Vector3 &pos) + const Ogre::Vector3& PhysicActor::getPosition() const { - assert(mBody); - if(pos != getPosition()) - { - mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation); - mEngine->adjustRigidBody(mRaycastingBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation); - } + return mPosition; } - void PhysicActor::setRotation(const Ogre::Quaternion &quat) + void PhysicActor::setPosition(const Ogre::Vector3 &position) { 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() - { - 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; + tr.setOrigin(BtOgre::Convert::toBullet(newPosition)); + mBody->setWorldTransform(tr); } - Ogre::Quaternion PhysicActor::getRotation() + void PhysicActor::setRotation (const Ogre::Quaternion& rotation) { - assert(mBody); - btQuaternion quat = mBody->getWorldTransform().getRotation(); - return Ogre::Quaternion(quat.getW(), quat.getX(), quat.getY(), quat.getZ()) * mBoxRotationInverse; + btTransform tr = mBody->getWorldTransform(); + tr.setRotation(BtOgre::Convert::toBullet(mMeshOrientation * rotation)); + mBody->setWorldTransform(tr); } - void PhysicActor::setScale(float scale){ - //We only need to change the scaled box translation, box rotations remain the same. - assert(mBody); - mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX(); - mBoxScaledTranslation *= scale; - 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 + void PhysicActor::setScale(float scale) + { + mScale = scale; + mShape->setLocalScaling(btVector3(scale,scale,scale)); + setPosition(mPosition); } Ogre::Vector3 PhysicActor::getHalfExtents() const { - if(mBody) - { - btBoxShape *box = static_cast(mBody->getCollisionShape()); - if(box != NULL) - { - btVector3 size = box->getHalfExtentsWithMargin(); - return Ogre::Vector3(size.getX(), size.getY(), size.getZ()); - } - } - return Ogre::Vector3(0.0f); + return mHalfExtents; } void PhysicActor::setInertialForce(const Ogre::Vector3 &force) @@ -139,12 +117,16 @@ namespace Physic void PhysicActor::disableCollisionBody() { - mEngine->dynamicsWorld->removeRigidBody(mBody); + mEngine->mDynamicsWorld->removeRigidBody(mBody); + mEngine->mDynamicsWorld->addRigidBody(mBody, CollisionType_Actor, + CollisionType_Raycasting); } 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(); // The world. - dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); - dynamicsWorld->setGravity(btVector3(0,0,-10)); + mDynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration); + mDynamicsWorld->setGravity(btVector3(0,0,-10)); if(BulletShapeManager::getSingletonPtr() == NULL) { @@ -208,10 +190,10 @@ namespace Physic if(!isDebugCreated) { Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); - mDebugDrawer = new BtOgre::DebugDrawer(node, dynamicsWorld); - dynamicsWorld->setDebugDrawer(mDebugDrawer); + mDebugDrawer = new BtOgre::DebugDrawer(node, mDynamicsWorld); + mDynamicsWorld->setDebugDrawer(mDebugDrawer); isDebugCreated = true; - dynamicsWorld->debugDrawWorld(); + mDynamicsWorld->debugDrawWorld(); } } @@ -241,7 +223,7 @@ namespace Physic HeightFieldContainer::iterator hf_it = mHeightFieldMap.begin(); 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.mBody; } @@ -251,7 +233,7 @@ namespace Physic { if (rb_it->second != NULL) { - dynamicsWorld->removeRigidBody(rb_it->second); + mDynamicsWorld->removeRigidBody(rb_it->second); delete rb_it->second; rb_it->second = NULL; @@ -262,7 +244,7 @@ namespace Physic { if (rb_it->second != NULL) { - dynamicsWorld->removeRigidBody(rb_it->second); + mDynamicsWorld->removeRigidBody(rb_it->second); delete rb_it->second; rb_it->second = NULL; @@ -281,7 +263,7 @@ namespace Physic delete mDebugDrawer; - delete dynamicsWorld; + delete mDynamicsWorld; delete solver; delete collisionConfiguration; delete dispatcher; @@ -331,7 +313,7 @@ namespace Physic mHeightFieldMap [name] = hf; - dynamicsWorld->addRigidBody(body,CollisionType_HeightMap|CollisionType_Raycasting, + mDynamicsWorld->addRigidBody(body,CollisionType_HeightMap, CollisionType_World|CollisionType_Actor|CollisionType_Raycasting); } @@ -343,7 +325,7 @@ namespace Physic HeightField hf = mHeightFieldMap [name]; - dynamicsWorld->removeRigidBody(hf.mBody); + mDynamicsWorld->removeRigidBody(hf.mBody); delete hf.mShape; delete hf.mBody; @@ -367,7 +349,6 @@ namespace Physic { std::string sid = (boost::format("%07.3f") % scale).str(); std::string outputstring = mesh + sid; - //std::cout << "The string" << outputstring << "\n"; //get the shape from the .nif 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) return; // nothing to do @@ -427,12 +408,11 @@ namespace Physic const std::string& name = (body ? body->mName : raycastingBody->mName); if (body){ - if(actor) dynamicsWorld->addRigidBody(body,CollisionType_Actor,CollisionType_World|CollisionType_HeightMap); - else dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap); + mDynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_Actor|CollisionType_HeightMap); } if (raycastingBody) - dynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World); + mDynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting); if(addToMap){ removeRigidBody(name); @@ -453,7 +433,7 @@ namespace Physic RigidBody* body = it->second; if(body != NULL) { - dynamicsWorld->removeRigidBody(body); + mDynamicsWorld->removeRigidBody(body); } } it = mRaycastingObjectMap.find(name); @@ -462,7 +442,7 @@ namespace Physic RigidBody* body = it->second; 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 body = getRigidBody(name, true); ContactTestResultCallback callback; - dynamicsWorld->contactTest(body, callback); + mDynamicsWorld->contactTest(body, callback); return callback.mResult; } @@ -615,8 +595,9 @@ namespace Physic btCollisionObject *object) { DeepestNotMeContactTestResultCallback callback(filter, origin); + callback.m_collisionFilterGroup = 0xff; 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); } @@ -624,7 +605,7 @@ namespace Physic void PhysicEngine::stepSimulation(double deltaT) { // 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) { mDebugDrawer->step(); @@ -684,14 +665,15 @@ namespace Physic float d = -1; btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); + resultCallback1.m_collisionFilterGroup = 0xff; if(raycastingObjectOnly) - resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; + resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor; else resultCallback1.m_collisionFilterMask = CollisionType_World; if(!ignoreHeightMap) resultCallback1.m_collisionFilterMask = resultCallback1.m_collisionFilterMask | CollisionType_HeightMap; - dynamicsWorld->rayTest(from, to, resultCallback1); + mDynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { name = static_cast(*resultCallback1.m_collisionObject).mName; @@ -724,6 +706,7 @@ namespace Physic std::pair PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to) { OurClosestConvexResultCallback callback(from, to); + callback.m_collisionFilterGroup = 0xff; callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap; btSphereShape shape(radius); @@ -732,7 +715,7 @@ namespace Physic btTransform from_ (btrot, from); btTransform to_ (btrot, to); - dynamicsWorld->convexSweepTest(&shape, from_, to_, callback); + mDynamicsWorld->convexSweepTest(&shape, from_, to_, callback); if (callback.hasHit()) return std::make_pair(true, callback.m_closestHitFraction); @@ -743,8 +726,9 @@ namespace Physic std::vector< std::pair > PhysicEngine::rayTest2(btVector3& from, btVector3& to) { MyRayResultCallback resultCallback1; - resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; - dynamicsWorld->rayTest(from, to, resultCallback1); + resultCallback1.m_collisionFilterGroup = 0xff; + resultCallback1.m_collisionFilterMask = CollisionType_Raycasting|CollisionType_Actor; + mDynamicsWorld->rayTest(from, to, resultCallback1); std::vector< std::pair > results = resultCallback1.results; std::vector< std::pair > results2; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 803986d5b..f24ef93d0 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -76,6 +76,9 @@ namespace Physic RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); virtual ~RigidBody(); 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; }; @@ -92,13 +95,6 @@ namespace Physic 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. */ @@ -111,26 +107,18 @@ namespace Physic 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 */ void setScale(float scale); + void setRotation (const Ogre::Quaternion& rotation); + + const Ogre::Vector3& getPosition() const; + /** * Returns the half extents for this PhysiActor */ @@ -153,7 +141,7 @@ namespace Physic bool getOnGround() const { - return mCollisionMode && mOnGround; + return mInternalCollisionMode && mOnGround; } btCollisionObject *getCollisionBody() const @@ -165,17 +153,21 @@ namespace Physic void disableCollisionBody(); void enableCollisionBody(); + boost::shared_ptr mShape; + OEngine::Physic::RigidBody* mBody; - OEngine::Physic::RigidBody* mRaycastingBody; - Ogre::Vector3 mBoxScaledTranslation; - Ogre::Quaternion mBoxRotation; - Ogre::Quaternion mBoxRotationInverse; + Ogre::Quaternion mMeshOrientation; + Ogre::Vector3 mMeshTranslation; + Ogre::Vector3 mHalfExtents; + + float mScale; + Ogre::Vector3 mPosition; Ogre::Vector3 mForce; bool mOnGround; - bool mCollisionMode; - bool mCollisionBody; + bool mInternalCollisionMode; + bool mExternalCollisionMode; std::string mMesh; std::string mName; @@ -242,7 +234,7 @@ namespace Physic /** * 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. @@ -335,7 +327,7 @@ namespace Physic btDefaultCollisionConfiguration* collisionConfiguration; btSequentialImpulseConstraintSolver* solver; btCollisionDispatcher* dispatcher; - btDiscreteDynamicsWorld* dynamicsWorld; + btDiscreteDynamicsWorld* mDynamicsWorld; //the NIF file loader. BulletShapeLoader* mShapeLoader; diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 6eab43a60..78fb5a3a7 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -65,12 +65,13 @@ void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, to.setOrigin(btend); ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); + newTraceCallback.m_collisionFilterGroup = CollisionType_Actor; newTraceCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor; btCollisionShape *shape = actor->getCollisionShape(); assert(shape->isConvex()); - enginePass->dynamicsWorld->convexSweepTest(static_cast(shape), + enginePass->mDynamicsWorld->convexSweepTest(static_cast(shape), from, to, newTraceCallback); // 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 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 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 | CollisionType_Actor; - const btBoxShape *shape = dynamic_cast(actor->getCollisionShape()); - assert(shape); + btVector3 halfExtents(actor->getHalfExtents().x, actor->getHalfExtents().y, actor->getHalfExtents().z); - btVector3 halfExtents = shape->getHalfExtentsWithMargin(); 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()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h index 92795c87f..b9fbce64d 100644 --- a/libs/openengine/bullet/trace.h +++ b/libs/openengine/bullet/trace.h @@ -12,6 +12,7 @@ namespace OEngine namespace Physic { class PhysicEngine; + class PhysicActor; struct ActorTracer { @@ -22,7 +23,7 @@ namespace Physic void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, 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); }; }