Bullet Collision Detection & Physics Library
btDbvt.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 */
16 
17 #include "btDbvt.h"
18 
19 //
22 
23 //
25 {
27  void Process(const btDbvtNode* n) { nodes.push_back(n); }
28 };
29 
30 //
31 static DBVT_INLINE int indexof(const btDbvtNode* node)
32 {
33  return (node->parent->childs[1] == node);
34 }
35 
36 //
38  const btDbvtVolume& b)
39 {
40 #if (DBVT_MERGE_IMPL == DBVT_IMPL_SSE)
41  ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
42  btDbvtVolume* ptr = (btDbvtVolume*)locals;
43  btDbvtVolume& res = *ptr;
44 #else
45  btDbvtVolume res;
46 #endif
47  Merge(a, b, res);
48  return (res);
49 }
50 
51 // volume+edge lengths
53 {
54  const btVector3 edges = a.Lengths();
55  return (edges.x() * edges.y() * edges.z() +
56  edges.x() + edges.y() + edges.z());
57 }
58 
59 //
60 static void getmaxdepth(const btDbvtNode* node, int depth, int& maxdepth)
61 {
62  if (node->isinternal())
63  {
64  getmaxdepth(node->childs[0], depth + 1, maxdepth);
65  getmaxdepth(node->childs[1], depth + 1, maxdepth);
66  }
67  else
68  maxdepth = btMax(maxdepth, depth);
69 }
70 
71 //
72 static DBVT_INLINE void deletenode(btDbvt* pdbvt,
73  btDbvtNode* node)
74 {
75  btAlignedFree(pdbvt->m_free);
76  pdbvt->m_free = node;
77 }
78 
79 //
80 static void recursedeletenode(btDbvt* pdbvt,
81  btDbvtNode* node)
82 {
83  if (!node->isleaf())
84  {
85  recursedeletenode(pdbvt, node->childs[0]);
86  recursedeletenode(pdbvt, node->childs[1]);
87  }
88  if (node == pdbvt->m_root) pdbvt->m_root = 0;
89  deletenode(pdbvt, node);
90 }
91 
92 //
94  btDbvtNode* parent,
95  void* data)
96 {
97  btDbvtNode* node;
98  if (pdbvt->m_free)
99  {
100  node = pdbvt->m_free;
101  pdbvt->m_free = 0;
102  }
103  else
104  {
105  node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
106  }
107  node->parent = parent;
108  node->data = data;
109  node->childs[1] = 0;
110  return (node);
111 }
112 
113 //
115  btDbvtNode* parent,
116  const btDbvtVolume& volume,
117  void* data)
118 {
119  btDbvtNode* node = createnode(pdbvt, parent, data);
120  node->volume = volume;
121  return (node);
122 }
123 
124 //
126  btDbvtNode* parent,
127  const btDbvtVolume& volume0,
128  const btDbvtVolume& volume1,
129  void* data)
130 {
131  btDbvtNode* node = createnode(pdbvt, parent, data);
132  Merge(volume0, volume1, node->volume);
133  return (node);
134 }
135 
136 //
137 static void insertleaf(btDbvt* pdbvt,
138  btDbvtNode* root,
139  btDbvtNode* leaf)
140 {
141  if (!pdbvt->m_root)
142  {
143  pdbvt->m_root = leaf;
144  leaf->parent = 0;
145  }
146  else
147  {
148  if (!root->isleaf())
149  {
150  do
151  {
152  root = root->childs[Select(leaf->volume,
153  root->childs[0]->volume,
154  root->childs[1]->volume)];
155  } while (!root->isleaf());
156  }
157  btDbvtNode* prev = root->parent;
158  btDbvtNode* node = createnode(pdbvt, prev, leaf->volume, root->volume, 0);
159  if (prev)
160  {
161  prev->childs[indexof(root)] = node;
162  node->childs[0] = root;
163  root->parent = node;
164  node->childs[1] = leaf;
165  leaf->parent = node;
166  do
167  {
168  if (!prev->volume.Contain(node->volume))
169  Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
170  else
171  break;
172  node = prev;
173  } while (0 != (prev = node->parent));
174  }
175  else
176  {
177  node->childs[0] = root;
178  root->parent = node;
179  node->childs[1] = leaf;
180  leaf->parent = node;
181  pdbvt->m_root = node;
182  }
183  }
184 }
185 
186 //
187 static btDbvtNode* removeleaf(btDbvt* pdbvt,
188  btDbvtNode* leaf)
189 {
190  if (leaf == pdbvt->m_root)
191  {
192  pdbvt->m_root = 0;
193  return (0);
194  }
195  else
196  {
197  btDbvtNode* parent = leaf->parent;
198  btDbvtNode* prev = parent->parent;
199  btDbvtNode* sibling = parent->childs[1 - indexof(leaf)];
200  if (prev)
201  {
202  prev->childs[indexof(parent)] = sibling;
203  sibling->parent = prev;
204  deletenode(pdbvt, parent);
205  while (prev)
206  {
207  const btDbvtVolume pb = prev->volume;
208  Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
209  if (NotEqual(pb, prev->volume))
210  {
211  prev = prev->parent;
212  }
213  else
214  break;
215  }
216  return (prev ? prev : pdbvt->m_root);
217  }
218  else
219  {
220  pdbvt->m_root = sibling;
221  sibling->parent = 0;
222  deletenode(pdbvt, parent);
223  return (pdbvt->m_root);
224  }
225  }
226 }
227 
228 //
229 static void fetchleaves(btDbvt* pdbvt,
230  btDbvtNode* root,
231  tNodeArray& leaves,
232  int depth = -1)
233 {
234  if (root->isinternal() && depth)
235  {
236  fetchleaves(pdbvt, root->childs[0], leaves, depth - 1);
237  fetchleaves(pdbvt, root->childs[1], leaves, depth - 1);
238  deletenode(pdbvt, root);
239  }
240  else
241  {
242  leaves.push_back(root);
243  }
244 }
245 
246 //
247 static bool leftOfAxis(const btDbvtNode* node,
248  const btVector3& org,
249  const btVector3& axis)
250 {
251  return btDot(axis, node->volume.Center() - org) <= 0;
252 }
253 
254 // Partitions leaves such that leaves[0, n) are on the
255 // left of axis, and leaves[n, count) are on the right
256 // of axis. returns N.
257 static int split(btDbvtNode** leaves,
258  int count,
259  const btVector3& org,
260  const btVector3& axis)
261 {
262  int begin = 0;
263  int end = count;
264  for (;;)
265  {
266  while (begin != end && leftOfAxis(leaves[begin], org, axis))
267  {
268  ++begin;
269  }
270 
271  if (begin == end)
272  {
273  break;
274  }
275 
276  while (begin != end && !leftOfAxis(leaves[end - 1], org, axis))
277  {
278  --end;
279  }
280 
281  if (begin == end)
282  {
283  break;
284  }
285 
286  // swap out of place nodes
287  --end;
288  btDbvtNode* temp = leaves[begin];
289  leaves[begin] = leaves[end];
290  leaves[end] = temp;
291  ++begin;
292  }
293 
294  return begin;
295 }
296 
297 //
299  int count)
300 {
301 #if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
302  ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
303  btDbvtVolume* ptr = (btDbvtVolume*)locals;
304  btDbvtVolume& volume = *ptr;
305  volume = leaves[0]->volume;
306 #else
307  btDbvtVolume volume = leaves[0]->volume;
308 #endif
309  for (int i = 1, ni = count; i < ni; ++i)
310  {
311  Merge(volume, leaves[i]->volume, volume);
312  }
313  return (volume);
314 }
315 
316 //
317 static void bottomup(btDbvt* pdbvt,
318  btDbvtNode** leaves,
319  int count)
320 {
321  while (count > 1)
322  {
323  btScalar minsize = SIMD_INFINITY;
324  int minidx[2] = {-1, -1};
325  for (int i = 0; i < count; ++i)
326  {
327  for (int j = i + 1; j < count; ++j)
328  {
329  const btScalar sz = size(merge(leaves[i]->volume, leaves[j]->volume));
330  if (sz < minsize)
331  {
332  minsize = sz;
333  minidx[0] = i;
334  minidx[1] = j;
335  }
336  }
337  }
338  btDbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
339  btDbvtNode* p = createnode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
340  p->childs[0] = n[0];
341  p->childs[1] = n[1];
342  n[0]->parent = p;
343  n[1]->parent = p;
344  leaves[minidx[0]] = p;
345  leaves[minidx[1]] = leaves[count - 1];
346  --count;
347  }
348 }
349 
350 //
351 static btDbvtNode* topdown(btDbvt* pdbvt,
352  btDbvtNode** leaves,
353  int count,
354  int bu_treshold)
355 {
356  static const btVector3 axis[] = {btVector3(1, 0, 0),
357  btVector3(0, 1, 0),
358  btVector3(0, 0, 1)};
359  btAssert(bu_treshold > 2);
360  if (count > 1)
361  {
362  if (count > bu_treshold)
363  {
364  const btDbvtVolume vol = bounds(leaves, count);
365  const btVector3 org = vol.Center();
366  int partition;
367  int bestaxis = -1;
368  int bestmidp = count;
369  int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
370  int i;
371  for (i = 0; i < count; ++i)
372  {
373  const btVector3 x = leaves[i]->volume.Center() - org;
374  for (int j = 0; j < 3; ++j)
375  {
376  ++splitcount[j][btDot(x, axis[j]) > 0 ? 1 : 0];
377  }
378  }
379  for (i = 0; i < 3; ++i)
380  {
381  if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
382  {
383  const int midp = (int)btFabs(btScalar(splitcount[i][0] - splitcount[i][1]));
384  if (midp < bestmidp)
385  {
386  bestaxis = i;
387  bestmidp = midp;
388  }
389  }
390  }
391  if (bestaxis >= 0)
392  {
393  partition = split(leaves, count, org, axis[bestaxis]);
394  btAssert(partition != 0 && partition != count);
395  }
396  else
397  {
398  partition = count / 2 + 1;
399  }
400  btDbvtNode* node = createnode(pdbvt, 0, vol, 0);
401  node->childs[0] = topdown(pdbvt, &leaves[0], partition, bu_treshold);
402  node->childs[1] = topdown(pdbvt, &leaves[partition], count - partition, bu_treshold);
403  node->childs[0]->parent = node;
404  node->childs[1]->parent = node;
405  return (node);
406  }
407  else
408  {
409  bottomup(pdbvt, leaves, count);
410  return (leaves[0]);
411  }
412  }
413  return (leaves[0]);
414 }
415 
416 //
418 {
419  btDbvtNode* p = n->parent;
420  btAssert(n->isinternal());
421  if (p > n)
422  {
423  const int i = indexof(n);
424  const int j = 1 - i;
425  btDbvtNode* s = p->childs[j];
426  btDbvtNode* q = p->parent;
427  btAssert(n == p->childs[i]);
428  if (q)
429  q->childs[indexof(p)] = n;
430  else
431  r = n;
432  s->parent = n;
433  p->parent = n;
434  n->parent = q;
435  p->childs[0] = n->childs[0];
436  p->childs[1] = n->childs[1];
437  n->childs[0]->parent = p;
438  n->childs[1]->parent = p;
439  n->childs[i] = p;
440  n->childs[j] = s;
441  btSwap(p->volume, n->volume);
442  return (p);
443  }
444  return (n);
445 }
446 
447 #if 0
448 static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
449 {
450  while(n&&(count--)) n=n->parent;
451  return(n);
452 }
453 #endif
454 
455 //
456 // Api
457 //
458 
459 //
461 {
462  m_root = 0;
463  m_free = 0;
464  m_lkhd = -1;
465  m_leaves = 0;
466  m_opath = 0;
467 }
468 
469 //
471 {
472  clear();
473 }
474 
475 //
477 {
478  if (m_root)
479  recursedeletenode(this, m_root);
481  m_free = 0;
482  m_lkhd = -1;
483  m_stkStack.clear();
484  m_opath = 0;
485 }
486 
487 //
489 {
490  if (m_root)
491  {
492  tNodeArray leaves;
493  leaves.reserve(m_leaves);
494  fetchleaves(this, m_root, leaves);
495  bottomup(this, &leaves[0], leaves.size());
496  m_root = leaves[0];
497  }
498 }
499 
500 //
501 void btDbvt::optimizeTopDown(int bu_treshold)
502 {
503  if (m_root)
504  {
505  tNodeArray leaves;
506  leaves.reserve(m_leaves);
507  fetchleaves(this, m_root, leaves);
508  m_root = topdown(this, &leaves[0], leaves.size(), bu_treshold);
509  }
510 }
511 
512 //
514 {
515  if (passes < 0) passes = m_leaves;
516  if (m_root && (passes > 0))
517  {
518  do
519  {
520  btDbvtNode* node = m_root;
521  unsigned bit = 0;
522  while (node->isinternal())
523  {
524  node = sort(node, m_root)->childs[(m_opath >> bit) & 1];
525  bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
526  }
527  update(node);
528  ++m_opath;
529  } while (--passes);
530  }
531 }
532 
533 //
534 btDbvtNode* btDbvt::insert(const btDbvtVolume& volume, void* data)
535 {
536  btDbvtNode* leaf = createnode(this, 0, volume, data);
537  insertleaf(this, m_root, leaf);
538  ++m_leaves;
539  return (leaf);
540 }
541 
542 //
543 void btDbvt::update(btDbvtNode* leaf, int lookahead)
544 {
545  btDbvtNode* root = removeleaf(this, leaf);
546  if (root)
547  {
548  if (lookahead >= 0)
549  {
550  for (int i = 0; (i < lookahead) && root->parent; ++i)
551  {
552  root = root->parent;
553  }
554  }
555  else
556  root = m_root;
557  }
558  insertleaf(this, root, leaf);
559 }
560 
561 //
563 {
564  btDbvtNode* root = removeleaf(this, leaf);
565  if (root)
566  {
567  if (m_lkhd >= 0)
568  {
569  for (int i = 0; (i < m_lkhd) && root->parent; ++i)
570  {
571  root = root->parent;
572  }
573  }
574  else
575  root = m_root;
576  }
577  leaf->volume = volume;
578  insertleaf(this, root, leaf);
579 }
580 
581 //
582 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin)
583 {
584  if (leaf->volume.Contain(volume)) return (false);
585  volume.Expand(btVector3(margin, margin, margin));
586  volume.SignedExpand(velocity);
587  update(leaf, volume);
588  return (true);
589 }
590 
591 //
592 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity)
593 {
594  if (leaf->volume.Contain(volume)) return (false);
595  volume.SignedExpand(velocity);
596  update(leaf, volume);
597  return (true);
598 }
599 
600 //
601 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin)
602 {
603  if (leaf->volume.Contain(volume)) return (false);
604  volume.Expand(btVector3(margin, margin, margin));
605  update(leaf, volume);
606  return (true);
607 }
608 
609 //
611 {
612  removeleaf(this, leaf);
613  deletenode(this, leaf);
614  --m_leaves;
615 }
616 
617 //
618 void btDbvt::write(IWriter* iwriter) const
619 {
620  btDbvtNodeEnumerator nodes;
621  nodes.nodes.reserve(m_leaves * 2);
622  enumNodes(m_root, nodes);
623  iwriter->Prepare(m_root, nodes.nodes.size());
624  for (int i = 0; i < nodes.nodes.size(); ++i)
625  {
626  const btDbvtNode* n = nodes.nodes[i];
627  int p = -1;
628  if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
629  if (n->isinternal())
630  {
631  const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
632  const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
633  iwriter->WriteNode(n, i, p, c0, c1);
634  }
635  else
636  {
637  iwriter->WriteLeaf(n, i, p);
638  }
639  }
640 }
641 
642 //
643 void btDbvt::clone(btDbvt& dest, IClone* iclone) const
644 {
645  dest.clear();
646  if (m_root != 0)
647  {
649  stack.reserve(m_leaves);
650  stack.push_back(sStkCLN(m_root, 0));
651  do
652  {
653  const int i = stack.size() - 1;
654  const sStkCLN e = stack[i];
655  btDbvtNode* n = createnode(&dest, e.parent, e.node->volume, e.node->data);
656  stack.pop_back();
657  if (e.parent != 0)
658  e.parent->childs[i & 1] = n;
659  else
660  dest.m_root = n;
661  if (e.node->isinternal())
662  {
663  stack.push_back(sStkCLN(e.node->childs[0], n));
664  stack.push_back(sStkCLN(e.node->childs[1], n));
665  }
666  else
667  {
668  iclone->CloneLeaf(n);
669  }
670  } while (stack.size() > 0);
671  }
672 }
673 
674 //
675 int btDbvt::maxdepth(const btDbvtNode* node)
676 {
677  int depth = 0;
678  if (node) getmaxdepth(node, 1, depth);
679  return (depth);
680 }
681 
682 //
684 {
685  if (node->isinternal())
686  return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
687  else
688  return (1);
689 }
690 
691 //
693 {
694  if (node->isinternal())
695  {
696  extractLeaves(node->childs[0], leaves);
697  extractLeaves(node->childs[1], leaves);
698  }
699  else
700  {
701  leaves.push_back(node);
702  }
703 }
704 
705 //
706 #if DBVT_ENABLE_BENCHMARK
707 
708 #include <stdio.h>
709 #include <stdlib.h>
710 #include "LinearMath/btQuickProf.h"
711 
712 /*
713 q6600,2.4ghz
714 
715 /Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
716 /GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
717 /Fo"..\..\out\release8\build\libbulletcollision\\"
718 /Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
719 /W3 /nologo /c /Wp64 /Zi /errorReport:prompt
720 
721 Benchmarking dbvt...
722 World scale: 100.000000
723 Extents base: 1.000000
724 Extents range: 4.000000
725 Leaves: 8192
726 sizeof(btDbvtVolume): 32 bytes
727 sizeof(btDbvtNode): 44 bytes
728 [1] btDbvtVolume intersections: 3499 ms (-1%)
729 [2] btDbvtVolume merges: 1934 ms (0%)
730 [3] btDbvt::collideTT: 5485 ms (-21%)
731 [4] btDbvt::collideTT self: 2814 ms (-20%)
732 [5] btDbvt::collideTT xform: 7379 ms (-1%)
733 [6] btDbvt::collideTT xform,self: 7270 ms (-2%)
734 [7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
735 [8] insert/remove: 2093 ms (0%),(1001983 ir/s)
736 [9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
737 [10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
738 [11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
739 [12] btDbvtVolume notequal: 3659 ms (0%)
740 [13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
741 [14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
742 [15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
743 [16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
744 [17] btDbvtVolume select: 3419 ms (0%)
745 */
746 
747 struct btDbvtBenchmark
748 {
749  struct NilPolicy : btDbvt::ICollide
750  {
751  NilPolicy() : m_pcount(0), m_depth(-SIMD_INFINITY), m_checksort(true) {}
752  void Process(const btDbvtNode*, const btDbvtNode*) { ++m_pcount; }
753  void Process(const btDbvtNode*) { ++m_pcount; }
754  void Process(const btDbvtNode*, btScalar depth)
755  {
756  ++m_pcount;
757  if (m_checksort)
758  {
759  if (depth >= m_depth)
760  m_depth = depth;
761  else
762  printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
763  }
764  }
765  int m_pcount;
766  btScalar m_depth;
767  bool m_checksort;
768  };
769  struct P14 : btDbvt::ICollide
770  {
771  struct Node
772  {
773  const btDbvtNode* leaf;
774  btScalar depth;
775  };
776  void Process(const btDbvtNode* leaf, btScalar depth)
777  {
778  Node n;
779  n.leaf = leaf;
780  n.depth = depth;
781  }
782  static int sortfnc(const Node& a, const Node& b)
783  {
784  if (a.depth < b.depth) return (+1);
785  if (a.depth > b.depth) return (-1);
786  return (0);
787  }
789  };
790  struct P15 : btDbvt::ICollide
791  {
792  struct Node
793  {
794  const btDbvtNode* leaf;
795  btScalar depth;
796  };
797  void Process(const btDbvtNode* leaf)
798  {
799  Node n;
800  n.leaf = leaf;
801  n.depth = dot(leaf->volume.Center(), m_axis);
802  }
803  static int sortfnc(const Node& a, const Node& b)
804  {
805  if (a.depth < b.depth) return (+1);
806  if (a.depth > b.depth) return (-1);
807  return (0);
808  }
810  btVector3 m_axis;
811  };
812  static btScalar RandUnit()
813  {
814  return (rand() / (btScalar)RAND_MAX);
815  }
816  static btVector3 RandVector3()
817  {
818  return (btVector3(RandUnit(), RandUnit(), RandUnit()));
819  }
820  static btVector3 RandVector3(btScalar cs)
821  {
822  return (RandVector3() * cs - btVector3(cs, cs, cs) / 2);
823  }
824  static btDbvtVolume RandVolume(btScalar cs, btScalar eb, btScalar es)
825  {
826  return (btDbvtVolume::FromCE(RandVector3(cs), btVector3(eb, eb, eb) + RandVector3() * es));
827  }
828  static btTransform RandTransform(btScalar cs)
829  {
830  btTransform t;
831  t.setOrigin(RandVector3(cs));
832  t.setRotation(btQuaternion(RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2).normalized());
833  return (t);
834  }
835  static void RandTree(btScalar cs, btScalar eb, btScalar es, int leaves, btDbvt& dbvt)
836  {
837  dbvt.clear();
838  for (int i = 0; i < leaves; ++i)
839  {
840  dbvt.insert(RandVolume(cs, eb, es), 0);
841  }
842  }
843 };
844 
845 void btDbvt::benchmark()
846 {
847  static const btScalar cfgVolumeCenterScale = 100;
848  static const btScalar cfgVolumeExentsBase = 1;
849  static const btScalar cfgVolumeExentsScale = 4;
850  static const int cfgLeaves = 8192;
851  static const bool cfgEnable = true;
852 
853  //[1] btDbvtVolume intersections
854  bool cfgBenchmark1_Enable = cfgEnable;
855  static const int cfgBenchmark1_Iterations = 8;
856  static const int cfgBenchmark1_Reference = 3499;
857  //[2] btDbvtVolume merges
858  bool cfgBenchmark2_Enable = cfgEnable;
859  static const int cfgBenchmark2_Iterations = 4;
860  static const int cfgBenchmark2_Reference = 1945;
861  //[3] btDbvt::collideTT
862  bool cfgBenchmark3_Enable = cfgEnable;
863  static const int cfgBenchmark3_Iterations = 512;
864  static const int cfgBenchmark3_Reference = 5485;
865  //[4] btDbvt::collideTT self
866  bool cfgBenchmark4_Enable = cfgEnable;
867  static const int cfgBenchmark4_Iterations = 512;
868  static const int cfgBenchmark4_Reference = 2814;
869  //[5] btDbvt::collideTT xform
870  bool cfgBenchmark5_Enable = cfgEnable;
871  static const int cfgBenchmark5_Iterations = 512;
872  static const btScalar cfgBenchmark5_OffsetScale = 2;
873  static const int cfgBenchmark5_Reference = 7379;
874  //[6] btDbvt::collideTT xform,self
875  bool cfgBenchmark6_Enable = cfgEnable;
876  static const int cfgBenchmark6_Iterations = 512;
877  static const btScalar cfgBenchmark6_OffsetScale = 2;
878  static const int cfgBenchmark6_Reference = 7270;
879  //[7] btDbvt::rayTest
880  bool cfgBenchmark7_Enable = cfgEnable;
881  static const int cfgBenchmark7_Passes = 32;
882  static const int cfgBenchmark7_Iterations = 65536;
883  static const int cfgBenchmark7_Reference = 6307;
884  //[8] insert/remove
885  bool cfgBenchmark8_Enable = cfgEnable;
886  static const int cfgBenchmark8_Passes = 32;
887  static const int cfgBenchmark8_Iterations = 65536;
888  static const int cfgBenchmark8_Reference = 2105;
889  //[9] updates (teleport)
890  bool cfgBenchmark9_Enable = cfgEnable;
891  static const int cfgBenchmark9_Passes = 32;
892  static const int cfgBenchmark9_Iterations = 65536;
893  static const int cfgBenchmark9_Reference = 1879;
894  //[10] updates (jitter)
895  bool cfgBenchmark10_Enable = cfgEnable;
896  static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
897  static const int cfgBenchmark10_Passes = 32;
898  static const int cfgBenchmark10_Iterations = 65536;
899  static const int cfgBenchmark10_Reference = 1244;
900  //[11] optimize (incremental)
901  bool cfgBenchmark11_Enable = cfgEnable;
902  static const int cfgBenchmark11_Passes = 64;
903  static const int cfgBenchmark11_Iterations = 65536;
904  static const int cfgBenchmark11_Reference = 2510;
905  //[12] btDbvtVolume notequal
906  bool cfgBenchmark12_Enable = cfgEnable;
907  static const int cfgBenchmark12_Iterations = 32;
908  static const int cfgBenchmark12_Reference = 3677;
909  //[13] culling(OCL+fullsort)
910  bool cfgBenchmark13_Enable = cfgEnable;
911  static const int cfgBenchmark13_Iterations = 1024;
912  static const int cfgBenchmark13_Reference = 2231;
913  //[14] culling(OCL+qsort)
914  bool cfgBenchmark14_Enable = cfgEnable;
915  static const int cfgBenchmark14_Iterations = 8192;
916  static const int cfgBenchmark14_Reference = 3500;
917  //[15] culling(KDOP+qsort)
918  bool cfgBenchmark15_Enable = cfgEnable;
919  static const int cfgBenchmark15_Iterations = 8192;
920  static const int cfgBenchmark15_Reference = 1151;
921  //[16] insert/remove batch
922  bool cfgBenchmark16_Enable = cfgEnable;
923  static const int cfgBenchmark16_BatchCount = 256;
924  static const int cfgBenchmark16_Passes = 16384;
925  static const int cfgBenchmark16_Reference = 5138;
926  //[17] select
927  bool cfgBenchmark17_Enable = cfgEnable;
928  static const int cfgBenchmark17_Iterations = 4;
929  static const int cfgBenchmark17_Reference = 3390;
930 
931  btClock wallclock;
932  printf("Benchmarking dbvt...\r\n");
933  printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
934  printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
935  printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
936  printf("\tLeaves: %u\r\n", cfgLeaves);
937  printf("\tsizeof(btDbvtVolume): %u bytes\r\n", sizeof(btDbvtVolume));
938  printf("\tsizeof(btDbvtNode): %u bytes\r\n", sizeof(btDbvtNode));
939  if (cfgBenchmark1_Enable)
940  { // Benchmark 1
941  srand(380843);
944  volumes.resize(cfgLeaves);
945  results.resize(cfgLeaves);
946  for (int i = 0; i < cfgLeaves; ++i)
947  {
948  volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
949  }
950  printf("[1] btDbvtVolume intersections: ");
951  wallclock.reset();
952  for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
953  {
954  for (int j = 0; j < cfgLeaves; ++j)
955  {
956  for (int k = 0; k < cfgLeaves; ++k)
957  {
958  results[k] = Intersect(volumes[j], volumes[k]);
959  }
960  }
961  }
962  const int time = (int)wallclock.getTimeMilliseconds();
963  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
964  }
965  if (cfgBenchmark2_Enable)
966  { // Benchmark 2
967  srand(380843);
970  volumes.resize(cfgLeaves);
971  results.resize(cfgLeaves);
972  for (int i = 0; i < cfgLeaves; ++i)
973  {
974  volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
975  }
976  printf("[2] btDbvtVolume merges: ");
977  wallclock.reset();
978  for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
979  {
980  for (int j = 0; j < cfgLeaves; ++j)
981  {
982  for (int k = 0; k < cfgLeaves; ++k)
983  {
984  Merge(volumes[j], volumes[k], results[k]);
985  }
986  }
987  }
988  const int time = (int)wallclock.getTimeMilliseconds();
989  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
990  }
991  if (cfgBenchmark3_Enable)
992  { // Benchmark 3
993  srand(380843);
994  btDbvt dbvt[2];
995  btDbvtBenchmark::NilPolicy policy;
996  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
997  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
998  dbvt[0].optimizeTopDown();
999  dbvt[1].optimizeTopDown();
1000  printf("[3] btDbvt::collideTT: ");
1001  wallclock.reset();
1002  for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
1003  {
1004  btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
1005  }
1006  const int time = (int)wallclock.getTimeMilliseconds();
1007  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
1008  }
1009  if (cfgBenchmark4_Enable)
1010  { // Benchmark 4
1011  srand(380843);
1012  btDbvt dbvt;
1013  btDbvtBenchmark::NilPolicy policy;
1014  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1015  dbvt.optimizeTopDown();
1016  printf("[4] btDbvt::collideTT self: ");
1017  wallclock.reset();
1018  for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
1019  {
1020  btDbvt::collideTT(dbvt.m_root, dbvt.m_root, policy);
1021  }
1022  const int time = (int)wallclock.getTimeMilliseconds();
1023  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
1024  }
1025  if (cfgBenchmark5_Enable)
1026  { // Benchmark 5
1027  srand(380843);
1028  btDbvt dbvt[2];
1030  btDbvtBenchmark::NilPolicy policy;
1031  transforms.resize(cfgBenchmark5_Iterations);
1032  for (int i = 0; i < transforms.size(); ++i)
1033  {
1034  transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
1035  }
1036  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
1037  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
1038  dbvt[0].optimizeTopDown();
1039  dbvt[1].optimizeTopDown();
1040  printf("[5] btDbvt::collideTT xform: ");
1041  wallclock.reset();
1042  for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
1043  {
1044  btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
1045  }
1046  const int time = (int)wallclock.getTimeMilliseconds();
1047  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
1048  }
1049  if (cfgBenchmark6_Enable)
1050  { // Benchmark 6
1051  srand(380843);
1052  btDbvt dbvt;
1054  btDbvtBenchmark::NilPolicy policy;
1055  transforms.resize(cfgBenchmark6_Iterations);
1056  for (int i = 0; i < transforms.size(); ++i)
1057  {
1058  transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
1059  }
1060  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1061  dbvt.optimizeTopDown();
1062  printf("[6] btDbvt::collideTT xform,self: ");
1063  wallclock.reset();
1064  for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
1065  {
1066  btDbvt::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
1067  }
1068  const int time = (int)wallclock.getTimeMilliseconds();
1069  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
1070  }
1071  if (cfgBenchmark7_Enable)
1072  { // Benchmark 7
1073  srand(380843);
1074  btDbvt dbvt;
1077  btDbvtBenchmark::NilPolicy policy;
1078  rayorg.resize(cfgBenchmark7_Iterations);
1079  raydir.resize(cfgBenchmark7_Iterations);
1080  for (int i = 0; i < rayorg.size(); ++i)
1081  {
1082  rayorg[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
1083  raydir[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
1084  }
1085  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1086  dbvt.optimizeTopDown();
1087  printf("[7] btDbvt::rayTest: ");
1088  wallclock.reset();
1089  for (int i = 0; i < cfgBenchmark7_Passes; ++i)
1090  {
1091  for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
1092  {
1093  btDbvt::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
1094  }
1095  }
1096  const int time = (int)wallclock.getTimeMilliseconds();
1097  unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
1098  printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
1099  }
1100  if (cfgBenchmark8_Enable)
1101  { // Benchmark 8
1102  srand(380843);
1103  btDbvt dbvt;
1104  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1105  dbvt.optimizeTopDown();
1106  printf("[8] insert/remove: ");
1107  wallclock.reset();
1108  for (int i = 0; i < cfgBenchmark8_Passes; ++i)
1109  {
1110  for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
1111  {
1112  dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
1113  }
1114  }
1115  const int time = (int)wallclock.getTimeMilliseconds();
1116  const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
1117  printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
1118  }
1119  if (cfgBenchmark9_Enable)
1120  { // Benchmark 9
1121  srand(380843);
1122  btDbvt dbvt;
1124  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1125  dbvt.optimizeTopDown();
1126  dbvt.extractLeaves(dbvt.m_root, leaves);
1127  printf("[9] updates (teleport): ");
1128  wallclock.reset();
1129  for (int i = 0; i < cfgBenchmark9_Passes; ++i)
1130  {
1131  for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
1132  {
1133  dbvt.update(const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]),
1134  btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
1135  }
1136  }
1137  const int time = (int)wallclock.getTimeMilliseconds();
1138  const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
1139  printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
1140  }
1141  if (cfgBenchmark10_Enable)
1142  { // Benchmark 10
1143  srand(380843);
1144  btDbvt dbvt;
1147  vectors.resize(cfgBenchmark10_Iterations);
1148  for (int i = 0; i < vectors.size(); ++i)
1149  {
1150  vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)) * cfgBenchmark10_Scale;
1151  }
1152  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1153  dbvt.optimizeTopDown();
1154  dbvt.extractLeaves(dbvt.m_root, leaves);
1155  printf("[10] updates (jitter): ");
1156  wallclock.reset();
1157 
1158  for (int i = 0; i < cfgBenchmark10_Passes; ++i)
1159  {
1160  for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
1161  {
1162  const btVector3& d = vectors[j];
1163  btDbvtNode* l = const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]);
1164  btDbvtVolume v = btDbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
1165  dbvt.update(l, v);
1166  }
1167  }
1168  const int time = (int)wallclock.getTimeMilliseconds();
1169  const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
1170  printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
1171  }
1172  if (cfgBenchmark11_Enable)
1173  { // Benchmark 11
1174  srand(380843);
1175  btDbvt dbvt;
1176  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1177  dbvt.optimizeTopDown();
1178  printf("[11] optimize (incremental): ");
1179  wallclock.reset();
1180  for (int i = 0; i < cfgBenchmark11_Passes; ++i)
1181  {
1182  dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
1183  }
1184  const int time = (int)wallclock.getTimeMilliseconds();
1185  const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
1186  printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
1187  }
1188  if (cfgBenchmark12_Enable)
1189  { // Benchmark 12
1190  srand(380843);
1193  volumes.resize(cfgLeaves);
1194  results.resize(cfgLeaves);
1195  for (int i = 0; i < cfgLeaves; ++i)
1196  {
1197  volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
1198  }
1199  printf("[12] btDbvtVolume notequal: ");
1200  wallclock.reset();
1201  for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
1202  {
1203  for (int j = 0; j < cfgLeaves; ++j)
1204  {
1205  for (int k = 0; k < cfgLeaves; ++k)
1206  {
1207  results[k] = NotEqual(volumes[j], volumes[k]);
1208  }
1209  }
1210  }
1211  const int time = (int)wallclock.getTimeMilliseconds();
1212  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
1213  }
1214  if (cfgBenchmark13_Enable)
1215  { // Benchmark 13
1216  srand(380843);
1217  btDbvt dbvt;
1219  btDbvtBenchmark::NilPolicy policy;
1220  vectors.resize(cfgBenchmark13_Iterations);
1221  for (int i = 0; i < vectors.size(); ++i)
1222  {
1223  vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1224  }
1225  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1226  dbvt.optimizeTopDown();
1227  printf("[13] culling(OCL+fullsort): ");
1228  wallclock.reset();
1229  for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
1230  {
1231  static const btScalar offset = 0;
1232  policy.m_depth = -SIMD_INFINITY;
1233  dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
1234  }
1235  const int time = (int)wallclock.getTimeMilliseconds();
1236  const int t = cfgBenchmark13_Iterations;
1237  printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
1238  }
1239  if (cfgBenchmark14_Enable)
1240  { // Benchmark 14
1241  srand(380843);
1242  btDbvt dbvt;
1244  btDbvtBenchmark::P14 policy;
1245  vectors.resize(cfgBenchmark14_Iterations);
1246  for (int i = 0; i < vectors.size(); ++i)
1247  {
1248  vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1249  }
1250  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1251  dbvt.optimizeTopDown();
1252  policy.m_nodes.reserve(cfgLeaves);
1253  printf("[14] culling(OCL+qsort): ");
1254  wallclock.reset();
1255  for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
1256  {
1257  static const btScalar offset = 0;
1258  policy.m_nodes.resize(0);
1259  dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
1260  policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
1261  }
1262  const int time = (int)wallclock.getTimeMilliseconds();
1263  const int t = cfgBenchmark14_Iterations;
1264  printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
1265  }
1266  if (cfgBenchmark15_Enable)
1267  { // Benchmark 15
1268  srand(380843);
1269  btDbvt dbvt;
1271  btDbvtBenchmark::P15 policy;
1272  vectors.resize(cfgBenchmark15_Iterations);
1273  for (int i = 0; i < vectors.size(); ++i)
1274  {
1275  vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1276  }
1277  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1278  dbvt.optimizeTopDown();
1279  policy.m_nodes.reserve(cfgLeaves);
1280  printf("[15] culling(KDOP+qsort): ");
1281  wallclock.reset();
1282  for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
1283  {
1284  static const btScalar offset = 0;
1285  policy.m_nodes.resize(0);
1286  policy.m_axis = vectors[i];
1287  dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
1288  policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
1289  }
1290  const int time = (int)wallclock.getTimeMilliseconds();
1291  const int t = cfgBenchmark15_Iterations;
1292  printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
1293  }
1294  if (cfgBenchmark16_Enable)
1295  { // Benchmark 16
1296  srand(380843);
1297  btDbvt dbvt;
1299  btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1300  dbvt.optimizeTopDown();
1301  batch.reserve(cfgBenchmark16_BatchCount);
1302  printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
1303  wallclock.reset();
1304  for (int i = 0; i < cfgBenchmark16_Passes; ++i)
1305  {
1306  for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
1307  {
1308  batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
1309  }
1310  for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
1311  {
1312  dbvt.remove(batch[j]);
1313  }
1314  batch.resize(0);
1315  }
1316  const int time = (int)wallclock.getTimeMilliseconds();
1317  const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
1318  printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
1319  }
1320  if (cfgBenchmark17_Enable)
1321  { // Benchmark 17
1322  srand(380843);
1324  btAlignedObjectArray<int> results;
1325  btAlignedObjectArray<int> indices;
1326  volumes.resize(cfgLeaves);
1327  results.resize(cfgLeaves);
1328  indices.resize(cfgLeaves);
1329  for (int i = 0; i < cfgLeaves; ++i)
1330  {
1331  indices[i] = i;
1332  volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
1333  }
1334  for (int i = 0; i < cfgLeaves; ++i)
1335  {
1336  btSwap(indices[i], indices[rand() % cfgLeaves]);
1337  }
1338  printf("[17] btDbvtVolume select: ");
1339  wallclock.reset();
1340  for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
1341  {
1342  for (int j = 0; j < cfgLeaves; ++j)
1343  {
1344  for (int k = 0; k < cfgLeaves; ++k)
1345  {
1346  const int idx = indices[k];
1347  results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
1348  }
1349  }
1350  }
1351  const int time = (int)wallclock.getTimeMilliseconds();
1352  printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);
1353  }
1354  printf("\r\n\r\n");
1355 }
1356 #endif
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:146
static DBVT_PREFIX void collideKDOP(const btDbvtNode *root, const btVector3 *normals, const btScalar *offsets, int count, DBVT_IPOLICY)
Definition: btDbvt.h:1176
DBVT_INLINE void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
Definition: btDbvt.h:700
void push_back(const T &_Val)
DBVT_INLINE const btVector3 & Mins() const
Definition: btDbvt.h:137
static void benchmark()
Definition: btDbvt.h:294
~btDbvt()
Definition: btDbvt.cpp:470
static DBVT_PREFIX void collideOCL(const btDbvtNode *root, const btVector3 *normals, const btScalar *offsets, const btVector3 &sortaxis, int count, DBVT_IPOLICY, bool fullsort=true)
Definition: btDbvt.h:1236
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
static void fetchleaves(btDbvt *pdbvt, btDbvtNode *root, tNodeArray &leaves, int depth=-1)
Definition: btDbvt.cpp:229
int findLinearSearch(const T &key) const
void * data
Definition: btDbvt.h:188
static bool leftOfAxis(const btDbvtNode *node, const btVector3 &org, const btVector3 &axis)
Definition: btDbvt.cpp:247
static void getmaxdepth(const btDbvtNode *node, int depth, int &maxdepth)
Definition: btDbvt.cpp:60
static void recursedeletenode(btDbvt *pdbvt, btDbvtNode *node)
Definition: btDbvt.cpp:80
static int split(btDbvtNode **leaves, int count, const btVector3 &org, const btVector3 &axis)
Definition: btDbvt.cpp:257
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define btAssert(x)
Definition: btScalar.h:133
The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes ...
Definition: btDbvt.h:198
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:134
btDbvtNode * insert(const btDbvtVolume &box, void *data)
Definition: btDbvt.cpp:534
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
Definition: btQuickprof.h:22
btDbvtNode * m_root
Definition: btDbvt.h:263
virtual void WriteNode(const btDbvtNode *, int index, int parent, int child0, int child1)=0
void reset()
Resets the initial reference time.
DBVT_INLINE btVector3 Lengths() const
Definition: btDbvt.h:135
static DBVT_PREFIX void rayTest(const btDbvtNode *root, const btVector3 &rayFrom, const btVector3 &rayTo, DBVT_IPOLICY)
rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thre...
Definition: btDbvt.h:1102
static btDbvtNode * topdown(btDbvt *pdbvt, btDbvtNode **leaves, int count, int bu_treshold)
Definition: btDbvt.cpp:351
DBVT_INLINE int Select(const btDbvtAabbMm &o, const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:621
tConstNodeArray nodes
Definition: btDbvt.cpp:26
void write(IWriter *iwriter) const
Definition: btDbvt.cpp:618
void Process(const btDbvtNode *n)
Definition: btDbvt.cpp:27
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:138
void update(btDbvtNode *leaf, int lookahead=-1)
Definition: btDbvt.cpp:543
#define SIMD_PI
Definition: btScalar.h:506
const btDbvtNode * node
Definition: btDbvt.h:224
btAlignedObjectArray< const btDbvtNode * > tConstNodeArray
Definition: btDbvt.cpp:21
#define SIMD_INFINITY
Definition: btScalar.h:524
static int countLeaves(const btDbvtNode *node)
Definition: btDbvt.cpp:683
void clear()
Definition: btDbvt.cpp:476
void optimizeIncremental(int passes)
Definition: btDbvt.cpp:513
static DBVT_INLINE btDbvtNode * createnode(btDbvt *pdbvt, btDbvtNode *parent, void *data)
Definition: btDbvt.cpp:93
static btDbvtAabbMm FromCE(const btVector3 &c, const btVector3 &e)
Definition: btDbvt.h:419
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
unsigned m_opath
Definition: btDbvt.h:267
static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume &a, const btDbvtVolume &b)
Definition: btDbvt.cpp:37
btDbvtNode * childs[2]
Definition: btDbvt.h:187
void btSwap(T &a, T &b)
Definition: btScalar.h:623
static int maxdepth(const btDbvtNode *node)
Definition: btDbvt.cpp:675
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:434
static void insertleaf(btDbvt *pdbvt, btDbvtNode *root, btDbvtNode *leaf)
Definition: btDbvt.cpp:137
#define btAlignedFree(ptr)
void setRotation(const btQuaternion &q)
Set the rotational element by btQuaternion.
Definition: btTransform.h:160
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
DBVT_INLINE void Expand(const btVector3 &e)
Definition: btDbvt.h:469
btAlignedObjectArray< sStkNN > m_stkStack
Definition: btDbvt.h:269
int m_lkhd
Definition: btDbvt.h:265
void optimizeTopDown(int bu_treshold=128)
Definition: btDbvt.cpp:501
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:84
int size() const
return the number of elements in the array
unsigned long long int getTimeMilliseconds()
Returns the time in ms since the last call to reset or since the btClock was created.
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:184
virtual void Prepare(const btDbvtNode *root, int numnodes)=0
btDbvt()
Definition: btDbvt.cpp:460
void resize(int newsize, const T &fillData=T())
btDbvtVolume volume
Definition: btDbvt.h:182
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:185
virtual void WriteLeaf(const btDbvtNode *, int index, int parent)=0
static btDbvtNode * removeleaf(btDbvt *pdbvt, btDbvtNode *leaf)
Definition: btDbvt.cpp:187
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
DBVT_INLINE bool Contain(const btDbvtAabbMm &a) const
Definition: btDbvt.h:493
#define DBVT_INLINE
Definition: btDbvt.h:54
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:576
#define btAlignedAlloc(size, alignment)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:298
static DBVT_INLINE int indexof(const btDbvtNode *node)
Definition: btDbvt.cpp:31
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:888
btAlignedObjectArray< btDbvtNode * > tNodeArray
btDbvt implementation by Nathanael Presson
Definition: btDbvt.cpp:20
DBVT_PREFIX void collideTT(const btDbvtNode *root0, const btDbvtNode *root1, DBVT_IPOLICY)
Definition: btDbvt.h:777
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:49
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
static DBVT_INLINE void deletenode(btDbvt *pdbvt, btDbvtNode *node)
Definition: btDbvt.cpp:72
void optimizeBottomUp()
Definition: btDbvt.cpp:488
void clone(btDbvt &dest, IClone *iclone=0) const
Definition: btDbvt.cpp:643
static DBVT_PREFIX void enumNodes(const btDbvtNode *root, DBVT_IPOLICY)
Definition: btDbvt.h:746
DBVT_INLINE void SignedExpand(const btVector3 &e)
Definition: btDbvt.h:476
static DBVT_INLINE btDbvtNode * sort(btDbvtNode *n, btDbvtNode *&r)
Definition: btDbvt.cpp:417
void remove(btDbvtNode *leaf)
Definition: btDbvt.cpp:610
static void bottomup(btDbvt *pdbvt, btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:317
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
btDbvtNode * m_free
Definition: btDbvt.h:264
virtual void CloneLeaf(btDbvtNode *)
Definition: btDbvt.h:252
int m_leaves
Definition: btDbvt.h:266
btDbvtNode * parent
Definition: btDbvt.h:225
static void extractLeaves(const btDbvtNode *node, btAlignedObjectArray< const btDbvtNode *> &leaves)
Definition: btDbvt.cpp:692
DBVT_INLINE bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:729
btDbvtNode * parent
Definition: btDbvt.h:183
btScalar btFabs(btScalar x)
Definition: btScalar.h:477