• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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