Refactoring to enable multi SAP broadphase.

This was already planned, and Pierre Terdiman recent thread motivated me to decouple the paircache from the sweep and prune.
http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
This commit is contained in:
ejcoumans
2007-08-02 23:48:46 +00:00
parent 5279f9e129
commit 1f7646f72a
29 changed files with 212 additions and 85 deletions

View File

@@ -152,7 +152,7 @@ void BasicDemo::initPhysics()
m_dispatcher = new btCollisionDispatcher(true); m_dispatcher = new btCollisionDispatcher(true);
#endif //USE_PARALLEL_DISPATCHER #endif //USE_PARALLEL_DISPATCHER
//#define USE_SWEEP_AND_PRUNE 1 #define USE_SWEEP_AND_PRUNE 1
#ifdef USE_SWEEP_AND_PRUNE #ifdef USE_SWEEP_AND_PRUNE
#define maxProxies 8192 #define maxProxies 8192
btVector3 worldAabbMin(-10000,-10000,-10000); btVector3 worldAabbMin(-10000,-10000,-10000);

View File

@@ -31,7 +31,7 @@ class BasicDemo : public DemoApplication
//keep the collision shapes, for deletion/cleanup //keep the collision shapes, for deletion/cleanup
btAlignedObjectArray<btCollisionShape*> m_collisionShapes; btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
btOverlappingPairCache* m_overlappingPairCache; btBroadphaseInterface* m_overlappingPairCache;
btCollisionDispatcher* m_dispatcher; btCollisionDispatcher* m_dispatcher;

View File

@@ -138,7 +138,7 @@ void BspDemo::initPhysics(char* bspfilename)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
btVector3 worldMin(-1000,-1000,-1000); btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000); btVector3 worldMax(1000,1000,1000);
btOverlappingPairCache* pairCache = new btAxisSweep3(worldMin,worldMax); btBroadphaseInterface* pairCache = new btAxisSweep3(worldMin,worldMax);
//btOverlappingPairCache* broadphase = new btSimpleBroadphase(); //btOverlappingPairCache* broadphase = new btSimpleBroadphase();
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
//ConstraintSolver* solver = new OdeConstraintSolver; //ConstraintSolver* solver = new OdeConstraintSolver;

View File

@@ -361,7 +361,7 @@ void CcdPhysicsDemo::initPhysics()
btVector3 worldAabbMin(-1000,-1000,-1000); btVector3 worldAabbMin(-1000,-1000,-1000);
btVector3 worldAabbMax(1000,1000,1000); btVector3 worldAabbMax(1000,1000,1000);
btOverlappingPairCache* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); btBroadphaseInterface* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
// btOverlappingPairCache* broadphase = new btSimpleBroadphase; // btOverlappingPairCache* broadphase = new btSimpleBroadphase;
#ifdef REGISTER_CUSTOM_COLLISION_ALGORITHM #ifdef REGISTER_CUSTOM_COLLISION_ALGORITHM

View File

@@ -173,7 +173,7 @@ void ColladaDemo::initPhysics(const char* filename)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
btVector3 worldMin(-1000,-1000,-1000); btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000); btVector3 worldMax(1000,1000,1000);
btOverlappingPairCache* pairCache = new btAxisSweep3(worldMin,worldMax); btBroadphaseInterface* pairCache = new btAxisSweep3(worldMin,worldMax);
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver);

View File

@@ -223,7 +223,7 @@ void ConcaveDemo::initPhysics()
btVector3 worldMin(-1000,-1000,-1000); btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000); btVector3 worldMax(1000,1000,1000);
btOverlappingPairCache* pairCache = new btAxisSweep3(worldMin,worldMax); btBroadphaseInterface* pairCache = new btAxisSweep3(worldMin,worldMax);
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver);
#ifdef USE_PARALLEL_DISPATCHER #ifdef USE_PARALLEL_DISPATCHER
@@ -276,7 +276,7 @@ void ConcaveDemo::clientMoveAndDisplay()
trimeshShape->refitTree(); trimeshShape->refitTree();
//clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation. //clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
m_dynamicsWorld->getBroadphase()->cleanProxyFromPairs(staticBody->getBroadphaseHandle()); m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(staticBody->getBroadphaseHandle());
} }
m_dynamicsWorld->stepSimulation(dt); m_dynamicsWorld->stepSimulation(dt);

View File

@@ -79,8 +79,8 @@ void ConstraintDemo::initPhysics()
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
btVector3 worldMin(-1000,-1000,-1000); btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000); btVector3 worldMax(1000,1000,1000);
btOverlappingPairCache* pairCache = new btAxisSweep3(worldMin,worldMax); btBroadphaseInterface* pairCache = new btAxisSweep3(worldMin,worldMax);
//btOverlappingPairCache* broadphase = new btSimpleBroadphase(); //btBroadphaseInterface* broadphase = new btSimpleBroadphase();
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
//ConstraintSolver* solver = new OdeConstraintSolver; //ConstraintSolver* solver = new OdeConstraintSolver;
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver);

View File

@@ -122,8 +122,8 @@ void ConvexDecompositionDemo::initPhysics(const char* filename)
btVector3 worldAabbMin(-10000,-10000,-10000); btVector3 worldAabbMin(-10000,-10000,-10000);
btVector3 worldAabbMax(10000,10000,10000); btVector3 worldAabbMax(10000,10000,10000);
btOverlappingPairCache* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax); btBroadphaseInterface* broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax);
//OverlappingPairCache* broadphase = new btSimpleBroadphase(); //btBroadphaseInterface* broadphase = new btSimpleBroadphase();
btConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver);

View File

@@ -1648,7 +1648,7 @@ void ConcaveDemo::initPhysics()
//btConstraintSolver* solver = new btSequentialImpulseConstraintSolver; //btConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
//btOverlappingPairCache* broadphase = new btSimpleBroadphase(); //btOverlappingPairCache* broadphase = new btSimpleBroadphase();
btOverlappingPairCache* broadphase = new btSimpleBroadphase(); btBroadphaseInterface* broadphase = new btSimpleBroadphase();
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver);

View File

@@ -450,12 +450,12 @@ void DemoApplication::shootBox(const btVector3& destination)
startTransform.setIdentity(); startTransform.setIdentity();
btVector3 camPos = getCameraPosition(); btVector3 camPos = getCameraPosition();
startTransform.setOrigin(camPos); startTransform.setOrigin(camPos);
#define TEST_UNIFORM_SCALING_SHAPE 1 //#define TEST_UNIFORM_SCALING_SHAPE 1
#ifdef TEST_UNIFORM_SCALING_SHAPE #ifdef TEST_UNIFORM_SCALING_SHAPE
btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f)); btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f));
btUniformScalingShape* boxShape = new btUniformScalingShape(childShape,0.5f); btUniformScalingShape* boxShape = new btUniformScalingShape(childShape,0.5f);
#else #else
btCollisionShape* boxShape = new btSphereShape(1); btCollisionShape* boxShape = new btBoxShape(btVector3(0.5f,0.5f,0.5f));
#endif// #endif//
btRigidBody* body = this->localCreateRigidBody(mass, startTransform,boxShape); btRigidBody* body = this->localCreateRigidBody(mass, startTransform,boxShape);
@@ -932,7 +932,7 @@ void DemoApplication::clientResetScene()
colObj->activate(); colObj->activate();
} }
//removed cached contact points //removed cached contact points
m_dynamicsWorld->getBroadphase()->cleanProxyFromPairs(colObj->getBroadphaseHandle()); m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(colObj->getBroadphaseHandle());
btRigidBody* body = btRigidBody::upcast(colObj); btRigidBody* body = btRigidBody::upcast(colObj);
if (body && !body->isStaticObject()) if (body && !body->isStaticObject())

View File

@@ -311,7 +311,7 @@ void RagdollDemo::initPhysics()
btPoint3 worldAabbMin(-10000,-10000,-10000); btPoint3 worldAabbMin(-10000,-10000,-10000);
btPoint3 worldAabbMax(10000,10000,10000); btPoint3 worldAabbMax(10000,10000,10000);
btOverlappingPairCache* overlappingPairCache = new btAxisSweep3 (worldAabbMin, worldAabbMax); btBroadphaseInterface* overlappingPairCache = new btAxisSweep3 (worldAabbMin, worldAabbMax);
btConstraintSolver* solver = new btSequentialImpulseConstraintSolver; btConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

View File

@@ -109,7 +109,7 @@ void UserCollisionAlgorithm::initPhysics()
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
btVector3 maxAabb(10000,10000,10000); btVector3 maxAabb(10000,10000,10000);
btOverlappingPairCache* broadphase = new btAxisSweep3(-maxAabb,maxAabb);//SimpleBroadphase(); btBroadphaseInterface* broadphase = new btAxisSweep3(-maxAabb,maxAabb);//SimpleBroadphase();
dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,GIMPACT_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc); dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,GIMPACT_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc);
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();

View File

@@ -121,7 +121,7 @@ void VehicleDemo::setupPhysics()
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(); btCollisionDispatcher* dispatcher = new btCollisionDispatcher();
btVector3 worldMin(-1000,-1000,-1000); btVector3 worldMin(-1000,-1000,-1000);
btVector3 worldMax(1000,1000,1000); btVector3 worldMax(1000,1000,1000);
btOverlappingPairCache* pairCache = new btAxisSweep3(worldMin,worldMax); btBroadphaseInterface* pairCache = new btAxisSweep3(worldMin,worldMax);
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver); m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver);
#ifdef FORCE_ZAXIS_UP #ifdef FORCE_ZAXIS_UP
@@ -490,7 +490,7 @@ void VehicleDemo::clientResetScene()
m_carChassis->setCenterOfMassTransform(btTransform::getIdentity()); m_carChassis->setCenterOfMassTransform(btTransform::getIdentity());
m_carChassis->setLinearVelocity(btVector3(0,0,0)); m_carChassis->setLinearVelocity(btVector3(0,0,0));
m_carChassis->setAngularVelocity(btVector3(0,0,0)); m_carChassis->setAngularVelocity(btVector3(0,0,0));
m_dynamicsWorld->getBroadphase()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle()); m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle());
if (m_vehicle) if (m_vehicle)
{ {
m_vehicle->resetSuspension(); m_vehicle->resetSuspension();

View File

@@ -74,9 +74,10 @@ void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,con
btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles)
:btOverlappingPairCache() :m_invalidPair(0)
{ {
m_invalidPair = 0; m_pairCache = new btOverlappingPairCache();
//assert(bounds.HasVolume()); //assert(bounds.HasVolume());
// 1 handle is reserved as sentinel // 1 handle is reserved as sentinel
@@ -244,7 +245,7 @@ void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle)
//explicitly remove the pairs containing the proxy //explicitly remove the pairs containing the proxy
//we could do it also in the sortMinUp (passing true) //we could do it also in the sortMinUp (passing true)
//todo: compare performance //todo: compare performance
removeOverlappingPairsContainingProxy(pHandle); m_pairCache->removeOverlappingPairsContainingProxy(pHandle);
// compute current limit of edge arrays // compute current limit of edge arrays
@@ -293,27 +294,16 @@ void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle)
extern int gOverlappingPairs; extern int gOverlappingPairs;
void btAxisSweep3::refreshOverlappingPairs() void btAxisSweep3::calculateOverlappingPairs()
{
}
void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
{ {
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
//remove the 'invalid' ones overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
#ifdef USE_POPBACK_REMOVAL
while (m_invalidPair>0)
{
m_invalidPair--;
m_overlappingPairArray.pop_back();
}
#else
m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0; m_invalidPair = 0;
#endif
int i; int i;
@@ -324,10 +314,10 @@ void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
previousPair.m_algorithm = 0; previousPair.m_algorithm = 0;
for (i=0;i<m_overlappingPairArray.size();i++) for (i=0;i<overlappingPairArray.size();i++)
{ {
btBroadphasePair& pair = m_overlappingPairArray[i]; btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair); bool isDuplicate = (pair == previousPair);
@@ -337,11 +327,11 @@ void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
if (!isDuplicate) if (!isDuplicate)
{ {
bool hasOverlap = testOverlap(pair.m_pProxy0,pair.m_pProxy1); bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap) if (hasOverlap)
{ {
needsRemoval = callback->processOverlap(pair); needsRemoval = false;//callback->processOverlap(pair);
} else } else
{ {
needsRemoval = true; needsRemoval = true;
@@ -356,7 +346,7 @@ void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
if (needsRemoval) if (needsRemoval)
{ {
cleanOverlappingPair(pair); m_pairCache->cleanOverlappingPair(pair);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back(); // m_overlappingPairArray.pop_back();
@@ -367,10 +357,24 @@ void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
} }
} }
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
} }
bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
bool btAxisSweep3::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{ {
const Handle* pHandleA = static_cast<Handle*>(proxy0); const Handle* pHandleA = static_cast<Handle*>(proxy0);
const Handle* pHandleB = static_cast<Handle*>(proxy1); const Handle* pHandleB = static_cast<Handle*>(proxy1);
@@ -485,7 +489,7 @@ void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlap
// if previous edge is a maximum check the bounds and add an overlap if necessary // if previous edge is a maximum check the bounds and add an overlap if necessary
if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
{ {
addOverlappingPair(pHandleEdge,pHandlePrev); m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
//AddOverlap(pEdge->m_handle, pPrev->m_handle); //AddOverlap(pEdge->m_handle, pPrev->m_handle);
@@ -636,7 +640,7 @@ void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
{ {
Handle* handle0 = getHandle(pEdge->m_handle); Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle); Handle* handle1 = getHandle(pNext->m_handle);
addOverlappingPair(handle0,handle1); m_pairCache->addOverlappingPair(handle0,handle1);
} }
// update edge reference in other handle // update edge reference in other handle
@@ -658,3 +662,5 @@ void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
} }
} }

View File

@@ -22,6 +22,7 @@
#include "LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h" #include "btOverlappingPairCache.h"
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h" #include "btBroadphaseProxy.h"
@@ -45,7 +46,7 @@
/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. /// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. /// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats.
/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos /// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos
class btAxisSweep3 : public btOverlappingPairCache class btAxisSweep3 : public btBroadphaseInterface
{ {
public: public:
@@ -77,7 +78,7 @@ public:
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
private: protected:
btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMin; // overall system bounds
btPoint3 m_worldAabbMax; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds
@@ -90,7 +91,9 @@ private:
Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
int m_invalidPair; btOverlappingPairCache* m_pairCache;
int m_invalidPair;
// allocation/deallocation // allocation/deallocation
BP_FP_INT_TYPE allocHandle(); BP_FP_INT_TYPE allocHandle();
@@ -117,7 +120,7 @@ public:
btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384);
virtual ~btAxisSweep3(); virtual ~btAxisSweep3();
virtual void refreshOverlappingPairs(); virtual void calculateOverlappingPairs();
BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask);
void removeHandle(BP_FP_INT_TYPE handle); void removeHandle(BP_FP_INT_TYPE handle);
@@ -130,7 +133,18 @@ public:
virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
virtual void destroyProxy(btBroadphaseProxy* proxy); virtual void destroyProxy(btBroadphaseProxy* proxy);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
}; };

View File

@@ -20,7 +20,9 @@ subject to the following restrictions:
struct btDispatcherInfo; struct btDispatcherInfo;
class btDispatcher; class btDispatcher;
struct btBroadphaseProxy; #include "btBroadphaseProxy.h"
class btOverlappingPairCache;
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
///BroadphaseInterface for aabb-overlapping object pairs ///BroadphaseInterface for aabb-overlapping object pairs
@@ -32,8 +34,12 @@ public:
virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0;
virtual void destroyProxy(btBroadphaseProxy* proxy)=0; virtual void destroyProxy(btBroadphaseProxy* proxy)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs()=0;
virtual btOverlappingPairCache* getOverlappingPairCache()=0;
virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
}; };

View File

@@ -182,6 +182,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
*/ */
class btBroadphasePairSortPredicate class btBroadphasePairSortPredicate
{ {
public: public:

View File

@@ -194,3 +194,6 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb
} }
} }

View File

@@ -40,19 +40,22 @@ struct btOverlapFilterCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
}; };
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
///btOverlappingPairCache maintains the objects with overlapping AABB ///btOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btOverlappingPairCache : public btBroadphaseInterface class btOverlappingPairCache
{ {
protected: protected:
//avoid brute-force finding all the time //avoid brute-force finding all the time
btAlignedObjectArray<btBroadphasePair> m_overlappingPairArray; btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy //during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges; bool m_blockedForChanges;
//if set, use the callback instead of the built in filter in needBroadphaseCollision //if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback; btOverlapFilterCallback* m_overlapFilterCallback;
public: public:
btOverlappingPairCache(); btOverlappingPairCache();
@@ -84,10 +87,16 @@ class btOverlappingPairCache : public btBroadphaseInterface
return collides; return collides;
} }
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void refreshOverlappingPairs() =0; const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
btBroadphasePair* getOverlappingPairArrayPtr() btBroadphasePair* getOverlappingPairArrayPtr()
{ {

View File

@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include <new> #include <new>
extern int gOverlappingPairs;
void btSimpleBroadphase::validate() void btSimpleBroadphase::validate()
{ {
@@ -36,11 +37,14 @@ void btSimpleBroadphase::validate()
} }
btSimpleBroadphase::btSimpleBroadphase(int maxProxies) btSimpleBroadphase::btSimpleBroadphase(int maxProxies)
:btOverlappingPairCache(), :
m_firstFreeProxy(0), m_firstFreeProxy(0),
m_numProxies(0), m_numProxies(0),
m_maxProxies(maxProxies) m_maxProxies(maxProxies),
m_invalidPair(0)
{ {
m_pairCache = new btOverlappingPairCache();
m_proxies = new btSimpleBroadphaseProxy[maxProxies]; m_proxies = new btSimpleBroadphaseProxy[maxProxies];
m_freeProxies = new int[maxProxies]; m_freeProxies = new int[maxProxies];
@@ -136,7 +140,7 @@ void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg)
btAssert (index < m_maxProxies); btAssert (index < m_maxProxies);
m_freeProxies[--m_firstFreeProxy] = index; m_freeProxies[--m_firstFreeProxy] = index;
removeOverlappingPairsContainingProxy(proxyOrg); m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg);
for (i=0;i<m_numProxies;i++) for (i=0;i<m_numProxies;i++)
{ {
@@ -186,7 +190,7 @@ public:
} }
}; };
void btSimpleBroadphase::refreshOverlappingPairs() void btSimpleBroadphase::calculateOverlappingPairs()
{ {
//first check for new overlapping pairs //first check for new overlapping pairs
int i,j; int i,j;
@@ -202,21 +206,95 @@ void btSimpleBroadphase::refreshOverlappingPairs()
if (aabbOverlap(p0,p1)) if (aabbOverlap(p0,p1))
{ {
if ( !findPair(proxy0,proxy1)) if ( !m_pairCache->findPair(proxy0,proxy1))
{ {
addOverlappingPair(proxy0,proxy1); m_pairCache->addOverlappingPair(proxy0,proxy1);
} }
} }
} }
} }
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
CheckOverlapCallback checkOverlap; //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
processAllOverlappingPairs(&checkOverlap); overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
m_pairCache->cleanOverlappingPair(pair);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
} }
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
return aabbOverlap(p0,p1);
}

View File

@@ -38,7 +38,7 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy
}; };
///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks ///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btOverlappingPairCache class btSimpleBroadphase : public btBroadphaseInterface
{ {
protected: protected:
@@ -50,7 +50,9 @@ protected:
btSimpleBroadphaseProxy** m_pProxies; btSimpleBroadphaseProxy** m_pProxies;
int m_numProxies; int m_numProxies;
btOverlappingPairCache* m_pairCache;
int m_invalidPair;
int m_maxProxies; int m_maxProxies;
@@ -67,7 +69,8 @@ protected:
protected: protected:
virtual void refreshOverlappingPairs(); virtual void calculateOverlappingPairs();
public: public:
btSimpleBroadphase(int maxProxies=16384); btSimpleBroadphase(int maxProxies=16384);
virtual ~btSimpleBroadphase(); virtual ~btSimpleBroadphase();
@@ -82,9 +85,16 @@ public:
virtual void destroyProxy(btBroadphaseProxy* proxy); virtual void destroyProxy(btBroadphaseProxy* proxy);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
}; };

View File

@@ -37,7 +37,8 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize)
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, int stackSize)
:m_dispatcher1(dispatcher), :m_dispatcher1(dispatcher),
m_broadphasePairCache(pairCache), m_broadphasePairCache(pairCache),
m_ownsDispatcher(false), m_ownsDispatcher(false),
@@ -65,7 +66,7 @@ btCollisionWorld::~btCollisionWorld()
// //
// only clear the cached algorithms // only clear the cached algorithms
// //
getBroadphase()->cleanProxyFromPairs(bp); getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp);
getBroadphase()->destroyProxy(bp); getBroadphase()->destroyProxy(bp);
} }
} }
@@ -136,8 +137,7 @@ void btCollisionWorld::performDiscreteCollisionDetection()
m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
} }
m_broadphasePairCache->refreshOverlappingPairs(); m_broadphasePairCache->calculateOverlappingPairs();
END_PROFILE("perform Broadphase Collision Detection"); END_PROFILE("perform Broadphase Collision Detection");
@@ -145,7 +145,7 @@ void btCollisionWorld::performDiscreteCollisionDetection()
btDispatcher* dispatcher = getDispatcher(); btDispatcher* dispatcher = getDispatcher();
if (dispatcher) if (dispatcher)
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo);
END_PROFILE("performDiscreteCollisionDetection"); END_PROFILE("performDiscreteCollisionDetection");
@@ -166,7 +166,7 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
// //
// only clear the cached algorithms // only clear the cached algorithms
// //
getBroadphase()->cleanProxyFromPairs(bp); getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp);
getBroadphase()->destroyProxy(bp); getBroadphase()->destroyProxy(bp);
collisionObject->setBroadphaseHandle(0); collisionObject->setBroadphaseHandle(0);
} }

View File

@@ -90,7 +90,7 @@ protected:
btStackAlloc* m_stackAlloc; btStackAlloc* m_stackAlloc;
btOverlappingPairCache* m_broadphasePairCache; btBroadphaseInterface* m_broadphasePairCache;
bool m_ownsDispatcher; bool m_ownsDispatcher;
bool m_ownsBroadphasePairCache; bool m_ownsBroadphasePairCache;
@@ -98,7 +98,7 @@ protected:
public: public:
//this constructor doesn't own the dispatcher and paircache/broadphase //this constructor doesn't own the dispatcher and paircache/broadphase
btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, int stackSize = 2*1024*1024);
virtual ~btCollisionWorld(); virtual ~btCollisionWorld();
@@ -110,7 +110,7 @@ public:
btOverlappingPairCache* getPairCache() btOverlappingPairCache* getPairCache()
{ {
return m_broadphasePairCache; return m_broadphasePairCache->getOverlappingPairCache();
} }

View File

@@ -66,7 +66,7 @@ plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle)
{ {
btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(physicsSdkHandle); btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(physicsSdkHandle);
btDispatcher* dispatcher = new btCollisionDispatcher(); btDispatcher* dispatcher = new btCollisionDispatcher();
btOverlappingPairCache* pairCache = new btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); btBroadphaseInterface* pairCache = new btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax);
btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver(); btConstraintSolver* constraintSolver = new btSequentialImpulseConstraintSolver();
return (plDynamicsWorldHandle) new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver); return (plDynamicsWorldHandle) new btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver);

View File

@@ -57,7 +57,7 @@ subject to the following restrictions:
btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver)
:btDynamicsWorld(dispatcher,pairCache), :btDynamicsWorld(dispatcher,pairCache),
m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver),
m_debugDrawer(0), m_debugDrawer(0),

View File

@@ -86,7 +86,7 @@ public:
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver);
virtual ~btDiscreteDynamicsWorld(); virtual ~btDiscreteDynamicsWorld();

View File

@@ -28,8 +28,8 @@ class btDynamicsWorld : public btCollisionWorld
public: public:
btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase)
:btCollisionWorld(dispatcher,pairCache) :btCollisionWorld(dispatcher,broadphase)
{ {
} }

View File

@@ -32,7 +32,7 @@ extern "C" void btBulletDynamicsProbe () {}
btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver)
:btDynamicsWorld(dispatcher,pairCache), :btDynamicsWorld(dispatcher,pairCache),
m_constraintSolver(constraintSolver), m_constraintSolver(constraintSolver),
m_ownsConstraintSolver(false), m_ownsConstraintSolver(false),

View File

@@ -48,7 +48,7 @@ public:
///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver);
virtual ~btSimpleDynamicsWorld(); virtual ~btSimpleDynamicsWorld();