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