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.
18 #include "btOverlappingPairCache.h"
20 #include "btDispatcher.h"
21 #include "btCollisionAlgorithm.h"
22 #include "LinearMath/btAabbUtil2.h"
26 int gOverlappingPairs = 0;
35 btHashedOverlappingPairCache::btHashedOverlappingPairCache():
36 m_overlapFilterCallback(0),
37 m_blockedForChanges(false),
38 m_ghostPairCallback(0)
40 int initialAllocatedSize= 2;
41 m_overlappingPairArray.reserve(initialAllocatedSize);
48 btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
54 void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
59 pair.m_algorithm->~btCollisionAlgorithm();
60 dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
69 void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
72 class CleanPairCallback : public btOverlapCallback
74 btBroadphaseProxy* m_cleanProxy;
75 btOverlappingPairCache* m_pairCache;
76 btDispatcher* m_dispatcher;
79 CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
80 :m_cleanProxy(cleanProxy),
81 m_pairCache(pairCache),
82 m_dispatcher(dispatcher)
85 virtual bool processOverlap(btBroadphasePair& pair)
87 if ((pair.m_pProxy0 == m_cleanProxy) ||
88 (pair.m_pProxy1 == m_cleanProxy))
90 m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
97 CleanPairCallback cleanPairs(proxy,this,dispatcher);
99 processAllOverlappingPairs(&cleanPairs,dispatcher);
106 void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
109 class RemovePairCallback : public btOverlapCallback
111 btBroadphaseProxy* m_obsoleteProxy;
114 RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
115 :m_obsoleteProxy(obsoleteProxy)
118 virtual bool processOverlap(btBroadphasePair& pair)
120 return ((pair.m_pProxy0 == m_obsoleteProxy) ||
121 (pair.m_pProxy1 == m_obsoleteProxy));
127 RemovePairCallback removeCallback(proxy);
129 processAllOverlappingPairs(&removeCallback,dispatcher);
136 btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
139 if(proxy0->m_uniqueId>proxy1->m_uniqueId)
140 btSwap(proxy0,proxy1);
141 int proxyId1 = proxy0->getUid();
142 int proxyId2 = proxy1->getUid();
144 /*if (proxyId1 > proxyId2)
145 btSwap(proxyId1, proxyId2);*/
147 int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
149 if (hash >= m_hashTable.size())
154 int index = m_hashTable[hash];
155 while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
157 index = m_next[index];
160 if (index == BT_NULL_PAIR)
165 btAssert(index < m_overlappingPairArray.size());
167 return &m_overlappingPairArray[index];
172 void btHashedOverlappingPairCache::growTables()
175 int newCapacity = m_overlappingPairArray.capacity();
177 if (m_hashTable.size() < newCapacity)
179 //grow hashtable and next table
180 int curHashtableSize = m_hashTable.size();
182 m_hashTable.resize(newCapacity);
183 m_next.resize(newCapacity);
188 for (i= 0; i < newCapacity; ++i)
190 m_hashTable[i] = BT_NULL_PAIR;
192 for (i = 0; i < newCapacity; ++i)
194 m_next[i] = BT_NULL_PAIR;
197 for(i=0;i<curHashtableSize;i++)
200 const btBroadphasePair& pair = m_overlappingPairArray[i];
201 int proxyId1 = pair.m_pProxy0->getUid();
202 int proxyId2 = pair.m_pProxy1->getUid();
203 /*if (proxyId1 > proxyId2)
204 btSwap(proxyId1, proxyId2);*/
205 int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
206 m_next[i] = m_hashTable[hashValue];
207 m_hashTable[hashValue] = i;
214 btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
216 if(proxy0->m_uniqueId>proxy1->m_uniqueId)
217 btSwap(proxy0,proxy1);
218 int proxyId1 = proxy0->getUid();
219 int proxyId2 = proxy1->getUid();
221 /*if (proxyId1 > proxyId2)
222 btSwap(proxyId1, proxyId2);*/
224 int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
227 btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
232 /*for(int i=0;i<m_overlappingPairArray.size();++i)
234 if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
235 (m_overlappingPairArray[i].m_pProxy1==proxy1))
237 printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
238 internalFindPair(proxy0, proxy1, hash);
241 int count = m_overlappingPairArray.size();
242 int oldCapacity = m_overlappingPairArray.capacity();
243 void* mem = &m_overlappingPairArray.expandNonInitializing();
245 //this is where we add an actual pair, so also call the 'ghost'
246 if (m_ghostPairCallback)
247 m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
249 int newCapacity = m_overlappingPairArray.capacity();
251 if (oldCapacity < newCapacity)
254 //hash with new capacity
255 hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
258 pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
259 // pair->m_pProxy0 = proxy0;
260 // pair->m_pProxy1 = proxy1;
261 pair->m_algorithm = 0;
262 pair->m_internalTmpValue = 0;
265 m_next[count] = m_hashTable[hash];
266 m_hashTable[hash] = count;
273 void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
276 if(proxy0->m_uniqueId>proxy1->m_uniqueId)
277 btSwap(proxy0,proxy1);
278 int proxyId1 = proxy0->getUid();
279 int proxyId2 = proxy1->getUid();
281 /*if (proxyId1 > proxyId2)
282 btSwap(proxyId1, proxyId2);*/
284 int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
286 btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
292 cleanOverlappingPair(*pair,dispatcher);
294 void* userData = pair->m_internalInfo1;
296 btAssert(pair->m_pProxy0->getUid() == proxyId1);
297 btAssert(pair->m_pProxy1->getUid() == proxyId2);
299 int pairIndex = int(pair - &m_overlappingPairArray[0]);
300 btAssert(pairIndex < m_overlappingPairArray.size());
302 // Remove the pair from the hash table.
303 int index = m_hashTable[hash];
304 btAssert(index != BT_NULL_PAIR);
306 int previous = BT_NULL_PAIR;
307 while (index != pairIndex)
310 index = m_next[index];
313 if (previous != BT_NULL_PAIR)
315 btAssert(m_next[previous] == pairIndex);
316 m_next[previous] = m_next[pairIndex];
320 m_hashTable[hash] = m_next[pairIndex];
323 // We now move the last pair into spot of the
324 // pair being removed. We need to fix the hash
325 // table indices to support the move.
327 int lastPairIndex = m_overlappingPairArray.size() - 1;
329 if (m_ghostPairCallback)
330 m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
332 // If the removed pair is the last pair, we are done.
333 if (lastPairIndex == pairIndex)
335 m_overlappingPairArray.pop_back();
339 // Remove the last pair from the hash table.
340 const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
341 /* missing swap here too, Nat. */
342 int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
344 index = m_hashTable[lastHash];
345 btAssert(index != BT_NULL_PAIR);
347 previous = BT_NULL_PAIR;
348 while (index != lastPairIndex)
351 index = m_next[index];
354 if (previous != BT_NULL_PAIR)
356 btAssert(m_next[previous] == lastPairIndex);
357 m_next[previous] = m_next[lastPairIndex];
361 m_hashTable[lastHash] = m_next[lastPairIndex];
364 // Copy the last pair into the remove pair's spot.
365 m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
367 // Insert the last pair into the hash table
368 m_next[pairIndex] = m_hashTable[lastHash];
369 m_hashTable[lastHash] = pairIndex;
371 m_overlappingPairArray.pop_back();
377 void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
382 // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
383 for (i=0;i<m_overlappingPairArray.size();)
386 btBroadphasePair* pair = &m_overlappingPairArray[i];
387 if (callback->processOverlap(*pair))
389 removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
399 void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
401 ///need to keep hashmap in sync with pair address, so rebuild all
402 btBroadphasePairArray tmpPairs;
404 for (i=0;i<m_overlappingPairArray.size();i++)
406 tmpPairs.push_back(m_overlappingPairArray[i]);
409 for (i=0;i<tmpPairs.size();i++)
411 removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
414 for (i = 0; i < m_next.size(); i++)
416 m_next[i] = BT_NULL_PAIR;
419 tmpPairs.quickSort(btBroadphasePairSortPredicate());
421 for (i=0;i<tmpPairs.size();i++)
423 addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
430 void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
432 if (!hasDeferredRemoval())
434 btBroadphasePair findPair(*proxy0,*proxy1);
436 int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
437 if (findIndex < m_overlappingPairArray.size())
440 btBroadphasePair& pair = m_overlappingPairArray[findIndex];
441 void* userData = pair.m_internalInfo1;
442 cleanOverlappingPair(pair,dispatcher);
443 if (m_ghostPairCallback)
444 m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
446 m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
447 m_overlappingPairArray.pop_back();
462 btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
464 //don't add overlap with own
465 btAssert(proxy0 != proxy1);
467 if (!needsBroadphaseCollision(proxy0,proxy1))
470 void* mem = &m_overlappingPairArray.expandNonInitializing();
471 btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
476 if (m_ghostPairCallback)
477 m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
482 ///this findPair becomes really slow. Either sort the list to speedup the query, or
483 ///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
484 ///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
485 ///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
486 btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
488 if (!needsBroadphaseCollision(proxy0,proxy1))
491 btBroadphasePair tmpPair(*proxy0,*proxy1);
492 int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
494 if (findIndex < m_overlappingPairArray.size())
496 //btAssert(it != m_overlappingPairSet.end());
497 btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
514 void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
519 for (i=0;i<m_overlappingPairArray.size();)
522 btBroadphasePair* pair = &m_overlappingPairArray[i];
523 if (callback->processOverlap(*pair))
525 cleanOverlappingPair(*pair,dispatcher);
528 m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
529 m_overlappingPairArray.pop_back();
541 btSortedOverlappingPairCache::btSortedOverlappingPairCache():
542 m_blockedForChanges(false),
543 m_hasDeferredRemoval(true),
544 m_overlapFilterCallback(0),
545 m_ghostPairCallback(0)
547 int initialAllocatedSize= 2;
548 m_overlappingPairArray.reserve(initialAllocatedSize);
551 btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
555 void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
557 if (pair.m_algorithm)
560 pair.m_algorithm->~btCollisionAlgorithm();
561 dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
569 void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
572 class CleanPairCallback : public btOverlapCallback
574 btBroadphaseProxy* m_cleanProxy;
575 btOverlappingPairCache* m_pairCache;
576 btDispatcher* m_dispatcher;
579 CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
580 :m_cleanProxy(cleanProxy),
581 m_pairCache(pairCache),
582 m_dispatcher(dispatcher)
585 virtual bool processOverlap(btBroadphasePair& pair)
587 if ((pair.m_pProxy0 == m_cleanProxy) ||
588 (pair.m_pProxy1 == m_cleanProxy))
590 m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
597 CleanPairCallback cleanPairs(proxy,this,dispatcher);
599 processAllOverlappingPairs(&cleanPairs,dispatcher);
604 void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
607 class RemovePairCallback : public btOverlapCallback
609 btBroadphaseProxy* m_obsoleteProxy;
612 RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
613 :m_obsoleteProxy(obsoleteProxy)
616 virtual bool processOverlap(btBroadphasePair& pair)
618 return ((pair.m_pProxy0 == m_obsoleteProxy) ||
619 (pair.m_pProxy1 == m_obsoleteProxy));
624 RemovePairCallback removeCallback(proxy);
626 processAllOverlappingPairs(&removeCallback,dispatcher);
629 void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
631 //should already be sorted