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)