1 //Bullet Continuous Collision Detection and Physics Library
2 //Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
7 // Copyright (c) 2006 Simon Hobbs
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.
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:
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.
15 // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
17 // 3. This notice may not be removed or altered from any source distribution.
19 #ifndef BT_AXIS_SWEEP_3_H
20 #define BT_AXIS_SWEEP_3_H
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"
29 //#define DEBUG_BROADPHASE 1
30 #define USE_OVERLAP_TEST_ON_REMOVES 1
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
40 BP_FP_INT_TYPE m_bpHandleMask;
41 BP_FP_INT_TYPE m_handleSentinel;
45 BT_DECLARE_ALIGNED_ALLOCATOR();
50 BP_FP_INT_TYPE m_pos; // low bit is min/max
51 BP_FP_INT_TYPE m_handle;
53 BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
57 class Handle : public btBroadphaseProxy
60 BT_DECLARE_ALIGNED_ALLOCATOR();
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
68 SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
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
74 btVector3 m_worldAabbMin; // overall system bounds
75 btVector3 m_worldAabbMax; // overall system bounds
77 btVector3 m_quantize; // scaling factor for quantization
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
83 BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
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];
88 btOverlappingPairCache* m_pairCache;
90 ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
91 btOverlappingPairCallback* m_userPairCallback;
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;
103 // allocation/deallocation
104 BP_FP_INT_TYPE allocHandle();
105 void freeHandle(BP_FP_INT_TYPE handle);
108 bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
110 #ifdef DEBUG_BROADPHASE
111 void debugPrintAxis(int axis,bool checkCardinality=true);
112 #endif //DEBUG_BROADPHASE
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);
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 );
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);
128 virtual ~btAxisSweep3Internal();
130 BP_FP_INT_TYPE getNumHandles() const
135 virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
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);
140 SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
142 virtual void resetPool(btDispatcher* dispatcher);
144 void processAllOverlappingPairs(btOverlapCallback* callback);
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;
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);
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;
160 bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
162 btOverlappingPairCache* getOverlappingPairCache()
166 const btOverlappingPairCache* getOverlappingPairCache() const
171 void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
173 m_userPairCallback = pairCallback;
175 const btOverlappingPairCallback* getOverlappingPairUserCallback() const
177 return m_userPairCallback;
180 ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
181 ///will add some transform later
182 virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
184 aabbMin = m_worldAabbMin;
185 aabbMax = m_worldAabbMax;
188 virtual void printStats()
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());
200 ////////////////////////////////////////////////////////////////////
205 #ifdef DEBUG_BROADPHASE
208 template <typename BP_FP_INT_TYPE>
209 void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
211 int numEdges = m_pHandles[0].m_maxEdges[axis];
212 printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
215 for (i=0;i<numEdges+1;i++)
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];
221 beginOrEnd=pEdge->IsMax()?'E':'B';
222 printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
225 if (checkCardinality)
226 btAssert(numEdges == m_numHandles*2+1);
228 #endif //DEBUG_BROADPHASE
230 template <typename BP_FP_INT_TYPE>
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)
234 BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
236 Handle* handle = getHandle(handleId);
238 if (m_raycastAccelerator)
240 btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0);
241 handle->m_dbvtProxy = rayProxy;
248 template <typename BP_FP_INT_TYPE>
249 void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
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);
257 template <typename BP_FP_INT_TYPE>
258 void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
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);
269 template <typename BP_FP_INT_TYPE>
270 void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
272 if (m_raycastAccelerator)
274 m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
278 BP_FP_INT_TYPE axis = 0;
280 for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
282 if (m_pEdges[axis][i].IsMax())
284 rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
290 template <typename BP_FP_INT_TYPE>
291 void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
293 if (m_raycastAccelerator)
295 m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
299 BP_FP_INT_TYPE axis = 0;
301 for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
303 if (m_pEdges[axis][i].IsMax())
305 Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
306 if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
308 callback.process(handle);
317 template <typename BP_FP_INT_TYPE>
318 void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
320 Handle* pHandle = static_cast<Handle*>(proxy);
321 aabbMin = pHandle->m_aabbMin;
322 aabbMax = pHandle->m_aabbMax;
326 template <typename BP_FP_INT_TYPE>
327 void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
329 Handle* pHandle = static_cast<Handle*>(proxy);
331 unsigned short vecInMin[3];
332 unsigned short vecInMax[3];
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 ;
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;
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;
351 template <typename BP_FP_INT_TYPE>
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),
359 m_raycastAccelerator(0)
361 BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
365 void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
366 m_pairCache = new(ptr) btHashedOverlappingPairCache();
367 m_ownsPairCache = true;
370 if (!disableRaycastAccelerator)
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
377 //btAssert(bounds.HasVolume());
380 m_worldAabbMin = worldAabbMin;
381 m_worldAabbMax = worldAabbMax;
383 btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
385 BP_FP_INT_TYPE maxInt = m_handleSentinel;
387 m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
389 // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
390 m_pHandles = new Handle[maxHandles];
392 m_maxHandles = maxHandles;
395 // handle 0 is reserved as the null index, and is also used as the sentinel
396 m_firstFreeHandle = 1;
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);
404 // allocate edge buffers
405 for (int i = 0; i < 3; i++)
407 m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
408 m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
411 //removed overlap management
413 // make boundary sentinels
415 m_pHandles[0].m_clientObject = 0;
417 for (int axis = 0; axis < 3; axis++)
419 m_pHandles[0].m_minEdges[axis] = 0;
420 m_pHandles[0].m_maxEdges[axis] = 1;
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
434 template <typename BP_FP_INT_TYPE>
435 btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
437 if (m_raycastAccelerator)
439 m_nullPairCache->~btOverlappingPairCache();
440 btAlignedFree(m_nullPairCache);
441 m_raycastAccelerator->~btDbvtBroadphase();
442 btAlignedFree (m_raycastAccelerator);
445 for (int i = 2; i >= 0; i--)
447 btAlignedFree(m_pEdgesRawPtr[i]);
449 delete [] m_pHandles;
453 m_pairCache->~btOverlappingPairCache();
454 btAlignedFree(m_pairCache);
458 template <typename BP_FP_INT_TYPE>
459 void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
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);
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
480 template <typename BP_FP_INT_TYPE>
481 BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
483 btAssert(m_firstFreeHandle);
485 BP_FP_INT_TYPE handle = m_firstFreeHandle;
486 m_firstFreeHandle = getHandle(handle)->GetNextFree();
492 template <typename BP_FP_INT_TYPE>
493 void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
495 btAssert(handle > 0 && handle < m_maxHandles);
497 getHandle(handle)->SetNextFree(m_firstFreeHandle);
498 m_firstFreeHandle = handle;
504 template <typename BP_FP_INT_TYPE>
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)
507 // quantize the bounds
508 BP_FP_INT_TYPE min[3], max[3];
509 quantize(min, aabbMin, 0);
510 quantize(max, aabbMax, 1);
513 BP_FP_INT_TYPE handle = allocHandle();
516 Handle* pHandle = getHandle(handle);
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;
525 // compute current limit of edge arrays
526 BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
529 // insert new edges just inside the max boundary edge
530 for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
533 m_pHandles[0].m_maxEdges[axis] += 2;
535 m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
537 m_pEdges[axis][limit - 1].m_pos = min[axis];
538 m_pEdges[axis][limit - 1].m_handle = handle;
540 m_pEdges[axis][limit].m_pos = max[axis];
541 m_pEdges[axis][limit].m_handle = handle;
543 pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
544 pHandle->m_maxEdges[axis] = limit;
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);
560 template <typename BP_FP_INT_TYPE>
561 void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
564 Handle* pHandle = getHandle(handle);
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())
571 m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
574 // compute current limit of edge arrays
575 int limit = static_cast<int>(m_numHandles * 2);
579 for (axis = 0;axis<3;axis++)
581 m_pHandles[0].m_maxEdges[axis] -= 2;
584 // remove the edges by sorting them up to the end of the list
585 for ( axis = 0; axis < 3; axis++)
587 Edge* pEdges = m_pEdges[axis];
588 BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
589 pEdges[max].m_pos = m_handleSentinel;
591 sortMaxUp(axis,max,dispatcher,false);
594 BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
595 pEdges[i].m_pos = m_handleSentinel;
598 sortMinUp(axis,i,dispatcher,false);
600 pEdges[limit-1].m_handle = 0;
601 pEdges[limit-1].m_pos = m_handleSentinel;
603 #ifdef DEBUG_BROADPHASE
604 debugPrintAxis(axis,false);
605 #endif //DEBUG_BROADPHASE
617 template <typename BP_FP_INT_TYPE>
618 void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
620 if (m_numHandles == 0)
622 m_firstFreeHandle = 1;
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);
632 extern int gOverlappingPairs;
635 template <typename BP_FP_INT_TYPE>
636 void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
639 if (m_pairCache->hasDeferredRemoval())
642 btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
644 //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
645 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
647 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
653 btBroadphasePair previousPair;
654 previousPair.m_pProxy0 = 0;
655 previousPair.m_pProxy1 = 0;
656 previousPair.m_algorithm = 0;
659 for (i=0;i<overlappingPairArray.size();i++)
662 btBroadphasePair& pair = overlappingPairArray[i];
664 bool isDuplicate = (pair == previousPair);
668 bool needsRemoval = false;
672 ///important to use an AABB test that is consistent with the broadphase
673 bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
677 needsRemoval = false;//callback->processOverlap(pair);
686 //should have no algorithm
687 btAssert(!pair.m_algorithm);
692 m_pairCache->cleanOverlappingPair(pair,dispatcher);
694 // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
695 // m_overlappingPairArray.pop_back();
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
708 //perform a sort, to sort 'invalid' pairs to the end
709 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
711 overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
713 #endif//CLEAN_INVALID_PAIRS
715 //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
721 template <typename BP_FP_INT_TYPE>
722 bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
724 const Handle* pHandleA = static_cast<Handle*>(proxy0);
725 const Handle* pHandleB = static_cast<Handle*>(proxy1);
727 //optimization 1: check the array index (memory address), instead of the m_pos
729 for (int axis = 0; axis < 3; axis++)
731 if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
732 pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
740 template <typename BP_FP_INT_TYPE>
741 bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
743 //optimization 1: check the array index (memory address), instead of the m_pos
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])
755 template <typename BP_FP_INT_TYPE>
756 void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
758 // btAssert(bounds.IsFinite());
759 //btAssert(bounds.HasVolume());
761 Handle* pHandle = getHandle(handle);
763 // quantize the new bounds
764 BP_FP_INT_TYPE min[3], max[3];
765 quantize(min, aabbMin, 0);
766 quantize(max, aabbMax, 1);
768 // update changed edges
769 for (int axis = 0; axis < 3; axis++)
771 BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
772 BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
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;
777 m_pEdges[axis][emin].m_pos = min[axis];
778 m_pEdges[axis][emax].m_pos = max[axis];
780 // expand (only adds overlaps)
782 sortMinDown(axis, emin,dispatcher,true);
785 sortMaxUp(axis, emax,dispatcher,true);
787 // shrink (only removes overlaps)
789 sortMinUp(axis, emin,dispatcher,true);
792 sortMaxDown(axis, emax,dispatcher,true);
794 #ifdef DEBUG_BROADPHASE
795 debugPrintAxis(axis);
796 #endif //DEBUG_BROADPHASE
805 // sorting a min edge downwards can only ever *add* overlaps
806 template <typename BP_FP_INT_TYPE>
807 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
810 Edge* pEdge = m_pEdges[axis] + edge;
811 Edge* pPrev = pEdge - 1;
812 Handle* pHandleEdge = getHandle(pEdge->m_handle);
814 while (pEdge->m_pos < pPrev->m_pos)
816 Handle* pHandlePrev = getHandle(pPrev->m_handle);
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))
825 m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
826 if (m_userPairCallback)
827 m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
829 //AddOverlap(pEdge->m_handle, pPrev->m_handle);
833 // update edge reference in other handle
834 pHandlePrev->m_maxEdges[axis]++;
837 pHandlePrev->m_minEdges[axis]++;
839 pHandleEdge->m_minEdges[axis]--;
851 #ifdef DEBUG_BROADPHASE
852 debugPrintAxis(axis);
853 #endif //DEBUG_BROADPHASE
857 // sorting a min edge upwards can only ever *remove* overlaps
858 template <typename BP_FP_INT_TYPE>
859 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
861 Edge* pEdge = m_pEdges[axis] + edge;
862 Edge* pNext = pEdge + 1;
863 Handle* pHandleEdge = getHandle(pEdge->m_handle);
865 while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
867 Handle* pHandleNext = getHandle(pNext->m_handle);
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;
876 // if next edge is maximum remove any overlap between the two handles
878 #ifdef USE_OVERLAP_TEST_ON_REMOVES
879 && testOverlap2D(handle0,handle1,axis1,axis2)
880 #endif //USE_OVERLAP_TEST_ON_REMOVES
885 m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
886 if (m_userPairCallback)
887 m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
892 // update edge reference in other handle
893 pHandleNext->m_maxEdges[axis]--;
896 pHandleNext->m_minEdges[axis]--;
898 pHandleEdge->m_minEdges[axis]++;
913 // sorting a max edge downwards can only ever *remove* overlaps
914 template <typename BP_FP_INT_TYPE>
915 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
918 Edge* pEdge = m_pEdges[axis] + edge;
919 Edge* pPrev = pEdge - 1;
920 Handle* pHandleEdge = getHandle(pEdge->m_handle);
922 while (pEdge->m_pos < pPrev->m_pos)
924 Handle* pHandlePrev = getHandle(pPrev->m_handle);
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;
935 #ifdef USE_OVERLAP_TEST_ON_REMOVES
936 && testOverlap2D(handle0,handle1,axis1,axis2)
937 #endif //USE_OVERLAP_TEST_ON_REMOVES
940 //this is done during the overlappingpairarray iteration/narrowphase collision
943 m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
944 if (m_userPairCallback)
945 m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
951 // update edge reference in other handle
952 pHandlePrev->m_minEdges[axis]++;;
955 pHandlePrev->m_maxEdges[axis]++;
957 pHandleEdge->m_maxEdges[axis]--;
970 #ifdef DEBUG_BROADPHASE
971 debugPrintAxis(axis);
972 #endif //DEBUG_BROADPHASE
976 // sorting a max edge upwards can only ever *add* overlaps
977 template <typename BP_FP_INT_TYPE>
978 void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
980 Edge* pEdge = m_pEdges[axis] + edge;
981 Edge* pNext = pEdge + 1;
982 Handle* pHandleEdge = getHandle(pEdge->m_handle);
984 while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
986 Handle* pHandleNext = getHandle(pNext->m_handle);
988 const int axis1 = (1 << axis) & 3;
989 const int axis2 = (1 << axis1) & 3;
993 // if next edge is a minimum check the bounds and add an overlap if necessary
994 if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
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);
1003 // update edge reference in other handle
1004 pHandleNext->m_minEdges[axis]--;
1007 pHandleNext->m_maxEdges[axis]--;
1009 pHandleEdge->m_maxEdges[axis]++;
1025 ////////////////////////////////////////////////////////////////////
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>
1035 btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
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>
1046 bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);