1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 ///btDbvtBroadphase implementation by Nathanael Presson
17
18 #include "btDbvtBroadphase.h"
19 #include "LinearMath/btThreads.h"
20 btScalar gDbvtMargin = btScalar(0.05);
21 //
22 // Profiling
23 //
24
25 #if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK
26 #include <stdio.h>
27 #endif
28
29 #if DBVT_BP_PROFILE
30 struct ProfileScope
31 {
ProfileScopeProfileScope32 __forceinline ProfileScope(btClock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
33 {
34 }
~ProfileScopeProfileScope35 __forceinline ~ProfileScope()
36 {
37 (*m_value) += m_clock->getTimeMicroseconds() - m_base;
38 }
39 btClock* m_clock;
40 unsigned long* m_value;
41 unsigned long m_base;
42 };
43 #define SPC(_value_) ProfileScope spc_scope(m_clock, _value_)
44 #else
45 #define SPC(_value_)
46 #endif
47
48 //
49 // Helpers
50 //
51
52 //
53 template <typename T>
listappend(T * item,T * & list)54 static inline void listappend(T* item, T*& list)
55 {
56 item->links[0] = 0;
57 item->links[1] = list;
58 if (list) list->links[0] = item;
59 list = item;
60 }
61
62 //
63 template <typename T>
listremove(T * item,T * & list)64 static inline void listremove(T* item, T*& list)
65 {
66 if (item->links[0])
67 item->links[0]->links[1] = item->links[1];
68 else
69 list = item->links[1];
70 if (item->links[1]) item->links[1]->links[0] = item->links[0];
71 }
72
73 //
74 template <typename T>
listcount(T * root)75 static inline int listcount(T* root)
76 {
77 int n = 0;
78 while (root)
79 {
80 ++n;
81 root = root->links[1];
82 }
83 return (n);
84 }
85
86 //
87 template <typename T>
clear(T & value)88 static inline void clear(T& value)
89 {
90 static const struct ZeroDummy : T
91 {
92 } zerodummy;
93 value = zerodummy;
94 }
95
96 //
97 // Colliders
98 //
99
100 /* Tree collider */
101 struct btDbvtTreeCollider : btDbvt::ICollide
102 {
103 btDbvtBroadphase* pbp;
104 btDbvtProxy* proxy;
btDbvtTreeColliderbtDbvtTreeCollider105 btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
ProcessbtDbvtTreeCollider106 void Process(const btDbvtNode* na, const btDbvtNode* nb)
107 {
108 if (na != nb)
109 {
110 btDbvtProxy* pa = (btDbvtProxy*)na->data;
111 btDbvtProxy* pb = (btDbvtProxy*)nb->data;
112 #if DBVT_BP_SORTPAIRS
113 if (pa->m_uniqueId > pb->m_uniqueId)
114 btSwap(pa, pb);
115 #endif
116 pbp->m_paircache->addOverlappingPair(pa, pb);
117 ++pbp->m_newpairs;
118 }
119 }
ProcessbtDbvtTreeCollider120 void Process(const btDbvtNode* n)
121 {
122 Process(n, proxy->leaf);
123 }
124 };
125
126 //
127 // btDbvtBroadphase
128 //
129
130 //
btDbvtBroadphase(btOverlappingPairCache * paircache)131 btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
132 {
133 m_deferedcollide = false;
134 m_needcleanup = true;
135 m_releasepaircache = (paircache != 0) ? false : true;
136 m_prediction = 0;
137 m_stageCurrent = 0;
138 m_fixedleft = 0;
139 m_fupdates = 1;
140 m_dupdates = 0;
141 m_cupdates = 10;
142 m_newpairs = 1;
143 m_updates_call = 0;
144 m_updates_done = 0;
145 m_updates_ratio = 0;
146 m_paircache = paircache ? paircache : new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
147 m_gid = 0;
148 m_pid = 0;
149 m_cid = 0;
150 for (int i = 0; i <= STAGECOUNT; ++i)
151 {
152 m_stageRoots[i] = 0;
153 }
154 #if BT_THREADSAFE
155 m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
156 #else
157 m_rayTestStacks.resize(1);
158 #endif
159 #if DBVT_BP_PROFILE
160 clear(m_profiling);
161 #endif
162 }
163
164 //
~btDbvtBroadphase()165 btDbvtBroadphase::~btDbvtBroadphase()
166 {
167 if (m_releasepaircache)
168 {
169 m_paircache->~btOverlappingPairCache();
170 btAlignedFree(m_paircache);
171 }
172 }
173
174 //
createProxy(const btVector3 & aabbMin,const btVector3 & aabbMax,int,void * userPtr,int collisionFilterGroup,int collisionFilterMask,btDispatcher *)175 btBroadphaseProxy* btDbvtBroadphase::createProxy(const btVector3& aabbMin,
176 const btVector3& aabbMax,
177 int /*shapeType*/,
178 void* userPtr,
179 int collisionFilterGroup,
180 int collisionFilterMask,
181 btDispatcher* /*dispatcher*/)
182 {
183 btDbvtProxy* proxy = new (btAlignedAlloc(sizeof(btDbvtProxy), 16)) btDbvtProxy(aabbMin, aabbMax, userPtr,
184 collisionFilterGroup,
185 collisionFilterMask);
186
187 btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
188
189 //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
190 proxy->stage = m_stageCurrent;
191 proxy->m_uniqueId = ++m_gid;
192 proxy->leaf = m_sets[0].insert(aabb, proxy);
193 listappend(proxy, m_stageRoots[m_stageCurrent]);
194 if (!m_deferedcollide)
195 {
196 btDbvtTreeCollider collider(this);
197 collider.proxy = proxy;
198 m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
199 m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
200 }
201 return (proxy);
202 }
203
204 //
destroyProxy(btBroadphaseProxy * absproxy,btDispatcher * dispatcher)205 void btDbvtBroadphase::destroyProxy(btBroadphaseProxy* absproxy,
206 btDispatcher* dispatcher)
207 {
208 btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
209 if (proxy->stage == STAGECOUNT)
210 m_sets[1].remove(proxy->leaf);
211 else
212 m_sets[0].remove(proxy->leaf);
213 listremove(proxy, m_stageRoots[proxy->stage]);
214 m_paircache->removeOverlappingPairsContainingProxy(proxy, dispatcher);
215 btAlignedFree(proxy);
216 m_needcleanup = true;
217 }
218
getAabb(btBroadphaseProxy * absproxy,btVector3 & aabbMin,btVector3 & aabbMax) const219 void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy, btVector3& aabbMin, btVector3& aabbMax) const
220 {
221 btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
222 aabbMin = proxy->m_aabbMin;
223 aabbMax = proxy->m_aabbMax;
224 }
225
226 struct BroadphaseRayTester : btDbvt::ICollide
227 {
228 btBroadphaseRayCallback& m_rayCallback;
BroadphaseRayTesterBroadphaseRayTester229 BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
230 : m_rayCallback(orgCallback)
231 {
232 }
ProcessBroadphaseRayTester233 void Process(const btDbvtNode* leaf)
234 {
235 btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
236 m_rayCallback.process(proxy);
237 }
238 };
239
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btBroadphaseRayCallback & rayCallback,const btVector3 & aabbMin,const btVector3 & aabbMax)240 void btDbvtBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
241 {
242 BroadphaseRayTester callback(rayCallback);
243 btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
244 #if BT_THREADSAFE
245 // for this function to be threadsafe, each thread must have a separate copy
246 // of this stack. This could be thread-local static to avoid dynamic allocations,
247 // instead of just a local.
248 int threadIndex = btGetCurrentThreadIndex();
249 btAlignedObjectArray<const btDbvtNode*> localStack;
250 //todo(erwincoumans, "why do we get tsan issue here?")
251 if (0)//threadIndex < m_rayTestStacks.size())
252 //if (threadIndex < m_rayTestStacks.size())
253 {
254 // use per-thread preallocated stack if possible to avoid dynamic allocations
255 stack = &m_rayTestStacks[threadIndex];
256 }
257 else
258 {
259 stack = &localStack;
260 }
261 #endif
262
263 m_sets[0].rayTestInternal(m_sets[0].m_root,
264 rayFrom,
265 rayTo,
266 rayCallback.m_rayDirectionInverse,
267 rayCallback.m_signs,
268 rayCallback.m_lambda_max,
269 aabbMin,
270 aabbMax,
271 *stack,
272 callback);
273
274 m_sets[1].rayTestInternal(m_sets[1].m_root,
275 rayFrom,
276 rayTo,
277 rayCallback.m_rayDirectionInverse,
278 rayCallback.m_signs,
279 rayCallback.m_lambda_max,
280 aabbMin,
281 aabbMax,
282 *stack,
283 callback);
284 }
285
286 struct BroadphaseAabbTester : btDbvt::ICollide
287 {
288 btBroadphaseAabbCallback& m_aabbCallback;
BroadphaseAabbTesterBroadphaseAabbTester289 BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
290 : m_aabbCallback(orgCallback)
291 {
292 }
ProcessBroadphaseAabbTester293 void Process(const btDbvtNode* leaf)
294 {
295 btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
296 m_aabbCallback.process(proxy);
297 }
298 };
299
aabbTest(const btVector3 & aabbMin,const btVector3 & aabbMax,btBroadphaseAabbCallback & aabbCallback)300 void btDbvtBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& aabbCallback)
301 {
302 BroadphaseAabbTester callback(aabbCallback);
303
304 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(aabbMin, aabbMax);
305 //process all children, that overlap with the given AABB bounds
306 m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
307 m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
308 }
309
310 //
setAabb(btBroadphaseProxy * absproxy,const btVector3 & aabbMin,const btVector3 & aabbMax,btDispatcher *)311 void btDbvtBroadphase::setAabb(btBroadphaseProxy* absproxy,
312 const btVector3& aabbMin,
313 const btVector3& aabbMax,
314 btDispatcher* /*dispatcher*/)
315 {
316 btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
317 ATTRIBUTE_ALIGNED16(btDbvtVolume)
318 aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
319 #if DBVT_BP_PREVENTFALSEUPDATE
320 if (NotEqual(aabb, proxy->leaf->volume))
321 #endif
322 {
323 bool docollide = false;
324 if (proxy->stage == STAGECOUNT)
325 { /* fixed -> dynamic set */
326 m_sets[1].remove(proxy->leaf);
327 proxy->leaf = m_sets[0].insert(aabb, proxy);
328 docollide = true;
329 }
330 else
331 { /* dynamic set */
332 ++m_updates_call;
333 if (Intersect(proxy->leaf->volume, aabb))
334 { /* Moving */
335
336 const btVector3 delta = aabbMin - proxy->m_aabbMin;
337 btVector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
338 if (delta[0] < 0) velocity[0] = -velocity[0];
339 if (delta[1] < 0) velocity[1] = -velocity[1];
340 if (delta[2] < 0) velocity[2] = -velocity[2];
341 if (
342 m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
343
344 )
345 {
346 ++m_updates_done;
347 docollide = true;
348 }
349 }
350 else
351 { /* Teleporting */
352 m_sets[0].update(proxy->leaf, aabb);
353 ++m_updates_done;
354 docollide = true;
355 }
356 }
357 listremove(proxy, m_stageRoots[proxy->stage]);
358 proxy->m_aabbMin = aabbMin;
359 proxy->m_aabbMax = aabbMax;
360 proxy->stage = m_stageCurrent;
361 listappend(proxy, m_stageRoots[m_stageCurrent]);
362 if (docollide)
363 {
364 m_needcleanup = true;
365 if (!m_deferedcollide)
366 {
367 btDbvtTreeCollider collider(this);
368 m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
369 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
370 }
371 }
372 }
373 }
374
375 //
setAabbForceUpdate(btBroadphaseProxy * absproxy,const btVector3 & aabbMin,const btVector3 & aabbMax,btDispatcher *)376 void btDbvtBroadphase::setAabbForceUpdate(btBroadphaseProxy* absproxy,
377 const btVector3& aabbMin,
378 const btVector3& aabbMax,
379 btDispatcher* /*dispatcher*/)
380 {
381 btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
382 ATTRIBUTE_ALIGNED16(btDbvtVolume)
383 aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
384 bool docollide = false;
385 if (proxy->stage == STAGECOUNT)
386 { /* fixed -> dynamic set */
387 m_sets[1].remove(proxy->leaf);
388 proxy->leaf = m_sets[0].insert(aabb, proxy);
389 docollide = true;
390 }
391 else
392 { /* dynamic set */
393 ++m_updates_call;
394 /* Teleporting */
395 m_sets[0].update(proxy->leaf, aabb);
396 ++m_updates_done;
397 docollide = true;
398 }
399 listremove(proxy, m_stageRoots[proxy->stage]);
400 proxy->m_aabbMin = aabbMin;
401 proxy->m_aabbMax = aabbMax;
402 proxy->stage = m_stageCurrent;
403 listappend(proxy, m_stageRoots[m_stageCurrent]);
404 if (docollide)
405 {
406 m_needcleanup = true;
407 if (!m_deferedcollide)
408 {
409 btDbvtTreeCollider collider(this);
410 m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
411 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
412 }
413 }
414 }
415
416 //
calculateOverlappingPairs(btDispatcher * dispatcher)417 void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
418 {
419 collide(dispatcher);
420 #if DBVT_BP_PROFILE
421 if (0 == (m_pid % DBVT_BP_PROFILING_RATE))
422 {
423 printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
424 unsigned int total = m_profiling.m_total;
425 if (total <= 0) total = 1;
426 printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / DBVT_BP_PROFILING_RATE);
427 printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / DBVT_BP_PROFILING_RATE);
428 printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / DBVT_BP_PROFILING_RATE);
429 printf("total: %uus\r\n", total / DBVT_BP_PROFILING_RATE);
430 const unsigned long sum = m_profiling.m_ddcollide +
431 m_profiling.m_fdcollide +
432 m_profiling.m_cleanup;
433 printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / DBVT_BP_PROFILING_RATE);
434 printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * DBVT_BP_PROFILING_RATE));
435 clear(m_profiling);
436 m_clock.reset();
437 }
438 #endif
439
440 performDeferredRemoval(dispatcher);
441 }
442
performDeferredRemoval(btDispatcher * dispatcher)443 void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
444 {
445 if (m_paircache->hasDeferredRemoval())
446 {
447 btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
448
449 //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
450 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
451
452 int invalidPair = 0;
453
454 int i;
455
456 btBroadphasePair previousPair;
457 previousPair.m_pProxy0 = 0;
458 previousPair.m_pProxy1 = 0;
459 previousPair.m_algorithm = 0;
460
461 for (i = 0; i < overlappingPairArray.size(); i++)
462 {
463 btBroadphasePair& pair = overlappingPairArray[i];
464
465 bool isDuplicate = (pair == previousPair);
466
467 previousPair = pair;
468
469 bool needsRemoval = false;
470
471 if (!isDuplicate)
472 {
473 //important to perform AABB check that is consistent with the broadphase
474 btDbvtProxy* pa = (btDbvtProxy*)pair.m_pProxy0;
475 btDbvtProxy* pb = (btDbvtProxy*)pair.m_pProxy1;
476 bool hasOverlap = Intersect(pa->leaf->volume, pb->leaf->volume);
477
478 if (hasOverlap)
479 {
480 needsRemoval = false;
481 }
482 else
483 {
484 needsRemoval = true;
485 }
486 }
487 else
488 {
489 //remove duplicate
490 needsRemoval = true;
491 //should have no algorithm
492 btAssert(!pair.m_algorithm);
493 }
494
495 if (needsRemoval)
496 {
497 m_paircache->cleanOverlappingPair(pair, dispatcher);
498
499 pair.m_pProxy0 = 0;
500 pair.m_pProxy1 = 0;
501 invalidPair++;
502 }
503 }
504
505 //perform a sort, to sort 'invalid' pairs to the end
506 overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
507 overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
508 }
509 }
510
511 //
collide(btDispatcher * dispatcher)512 void btDbvtBroadphase::collide(btDispatcher* dispatcher)
513 {
514 /*printf("---------------------------------------------------------\n");
515 printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
516 printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
517 printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
518 {
519 int i;
520 for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
521 {
522 printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
523 getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
524 }
525 printf("\n");
526 }
527 */
528
529 SPC(m_profiling.m_total);
530 /* optimize */
531 m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
532 if (m_fixedleft)
533 {
534 const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
535 m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
536 m_fixedleft = btMax<int>(0, m_fixedleft - count);
537 }
538 /* dynamic -> fixed set */
539 m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
540 btDbvtProxy* current = m_stageRoots[m_stageCurrent];
541 if (current)
542 {
543 #if DBVT_BP_ACCURATESLEEPING
544 btDbvtTreeCollider collider(this);
545 #endif
546 do
547 {
548 btDbvtProxy* next = current->links[1];
549 listremove(current, m_stageRoots[current->stage]);
550 listappend(current, m_stageRoots[STAGECOUNT]);
551 #if DBVT_BP_ACCURATESLEEPING
552 m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
553 collider.proxy = current;
554 btDbvt::collideTV(m_sets[0].m_root, current->aabb, collider);
555 btDbvt::collideTV(m_sets[1].m_root, current->aabb, collider);
556 #endif
557 m_sets[0].remove(current->leaf);
558 ATTRIBUTE_ALIGNED16(btDbvtVolume)
559 curAabb = btDbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
560 current->leaf = m_sets[1].insert(curAabb, current);
561 current->stage = STAGECOUNT;
562 current = next;
563 } while (current);
564 m_fixedleft = m_sets[1].m_leaves;
565 m_needcleanup = true;
566 }
567 /* collide dynamics */
568 {
569 btDbvtTreeCollider collider(this);
570 if (m_deferedcollide)
571 {
572 SPC(m_profiling.m_fdcollide);
573 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
574 }
575 if (m_deferedcollide)
576 {
577 SPC(m_profiling.m_ddcollide);
578 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
579 }
580 }
581 /* clean up */
582 if (m_needcleanup)
583 {
584 SPC(m_profiling.m_cleanup);
585 btBroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
586 if (pairs.size() > 0)
587 {
588 int ni = btMin(pairs.size(), btMax<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
589 for (int i = 0; i < ni; ++i)
590 {
591 btBroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
592 btDbvtProxy* pa = (btDbvtProxy*)p.m_pProxy0;
593 btDbvtProxy* pb = (btDbvtProxy*)p.m_pProxy1;
594 if (!Intersect(pa->leaf->volume, pb->leaf->volume))
595 {
596 #if DBVT_BP_SORTPAIRS
597 if (pa->m_uniqueId > pb->m_uniqueId)
598 btSwap(pa, pb);
599 #endif
600 m_paircache->removeOverlappingPair(pa, pb, dispatcher);
601 --ni;
602 --i;
603 }
604 }
605 if (pairs.size() > 0)
606 m_cid = (m_cid + ni) % pairs.size();
607 else
608 m_cid = 0;
609 }
610 }
611 ++m_pid;
612 m_newpairs = 1;
613 m_needcleanup = false;
614 if (m_updates_call > 0)
615 {
616 m_updates_ratio = m_updates_done / (btScalar)m_updates_call;
617 }
618 else
619 {
620 m_updates_ratio = 0;
621 }
622 m_updates_done /= 2;
623 m_updates_call /= 2;
624 }
625
626 //
optimize()627 void btDbvtBroadphase::optimize()
628 {
629 m_sets[0].optimizeTopDown();
630 m_sets[1].optimizeTopDown();
631 }
632
633 //
getOverlappingPairCache()634 btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
635 {
636 return (m_paircache);
637 }
638
639 //
getOverlappingPairCache() const640 const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
641 {
642 return (m_paircache);
643 }
644
645 //
getBroadphaseAabb(btVector3 & aabbMin,btVector3 & aabbMax) const646 void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
647 {
648 ATTRIBUTE_ALIGNED16(btDbvtVolume)
649 bounds;
650
651 if (!m_sets[0].empty())
652 if (!m_sets[1].empty())
653 Merge(m_sets[0].m_root->volume,
654 m_sets[1].m_root->volume, bounds);
655 else
656 bounds = m_sets[0].m_root->volume;
657 else if (!m_sets[1].empty())
658 bounds = m_sets[1].m_root->volume;
659 else
660 bounds = btDbvtVolume::FromCR(btVector3(0, 0, 0), 0);
661 aabbMin = bounds.Mins();
662 aabbMax = bounds.Maxs();
663 }
664
resetPool(btDispatcher * dispatcher)665 void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
666 {
667 int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
668 if (!totalObjects)
669 {
670 //reset internal dynamic tree data structures
671 m_sets[0].clear();
672 m_sets[1].clear();
673
674 m_deferedcollide = false;
675 m_needcleanup = true;
676 m_stageCurrent = 0;
677 m_fixedleft = 0;
678 m_fupdates = 1;
679 m_dupdates = 0;
680 m_cupdates = 10;
681 m_newpairs = 1;
682 m_updates_call = 0;
683 m_updates_done = 0;
684 m_updates_ratio = 0;
685
686 m_gid = 0;
687 m_pid = 0;
688 m_cid = 0;
689 for (int i = 0; i <= STAGECOUNT; ++i)
690 {
691 m_stageRoots[i] = 0;
692 }
693 }
694 }
695
696 //
printStats()697 void btDbvtBroadphase::printStats()
698 {
699 }
700
701 //
702 #if DBVT_BP_ENABLE_BENCHMARK
703
704 struct btBroadphaseBenchmark
705 {
706 struct Experiment
707 {
708 const char* name;
709 int object_count;
710 int update_count;
711 int spawn_count;
712 int iterations;
713 btScalar speed;
714 btScalar amplitude;
715 };
716 struct Object
717 {
718 btVector3 center;
719 btVector3 extents;
720 btBroadphaseProxy* proxy;
721 btScalar time;
updatebtBroadphaseBenchmark::Object722 void update(btScalar speed, btScalar amplitude, btBroadphaseInterface* pbi)
723 {
724 time += speed;
725 center[0] = btCos(time * (btScalar)2.17) * amplitude +
726 btSin(time) * amplitude / 2;
727 center[1] = btCos(time * (btScalar)1.38) * amplitude +
728 btSin(time) * amplitude;
729 center[2] = btSin(time * (btScalar)0.777) * amplitude;
730 pbi->setAabb(proxy, center - extents, center + extents, 0);
731 }
732 };
UnsignedRandbtBroadphaseBenchmark733 static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
UnitRandbtBroadphaseBenchmark734 static btScalar UnitRand() { return (UnsignedRand(16384) / (btScalar)16384); }
OutputTimebtBroadphaseBenchmark735 static void OutputTime(const char* name, btClock& c, unsigned count = 0)
736 {
737 const unsigned long us = c.getTimeMicroseconds();
738 const unsigned long ms = (us + 500) / 1000;
739 const btScalar sec = us / (btScalar)(1000 * 1000);
740 if (count > 0)
741 printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
742 else
743 printf("%s : %u us (%u ms)\r\n", name, us, ms);
744 }
745 };
746
benchmark(btBroadphaseInterface * pbi)747 void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
748 {
749 static const btBroadphaseBenchmark::Experiment experiments[] =
750 {
751 {"1024o.10%", 1024, 10, 0, 8192, (btScalar)0.005, (btScalar)100},
752 /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
753 {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
754 };
755 static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
756 btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
757 btClock wallclock;
758 /* Begin */
759 for (int iexp = 0; iexp < nexperiments; ++iexp)
760 {
761 const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
762 const int object_count = experiment.object_count;
763 const int update_count = (object_count * experiment.update_count) / 100;
764 const int spawn_count = (object_count * experiment.spawn_count) / 100;
765 const btScalar speed = experiment.speed;
766 const btScalar amplitude = experiment.amplitude;
767 printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
768 printf("\tObjects: %u\r\n", object_count);
769 printf("\tUpdate: %u\r\n", update_count);
770 printf("\tSpawn: %u\r\n", spawn_count);
771 printf("\tSpeed: %f\r\n", speed);
772 printf("\tAmplitude: %f\r\n", amplitude);
773 srand(180673);
774 /* Create objects */
775 wallclock.reset();
776 objects.reserve(object_count);
777 for (int i = 0; i < object_count; ++i)
778 {
779 btBroadphaseBenchmark::Object* po = new btBroadphaseBenchmark::Object();
780 po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
781 po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
782 po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
783 po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
784 po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
785 po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
786 po->time = btBroadphaseBenchmark::UnitRand() * 2000;
787 po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
788 objects.push_back(po);
789 }
790 btBroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
791 /* First update */
792 wallclock.reset();
793 for (int i = 0; i < objects.size(); ++i)
794 {
795 objects[i]->update(speed, amplitude, pbi);
796 }
797 btBroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
798 /* Updates */
799 wallclock.reset();
800 for (int i = 0; i < experiment.iterations; ++i)
801 {
802 for (int j = 0; j < update_count; ++j)
803 {
804 objects[j]->update(speed, amplitude, pbi);
805 }
806 pbi->calculateOverlappingPairs(0);
807 }
808 btBroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
809 /* Clean up */
810 wallclock.reset();
811 for (int i = 0; i < objects.size(); ++i)
812 {
813 pbi->destroyProxy(objects[i]->proxy, 0);
814 delete objects[i];
815 }
816 objects.resize(0);
817 btBroadphaseBenchmark::OutputTime("\tRelease", wallclock);
818 }
819 }
820 #else
benchmark(btBroadphaseInterface *)821 void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
822 {
823 }
824 #endif
825
826 #if DBVT_BP_PROFILE
827 #undef SPC
828 #endif
829