#include "trace.h" #include #include #include #include "physic.hpp" void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass) //Traceobj was a Aedra Object { const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); const btQuaternion btorient (orient.x, orient.y, orient.z, orient.w); const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); //const btCapsuleShapeZ newshape(BBHalfExtents.x, BBHalfExtents.z * 2 - BBHalfExtents.x * 2); const btTransform from(btorient, btstart); const btTransform to(btorient, btend); btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend); newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap|OEngine::Physic::CollisionType_Actor; enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); // Copy the hit data over to our trace results struct: if(newTraceCallback.hasHit()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; results->fraction = newTraceCallback.m_closestHitFraction; results->planenormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); results->endpos = (end-start)*results->fraction + start; } else { results->endpos = end; results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); results->fraction = 1.0f; } } class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: ClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), mMe(me), mUp(up), mMinSlopeDot(minSlopeDot) { } virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) { if(convexResult.m_hitCollisionObject == mMe) return btScalar( 1 ); btVector3 hitNormalWorld; if(normalInWorldSpace) hitNormalWorld = convexResult.m_hitNormalLocal; else { ///need to transform normal into worldspace hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; } // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... btScalar dotUp = mUp.dot(hitNormalWorld); if(dotUp < mMinSlopeDot) return btScalar(1); return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); } protected: btCollisionObject *mMe; const btVector3 mUp; const btScalar mMinSlopeDot; }; void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, OEngine::Physic::PhysicEngine *enginePass) { const btVector3 btstart(start.x, start.y, start.z); const btVector3 btend(end.x, end.y, end.z); const btTransform &trans = actor->getWorldTransform(); btTransform from(trans); btTransform to(trans); from.setOrigin(btstart); to.setOrigin(btend); ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World | OEngine::Physic::CollisionType_HeightMap | OEngine::Physic::CollisionType_Actor; btCollisionShape *shape = actor->getCollisionShape(); assert(shape->isConvex()); enginePass->dynamicsWorld->convexSweepTest(static_cast(shape), from, to, newTraceCallback); // Copy the hit data over to our trace results struct: if(newTraceCallback.hasHit()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; results->fraction = newTraceCallback.m_closestHitFraction; results->planenormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); results->endpos = (end-start)*results->fraction + start; } else { results->endpos = end; results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); results->fraction = 1.0f; } }