Bullet Collision Detection & Physics Library
btDbvtBroadphase.cpp
Go to the documentation of this file.
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 
17 
18 #include "btDbvtBroadphase.h"
19 #include "LinearMath/btThreads.h"
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 {
32  __forceinline ProfileScope(btClock& clock,unsigned long& value) :
33  m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
34  {
35  }
36  __forceinline ~ProfileScope()
37  {
38  (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
39  }
40  btClock* m_clock;
41  unsigned long* m_value;
42  unsigned long m_base;
43 };
44 #define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
45 #else
46 #define SPC(_value_)
47 #endif
48 
49 //
50 // Helpers
51 //
52 
53 //
54 template <typename T>
55 static inline void listappend(T* item,T*& list)
56 {
57  item->links[0]=0;
58  item->links[1]=list;
59  if(list) list->links[0]=item;
60  list=item;
61 }
62 
63 //
64 template <typename T>
65 static inline void listremove(T* item,T*& list)
66 {
67  if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
68  if(item->links[1]) item->links[1]->links[0]=item->links[0];
69 }
70 
71 //
72 template <typename T>
73 static inline int listcount(T* root)
74 {
75  int n=0;
76  while(root) { ++n;root=root->links[1]; }
77  return(n);
78 }
79 
80 //
81 template <typename T>
82 static inline void clear(T& value)
83 {
84  static const struct ZeroDummy : T {} zerodummy;
85  value=zerodummy;
86 }
87 
88 //
89 // Colliders
90 //
91 
92 /* Tree collider */
94 {
98  void Process(const btDbvtNode* na,const btDbvtNode* nb)
99  {
100  if(na!=nb)
101  {
102  btDbvtProxy* pa=(btDbvtProxy*)na->data;
103  btDbvtProxy* pb=(btDbvtProxy*)nb->data;
104 #if DBVT_BP_SORTPAIRS
105  if(pa->m_uniqueId>pb->m_uniqueId)
106  btSwap(pa,pb);
107 #endif
108  pbp->m_paircache->addOverlappingPair(pa,pb);
109  ++pbp->m_newpairs;
110  }
111  }
112  void Process(const btDbvtNode* n)
113  {
114  Process(n,proxy->leaf);
115  }
116 };
117 
118 //
119 // btDbvtBroadphase
120 //
121 
122 //
124 {
125  m_deferedcollide = false;
126  m_needcleanup = true;
127  m_releasepaircache = (paircache!=0)?false:true;
128  m_prediction = 0;
129  m_stageCurrent = 0;
130  m_fixedleft = 0;
131  m_fupdates = 1;
132  m_dupdates = 0;
133  m_cupdates = 10;
134  m_newpairs = 1;
135  m_updates_call = 0;
136  m_updates_done = 0;
137  m_updates_ratio = 0;
138  m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
139  m_gid = 0;
140  m_pid = 0;
141  m_cid = 0;
142  for(int i=0;i<=STAGECOUNT;++i)
143  {
144  m_stageRoots[i]=0;
145  }
146 #if BT_THREADSAFE
147  m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
148 #else
149  m_rayTestStacks.resize(1);
150 #endif
151 #if DBVT_BP_PROFILE
152  clear(m_profiling);
153 #endif
154 }
155 
156 //
158 {
159  if(m_releasepaircache)
160  {
161  m_paircache->~btOverlappingPairCache();
162  btAlignedFree(m_paircache);
163  }
164 }
165 
166 //
168  const btVector3& aabbMax,
169  int /*shapeType*/,
170  void* userPtr,
171  int collisionFilterGroup,
172  int collisionFilterMask,
173  btDispatcher* /*dispatcher*/)
174 {
175  btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr,
176  collisionFilterGroup,
177  collisionFilterMask);
178 
179  btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
180 
181  //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
182  proxy->stage = m_stageCurrent;
183  proxy->m_uniqueId = ++m_gid;
184  proxy->leaf = m_sets[0].insert(aabb,proxy);
185  listappend(proxy,m_stageRoots[m_stageCurrent]);
186  if(!m_deferedcollide)
187  {
188  btDbvtTreeCollider collider(this);
189  collider.proxy=proxy;
190  m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
191  m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
192  }
193  return(proxy);
194 }
195 
196 //
198  btDispatcher* dispatcher)
199 {
200  btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
201  if(proxy->stage==STAGECOUNT)
202  m_sets[1].remove(proxy->leaf);
203  else
204  m_sets[0].remove(proxy->leaf);
205  listremove(proxy,m_stageRoots[proxy->stage]);
206  m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
207  btAlignedFree(proxy);
208  m_needcleanup=true;
209 }
210 
211 void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
212 {
213  btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
214  aabbMin = proxy->m_aabbMin;
215  aabbMax = proxy->m_aabbMax;
216 }
217 
219 {
222  :m_rayCallback(orgCallback)
223  {
224  }
225  void Process(const btDbvtNode* leaf)
226  {
227  btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
228  m_rayCallback.process(proxy);
229  }
230 };
231 
232 void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
233 {
234  BroadphaseRayTester callback(rayCallback);
235  btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
236 #if BT_THREADSAFE
237  // for this function to be threadsafe, each thread must have a separate copy
238  // of this stack. This could be thread-local static to avoid dynamic allocations,
239  // instead of just a local.
240  int threadIndex = btGetCurrentThreadIndex();
242  if (threadIndex < m_rayTestStacks.size())
243  {
244  // use per-thread preallocated stack if possible to avoid dynamic allocations
245  stack = &m_rayTestStacks[threadIndex];
246  }
247  else
248  {
249  stack = &localStack;
250  }
251 #endif
252 
253  m_sets[0].rayTestInternal( m_sets[0].m_root,
254  rayFrom,
255  rayTo,
256  rayCallback.m_rayDirectionInverse,
257  rayCallback.m_signs,
258  rayCallback.m_lambda_max,
259  aabbMin,
260  aabbMax,
261  *stack,
262  callback);
263 
264  m_sets[1].rayTestInternal( m_sets[1].m_root,
265  rayFrom,
266  rayTo,
267  rayCallback.m_rayDirectionInverse,
268  rayCallback.m_signs,
269  rayCallback.m_lambda_max,
270  aabbMin,
271  aabbMax,
272  *stack,
273  callback);
274 
275 }
276 
277 
279 {
282  :m_aabbCallback(orgCallback)
283  {
284  }
285  void Process(const btDbvtNode* leaf)
286  {
287  btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
288  m_aabbCallback.process(proxy);
289  }
290 };
291 
292 void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
293 {
294  BroadphaseAabbTester callback(aabbCallback);
295 
297  //process all children, that overlap with the given AABB bounds
298  m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
299  m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
300 
301 }
302 
303 
304 
305 //
307  const btVector3& aabbMin,
308  const btVector3& aabbMax,
309  btDispatcher* /*dispatcher*/)
310 {
311  btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
313 #if DBVT_BP_PREVENTFALSEUPDATE
314  if(NotEqual(aabb,proxy->leaf->volume))
315 #endif
316  {
317  bool docollide=false;
318  if(proxy->stage==STAGECOUNT)
319  {/* fixed -> dynamic set */
320  m_sets[1].remove(proxy->leaf);
321  proxy->leaf=m_sets[0].insert(aabb,proxy);
322  docollide=true;
323  }
324  else
325  {/* dynamic set */
326  ++m_updates_call;
327  if(Intersect(proxy->leaf->volume,aabb))
328  {/* Moving */
329 
330  const btVector3 delta=aabbMin-proxy->m_aabbMin;
331  btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
332  if(delta[0]<0) velocity[0]=-velocity[0];
333  if(delta[1]<0) velocity[1]=-velocity[1];
334  if(delta[2]<0) velocity[2]=-velocity[2];
335  if (
336  m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
337 
338  )
339  {
340  ++m_updates_done;
341  docollide=true;
342  }
343  }
344  else
345  {/* Teleporting */
346  m_sets[0].update(proxy->leaf,aabb);
347  ++m_updates_done;
348  docollide=true;
349  }
350  }
351  listremove(proxy,m_stageRoots[proxy->stage]);
352  proxy->m_aabbMin = aabbMin;
353  proxy->m_aabbMax = aabbMax;
354  proxy->stage = m_stageCurrent;
355  listappend(proxy,m_stageRoots[m_stageCurrent]);
356  if(docollide)
357  {
358  m_needcleanup=true;
359  if(!m_deferedcollide)
360  {
361  btDbvtTreeCollider collider(this);
362  m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
363  m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
364  }
365  }
366  }
367 }
368 
369 
370 //
372  const btVector3& aabbMin,
373  const btVector3& aabbMax,
374  btDispatcher* /*dispatcher*/)
375 {
376  btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
378  bool docollide=false;
379  if(proxy->stage==STAGECOUNT)
380  {/* fixed -> dynamic set */
381  m_sets[1].remove(proxy->leaf);
382  proxy->leaf=m_sets[0].insert(aabb,proxy);
383  docollide=true;
384  }
385  else
386  {/* dynamic set */
387  ++m_updates_call;
388  /* Teleporting */
389  m_sets[0].update(proxy->leaf,aabb);
390  ++m_updates_done;
391  docollide=true;
392  }
393  listremove(proxy,m_stageRoots[proxy->stage]);
394  proxy->m_aabbMin = aabbMin;
395  proxy->m_aabbMax = aabbMax;
396  proxy->stage = m_stageCurrent;
397  listappend(proxy,m_stageRoots[m_stageCurrent]);
398  if(docollide)
399  {
400  m_needcleanup=true;
401  if(!m_deferedcollide)
402  {
403  btDbvtTreeCollider collider(this);
404  m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
405  m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
406  }
407  }
408 }
409 
410 //
412 {
413  collide(dispatcher);
414 #if DBVT_BP_PROFILE
415  if(0==(m_pid%DBVT_BP_PROFILING_RATE))
416  {
417  printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
418  unsigned int total=m_profiling.m_total;
419  if(total<=0) total=1;
420  printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
421  printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
422  printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
423  printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
424  const unsigned long sum=m_profiling.m_ddcollide+
425  m_profiling.m_fdcollide+
426  m_profiling.m_cleanup;
427  printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
428  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));
429  clear(m_profiling);
430  m_clock.reset();
431  }
432 #endif
433 
434  performDeferredRemoval(dispatcher);
435 
436 }
437 
439 {
440 
441  if (m_paircache->hasDeferredRemoval())
442  {
443 
444  btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
445 
446  //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
447  overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
448 
449  int invalidPair = 0;
450 
451 
452  int i;
453 
454  btBroadphasePair previousPair;
455  previousPair.m_pProxy0 = 0;
456  previousPair.m_pProxy1 = 0;
457  previousPair.m_algorithm = 0;
458 
459 
460  for (i=0;i<overlappingPairArray.size();i++)
461  {
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  } else
482  {
483  needsRemoval = true;
484  }
485  } else
486  {
487  //remove duplicate
488  needsRemoval = true;
489  //should have no algorithm
490  btAssert(!pair.m_algorithm);
491  }
492 
493  if (needsRemoval)
494  {
495  m_paircache->cleanOverlappingPair(pair,dispatcher);
496 
497  pair.m_pProxy0 = 0;
498  pair.m_pProxy1 = 0;
499  invalidPair++;
500  }
501 
502  }
503 
504  //perform a sort, to sort 'invalid' pairs to the end
505  overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
506  overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
507  }
508 }
509 
510 //
512 {
513  /*printf("---------------------------------------------------------\n");
514  printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
515  printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
516  printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
517  {
518  int i;
519  for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
520  {
521  printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
522  getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
523  }
524  printf("\n");
525  }
526 */
527 
528 
529 
530  SPC(m_profiling.m_total);
531  /* optimize */
532  m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
533  if(m_fixedleft)
534  {
535  const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
536  m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
537  m_fixedleft=btMax<int>(0,m_fixedleft-count);
538  }
539  /* dynamic -> fixed set */
540  m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
541  btDbvtProxy* current=m_stageRoots[m_stageCurrent];
542  if(current)
543  {
544 #if DBVT_BP_ACCURATESLEEPING
545  btDbvtTreeCollider collider(this);
546 #endif
547  do {
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);
559  current->leaf = m_sets[1].insert(curAabb,current);
560  current->stage = STAGECOUNT;
561  current = next;
562  } while(current);
563  m_fixedleft=m_sets[1].m_leaves;
564  m_needcleanup=true;
565  }
566  /* collide dynamics */
567  {
568  btDbvtTreeCollider collider(this);
569  if(m_deferedcollide)
570  {
571  SPC(m_profiling.m_fdcollide);
572  m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
573  }
574  if(m_deferedcollide)
575  {
576  SPC(m_profiling.m_ddcollide);
577  m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
578  }
579  }
580  /* clean up */
581  if(m_needcleanup)
582  {
583  SPC(m_profiling.m_cleanup);
584  btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
585  if(pairs.size()>0)
586  {
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()];
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;--i;
602  }
603  }
604  if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
605  }
606  }
607  ++m_pid;
608  m_newpairs=1;
609  m_needcleanup=false;
610  if(m_updates_call>0)
611  { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
612  else
613  { m_updates_ratio=0; }
614  m_updates_done/=2;
615  m_updates_call/=2;
616 }
617 
618 //
620 {
621  m_sets[0].optimizeTopDown();
622  m_sets[1].optimizeTopDown();
623 }
624 
625 //
627 {
628  return(m_paircache);
629 }
630 
631 //
633 {
634  return(m_paircache);
635 }
636 
637 //
639 {
640 
642 
643  if(!m_sets[0].empty())
644  if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
645  m_sets[1].m_root->volume,bounds);
646  else
647  bounds=m_sets[0].m_root->volume;
648  else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
649  else
651  aabbMin=bounds.Mins();
652  aabbMax=bounds.Maxs();
653 }
654 
656 {
657 
658  int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
659  if (!totalObjects)
660  {
661  //reset internal dynamic tree data structures
662  m_sets[0].clear();
663  m_sets[1].clear();
664 
665  m_deferedcollide = false;
666  m_needcleanup = true;
667  m_stageCurrent = 0;
668  m_fixedleft = 0;
669  m_fupdates = 1;
670  m_dupdates = 0;
671  m_cupdates = 10;
672  m_newpairs = 1;
673  m_updates_call = 0;
674  m_updates_done = 0;
675  m_updates_ratio = 0;
676 
677  m_gid = 0;
678  m_pid = 0;
679  m_cid = 0;
680  for(int i=0;i<=STAGECOUNT;++i)
681  {
682  m_stageRoots[i]=0;
683  }
684  }
685 }
686 
687 //
689 {}
690 
691 //
692 #if DBVT_BP_ENABLE_BENCHMARK
693 
694 struct btBroadphaseBenchmark
695 {
696  struct Experiment
697  {
698  const char* name;
699  int object_count;
700  int update_count;
701  int spawn_count;
702  int iterations;
703  btScalar speed;
704  btScalar amplitude;
705  };
706  struct Object
707  {
708  btVector3 center;
709  btVector3 extents;
710  btBroadphaseProxy* proxy;
711  btScalar time;
712  void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
713  {
714  time += speed;
715  center[0] = btCos(time*(btScalar)2.17)*amplitude+
716  btSin(time)*amplitude/2;
717  center[1] = btCos(time*(btScalar)1.38)*amplitude+
718  btSin(time)*amplitude;
719  center[2] = btSin(time*(btScalar)0.777)*amplitude;
720  pbi->setAabb(proxy,center-extents,center+extents,0);
721  }
722  };
723  static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
724  static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
725  static void OutputTime(const char* name,btClock& c,unsigned count=0)
726  {
727  const unsigned long us=c.getTimeMicroseconds();
728  const unsigned long ms=(us+500)/1000;
729  const btScalar sec=us/(btScalar)(1000*1000);
730  if(count>0)
731  printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
732  else
733  printf("%s : %u us (%u ms)\r\n",name,us,ms);
734  }
735 };
736 
738 {
739  static const btBroadphaseBenchmark::Experiment experiments[]=
740  {
741  {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
742  /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
743  {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
744  };
745  static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
747  btClock wallclock;
748  /* Begin */
749  for(int iexp=0;iexp<nexperiments;++iexp)
750  {
751  const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
752  const int object_count=experiment.object_count;
753  const int update_count=(object_count*experiment.update_count)/100;
754  const int spawn_count=(object_count*experiment.spawn_count)/100;
755  const btScalar speed=experiment.speed;
756  const btScalar amplitude=experiment.amplitude;
757  printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
758  printf("\tObjects: %u\r\n",object_count);
759  printf("\tUpdate: %u\r\n",update_count);
760  printf("\tSpawn: %u\r\n",spawn_count);
761  printf("\tSpeed: %f\r\n",speed);
762  printf("\tAmplitude: %f\r\n",amplitude);
763  srand(180673);
764  /* Create objects */
765  wallclock.reset();
766  objects.reserve(object_count);
767  for(int i=0;i<object_count;++i)
768  {
769  btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
770  po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
771  po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
772  po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
773  po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
774  po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
775  po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
776  po->time=btBroadphaseBenchmark::UnitRand()*2000;
777  po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
778  objects.push_back(po);
779  }
780  btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
781  /* First update */
782  wallclock.reset();
783  for(int i=0;i<objects.size();++i)
784  {
785  objects[i]->update(speed,amplitude,pbi);
786  }
787  btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
788  /* Updates */
789  wallclock.reset();
790  for(int i=0;i<experiment.iterations;++i)
791  {
792  for(int j=0;j<update_count;++j)
793  {
794  objects[j]->update(speed,amplitude,pbi);
795  }
797  }
798  btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
799  /* Clean up */
800  wallclock.reset();
801  for(int i=0;i<objects.size();++i)
802  {
803  pbi->destroyProxy(objects[i]->proxy,0);
804  delete objects[i];
805  }
806  objects.resize(0);
807  btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
808  }
809 
810 }
811 #else
813 {}
814 #endif
815 
816 #if DBVT_BP_PROFILE
817 #undef SPC
818 #endif
819 
virtual void aabbTest(const btVector3 &aabbMin, const btVector3 &aabbMax, btBroadphaseAabbCallback &callback)
static T sum(const btAlignedObjectArray< T > &items)
DBVT_INLINE void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
Definition: btDbvt.h:667
void push_back(const T &_Val)
static void benchmark(btBroadphaseInterface *)
btBroadphaseRayCallback & m_rayCallback
static void listappend(T *item, T *&list)
virtual void resetPool(btDispatcher *dispatcher)
reset broadphase internal structures, to ensure determinism/reproducability
btScalar btSin(btScalar x)
Definition: btScalar.h:477
void * data
Definition: btDbvt.h:187
btOverlappingPairCache * m_paircache
void Process(const btDbvtNode *na, const btDbvtNode *nb)
#define btAssert(x)
Definition: btScalar.h:131
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
Definition: btQuickprof.h:24
The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees...
void reset()
Resets the initial reference time.
void performDeferredRemoval(btDispatcher *dispatcher)
void collide(btDispatcher *dispatcher)
btDbvtNode * leaf
btDbvtProxy * links[2]
const unsigned int BT_MAX_THREAD_COUNT
Definition: btThreads.h:33
The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
void Process(const btDbvtNode *leaf)
btDbvtBroadphase(btOverlappingPairCache *paircache=0)
void Process(const btDbvtNode *n)
int size() const
return the number of elements in the array
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)
#define SPC(_value_)
virtual btOverlappingPairCache * getOverlappingPairCache()
void btSwap(T &a, T &b)
Definition: btScalar.h:621
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:425
virtual void destroyProxy(btBroadphaseProxy *proxy, btDispatcher *dispatcher)
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))
static void listremove(T *item, T *&list)
#define btAlignedFree(ptr)
virtual btBroadphaseProxy * createProxy(const btVector3 &aabbMin, const btVector3 &aabbMax, int shapeType, void *userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher *dispatcher)=0
unsigned long long int getTimeMicroseconds()
Returns the time in us since the last call to reset or since the Clock was created.
static int listcount(T *root)
virtual void printStats()
static btDbvtAabbMm FromCR(const btVector3 &c, btScalar r)
Definition: btDbvt.h:419
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs...
The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:82
virtual bool process(const btBroadphaseProxy *proxy)=0
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:137
btBroadphaseAabbCallback & m_aabbCallback
btBroadphaseProxy * m_pProxy0
void setAabbForceUpdate(btBroadphaseProxy *absproxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *)
this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
btDbvtTreeCollider(btDbvtBroadphase *p)
BroadphaseRayTester(btBroadphaseRayCallback &orgCallback)
virtual btBroadphasePair * addOverlappingPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1)=0
static void clear(T &value)
virtual void getBroadphaseAabb(btVector3 &aabbMin, btVector3 &aabbMax) const
getAabb returns the axis aligned bounding box in the &#39;global&#39; coordinate frame will add some transfor...
void resize(int newsize, const T &fillData=T())
btDbvtVolume volume
Definition: btDbvt.h:180
btVector3 m_rayDirectionInverse
added some cached data to accelerate ray-AABB tests
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:534
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)=0
#define btAlignedAlloc(size, alignment)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:284
virtual void calculateOverlappingPairs(btDispatcher *dispatcher)
calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during th...
unsigned int btGetCurrentThreadIndex()
Definition: btThreads.cpp:304
virtual void getAabb(btBroadphaseProxy *proxy, btVector3 &aabbMin, btVector3 &aabbMax) const
btScalar gDbvtMargin
btDbvtBroadphase implementation by Nathanael Presson
btDbvtBroadphase * pbp
DBVT_INLINE const btVector3 & Mins() const
Definition: btDbvt.h:136
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:23
DBVT_PREFIX void collideTV(const btDbvtNode *root, const btDbvtVolume &volume, DBVT_IPOLICY) const
Definition: btDbvt.h:935
BroadphaseAabbTester(btBroadphaseAabbCallback &orgCallback)
virtual void destroyProxy(btBroadphaseProxy *proxy, btDispatcher *dispatcher)=0
btBroadphaseProxy * createProxy(const btVector3 &aabbMin, const btVector3 &aabbMax, int shapeType, void *userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher *dispatcher)
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman...
virtual void calculateOverlappingPairs(btDispatcher *dispatcher)=0
calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during th...
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
void quickSort(const L &CompareFunc)
btScalar btCos(btScalar x)
Definition: btScalar.h:476
DBVT_INLINE bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:690
void Process(const btDbvtNode *leaf)
The btBroadphasePair class contains a pair of aabb-overlapping objects.