1 //Bullet Continuous Collision Detection and Physics Library
2 //Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
3
4 //
5 // btAxisSweep3.h
6 //
7 // Copyright (c) 2006 Simon Hobbs
8 //
9 // This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
12 //
13 // 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.
14 //
15 // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 //
17 // 3. This notice may not be removed or altered from any source distribution.
18
19 #ifndef BT_AXIS_SWEEP_3_H
20 #define BT_AXIS_SWEEP_3_H
21
22 #include "LinearMath/btVector3.h"
23 #include "btOverlappingPairCache.h"
24 #include "btBroadphaseInterface.h"
25 #include "btBroadphaseProxy.h"
26 #include "btOverlappingPairCallback.h"
27 #include "btDbvtBroadphase.h"
28
29 //#define DEBUG_BROADPHASE 1
30 #define USE_OVERLAP_TEST_ON_REMOVES 1
31
32 /// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
33 /// It uses quantized integers to represent the begin and end points for each of the 3 axis.
34 /// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
35 template <typename BP_FP_INT_TYPE>
36 class btAxisSweep3Internal : public btBroadphaseInterface
37 {
38 protected:
39
40 BP_FP_INT_TYPE m_bpHandleMask;
41 BP_FP_INT_TYPE m_handleSentinel;
42
43 public:
44
45 BT_DECLARE_ALIGNED_ALLOCATOR();
46
47 class Edge
48 {
49 public:
50 BP_FP_INT_TYPE m_pos; // low bit is min/max
51 BP_FP_INT_TYPE m_handle;
52
IsMax()53 BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
54 };
55
56 public:
57 class Handle : public btBroadphaseProxy
58 {
59 public:
60 BT_DECLARE_ALIGNED_ALLOCATOR();
61
62 // indexes into the edge arrays
63 BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
64 // BP_FP_INT_TYPE m_uniqueId;
65 btBroadphaseProxy* m_dbvtProxy;//for faster raycast
66 //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
67
SetNextFree(BP_FP_INT_TYPE next)68 SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
GetNextFree()69 SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
70 }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
71
72
73 protected:
74 btVector3 m_worldAabbMin; // overall system bounds
75 btVector3 m_worldAabbMax; // overall system bounds
76
77 btVector3 m_quantize; // scaling factor for quantization
78
79 BP_FP_INT_TYPE m_numHandles; // number of active handles
80 BP_FP_INT_TYPE m_maxHandles; // max number of handles
81 Handle* m_pHandles; // handles pool
82
83 BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
84
85 Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
86 void* m_pEdgesRawPtr[3];
87
88 btOverlappingPairCache* m_pairCache;
89
90 ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
91 btOverlappingPairCallback* m_userPairCallback;
92
93 bool m_ownsPairCache;
94
95 int m_invalidPair;
96
97 ///additional dynamic aabb structure, used to accelerate ray cast queries.
98 ///can be disabled using a optional argument in the constructor
99 btDbvtBroadphase* m_raycastAccelerator;
100 btOverlappingPairCache* m_nullPairCache;
101
102
103 // allocation/deallocation
104 BP_FP_INT_TYPE allocHandle();
105 void freeHandle(BP_FP_INT_TYPE handle);
106
107
108 bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
109
110 #ifdef DEBUG_BROADPHASE
111 void debugPrintAxis(int axis,bool checkCardinality=true);
112 #endif //DEBUG_BROADPHASE
113
114 //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
115 //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
116
117
118
119 void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
120 void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
121 void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
122 void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
123
124 public:
125
126 btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
127
128 virtual ~btAxisSweep3Internal();
129
getNumHandles()130 BP_FP_INT_TYPE getNumHandles() const
131 {
132 return m_numHandles;
133 }
134
135 virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
136
137 BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
138 void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
139 void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
getHandle(BP_FP_INT_TYPE index)140 SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
141
142 virtual void resetPool(btDispatcher* dispatcher);
143
144 void processAllOverlappingPairs(btOverlapCallback* callback);
145
146 //Broadphase Interface
147 virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
148 virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
149 virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
150 virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
151
152 virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
153 virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
154
155
156 void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
157 ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
158 void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
159
160 bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
161
getOverlappingPairCache()162 btOverlappingPairCache* getOverlappingPairCache()
163 {
164 return m_pairCache;
165 }
getOverlappingPairCache()166 const btOverlappingPairCache* getOverlappingPairCache() const
167 {
168 return m_pairCache;
169 }
170
setOverlappingPairUserCallback(btOverlappingPairCallback * pairCallback)171 void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
172 {
173 m_userPairCallback = pairCallback;
174 }
getOverlappingPairUserCallback()175 const btOverlappingPairCallback* getOverlappingPairUserCallback() const
176 {
177 return m_userPairCallback;
178 }
179
180 ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
181 ///will add some transform later
getBroadphaseAabb(btVector3 & aabbMin,btVector3 & aabbMax)182 virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
183 {
184 aabbMin = m_worldAabbMin;
185 aabbMax = m_worldAabbMax;
186 }
187
printStats()188 virtual void printStats()
189 {
190 /* printf("btAxisSweep3.h\n");
191 printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
192 printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
193 m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
194 */
195
196 }
197
198 };
199
200 ////////////////////////////////////////////////////////////////////
201
202
203
204
205 #ifdef DEBUG_BROADPHASE
206 #include <stdio.h>
207
208 template <typename BP_FP_INT_TYPE>
debugPrintAxis(int axis,bool checkCardinality)209 void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
210 {
211 int numEdges = m_pHandles[0].m_maxEdges[axis];
212 printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
213
214 int i;
215 for (i=0;i<numEdges+1;i++)
216 {
217 Edge* pEdge = m_pEdges[axis] + i;
218 Handle* pHandlePrev = getHandle(pEdge->m_handle);
219 int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
220 char beginOrEnd;
221 beginOrEnd=pEdge->IsMax()?'E':'B';
222 printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
223 }
224
225 if (checkCardinality)
226 btAssert(numEdges == m_numHandles*2+1);
227 }
228 #endif //DEBUG_BROADPHASE
229
230 template <typename BP_FP_INT_TYPE>
createProxy(const btVector3 & aabbMin,const btVector3 & aabbMax,int shapeType,void * userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher * dispatcher,void * multiSapProxy)231 btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
232 {
233 (void)shapeType;
234 BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
235
236 Handle* handle = getHandle(handleId);
237
238 if (m_raycastAccelerator)
239 {
240 btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0);
241 handle->m_dbvtProxy = rayProxy;
242 }
243 return handle;
244 }
245
246
247
248 template <typename BP_FP_INT_TYPE>
destroyProxy(btBroadphaseProxy * proxy,btDispatcher * dispatcher)249 void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
250 {
251 Handle* handle = static_cast<Handle*>(proxy);
252 if (m_raycastAccelerator)
253 m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
254 removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
255 }
256
257 template <typename BP_FP_INT_TYPE>
setAabb(btBroadphaseProxy * proxy,const btVector3 & aabbMin,const btVector3 & aabbMax,btDispatcher * dispatcher)258 void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
259 {
260 Handle* handle = static_cast<Handle*>(proxy);
261 handle->m_aabbMin = aabbMin;
262 handle->m_aabbMax = aabbMax;
263 updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
264 if (m_raycastAccelerator)
265 m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
266
267 }
268
269 template <typename BP_FP_INT_TYPE>
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btBroadphaseRayCallback & rayCallback,const btVector3 & aabbMin,const btVector3 & aabbMax)270 void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
271 {
272 if (m_raycastAccelerator)
273 {
274 m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
275 } else
276 {
277 //choose axis?
278 BP_FP_INT_TYPE axis = 0;
279 //for each proxy
280 for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
281 {
282 if (m_pEdges[axis][i].IsMax())
283 {
284 rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
285 }
286 }
287 }
288 }
289
290 template <typename BP_FP_INT_TYPE>
aabbTest(const btVector3 & aabbMin,const btVector3 & aabbMax,btBroadphaseAabbCallback & callback)291 void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
292 {
293 if (m_raycastAccelerator)
294 {
295 m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
296 } else
297 {
298 //choose axis?
299 BP_FP_INT_TYPE axis = 0;
300 //for each proxy
301 for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
302 {
303 if (m_pEdges[axis][i].IsMax())
304 {
305 Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
306 if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
307 {
308 callback.process(handle);
309 }
310 }
311 }
312 }
313 }
314
315
316
317 template <typename BP_FP_INT_TYPE>
getAabb(btBroadphaseProxy * proxy,btVector3 & aabbMin,btVector3 & aabbMax)318 void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
319 {
320 Handle* pHandle = static_cast<Handle*>(proxy);
321 aabbMin = pHandle->m_aabbMin;
322 aabbMax = pHandle->m_aabbMax;
323 }
324
325
326 template <typename BP_FP_INT_TYPE>
unQuantize(btBroadphaseProxy * proxy,btVector3 & aabbMin,btVector3 & aabbMax)327 void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
328 {
329 Handle* pHandle = static_cast<Handle*>(proxy);
330
331 unsigned short vecInMin[3];
332 unsigned short vecInMax[3];
333
334 vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
335 vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
336 vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
337 vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
338 vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
339 vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
340
341 aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
342 aabbMin += m_worldAabbMin;
343
344 aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
345 aabbMax += m_worldAabbMin;
346 }
347
348
349
350
351 template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal(const btVector3 & worldAabbMin,const btVector3 & worldAabbMax,BP_FP_INT_TYPE handleMask,BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles,btOverlappingPairCache * pairCache,bool disableRaycastAccelerator)352 btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
353 :m_bpHandleMask(handleMask),
354 m_handleSentinel(handleSentinel),
355 m_pairCache(pairCache),
356 m_userPairCallback(0),
357 m_ownsPairCache(false),
358 m_invalidPair(0),
359 m_raycastAccelerator(0)
360 {
361 BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
362
363 if (!m_pairCache)
364 {
365 void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
366 m_pairCache = new(ptr) btHashedOverlappingPairCache();
367 m_ownsPairCache = true;
368 }
369
370 if (!disableRaycastAccelerator)
371 {
372 m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
373 m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
374 m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
375 }
376
377 //btAssert(bounds.HasVolume());
378
379 // init bounds
380 m_worldAabbMin = worldAabbMin;
381 m_worldAabbMax = worldAabbMax;
382
383 btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
384
385 BP_FP_INT_TYPE maxInt = m_handleSentinel;
386
387 m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
388
389 // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
390 m_pHandles = new Handle[maxHandles];
391
392 m_maxHandles = maxHandles;
393 m_numHandles = 0;
394
395 // handle 0 is reserved as the null index, and is also used as the sentinel
396 m_firstFreeHandle = 1;
397 {
398 for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
399 m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
400 m_pHandles[maxHandles - 1].SetNextFree(0);
401 }
402
403 {
404 // allocate edge buffers
405 for (int i = 0; i < 3; i++)
406 {
407 m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
408 m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
409 }
410 }
411 //removed overlap management
412
413 // make boundary sentinels
414
415 m_pHandles[0].m_clientObject = 0;
416
417 for (int axis = 0; axis < 3; axis++)
418 {
419 m_pHandles[0].m_minEdges[axis] = 0;
420 m_pHandles[0].m_maxEdges[axis] = 1;
421
422 m_pEdges[axis][0].m_pos = 0;
423 m_pEdges[axis][0].m_handle = 0;
424 m_pEdges[axis][1].m_pos = m_handleSentinel;
425 m_pEdges[axis][1].m_handle = 0;
426 #ifdef DEBUG_BROADPHASE
427 debugPrintAxis(axis);
428 #endif //DEBUG_BROADPHASE
429
430 }
431
432 }
433
434 template <typename BP_FP_INT_TYPE>
~btAxisSweep3Internal()435 btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
436 {
437 if (m_raycastAccelerator)
438 {
439 m_nullPairCache->~btOverlappingPairCache();
440 btAlignedFree(m_nullPairCache);
441 m_raycastAccelerator->~btDbvtBroadphase();
442 btAlignedFree (m_raycastAccelerator);
443 }
444
445 for (int i = 2; i >= 0; i--)
446 {
447 btAlignedFree(m_pEdgesRawPtr[i]);
448 }
449 delete [] m_pHandles;
450
451 if (m_ownsPairCache)
452 {
453 m_pairCache->~btOverlappingPairCache();
454 btAlignedFree(m_pairCache);
455 }
456 }
457
458 template <typename BP_FP_INT_TYPE>
quantize(BP_FP_INT_TYPE * out,const btVector3 & point,int isMax)459 void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
460 {
461 #ifdef OLD_CLAMPING_METHOD
462 ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
463 ///see http://code.google.com/p/bullet/issues/detail?id=87
464 btVector3 clampedPoint(point);
465 clampedPoint.setMax(m_worldAabbMin);
466 clampedPoint.setMin(m_worldAabbMax);
467 btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
468 out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
469 out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
470 out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
471 #else
472 btVector3 v = (point - m_worldAabbMin) * m_quantize;
473 out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
474 out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
475 out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
476 #endif //OLD_CLAMPING_METHOD
477 }
478
479
480 template <typename BP_FP_INT_TYPE>
allocHandle()481 BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
482 {
483 btAssert(m_firstFreeHandle);
484
485 BP_FP_INT_TYPE handle = m_firstFreeHandle;
486 m_firstFreeHandle = getHandle(handle)->GetNextFree();
487 m_numHandles++;
488
489 return handle;
490 }
491
492 template <typename BP_FP_INT_TYPE>
freeHandle(BP_FP_INT_TYPE handle)493 void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
494 {
495 btAssert(handle > 0 && handle < m_maxHandles);
496
497 getHandle(handle)->SetNextFree(m_firstFreeHandle);
498 m_firstFreeHandle = handle;
499
500 m_numHandles--;
501 }
502
503
504 template <typename BP_FP_INT_TYPE>
addHandle(const btVector3 & aabbMin,const btVector3 & aabbMax,void * pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher * dispatcher,void * multiSapProxy)505 BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
506 {
507 // quantize the bounds
508 BP_FP_INT_TYPE min[3], max[3];
509 quantize(min, aabbMin, 0);
510 quantize(max, aabbMax, 1);
511
512 // allocate a handle
513 BP_FP_INT_TYPE handle = allocHandle();
514
515
516 Handle* pHandle = getHandle(handle);
517
518 pHandle->m_uniqueId = static_cast<int>(handle);
519 //pHandle->m_pOverlaps = 0;
520 pHandle->m_clientObject = pOwner;
521 pHandle->m_collisionFilterGroup = collisionFilterGroup;
522 pHandle->m_collisionFilterMask = collisionFilterMask;
523 pHandle->m_multiSapParentProxy = multiSapProxy;
524
525 // compute current limit of edge arrays
526 BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
527
528
529 // insert new edges just inside the max boundary edge
530 for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
531 {
532
533 m_pHandles[0].m_maxEdges[axis] += 2;
534
535 m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
536
537 m_pEdges[axis][limit - 1].m_pos = min[axis];
538 m_pEdges[axis][limit - 1].m_handle = handle;
539
540 m_pEdges[axis][limit].m_pos = max[axis];
541 m_pEdges[axis][limit].m_handle = handle;
542
543 pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
544 pHandle->m_maxEdges[axis] = limit;
545 }
546
547 // now sort the new edges to their correct position
548 sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
549 sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
550 sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
551 sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
552 sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
553 sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
554
555
556 return handle;
557 }
558
559
560 template <typename BP_FP_INT_TYPE>
removeHandle(BP_FP_INT_TYPE handle,btDispatcher * dispatcher)561 void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
562 {
563
564 Handle* pHandle = getHandle(handle);
565
566 //explicitly remove the pairs containing the proxy
567 //we could do it also in the sortMinUp (passing true)
568 ///@todo: compare performance
569 if (!m_pairCache->hasDeferredRemoval())
570 {
571 m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
572 }
573
574 // compute current limit of edge arrays
575 int limit = static_cast<int>(m_numHandles * 2);
576
577 int axis;
578
579 for (axis = 0;axis<3;axis++)
580 {
581 m_pHandles[0].m_maxEdges[axis] -= 2;
582 }
583
584 // remove the edges by sorting them up to the end of the list
585 for ( axis = 0; axis < 3; axis++)
586 {
587 Edge* pEdges = m_pEdges[axis];
588 BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
589 pEdges[max].m_pos = m_handleSentinel;
590
591 sortMaxUp(axis,max,dispatcher,false);
592
593
594 BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
595 pEdges[i].m_pos = m_handleSentinel;
596
597
598 sortMinUp(axis,i,dispatcher,false);
599
600 pEdges[limit-1].m_handle = 0;
601 pEdges[limit-1].m_pos = m_handleSentinel;
602
603 #ifdef DEBUG_BROADPHASE
604 debugPrintAxis(axis,false);
605 #endif //DEBUG_BROADPHASE
606
607
608 }
609
610
611 // free the handle
612 freeHandle(handle);
613
614
615 }
616
617 template <typename BP_FP_INT_TYPE>
resetPool(btDispatcher *)618 void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
619 {
620 if (m_numHandles == 0)
621 {
622 m_firstFreeHandle = 1;
623 {
624 for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
625 m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
626 m_pHandles[m_maxHandles - 1].SetNextFree(0);
627 }
628 }
629 }
630
631
632 extern int gOverlappingPairs;
633 //#include <stdio.h>
634
635 template <typename BP_FP_INT_TYPE>
calculateOverlappingPairs(btDispatcher * dispatcher)636 void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
637 {
638
639 if (m_pairCache->hasDeferredRemoval())
640 {
641
642 btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
643
644 //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
645 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
646
647 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
648 m_invalidPair = 0;
649
650
651 int i;
652
653 btBroadphasePair previousPair;
654 previousPair.m_pProxy0 = 0;
655 previousPair.m_pProxy1 = 0;
656 previousPair.m_algorithm = 0;
657
658
659 for (i=0;i<overlappingPairArray.size();i++)
660 {
661
662 btBroadphasePair& pair = overlappingPairArray[i];
663
664 bool isDuplicate = (pair == previousPair);
665
666 previousPair = pair;
667
668 bool needsRemoval = false;
669
670 if (!isDuplicate)
671 {
672 ///important to use an AABB test that is consistent with the broadphase
673 bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
674
675 if (hasOverlap)
676 {
677 needsRemoval = false;//callback->processOverlap(pair);
678 } else
679 {
680 needsRemoval = true;
681 }
682 } else
683 {
684 //remove duplicate
685 needsRemoval = true;
686 //should have no algorithm
687 btAssert(!pair.m_algorithm);
688 }
689
690 if (needsRemoval)
691 {
692 m_pairCache->cleanOverlappingPair(pair,dispatcher);
693
694 // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
695 // m_overlappingPairArray.pop_back();
696 pair.m_pProxy0 = 0;
697 pair.m_pProxy1 = 0;
698 m_invalidPair++;
699 gOverlappingPairs--;
700 }
701
702 }
703
704 ///if you don't like to skip the invalid pairs in the array, execute following code:
705 #define CLEAN_INVALID_PAIRS 1
706 #ifdef CLEAN_INVALID_PAIRS
707
708 //perform a sort, to sort 'invalid' pairs to the end
709 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
710
711 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
712 m_invalidPair = 0;
713 #endif//CLEAN_INVALID_PAIRS
714
715 //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
716 }
717
718 }
719
720
721 template <typename BP_FP_INT_TYPE>
testAabbOverlap(btBroadphaseProxy * proxy0,btBroadphaseProxy * proxy1)722 bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
723 {
724 const Handle* pHandleA = static_cast<Handle*>(proxy0);
725 const Handle* pHandleB = static_cast<Handle*>(proxy1);
726
727 //optimization 1: check the array index (memory address), instead of the m_pos
728
729 for (int axis = 0; axis < 3; axis++)
730 {
731 if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
732 pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
733 {
734 return false;
735 }
736 }
737 return true;
738 }
739
740 template <typename BP_FP_INT_TYPE>
testOverlap2D(const Handle * pHandleA,const Handle * pHandleB,int axis0,int axis1)741 bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
742 {
743 //optimization 1: check the array index (memory address), instead of the m_pos
744
745 if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
746 pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
747 pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
748 pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
749 {
750 return false;
751 }
752 return true;
753 }
754
755 template <typename BP_FP_INT_TYPE>
updateHandle(BP_FP_INT_TYPE handle,const btVector3 & aabbMin,const btVector3 & aabbMax,btDispatcher * dispatcher)756 void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
757 {
758 // btAssert(bounds.IsFinite());
759 //btAssert(bounds.HasVolume());
760
761 Handle* pHandle = getHandle(handle);
762
763 // quantize the new bounds
764 BP_FP_INT_TYPE min[3], max[3];
765 quantize(min, aabbMin, 0);
766 quantize(max, aabbMax, 1);
767
768 // update changed edges
769 for (int axis = 0; axis < 3; axis++)
770 {
771 BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
772 BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
773
774 int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
775 int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
776
777 m_pEdges[axis][emin].m_pos = min[axis];
778 m_pEdges[axis][emax].m_pos = max[axis];
779
780 // expand (only adds overlaps)
781 if (dmin < 0)
782 sortMinDown(axis, emin,dispatcher,true);
783
784 if (dmax > 0)
785 sortMaxUp(axis, emax,dispatcher,true);
786
787 // shrink (only removes overlaps)
788 if (dmin > 0)
789 sortMinUp(axis, emin,dispatcher,true);
790
791 if (dmax < 0)
792 sortMaxDown(axis, emax,dispatcher,true);
793
794 #ifdef DEBUG_BROADPHASE
795 debugPrintAxis(axis);
796 #endif //DEBUG_BROADPHASE
797 }
798
799
800 }
801
802
803
804
805 // sorting a min edge downwards can only ever *add* overlaps
806 template <typename BP_FP_INT_TYPE>
sortMinDown(int axis,BP_FP_INT_TYPE edge,btDispatcher *,bool updateOverlaps)807 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
808 {
809
810 Edge* pEdge = m_pEdges[axis] + edge;
811 Edge* pPrev = pEdge - 1;
812 Handle* pHandleEdge = getHandle(pEdge->m_handle);
813
814 while (pEdge->m_pos < pPrev->m_pos)
815 {
816 Handle* pHandlePrev = getHandle(pPrev->m_handle);
817
818 if (pPrev->IsMax())
819 {
820 // if previous edge is a maximum check the bounds and add an overlap if necessary
821 const int axis1 = (1 << axis) & 3;
822 const int axis2 = (1 << axis1) & 3;
823 if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
824 {
825 m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
826 if (m_userPairCallback)
827 m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
828
829 //AddOverlap(pEdge->m_handle, pPrev->m_handle);
830
831 }
832
833 // update edge reference in other handle
834 pHandlePrev->m_maxEdges[axis]++;
835 }
836 else
837 pHandlePrev->m_minEdges[axis]++;
838
839 pHandleEdge->m_minEdges[axis]--;
840
841 // swap the edges
842 Edge swap = *pEdge;
843 *pEdge = *pPrev;
844 *pPrev = swap;
845
846 // decrement
847 pEdge--;
848 pPrev--;
849 }
850
851 #ifdef DEBUG_BROADPHASE
852 debugPrintAxis(axis);
853 #endif //DEBUG_BROADPHASE
854
855 }
856
857 // sorting a min edge upwards can only ever *remove* overlaps
858 template <typename BP_FP_INT_TYPE>
sortMinUp(int axis,BP_FP_INT_TYPE edge,btDispatcher * dispatcher,bool updateOverlaps)859 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
860 {
861 Edge* pEdge = m_pEdges[axis] + edge;
862 Edge* pNext = pEdge + 1;
863 Handle* pHandleEdge = getHandle(pEdge->m_handle);
864
865 while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
866 {
867 Handle* pHandleNext = getHandle(pNext->m_handle);
868
869 if (pNext->IsMax())
870 {
871 Handle* handle0 = getHandle(pEdge->m_handle);
872 Handle* handle1 = getHandle(pNext->m_handle);
873 const int axis1 = (1 << axis) & 3;
874 const int axis2 = (1 << axis1) & 3;
875
876 // if next edge is maximum remove any overlap between the two handles
877 if (updateOverlaps
878 #ifdef USE_OVERLAP_TEST_ON_REMOVES
879 && testOverlap2D(handle0,handle1,axis1,axis2)
880 #endif //USE_OVERLAP_TEST_ON_REMOVES
881 )
882 {
883
884
885 m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
886 if (m_userPairCallback)
887 m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
888
889 }
890
891
892 // update edge reference in other handle
893 pHandleNext->m_maxEdges[axis]--;
894 }
895 else
896 pHandleNext->m_minEdges[axis]--;
897
898 pHandleEdge->m_minEdges[axis]++;
899
900 // swap the edges
901 Edge swap = *pEdge;
902 *pEdge = *pNext;
903 *pNext = swap;
904
905 // increment
906 pEdge++;
907 pNext++;
908 }
909
910
911 }
912
913 // sorting a max edge downwards can only ever *remove* overlaps
914 template <typename BP_FP_INT_TYPE>
sortMaxDown(int axis,BP_FP_INT_TYPE edge,btDispatcher * dispatcher,bool updateOverlaps)915 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
916 {
917
918 Edge* pEdge = m_pEdges[axis] + edge;
919 Edge* pPrev = pEdge - 1;
920 Handle* pHandleEdge = getHandle(pEdge->m_handle);
921
922 while (pEdge->m_pos < pPrev->m_pos)
923 {
924 Handle* pHandlePrev = getHandle(pPrev->m_handle);
925
926 if (!pPrev->IsMax())
927 {
928 // if previous edge was a minimum remove any overlap between the two handles
929 Handle* handle0 = getHandle(pEdge->m_handle);
930 Handle* handle1 = getHandle(pPrev->m_handle);
931 const int axis1 = (1 << axis) & 3;
932 const int axis2 = (1 << axis1) & 3;
933
934 if (updateOverlaps
935 #ifdef USE_OVERLAP_TEST_ON_REMOVES
936 && testOverlap2D(handle0,handle1,axis1,axis2)
937 #endif //USE_OVERLAP_TEST_ON_REMOVES
938 )
939 {
940 //this is done during the overlappingpairarray iteration/narrowphase collision
941
942
943 m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
944 if (m_userPairCallback)
945 m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
946
947
948
949 }
950
951 // update edge reference in other handle
952 pHandlePrev->m_minEdges[axis]++;;
953 }
954 else
955 pHandlePrev->m_maxEdges[axis]++;
956
957 pHandleEdge->m_maxEdges[axis]--;
958
959 // swap the edges
960 Edge swap = *pEdge;
961 *pEdge = *pPrev;
962 *pPrev = swap;
963
964 // decrement
965 pEdge--;
966 pPrev--;
967 }
968
969
970 #ifdef DEBUG_BROADPHASE
971 debugPrintAxis(axis);
972 #endif //DEBUG_BROADPHASE
973
974 }
975
976 // sorting a max edge upwards can only ever *add* overlaps
977 template <typename BP_FP_INT_TYPE>
sortMaxUp(int axis,BP_FP_INT_TYPE edge,btDispatcher *,bool updateOverlaps)978 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
979 {
980 Edge* pEdge = m_pEdges[axis] + edge;
981 Edge* pNext = pEdge + 1;
982 Handle* pHandleEdge = getHandle(pEdge->m_handle);
983
984 while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
985 {
986 Handle* pHandleNext = getHandle(pNext->m_handle);
987
988 const int axis1 = (1 << axis) & 3;
989 const int axis2 = (1 << axis1) & 3;
990
991 if (!pNext->IsMax())
992 {
993 // if next edge is a minimum check the bounds and add an overlap if necessary
994 if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
995 {
996 Handle* handle0 = getHandle(pEdge->m_handle);
997 Handle* handle1 = getHandle(pNext->m_handle);
998 m_pairCache->addOverlappingPair(handle0,handle1);
999 if (m_userPairCallback)
1000 m_userPairCallback->addOverlappingPair(handle0,handle1);
1001 }
1002
1003 // update edge reference in other handle
1004 pHandleNext->m_minEdges[axis]--;
1005 }
1006 else
1007 pHandleNext->m_maxEdges[axis]--;
1008
1009 pHandleEdge->m_maxEdges[axis]++;
1010
1011 // swap the edges
1012 Edge swap = *pEdge;
1013 *pEdge = *pNext;
1014 *pNext = swap;
1015
1016 // increment
1017 pEdge++;
1018 pNext++;
1019 }
1020
1021 }
1022
1023
1024
1025 ////////////////////////////////////////////////////////////////////
1026
1027
1028 /// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
1029 /// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
1030 /// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
1031 class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
1032 {
1033 public:
1034
1035 btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
1036
1037 };
1038
1039 /// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
1040 /// This comes at the cost of more memory per handle, and a bit slower performance.
1041 /// It uses arrays rather then lists for storage of the 3 axis.
1042 class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
1043 {
1044 public:
1045
1046 bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
1047
1048 };
1049
1050 #endif
1051
1052