1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 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: 10 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. 14 */ 15 16 #ifndef BT_OVERLAPPING_PAIR_CACHE_H 17 #define BT_OVERLAPPING_PAIR_CACHE_H 18 19 20 #include "btBroadphaseInterface.h" 21 #include "btBroadphaseProxy.h" 22 #include "btOverlappingPairCallback.h" 23 24 #include "LinearMath/btAlignedObjectArray.h" 25 class btDispatcher; 26 27 typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray; 28 29 struct btOverlapCallback 30 { ~btOverlapCallbackbtOverlapCallback31 virtual ~btOverlapCallback() 32 {} 33 //return true for deletion of the pair 34 virtual bool processOverlap(btBroadphasePair& pair) = 0; 35 36 }; 37 38 struct btOverlapFilterCallback 39 { ~btOverlapFilterCallbackbtOverlapFilterCallback40 virtual ~btOverlapFilterCallback() 41 {} 42 // return true when pairs need collision 43 virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; 44 }; 45 46 47 48 49 50 51 52 extern int gRemovePairs; 53 extern int gAddedPairs; 54 extern int gFindPairs; 55 56 const int BT_NULL_PAIR=0xffffffff; 57 58 ///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. 59 ///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. 60 class btOverlappingPairCache : public btOverlappingPairCallback 61 { 62 public: ~btOverlappingPairCache()63 virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor 64 65 virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; 66 67 virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; 68 69 virtual btBroadphasePairArray& getOverlappingPairArray() = 0; 70 71 virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; 72 73 virtual int getNumOverlappingPairs() const = 0; 74 75 virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; 76 77 virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; 78 79 virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; 80 81 virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; 82 83 virtual bool hasDeferredRemoval() = 0; 84 85 virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0; 86 87 virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0; 88 89 90 }; 91 92 /// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com 93 class btHashedOverlappingPairCache : public btOverlappingPairCache 94 { 95 btBroadphasePairArray m_overlappingPairArray; 96 btOverlapFilterCallback* m_overlapFilterCallback; 97 bool m_blockedForChanges; 98 99 protected: 100 101 btAlignedObjectArray<int> m_hashTable; 102 btAlignedObjectArray<int> m_next; 103 btOverlappingPairCallback* m_ghostPairCallback; 104 105 106 public: 107 btHashedOverlappingPairCache(); 108 virtual ~btHashedOverlappingPairCache(); 109 110 111 void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); 112 113 virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); 114 needsBroadphaseCollision(btBroadphaseProxy * proxy0,btBroadphaseProxy * proxy1)115 SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const 116 { 117 if (m_overlapFilterCallback) 118 return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); 119 120 bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; 121 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); 122 123 return collides; 124 } 125 126 // Add a pair and return the new pair. If the pair already exists, 127 // no new pair is created and the old one is returned. addOverlappingPair(btBroadphaseProxy * proxy0,btBroadphaseProxy * proxy1)128 virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) 129 { 130 gAddedPairs++; 131 132 if (!needsBroadphaseCollision(proxy0,proxy1)) 133 return 0; 134 135 return internalAddPair(proxy0,proxy1); 136 } 137 138 139 140 void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); 141 142 143 virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); 144 getOverlappingPairArrayPtr()145 virtual btBroadphasePair* getOverlappingPairArrayPtr() 146 { 147 return &m_overlappingPairArray[0]; 148 } 149 getOverlappingPairArrayPtr()150 const btBroadphasePair* getOverlappingPairArrayPtr() const 151 { 152 return &m_overlappingPairArray[0]; 153 } 154 getOverlappingPairArray()155 btBroadphasePairArray& getOverlappingPairArray() 156 { 157 return m_overlappingPairArray; 158 } 159 getOverlappingPairArray()160 const btBroadphasePairArray& getOverlappingPairArray() const 161 { 162 return m_overlappingPairArray; 163 } 164 165 void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); 166 167 168 169 btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); 170 GetCount()171 int GetCount() const { return m_overlappingPairArray.size(); } 172 // btBroadphasePair* GetPairs() { return m_pairs; } 173 getOverlapFilterCallback()174 btOverlapFilterCallback* getOverlapFilterCallback() 175 { 176 return m_overlapFilterCallback; 177 } 178 setOverlapFilterCallback(btOverlapFilterCallback * callback)179 void setOverlapFilterCallback(btOverlapFilterCallback* callback) 180 { 181 m_overlapFilterCallback = callback; 182 } 183 getNumOverlappingPairs()184 int getNumOverlappingPairs() const 185 { 186 return m_overlappingPairArray.size(); 187 } 188 private: 189 190 btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); 191 192 void growTables(); 193 equalsPair(const btBroadphasePair & pair,int proxyId1,int proxyId2)194 SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) 195 { 196 return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; 197 } 198 199 /* 200 // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm 201 // This assumes proxyId1 and proxyId2 are 16-bit. 202 SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) 203 { 204 int key = (proxyId2 << 16) | proxyId1; 205 key = ~key + (key << 15); 206 key = key ^ (key >> 12); 207 key = key + (key << 2); 208 key = key ^ (key >> 4); 209 key = key * 2057; 210 key = key ^ (key >> 16); 211 return key; 212 } 213 */ 214 215 216 getHash(unsigned int proxyId1,unsigned int proxyId2)217 SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) 218 { 219 int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); 220 // Thomas Wang's hash 221 222 key += ~(key << 15); 223 key ^= (key >> 10); 224 key += (key << 3); 225 key ^= (key >> 6); 226 key += ~(key << 11); 227 key ^= (key >> 16); 228 return static_cast<unsigned int>(key); 229 } 230 231 232 233 234 internalFindPair(btBroadphaseProxy * proxy0,btBroadphaseProxy * proxy1,int hash)235 SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) 236 { 237 int proxyId1 = proxy0->getUid(); 238 int proxyId2 = proxy1->getUid(); 239 #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. 240 if (proxyId1 > proxyId2) 241 btSwap(proxyId1, proxyId2); 242 #endif 243 244 int index = m_hashTable[hash]; 245 246 while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) 247 { 248 index = m_next[index]; 249 } 250 251 if ( index == BT_NULL_PAIR ) 252 { 253 return NULL; 254 } 255 256 btAssert(index < m_overlappingPairArray.size()); 257 258 return &m_overlappingPairArray[index]; 259 } 260 hasDeferredRemoval()261 virtual bool hasDeferredRemoval() 262 { 263 return false; 264 } 265 setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)266 virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) 267 { 268 m_ghostPairCallback = ghostPairCallback; 269 } 270 271 virtual void sortOverlappingPairs(btDispatcher* dispatcher); 272 273 274 275 }; 276 277 278 279 280 ///btSortedOverlappingPairCache maintains the objects with overlapping AABB 281 ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase 282 class btSortedOverlappingPairCache : public btOverlappingPairCache 283 { 284 protected: 285 //avoid brute-force finding all the time 286 btBroadphasePairArray m_overlappingPairArray; 287 288 //during the dispatch, check that user doesn't destroy/create proxy 289 bool m_blockedForChanges; 290 291 ///by default, do the removal during the pair traversal 292 bool m_hasDeferredRemoval; 293 294 //if set, use the callback instead of the built in filter in needBroadphaseCollision 295 btOverlapFilterCallback* m_overlapFilterCallback; 296 297 btOverlappingPairCallback* m_ghostPairCallback; 298 299 public: 300 301 btSortedOverlappingPairCache(); 302 virtual ~btSortedOverlappingPairCache(); 303 304 virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); 305 306 void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); 307 308 void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); 309 310 btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); 311 312 btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); 313 314 315 void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); 316 317 void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); 318 319 needsBroadphaseCollision(btBroadphaseProxy * proxy0,btBroadphaseProxy * proxy1)320 inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const 321 { 322 if (m_overlapFilterCallback) 323 return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); 324 325 bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; 326 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); 327 328 return collides; 329 } 330 getOverlappingPairArray()331 btBroadphasePairArray& getOverlappingPairArray() 332 { 333 return m_overlappingPairArray; 334 } 335 getOverlappingPairArray()336 const btBroadphasePairArray& getOverlappingPairArray() const 337 { 338 return m_overlappingPairArray; 339 } 340 341 342 343 getOverlappingPairArrayPtr()344 btBroadphasePair* getOverlappingPairArrayPtr() 345 { 346 return &m_overlappingPairArray[0]; 347 } 348 getOverlappingPairArrayPtr()349 const btBroadphasePair* getOverlappingPairArrayPtr() const 350 { 351 return &m_overlappingPairArray[0]; 352 } 353 getNumOverlappingPairs()354 int getNumOverlappingPairs() const 355 { 356 return m_overlappingPairArray.size(); 357 } 358 getOverlapFilterCallback()359 btOverlapFilterCallback* getOverlapFilterCallback() 360 { 361 return m_overlapFilterCallback; 362 } 363 setOverlapFilterCallback(btOverlapFilterCallback * callback)364 void setOverlapFilterCallback(btOverlapFilterCallback* callback) 365 { 366 m_overlapFilterCallback = callback; 367 } 368 hasDeferredRemoval()369 virtual bool hasDeferredRemoval() 370 { 371 return m_hasDeferredRemoval; 372 } 373 setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)374 virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) 375 { 376 m_ghostPairCallback = ghostPairCallback; 377 } 378 379 virtual void sortOverlappingPairs(btDispatcher* dispatcher); 380 381 382 }; 383 384 385 386 ///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing. 387 class btNullPairCache : public btOverlappingPairCache 388 { 389 390 btBroadphasePairArray m_overlappingPairArray; 391 392 public: 393 getOverlappingPairArrayPtr()394 virtual btBroadphasePair* getOverlappingPairArrayPtr() 395 { 396 return &m_overlappingPairArray[0]; 397 } getOverlappingPairArrayPtr()398 const btBroadphasePair* getOverlappingPairArrayPtr() const 399 { 400 return &m_overlappingPairArray[0]; 401 } getOverlappingPairArray()402 btBroadphasePairArray& getOverlappingPairArray() 403 { 404 return m_overlappingPairArray; 405 } 406 cleanOverlappingPair(btBroadphasePair &,btDispatcher *)407 virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) 408 { 409 410 } 411 getNumOverlappingPairs()412 virtual int getNumOverlappingPairs() const 413 { 414 return 0; 415 } 416 cleanProxyFromPairs(btBroadphaseProxy *,btDispatcher *)417 virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) 418 { 419 420 } 421 setOverlapFilterCallback(btOverlapFilterCallback *)422 virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) 423 { 424 } 425 processAllOverlappingPairs(btOverlapCallback *,btDispatcher *)426 virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) 427 { 428 } 429 findPair(btBroadphaseProxy *,btBroadphaseProxy *)430 virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) 431 { 432 return 0; 433 } 434 hasDeferredRemoval()435 virtual bool hasDeferredRemoval() 436 { 437 return true; 438 } 439 setInternalGhostPairCallback(btOverlappingPairCallback *)440 virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */) 441 { 442 443 } 444 addOverlappingPair(btBroadphaseProxy *,btBroadphaseProxy *)445 virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) 446 { 447 return 0; 448 } 449 removeOverlappingPair(btBroadphaseProxy *,btBroadphaseProxy *,btDispatcher *)450 virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) 451 { 452 return 0; 453 } 454 removeOverlappingPairsContainingProxy(btBroadphaseProxy *,btDispatcher *)455 virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) 456 { 457 } 458 sortOverlappingPairs(btDispatcher * dispatcher)459 virtual void sortOverlappingPairs(btDispatcher* dispatcher) 460 { 461 (void) dispatcher; 462 } 463 464 465 }; 466 467 468 #endif //BT_OVERLAPPING_PAIR_CACHE_H 469 470 471