diff --git a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp index 6baf7233d..e5af3e90a 100644 --- a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp +++ b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp @@ -16,6 +16,7 @@ subject to the following restrictions: //#define PRINT_CONTACT_STATISTICS 1 //#define REGISTER_CUSTOM_COLLISION_ALGORITHM 1 //#define USER_DEFINED_FRICTION_MODEL 1 +#define USE_CUSTOM_NEAR_CALLBACK 1 //following define allows to compare/replace Bullet's constraint solver with ODE quickstep //this define requires to either add the libquickstep library (win32, see msvc/8/libquickstep.vcproj) or manually add the files from Extras/quickstep @@ -110,6 +111,42 @@ btCollisionShape* shapePtr[numShapes] = +//by default, Bullet will use its own nearcallback, but you can override it using dispatcher->setNearCallback() +void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher.needsCollision(colObj0,colObj1)) + { + //dispatcher will keep algorithms persistent in the collision pair + if (!collisionPair.m_algorithm) + { + collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); + } + + if (collisionPair.m_algorithm) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + float toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + +} + + @@ -254,6 +291,11 @@ void CcdPhysicsDemo::initPhysics() btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); +#ifdef USE_CUSTOM_NEAR_CALLBACK + //this is optional + dispatcher->setNearCallback(customNearCallback); +#endif + btVector3 worldAabbMin(-10000,-10000,-10000); btVector3 worldAabbMax(10000,10000,10000); diff --git a/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index 3ad246788..b279022c8 100644 --- a/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -70,7 +70,8 @@ struct btBroadphaseProxy StaticFilter = 2, KinematicFilter = 4, DebrisFilter = 8, - AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter, + SensorTrigger = 16, + AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger, }; //Usually the client btCollisionObject or Rigidbody class @@ -118,8 +119,7 @@ class btCollisionAlgorithm; struct btBroadphaseProxy; -//Increase SIMPLE_MAX_ALGORITHMS to allow multiple btDispatchers caching their own algorithms -#define SIMPLE_MAX_ALGORITHMS 1 + /// contains a pair of aabb-overlapping objects struct btBroadphasePair @@ -127,22 +127,16 @@ struct btBroadphasePair btBroadphasePair () : m_pProxy0(0), - m_pProxy1(0) + m_pProxy1(0), + m_algorithm(0) { - for (int i=0;im_clientObject; - btCollisionObject* body1 = (btCollisionObject*)pair.m_pProxy1->m_clientObject; + (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); - if (!m_dispatcher->needsCollision(body0,body1)) - return false; - - //dispatcher will keep algorithms persistent in the collision pair - if (!pair.m_algorithms[m_dispatcherId]) - { - pair.m_algorithms[m_dispatcherId] = m_dispatcher->findAlgorithm( - body0, - body1); - } - - if (pair.m_algorithms[m_dispatcherId]) - { - btManifoldResult* resultOut = m_dispatcher->internalGetNewManifoldResult(body0,body1); - if (m_dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) - { - - pair.m_algorithms[m_dispatcherId]->processCollision(body0,body1,m_dispatchInfo,resultOut); - } else - { - float toi = pair.m_algorithms[m_dispatcherId]->calculateTimeOfImpact(body0,body1,m_dispatchInfo,resultOut); - if (m_dispatchInfo.m_timeOfImpact > toi) - m_dispatchInfo.m_timeOfImpact = toi; - - } - m_dispatcher->internalReleaseManifoldResult(resultOut); - } return false; - } }; @@ -327,9 +301,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa { //m_blockedForChanges = true; - int dispatcherId = getUniqueId(); - - btCollisionPairCallback collisionCallback(dispatchInfo,this,dispatcherId); + btCollisionPairCallback collisionCallback(dispatchInfo,this); pairCache->processAllOverlappingPairs(&collisionCallback); @@ -338,3 +310,39 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa } + + +//by default, Bullet will use this near callback +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher.needsCollision(colObj0,colObj1)) + { + //dispatcher will keep algorithms persistent in the collision pair + if (!collisionPair.m_algorithm) + { + collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); + } + + if (collisionPair.m_algorithm) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + float toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + +} \ No newline at end of file diff --git a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index 41bc98e1d..77c09b618 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -32,6 +32,10 @@ class btOverlappingPairCache; #define USE_DISPATCH_REGISTRY_ARRAY 1 +class btCollisionDispatcher; +///user can override this nearcallback for collision filtering and more finegrained control over collision detection +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. ///Time of Impact, Closest Points and Penetration Depth. @@ -43,6 +47,8 @@ class btCollisionDispatcher : public btDispatcher bool m_useIslands; btManifoldResult m_defaultManifoldResult; + + btNearCallback m_nearCallback; btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; @@ -62,19 +68,7 @@ class btCollisionDispatcher : public btDispatcher public: - ///allows the user to get contact point callbacks - inline btManifoldResult* internalGetNewManifoldResult(btCollisionObject* obj0,btCollisionObject* obj1) - { - //in-place, this prevents parallel dispatching, but just adding a list would fix that. - btManifoldResult* manifoldResult = new (&m_defaultManifoldResult) btManifoldResult(obj0,obj1); - return manifoldResult; - } - - ///allows the user to get contact point callbacks - inline void internalReleaseManifoldResult(btManifoldResult*) - { - } - + ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); @@ -121,12 +115,21 @@ public: virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1); virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - - virtual int getUniqueId() { return RIGIDBODY_DISPATCHER;} virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); - + void setNearCallback(btNearCallback nearCallback) + { + m_nearCallback = nearCallback; + } + + btNearCallback getNearCallback() const + { + return m_nearCallback; + } + + //by default, Bullet will use this near callback + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); }; diff --git a/src/BulletDynamics/Dynamics/btRigidBody.cpp b/src/BulletDynamics/Dynamics/btRigidBody.cpp index db05f37d8..453b8ec42 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -35,6 +35,7 @@ btRigidBody::btRigidBody(float mass, btMotionState* motionState, btCollisionShap m_totalTorque(0.0f, 0.0f, 0.0f), m_linearVelocity(0.0f, 0.0f, 0.0f), m_angularVelocity(0.f,0.f,0.f), + m_angularFactor(1.f), m_linearDamping(0.f), m_angularDamping(0.5f), m_optionalMotionState(motionState), diff --git a/src/BulletDynamics/Dynamics/btRigidBody.h b/src/BulletDynamics/Dynamics/btRigidBody.h index c5fecdb87..43869363c 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/src/BulletDynamics/Dynamics/btRigidBody.h @@ -47,6 +47,7 @@ class btRigidBody : public btCollisionObject btVector3 m_linearVelocity; btVector3 m_angularVelocity; btScalar m_inverseMass; + btScalar m_angularFactor; btVector3 m_gravity; btVector3 m_invInertiaLocal; @@ -159,7 +160,10 @@ public: if (m_inverseMass != 0.f) { applyCentralImpulse(impulse); - applyTorqueImpulse(rel_pos.cross(impulse)); + if (m_angularFactor) + { + applyTorqueImpulse(rel_pos.cross(impulse)*m_angularFactor); + } } } @@ -169,7 +173,10 @@ public: if (m_inverseMass != 0.f) { m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*impulseMagnitude; + if (m_angularFactor) + { + m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + } } } @@ -321,7 +328,20 @@ public: int m_contactSolverType; int m_frictionSolverType; - + void setAngularFactor(float angFac) + { + m_angularFactor = angFac; + } + float getAngularFactor() const + { + return m_angularFactor; + } + + //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? + bool isInWorld() const + { + return (getBroadphaseProxy() != 0); + } int m_debugBodyId; };