2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #include "btMultiSapBroadphase.h"
18 #include "btSimpleBroadphase.h"
19 #include "LinearMath/btAabbUtil2.h"
20 #include "btQuantizedBvh.h"
22 /// btSapBroadphaseArray m_sapBroadphases;
24 /// btOverlappingPairCache* m_overlappingPairs;
25 extern int gOverlappingPairs;
28 class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
32 virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
34 return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
40 btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
41 :m_overlappingPairs(pairCache),
42 m_optimizedAabbTree(0),
43 m_ownsPairCache(false),
46 if (!m_overlappingPairs)
48 m_ownsPairCache = true;
49 void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
50 m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
53 struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
55 virtual ~btMultiSapOverlapFilterCallback()
57 // return true when pairs need collision
58 virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
60 btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
61 btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
63 bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
64 collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
70 void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
71 m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
73 m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
74 // mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
75 // m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
78 btMultiSapBroadphase::~btMultiSapBroadphase()
82 m_overlappingPairs->~btOverlappingPairCache();
83 btAlignedFree(m_overlappingPairs);
88 void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
90 m_optimizedAabbTree = new btQuantizedBvh();
91 m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
92 QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
93 for (int i=0;i<m_sapBroadphases.size();i++)
95 btQuantizedBvhNode node;
96 btVector3 aabbMin,aabbMax;
97 m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
98 m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
99 m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
101 node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
102 nodes.push_back(node);
104 m_optimizedAabbTree->buildInternal();
107 btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
109 //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
111 void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
112 btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
113 m_multiSapProxies.push_back(proxy);
115 ///this should deal with inserting/removal into child broadphases
116 setAabb(proxy,aabbMin,aabbMax,dispatcher);
120 void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
128 void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
130 void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
131 btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
132 bridgeProxyRef->m_childProxy = childProxy;
133 bridgeProxyRef->m_childBroadphase = childBroadphase;
134 parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
138 bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
139 bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
142 amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
143 amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
144 amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
152 void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
154 btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
155 aabbMin = multiProxy->m_aabbMin;
156 aabbMax = multiProxy->m_aabbMax;
159 void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
161 for (int i=0;i<m_multiSapProxies.size();i++)
163 rayCallback.process(m_multiSapProxies[i]);
170 void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
172 btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
173 multiProxy->m_aabbMin = aabbMin;
174 multiProxy->m_aabbMax = aabbMax;
177 // bool fullyContained = false;
178 // bool alreadyInSimple = false;
183 struct MyNodeOverlapCallback : public btNodeOverlapCallback
185 btMultiSapBroadphase* m_multiSap;
186 btMultiSapProxy* m_multiProxy;
187 btDispatcher* m_dispatcher;
189 MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
190 :m_multiSap(multiSap),
191 m_multiProxy(multiProxy),
192 m_dispatcher(dispatcher)
197 virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
199 btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
201 int containingBroadphaseIndex = -1;
203 for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
206 if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
208 containingBroadphaseIndex = i;
212 if (containingBroadphaseIndex<0)
215 btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
216 m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
222 MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
227 if (m_optimizedAabbTree)
228 m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
232 for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
234 btVector3 worldAabbMin,worldAabbMax;
235 multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
236 bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
237 if (!overlapsBroadphase)
240 btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
242 btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
243 bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
245 multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
246 multiProxy->m_bridgeProxies.pop_back();
257 //find broadphase that contain this multiProxy
258 int numChildBroadphases = getBroadphaseArray().size();
259 for (int i=0;i<numChildBroadphases;i++)
261 btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
262 btVector3 worldAabbMin,worldAabbMax;
263 childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
264 bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
266 // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
267 int containingBroadphaseIndex = -1;
269 //if already contains this
271 for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
273 if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
275 containingBroadphaseIndex = i;
277 alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
280 if (overlapsBroadphase)
282 if (containingBroadphaseIndex<0)
284 btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
285 childProxy->m_multiSapParentProxy = multiProxy;
286 addToChildBroadphase(multiProxy,childProxy,childBroadphase);
290 if (containingBroadphaseIndex>=0)
293 btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
295 btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
296 bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
298 multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
299 multiProxy->m_bridgeProxies.pop_back();
305 ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
306 ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
307 if (0)//!multiProxy->m_bridgeProxies.size())
309 ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
310 ///this is needed to be able to calculate the aabb overlap
311 btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
312 childProxy->m_multiSapParentProxy = multiProxy;
313 addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
317 if (!multiProxy->m_bridgeProxies.size())
319 ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
320 ///this is needed to be able to calculate the aabb overlap
321 btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
322 childProxy->m_multiSapParentProxy = multiProxy;
323 addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
329 for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
331 btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
332 bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
336 bool stopUpdating=false;
340 class btMultiSapBroadphasePairSortPredicate
344 bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
346 btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
347 btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
348 btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
349 btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
351 return aProxy0 > bProxy0 ||
352 (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
353 (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
358 ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
359 void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
362 // m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
364 if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
367 btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
369 // quicksort(overlappingPairArray,0,overlappingPairArray.size());
371 overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
373 //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
374 // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
376 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
382 btBroadphasePair previousPair;
383 previousPair.m_pProxy0 = 0;
384 previousPair.m_pProxy1 = 0;
385 previousPair.m_algorithm = 0;
388 for (i=0;i<overlappingPairArray.size();i++)
391 btBroadphasePair& pair = overlappingPairArray[i];
393 btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
394 btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
395 btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
396 btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
398 bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
402 bool needsRemoval = false;
406 bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
410 needsRemoval = false;//callback->processOverlap(pair);
419 //should have no algorithm
420 btAssert(!pair.m_algorithm);
425 getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
427 // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
428 // m_overlappingPairArray.pop_back();
437 ///if you don't like to skip the invalid pairs in the array, execute following code:
438 #define CLEAN_INVALID_PAIRS 1
439 #ifdef CLEAN_INVALID_PAIRS
441 //perform a sort, to sort 'invalid' pairs to the end
442 //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
443 overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
445 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
447 #endif//CLEAN_INVALID_PAIRS
449 //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
456 bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
458 btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
459 btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
461 return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
462 multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
467 void btMultiSapBroadphase::printStats()
469 /* printf("---------------------------------\n");
471 printf("btMultiSapBroadphase.h\n");
472 printf("numHandles = %d\n",m_multiSapProxies.size());
473 //find broadphase that contain this multiProxy
474 int numChildBroadphases = getBroadphaseArray().size();
475 for (int i=0;i<numChildBroadphases;i++)
478 btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
479 childBroadphase->printStats();
486 void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)