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 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 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 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 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); 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 162 btOverlappingPairCache* getOverlappingPairCache() 163 { 164 return m_pairCache; 165 } 166 const btOverlappingPairCache* getOverlappingPairCache() const 167 { 168 return m_pairCache; 169 } 170 171 void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) 172 { 173 m_userPairCallback = pairCallback; 174 } 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 182 virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const 183 { 184 aabbMin = m_worldAabbMin; 185 aabbMax = m_worldAabbMax; 186 } 187 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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