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