diff --git a/Demos/CharacterDemo/CharacterControllerInterface.h b/Demos/CharacterDemo/CharacterControllerInterface.h index f2189bb8e..cd043f3dd 100644 --- a/Demos/CharacterDemo/CharacterControllerInterface.h +++ b/Demos/CharacterDemo/CharacterControllerInterface.h @@ -12,16 +12,12 @@ class CharacterControllerInterface public: CharacterControllerInterface () {}; virtual ~CharacterControllerInterface () {}; - virtual void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0; - virtual void destroy () = 0; - - virtual btCollisionObject* getCollisionObject () = 0; - + virtual void reset () = 0; virtual void warp (const btVector3& origin) = 0; - virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)=0; - virtual void preStep (const btCollisionWorld* collisionWorld) = 0; - virtual void playerStep (const btCollisionWorld* collisionWorld, btScalar dt, + + virtual void preStep ( btCollisionWorld* collisionWorld) = 0; + virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt, int forward, int backward, int left, diff --git a/Demos/CharacterDemo/CharacterDemo.cpp b/Demos/CharacterDemo/CharacterDemo.cpp index 492b4ed9e..5b4cd6fe8 100644 --- a/Demos/CharacterDemo/CharacterDemo.cpp +++ b/Demos/CharacterDemo/CharacterDemo.cpp @@ -13,13 +13,9 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -/// September 2006: CharacterDemo is work in progress, this file is mostly just a placeholder -/// This CharacterDemo file is very early in development, please check it later -/// One todo is a basic engine model: -/// A function that maps user input (throttle) into torque/force applied on the wheels -/// with gears etc. #include "btBulletDynamicsCommon.h" #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" +#include "BulletCollision/CollisionDispatch/btGhostObject.h" #include "GLDebugDrawer.h" #include //printf debugging @@ -54,55 +50,6 @@ void playerStepCallback(btDynamicsWorld* dynamicsWorld, btScalar timeStep) } -#define QUAKE_BSP_IMPORTING 1 -#ifdef QUAKE_BSP_IMPORTING -#include "../BspDemo/BspLoader.h" -#include "../BspDemo/BspConverter.h" - - - - -class BspToBulletConverter : public BspConverter -{ - CharacterDemo* m_demoApp; - -public: - - BspToBulletConverter(CharacterDemo* demoApp) - :m_demoApp(demoApp) - { - } - - virtual void addConvexVerticesCollider(btAlignedObjectArray& vertices, bool isEntity, const btVector3& entityTargetLocation) - { - ///perhaps we can do something special with entities (isEntity) - ///like adding a collision Triggering (as example) - - if (vertices.size() > 0) - { - float mass = 0.f; - btTransform startTransform; - //can use a shift - startTransform.setIdentity(); - startTransform.setOrigin(btVector3(0,-10.0f,0.0f)); - //this create an internal copy of the vertices - for (int i = 0; i < vertices.size(); i++) - { - vertices[i] *= btScalar(0.5); - float t = vertices[i].getZ() * btScalar(0.75); - vertices[i].setZ(-vertices[i].getY()); - vertices[i].setY(t); - } - - btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size()); - m_demoApp->m_collisionShapes.push_back(shape); - - //btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape); - m_demoApp->localCreateRigidBody(mass, startTransform,shape); - } - } -}; -#endif //QUAKE_BSP_IMPORTING CharacterDemo::CharacterDemo() : m_cameraHeight(4.f), @@ -115,130 +62,6 @@ m_vertices(0) m_cameraPosition = btVector3(30,30,30); } -CharacterDemo::~CharacterDemo() -{ - //cleanup in the reverse order of creation/initialization - if (m_character) - { - m_dynamicsWorld->removeCollisionObject(m_character->getCollisionObject()); - m_character->destroy (); - } - - - //remove the rigidbodies from the dynamics world and delete them - int i; - for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) - { - btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; - btRigidBody* body = btRigidBody::upcast(obj); - if (body && body->getMotionState()) - { - delete body->getMotionState(); - } - m_dynamicsWorld->removeCollisionObject( obj ); - delete obj; - } - - //delete collision shapes - for (int j=0;jm_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; - collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); - return collides; - - } - } myCustomOverlapFilterCallback; - -public: - - MyCustomOverlappingPairCallback(CharacterDemo* demo,btCollisionObject* characterCollider) - :m_characterDemo(demo), - m_characterCollider(characterCollider) - { - m_hashPairCache = new btHashedOverlappingPairCache(); - m_hashPairCache->setOverlapFilterCallback (&myCustomOverlapFilterCallback); - } - - virtual ~MyCustomOverlappingPairCallback() - { - delete m_hashPairCache; - } - - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) - { - if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider) - { - //printf("addOverlappingPair (%p,%p)\n",proxy0,proxy1); - return m_hashPairCache->addOverlappingPair(proxy0,proxy1); - } - return 0; - } - - virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) - { - if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider) - { - //printf("removeOverlappingPair (%p,%p)\n",proxy0,proxy1); - return m_hashPairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - } - return 0; - } - - virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) - { - if (proxy0->m_clientObject==m_characterCollider) - { - //printf("removeOverlappingPairsContainingProxy (%p)\n",proxy0); - m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); - } - } - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_hashPairCache->getOverlappingPairArray(); - } - - btOverlappingPairCache* getOverlappingPairCache() - { - return m_hashPairCache; - } - -}; void CharacterDemo::initPhysics() { @@ -254,29 +77,56 @@ void CharacterDemo::initPhysics() m_constraintSolver = new btSequentialImpulseConstraintSolver(); m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); +#ifdef DYNAMIC_CHARACTER_CONTROLLER + m_character = new DynamicCharacterController (); +#else + + btTransform startTransform; + startTransform.setIdentity (); + startTransform.setOrigin (btVector3(0.0, 4.0, 0.0)); + + m_ghostObject = new btPairCachingGhostObject(); + m_ghostObject->setWorldTransform(startTransform); + sweepBP->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback()); + btScalar characterHeight=1.75; + btScalar characterWidth =1.75; + btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight); + m_ghostObject->setCollisionShape (capsule); + m_ghostObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE); + + btScalar stepHeight = btScalar(0.35); + m_character = new KinematicCharacterController (m_ghostObject,capsule,stepHeight); +#endif + + + m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character); + + + ///only collide with static for now (no interaction with dynamic objects) + m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::DebrisFilter, btBroadphaseProxy::StaticFilter); + + + //////////////// + + /// Create some basic environment from a Quake level + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); btTransform tr; tr.setIdentity(); - -#ifdef QUAKE_BSP_IMPORTING char* bspfilename = "BspDemo.bsp"; void* memoryBuffer = 0; FILE* file = fopen(bspfilename,"r"); if (!file) { - //try again other path, - //sight... visual studio leaves the current working directory in the projectfiles folder - //instead of executable folder. who wants this default behaviour?!? + //visual studio leaves the current working directory in the projectfiles folder bspfilename = "../../BspDemo.bsp"; file = fopen(bspfilename,"r"); } if (!file) { - //try again other path, - //sight... visual studio leaves the current working directory in the projectfiles folder - //instead of executable folder. who wants this default behaviour?!? + //visual studio leaves the current working directory in the projectfiles folder bspfilename = "BspDemo.bsp"; file = fopen(bspfilename,"r"); } @@ -302,211 +152,11 @@ void CharacterDemo::initPhysics() fclose(file); } -#else -#define USE_TRIMESH_GROUND 1 -#ifdef USE_TRIMESH_GROUND - int i; + /////////////// -const float TRIANGLE_SIZE=20.f; - - //create a triangle-mesh ground - int vertStride = sizeof(btVector3); - int indexStride = 3*sizeof(int); - - const int NUM_VERTS_X = 20; - const int NUM_VERTS_Y = 20; - const int totalVerts = NUM_VERTS_X*NUM_VERTS_Y; - - const int totalTriangles = 2*(NUM_VERTS_X-1)*(NUM_VERTS_Y-1); - - m_vertices = new btVector3[totalVerts]; - int* gIndices = new int[totalTriangles*3]; - - - - for ( i=0;isetUseDiamondSubdivision(true); - - btVector3 localScaling(20,20,20); - localScaling[upIndex]=1.f; - groundShape->setLocalScaling(localScaling); - - tr.setOrigin(btVector3(0,-64.5f,0)); - -#endif // - - m_collisionShapes.push_back(groundShape); - //create ground object - localCreateRigidBody(0,tr,groundShape); - - - -#define CUBE_HALF_EXTENTS 0.5 -#define EXTRA_HEIGHT 10.0 - btBoxShape* boxShape = new btBoxShape (btVector3(1.0, 1.0, 1.0)); - m_collisionShapes.push_back (boxShape); -#define DO_WALL -#ifdef DO_WALL - for (i=0;i<50;i++) - { - btCollisionShape* shape = boxShape; - //shape->setMargin(gCollisionMargin); - - bool isDyna = i>0; - - btTransform trans; - trans.setIdentity(); - - if (i>0) - { - //stack them - int colsize = 10; - int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS); - int row2 = row; - int col = (i)%(colsize)-colsize/2; - - - if (col>3) - { - col=11; - row2 |=1; - } - - btVector3 pos(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS, - row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0); - - trans.setOrigin(pos); - } else - { - trans.setOrigin(btVector3(0,EXTRA_HEIGHT-CUBE_HALF_EXTENTS,0)); - } - - float mass = 1.f; - - if (!isDyna) - mass = 0.f; - - btRigidBody* body = localCreateRigidBody(mass,trans,shape); -#ifdef USE_KINEMATIC_GROUND - if (mass == 0.f) - { - body->setCollisionFlags( body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - } -#endif //USE_KINEMATIC_GROUND - - } -#endif - -#endif - -#ifdef DYNAMIC_CHARACTER_CONTROLLER - m_character = new DynamicCharacterController (); -#else - m_character = new KinematicCharacterController (); -#endif - m_character->setup (); - - m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character); - - //some custom callback sample - m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getCollisionObject()); - sweepBP->setOverlappingPairUserCallback(m_customPairCallback); - m_character->registerPairCacheAndDispatcher (m_customPairCallback->getOverlappingPairCache(), m_dispatcher); - - ///only collide with static for now (no interaction with dynamic objects) - m_dynamicsWorld->addCollisionObject(m_character->getCollisionObject(),btBroadphaseProxy::DebrisFilter, btBroadphaseProxy::StaticFilter); - clientResetScene(); - setCameraDistance(26.f); + setCameraDistance(56.f); } @@ -526,13 +176,16 @@ void CharacterDemo::debugDrawContacts() // printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size()); { btManifoldArray manifoldArray; - for (int i=0;igetOverlappingPairArray().size();i++) + btBroadphasePairArray& pairArray = m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray(); + int numPairs = pairArray.size(); + + for (int i=0;igetOverlappingPairArray()[i]; + const btBroadphasePair& pair = pairArray[i]; + btBroadphasePair* collisionPair = m_overlappingPairCache->getOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1); - if (!collisionPair) continue; @@ -546,7 +199,8 @@ void CharacterDemo::debugDrawContacts() { const btManifoldPoint&pt = manifold->getContactPoint(p); - m_dynamicsWorld->getDebugDrawer()->drawContactPoint(pt.getPositionWorldOnB(),pt.m_normalWorldOnB,pt.getDistance(),pt.getLifeTime(),btVector3(1.f,1.f,0.f)); + btVector3 color(255,255,255); + m_dynamicsWorld->getDebugDrawer()->drawContactPoint(pt.getPositionWorldOnB(),pt.m_normalWorldOnB,pt.getDistance(),pt.getLifeTime(),color); } } } @@ -645,7 +299,7 @@ void CharacterDemo::displayCallback(void) void CharacterDemo::clientResetScene() { - m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getCollisionObject()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); + m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); m_character->reset (); ///WTF @@ -741,14 +395,14 @@ void CharacterDemo::updateCamera() btTransform characterWorldTrans; //look at the vehicle - characterWorldTrans = m_character->getCollisionObject()->getWorldTransform(); + characterWorldTrans = m_ghostObject->getWorldTransform(); btVector3 up = characterWorldTrans.getBasis()[1]; btVector3 backward = -characterWorldTrans.getBasis()[2]; up.normalize (); backward.normalize (); m_cameraTargetPosition = characterWorldTrans.getOrigin(); - m_cameraPosition = m_cameraTargetPosition + up * 2.0 + backward * 2.0; + m_cameraPosition = m_cameraTargetPosition + up * 2.0 + backward * 12.0; //update OpenGL camera settings glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0); @@ -764,3 +418,51 @@ void CharacterDemo::updateCamera() } + +CharacterDemo::~CharacterDemo() +{ + //cleanup in the reverse order of creation/initialization + if (m_character) + { + m_dynamicsWorld->removeCollisionObject(m_ghostObject); + } + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;j m_collisionShapes; @@ -51,8 +54,6 @@ class CharacterDemo : public DemoApplication class btTriangleIndexVertexArray* m_indexVertexArrays; - class MyCustomOverlappingPairCallback* m_customPairCallback; - btVector3* m_vertices; void debugDrawContacts(); @@ -93,6 +94,59 @@ class CharacterDemo : public DemoApplication } }; + + +#define QUAKE_BSP_IMPORTING 1 +#ifdef QUAKE_BSP_IMPORTING +#include "../BspDemo/BspLoader.h" +#include "../BspDemo/BspConverter.h" + + + + +class BspToBulletConverter : public BspConverter +{ + CharacterDemo* m_demoApp; + +public: + + BspToBulletConverter(CharacterDemo* demoApp) + :m_demoApp(demoApp) + { + } + + virtual void addConvexVerticesCollider(btAlignedObjectArray& vertices, bool isEntity, const btVector3& entityTargetLocation) + { + ///perhaps we can do something special with entities (isEntity) + ///like adding a collision Triggering (as example) + + if (vertices.size() > 0) + { + float mass = 0.f; + btTransform startTransform; + //can use a shift + startTransform.setIdentity(); + startTransform.setOrigin(btVector3(0,-10.0f,0.0f)); + //this create an internal copy of the vertices + for (int i = 0; i < vertices.size(); i++) + { + vertices[i] *= btScalar(0.5); + float t = vertices[i].getZ() * btScalar(0.75); + vertices[i].setZ(-vertices[i].getY()); + vertices[i].setY(t); + } + + btCollisionShape* shape = new btConvexHullShape(&(vertices[0].getX()),vertices.size()); + m_demoApp->m_collisionShapes.push_back(shape); + + //btRigidBody* body = m_demoApp->localCreateRigidBody(mass, startTransform,shape); + m_demoApp->localCreateRigidBody(mass, startTransform,shape); + } + } +}; +#endif //QUAKE_BSP_IMPORTING + + #endif //CHARACTER_DEMO_H diff --git a/Demos/CharacterDemo/KinematicCharacterController.cpp b/Demos/CharacterDemo/KinematicCharacterController.cpp index bb5dda37a..04b58dfce 100644 --- a/Demos/CharacterDemo/KinematicCharacterController.cpp +++ b/Demos/CharacterDemo/KinematicCharacterController.cpp @@ -1,6 +1,6 @@ #include "GLDebugDrawer.h" - +#include "BulletCollision/CollisionDispatch/btGhostObject.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" @@ -81,85 +81,42 @@ btVector3 perpindicularComponent (const btVector3& direction, const btVector3& n return direction - parallelComponent(direction, normal); } -KinematicCharacterController::KinematicCharacterController () +KinematicCharacterController::KinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight) { + m_useGhostObjectSweepTest = true; + m_ghostObject = ghostObject; + m_stepHeight = stepHeight; m_turnAngle = btScalar(0.0); m_walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s - m_shape = NULL; - m_pairCache = NULL; - m_collisionObject = NULL; + m_convexShape=convexShape; + } KinematicCharacterController::~KinematicCharacterController () { } -void KinematicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight) + +btPairCachingGhostObject* KinematicCharacterController::getGhostObject() { - btVector3 spherePositions[2]; - btScalar sphereRadii[2]; - - sphereRadii[0] = width; - sphereRadii[1] = width; - spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) ), 0.0); - spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0)), 0.0); - - m_halfHeight = height/btScalar(2.0); - - m_shape = new btMultiSphereShape (btVector3(width/btScalar(2.0), height/btScalar(2.0), width/btScalar(2.0)), &spherePositions[0], &sphereRadii[0], 2); - m_stepHeight = stepHeight; - m_height = height; - m_width = width; - btTransform startTransform; - startTransform.setIdentity (); - startTransform.setOrigin (btVector3(0.0, 4.0, 0.0)); - //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - - m_collisionObject = new btCollisionObject (); - - m_collisionObject->setWorldTransform(startTransform); - m_collisionObject->setCollisionShape (m_shape); - m_collisionObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE); - + return m_ghostObject; } -void KinematicCharacterController::destroy () -{ - if (m_collisionObject) - { - delete m_collisionObject; - } - - if (m_shape) - { - delete m_shape; - } -} - -btCollisionObject* KinematicCharacterController::getCollisionObject () -{ - return m_collisionObject; -} - -bool KinematicCharacterController::recoverFromPenetration (const btCollisionWorld* collisionWorld) +bool KinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld) { - if (m_pairCache == NULL) - return false; - bool penetration = false; - - m_dispatcher->dispatchAllCollisionPairs (m_pairCache, collisionWorld->getDispatchInfo(), m_dispatcher); + collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher()); - m_currentPosition = m_collisionObject->getWorldTransform().getOrigin(); + m_currentPosition = m_ghostObject->getWorldTransform().getOrigin(); btScalar maxPen = btScalar(0.0); - for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++) + for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) { m_manifoldArray.resize(0); - btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i]; + btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i]; if (collisionPair->m_algorithm) collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); @@ -168,7 +125,7 @@ bool KinematicCharacterController::recoverFromPenetration (const btCollisionWorl for (int j=0;jgetBody0() == m_collisionObject ? btScalar(-1.0) : btScalar(1.0); + btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0); for (int p=0;pgetNumContacts();p++) { const btManifoldPoint&pt = manifold->getContactPoint(p); @@ -191,14 +148,14 @@ bool KinematicCharacterController::recoverFromPenetration (const btCollisionWorl //manifold->clearManifold(); } } - btTransform newTrans = m_collisionObject->getWorldTransform(); + btTransform newTrans = m_ghostObject->getWorldTransform(); newTrans.setOrigin(m_currentPosition); - m_collisionObject->setWorldTransform(newTrans); + m_ghostObject->setWorldTransform(newTrans); // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); return penetration; } -void KinematicCharacterController::stepUp (const btCollisionWorld* world) +void KinematicCharacterController::stepUp ( btCollisionWorld* world) { // phase 1: up btTransform start, end; @@ -211,12 +168,19 @@ void KinematicCharacterController::stepUp (const btCollisionWorld* world) start.setOrigin (m_currentPosition + btVector3(btScalar(0.0), btScalar(0.1), btScalar(0.0))); end.setOrigin (m_targetPosition); - ClosestNotMeConvexResultCallback callback (m_collisionObject); - callback.m_collisionFilterGroup = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterMask; + ClosestNotMeConvexResultCallback callback (m_ghostObject); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, world->getDispatchInfo().m_allowedCcdPenetration,callback); + } + else + { + world->convexSweepTest (m_convexShape, start, end, callback); + } - world->convexSweepTest (m_shape, start, end, callback); - if (callback.hasHit()) { // we moved up only a fraction of the step height @@ -264,7 +228,7 @@ void KinematicCharacterController::updateTargetPositionBasedOnCollision (const b } } -void KinematicCharacterController::stepForwardAndStrafe (const btCollisionWorld* collisionWorld, const btVector3& walkMove) +void KinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove) { btVector3 originalDir = walkMove.normalized(); @@ -296,15 +260,23 @@ void KinematicCharacterController::stepForwardAndStrafe (const btCollisionWorld* start.setOrigin (m_currentPosition); end.setOrigin (m_targetPosition); - ClosestNotMeConvexResultCallback callback (m_collisionObject); - callback.m_collisionFilterGroup = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterMask; + ClosestNotMeConvexResultCallback callback (m_ghostObject); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; - //btScalar margin = m_shape->getMargin(); - //m_shape->setMargin(margin - 0.06f); - collisionWorld->convexSweepTest (m_shape, start, end, callback); - //m_shape->setMargin(margin); + //btScalar margin = m_convexShape->getMargin(); + //m_convexShape->setMargin(margin - 0.06f); + + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, collisionWorld->getDispatchInfo().m_allowedCcdPenetration,callback); + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback); + } + + //m_convexShape->setMargin(margin); fraction -= callback.m_closestHitFraction; @@ -352,7 +324,7 @@ void KinematicCharacterController::stepForwardAndStrafe (const btCollisionWorld* } } -void KinematicCharacterController::stepDown (const btCollisionWorld* collisionWorld, btScalar dt) +void KinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt) { btTransform start, end; @@ -367,11 +339,17 @@ void KinematicCharacterController::stepDown (const btCollisionWorld* collisionWo start.setOrigin (m_currentPosition); end.setOrigin (m_targetPosition); - ClosestNotMeConvexResultCallback callback (m_collisionObject); - callback.m_collisionFilterGroup = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterGroup; - callback.m_collisionFilterMask = getCollisionObject()->getBroadphaseHandle()->m_collisionFilterMask; + ClosestNotMeConvexResultCallback callback (m_ghostObject); + callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; + callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; - collisionWorld->convexSweepTest (m_shape, start, end, callback); + if (m_useGhostObjectSweepTest) + { + m_ghostObject->convexSweepTest (m_convexShape, start, end, collisionWorld->getDispatchInfo().m_allowedCcdPenetration,callback); + } else + { + collisionWorld->convexSweepTest (m_convexShape, start, end, callback); + } if (callback.hasHit()) { @@ -393,16 +371,11 @@ void KinematicCharacterController::warp (const btVector3& origin) btTransform xform; xform.setIdentity(); xform.setOrigin (origin); - m_collisionObject->setWorldTransform (xform); + m_ghostObject->setWorldTransform (xform); } -void KinematicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher) -{ - m_pairCache = pairCache; - m_dispatcher = dispatcher; -} -void KinematicCharacterController::preStep (const btCollisionWorld* collisionWorld) +void KinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) { int numPenetrationLoops = 0; @@ -418,7 +391,7 @@ void KinematicCharacterController::preStep (const btCollisionWorld* collisionWor } } btTransform xform; - xform = m_collisionObject->getWorldTransform (); + xform = m_ghostObject->getWorldTransform (); btVector3 forwardDir = xform.getBasis()[2]; // printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]); @@ -439,7 +412,7 @@ void KinematicCharacterController::preStep (const btCollisionWorld* collisionWor } -void KinematicCharacterController::playerStep (const btCollisionWorld* collisionWorld, +void KinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt, int forward, int backward, @@ -463,7 +436,7 @@ void KinematicCharacterController::playerStep (const btCollisionWorld* collision walkDirection -= m_forwardDirection; btTransform xform; - xform = m_collisionObject->getWorldTransform (); + xform = m_ghostObject->getWorldTransform (); // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); // printf("walkSpeed=%f\n",walkSpeed); @@ -473,7 +446,7 @@ void KinematicCharacterController::playerStep (const btCollisionWorld* collision stepDown (collisionWorld, dt); xform.setOrigin (m_currentPosition); - m_collisionObject->setWorldTransform (xform); + m_ghostObject->setWorldTransform (xform); } void KinematicCharacterController::setFallSpeed (btScalar fallSpeed) diff --git a/Demos/CharacterDemo/KinematicCharacterController.h b/Demos/CharacterDemo/KinematicCharacterController.h index aa8020c0f..23a203882 100644 --- a/Demos/CharacterDemo/KinematicCharacterController.h +++ b/Demos/CharacterDemo/KinematicCharacterController.h @@ -9,7 +9,7 @@ class btCollisionShape; class btRigidBody; class btCollisionWorld; class btCollisionDispatcher; - +class btPairCachingGhostObject; ///KinematicCharacterController is a collision object with support for sliding motion in a world. ///It uses the convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. @@ -18,11 +18,10 @@ class KinematicCharacterController : public CharacterControllerInterface { protected: btScalar m_halfHeight; - btConvexShape* m_shape; - btCollisionObject* m_collisionObject; - btOverlappingPairCache* m_pairCache; - btCollisionDispatcher* m_dispatcher; - + + btPairCachingGhostObject* m_ghostObject; + btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast + btScalar m_fallSpeed; btScalar m_jumpSpeed; btScalar m_maxJumpHeight; @@ -30,8 +29,6 @@ protected: btScalar m_turnAngle; btScalar m_walkVelocity; - btScalar m_height; - btScalar m_width; btScalar m_stepHeight; btVector3 m_upDirection; @@ -46,26 +43,26 @@ protected: bool m_touchingContact; btVector3 m_touchingNormal; - - bool recoverFromPenetration (const btCollisionWorld* collisionWorld); - void stepUp (const btCollisionWorld* collisionWorld); - void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); - void stepForwardAndStrafe (const btCollisionWorld* collisionWorld, const btVector3& walkMove); - void stepDown (const btCollisionWorld* collisionWorld, btScalar dt); -public: - KinematicCharacterController (); - ~KinematicCharacterController (); - void setup (btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35)); - void destroy (); - btCollisionObject* getCollisionObject (); + bool m_useGhostObjectSweepTest; + + bool recoverFromPenetration (btCollisionWorld* collisionWorld); + void stepUp (btCollisionWorld* collisionWorld); + void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); + void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove); + void stepDown (btCollisionWorld* collisionWorld, btScalar dt); +public: + KinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight); + ~KinematicCharacterController (); + + + btPairCachingGhostObject* getGhostObject(); void reset (); void warp (const btVector3& origin); - virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher); - void preStep (const btCollisionWorld* collisionWorld); - void playerStep (const btCollisionWorld* collisionWorld, btScalar dt, + void preStep ( btCollisionWorld* collisionWorld); + void playerStep (btCollisionWorld* collisionWorld, btScalar dt, int forward, int backward, int left, @@ -77,6 +74,10 @@ public: void setMaxJumpHeight (btScalar maxJumpHeight); bool canJump () const; void jump (); + void setUseGhostSweepTest(bool useGhostObjectSweepTest) + { + m_useGhostObjectSweepTest = useGhostObjectSweepTest; + } bool onGround () const; }; diff --git a/Demos/OpenGL/GLDebugDrawer.cpp b/Demos/OpenGL/GLDebugDrawer.cpp index fa8695c16..02f8f98ff 100644 --- a/Demos/OpenGL/GLDebugDrawer.cpp +++ b/Demos/OpenGL/GLDebugDrawer.cpp @@ -27,7 +27,7 @@ void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btV // if (m_debugMode > 0) { glBegin(GL_LINES); - glColor3f(color.getX(), color.getY(), color.getZ()); + glColor4f(color.getX(), color.getY(), color.getZ(),1.f); glVertex3d(from.getX(), from.getY(), from.getZ()); glVertex3d(to.getX(), to.getY(), to.getZ()); glEnd(); @@ -72,13 +72,15 @@ void GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& { btVector3 to=pointOnB+normalOnB*distance; const btVector3&from = pointOnB; + glColor4f(color.getX(), color.getY(), color.getZ(),1.f); + //glColor4f(0,0,0,1.f); + glBegin(GL_LINES); - glColor3f(color.getX(), color.getY(), color.getZ()); glVertex3d(from.getX(), from.getY(), from.getZ()); glVertex3d(to.getX(), to.getY(), to.getZ()); glEnd(); - + glRasterPos3f(from.x(), from.y(), from.z()); char buf[12]; sprintf(buf," %d",lifeTime); diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index 359807c25..2f581047e 100644 --- a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -33,7 +33,8 @@ int gFindPairs =0; btHashedOverlappingPairCache::btHashedOverlappingPairCache(): m_overlapFilterCallback(0), - m_blockedForChanges(false) + m_blockedForChanges(false), + m_ghostPairCallback(0) { int initialAllocatedSize= 2; m_overlappingPairArray.reserve(initialAllocatedSize); @@ -238,6 +239,11 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx int count = m_overlappingPairArray.size(); int oldCapacity = m_overlappingPairArray.capacity(); void* mem = &m_overlappingPairArray.expand(); + + //this is where we add an actual pair, so also call the 'ghost' + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0,proxy1); + int newCapacity = m_overlappingPairArray.capacity(); if (oldCapacity < newCapacity) @@ -317,6 +323,9 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro int lastPairIndex = m_overlappingPairArray.size() - 1; + if (m_ghostPairCallback) + m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); + // If the removed pair is the last pair, we are done. if (lastPairIndex == pairIndex) { @@ -399,6 +408,8 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro btBroadphasePair& pair = m_overlappingPairArray[findIndex]; void* userData = pair.m_userInfo; cleanOverlappingPair(pair,dispatcher); + if (m_ghostPairCallback) + m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher); m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); m_overlappingPairArray.pop_back(); @@ -426,8 +437,12 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP void* mem = &m_overlappingPairArray.expand(); btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + gOverlappingPairs++; gAddedPairs++; + + if (m_ghostPairCallback) + m_ghostPairCallback->addOverlappingPair(proxy0, proxy1); return pair; } @@ -493,7 +508,8 @@ void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* btSortedOverlappingPairCache::btSortedOverlappingPairCache(): m_blockedForChanges(false), m_hasDeferredRemoval(true), - m_overlapFilterCallback(0) + m_overlapFilterCallback(0), + m_ghostPairCallback(0) { int initialAllocatedSize= 2; m_overlappingPairArray.reserve(initialAllocatedSize); diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index f91226c28..d356f2b13 100644 --- a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -83,6 +83,8 @@ public: virtual bool hasDeferredRemoval() = 0; + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; + }; /// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com @@ -253,10 +255,16 @@ private: return false; } + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + public: btAlignedObjectArray m_hashTable; btAlignedObjectArray m_next; + btOverlappingPairCallback* m_ghostPairCallback; }; @@ -280,6 +288,8 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; + btOverlappingPairCallback* m_ghostPairCallback; + public: btSortedOverlappingPairCache(); @@ -355,12 +365,17 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache return m_hasDeferredRemoval; } + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + m_ghostPairCallback = ghostPairCallback; + } + }; -///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing. +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. class btNullPairCache : public btOverlappingPairCache { @@ -414,6 +429,10 @@ public: return true; } + virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) + { + } + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) { return 0; @@ -427,6 +446,7 @@ public: virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) { } + }; diff --git a/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index c6728918d..a6da5f61a 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -17,7 +17,6 @@ subject to the following restrictions: #define COLLISION_CREATE_FUNC #include "LinearMath/btAlignedObjectArray.h" -typedef btAlignedObjectArray btCollisionObjectArray; class btCollisionAlgorithm; class btCollisionObject; diff --git a/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 37ccd5d91..a95728ff6 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -29,8 +29,11 @@ struct btBroadphaseProxy; class btCollisionShape; #include "LinearMath/btMotionState.h" #include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" +typedef btAlignedObjectArray btCollisionObjectArray; + /// btCollisionObject can be used to manage collision detection objects. /// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 20362349d..b10423818 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -71,7 +71,7 @@ class btBroadphaseInterface; #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" #include "btCollisionObject.h" -#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray +#include "btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" #include "LinearMath/btAlignedObjectArray.h" diff --git a/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/src/BulletCollision/CollisionDispatch/btGhostObject.cpp index 492ad1637..06b1e6c1c 100644 --- a/src/BulletCollision/CollisionDispatch/btGhostObject.cpp +++ b/src/BulletCollision/CollisionDispatch/btGhostObject.cpp @@ -14,16 +14,149 @@ subject to the following restrictions: */ #include "btGhostObject.h" +#include "btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btAabbUtil2.h" btGhostObject::btGhostObject() { m_internalType = CO_GHOST_OBJECT; - - m_overlappingPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); - m_overlappingPairCache->setOverlapFilterCallback(&m_ghostOverlapFilterCallback); } btGhostObject::~btGhostObject() { - btAlignedFree(m_overlappingPairCache); + ///btGhostObject should have been removed from the world, so no overlapping objects + btAssert(!m_overlappingObjects.size()); } + + +void btGhostObject::addOverlappingObject(btBroadphaseProxy* otherProxy) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + m_overlappingObjects.push_back(otherObject); + } +} + +void btGhostObject::removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (indexm_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (index==m_overlappingObjects.size()) + { + m_overlappingObjects.push_back(otherObject); + m_hashPairCache->addOverlappingPair(getBroadphaseHandle(),otherProxy); + } +} + +void btPairCachingGhostObject::removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher) +{ + btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject; + btAssert(otherObject); + int index = m_overlappingObjects.findLinearSearch(otherObject); + if (indexremoveOverlappingPair(getBroadphaseHandle(),otherProxy,dispatcher); + } +} + + +void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btScalar allowedCcdPenetration, btCollisionWorld::ConvexResultCallback& resultCallback) const +{ + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + allowedCcdPenetration); + } + } + } + +} + +void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const +{ + btTransform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFromWorld); + btTransform rayToTrans; + rayToTrans.setIdentity(); + rayToTrans.setOrigin(rayToWorld); + + + int i; + for (i=0;igetBroadphaseHandle())) + { + btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback); + } + } +} + diff --git a/src/BulletCollision/CollisionDispatch/btGhostObject.h b/src/BulletCollision/CollisionDispatch/btGhostObject.h index 9b43ff821..2beda0aee 100644 --- a/src/BulletCollision/CollisionDispatch/btGhostObject.h +++ b/src/BulletCollision/CollisionDispatch/btGhostObject.h @@ -21,8 +21,11 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h" #include "LinearMath/btAlignedAllocator.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "btCollisionWorld.h" -///work-in-progress, not complete +class btConvexShape; + +class btDispatcher; ///The btGhostObject can keep track of all objects that are overlapping ///By default, this overlap is based on the AABB @@ -32,20 +35,7 @@ ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject { protected: - btOverlappingPairCache* m_overlappingPairCache; - - struct btGhostOverlapFilterCallback : public btOverlapFilterCallback - { - bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const - { - bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; - collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); - return collides; - } - }; - - btGhostOverlapFilterCallback m_ghostOverlapFilterCallback; - + btAlignedObjectArray m_overlappingObjects; public: @@ -53,33 +43,41 @@ public: virtual ~btGhostObject(); + void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btScalar allowedCcdPenetration,btCollisionWorld::ConvexResultCallback& resultCallback) const; - virtual void addOverlappingObject(btCollisionObject* otherObject); + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; - virtual void removeOverlappingObject(btCollisionObject* otherObject); + virtual void addOverlappingObject(btBroadphaseProxy* otherProxy); - btOverlappingPairCache* getPairCache() + virtual void removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher); + + int getNumOverlappingObjects() const { - return m_overlappingPairCache; - }; - - const btOverlappingPairCache* getPairCache() const - { - return m_overlappingPairCache; - }; - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairCache->getOverlappingPairArray(); + return m_overlappingObjects.size(); } - btOverlappingPairCache* getOverlappingPairCache() + btCollisionObject* getOverlappingObject(int index) { - return m_overlappingPairCache; + return m_overlappingObjects[index]; + } + + const btCollisionObject* getOverlappingObject(int index) const + { + return m_overlappingObjects[index]; + } + + btAlignedObjectArray& getOverlappingPairs() + { + return m_overlappingObjects; + } + + const btAlignedObjectArray getOverlappingPairs() const + { + return m_overlappingObjects; } // - // Cast + // internal cast // static const btGhostObject* upcast(const btCollisionObject* colObj) @@ -95,11 +93,31 @@ public: return 0; } +}; +class btPairCachingGhostObject : public btGhostObject +{ + btHashedOverlappingPairCache* m_hashPairCache; + +public: + + btPairCachingGhostObject(); + + virtual ~btPairCachingGhostObject(); + + virtual void addOverlappingObject(btBroadphaseProxy* otherProxy); + + virtual void removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher); + + btHashedOverlappingPairCache* getOverlappingPairCache() + { + return m_hashPairCache; + } }; + ///btGhostPairCache keeps track of overlapping objects that have AABB overlap with the ghost class btGhostPairCallback : public btOverlappingPairCallback { @@ -121,9 +139,10 @@ public: btGhostObject* ghost0 = btGhostObject::upcast(colObj0); btGhostObject* ghost1 = btGhostObject::upcast(colObj1); if (ghost0) - ghost0->addOverlappingObject(colObj1); + ghost0->addOverlappingObject(proxy1); if (ghost1) - ghost1->addOverlappingObject(colObj0); + ghost1->addOverlappingObject(proxy0); + return 0; } virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) @@ -133,9 +152,10 @@ public: btGhostObject* ghost0 = btGhostObject::upcast(colObj0); btGhostObject* ghost1 = btGhostObject::upcast(colObj1); if (ghost0) - ghost0->removeOverlappingObject(colObj1); + ghost0->removeOverlappingObject(proxy1,dispatcher); if (ghost1) - ghost1->removeOverlappingObject(colObj0); + ghost1->removeOverlappingObject(proxy0,dispatcher); + return 0; } virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) diff --git a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index 5f4d54cd8..d44f975b4 100644 --- a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -19,7 +19,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" #include "LinearMath/btAlignedObjectArray.h" - +#include "btCollisionObject.h" class btCollisionObject; class btCollisionWorld;