Bullet Collision Detection & Physics Library: btDbvt.cpp Source File

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 //
20 typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
21 typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
22
23 //
24 struct btDbvtNodeEnumerator : btDbvt::ICollide
25 {
26 tConstNodeArray nodes;
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 //
37 static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume& a,
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
52 static DBVT_INLINE btScalar size(const btDbvtVolume& a)
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 //
93 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
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 //
114 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
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 //
125 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
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 //
298 static btDbvtVolume bounds(btDbvtNode** leaves,
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 //
417 static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n, btDbvtNode*& r)
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 //
460 btDbvt::btDbvt()
461 {
462 m_root = 0;
463 m_free = 0;
464 m_lkhd = -1;
465 m_leaves = 0;
466 m_opath = 0;
467 }
468
469 //
470 btDbvt::~btDbvt()
471 {
472 clear();
473 }
474
475 //
476 void btDbvt::clear()
477 {
478 if (m_root)
479 recursedeletenode(this, m_root);
480 btAlignedFree(m_free);
481 m_free = 0;
482 m_lkhd = -1;
483 m_stkStack.clear();
484 m_opath = 0;
485 }
486
487 //
488 void btDbvt::optimizeBottomUp()
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 //
513 void btDbvt::optimizeIncremental(int passes)
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 //
562 void btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume)
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 //
610 void btDbvt::remove(btDbvtNode* leaf)
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 {
648 btAlignedObjectArray<sStkCLN> stack;
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 //
683 int btDbvt::countLeaves(const btDbvtNode* node)
684 {
685 if (node->isinternal())
686 return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
687 else
688 return (1);
689 }
690
691 //
692 void btDbvt::extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves)
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 }
788 btAlignedObjectArray<Node> m_nodes;
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 }
809 btAlignedObjectArray<Node> m_nodes;
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);
942 btAlignedObjectArray<btDbvtVolume> volumes;
943 btAlignedObjectArray<bool> results;
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);
968 btAlignedObjectArray<btDbvtVolume> volumes;
969 btAlignedObjectArray<btDbvtVolume> results;
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];
1029 btAlignedObjectArray<btTransform> transforms;
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;
1053 btAlignedObjectArray<btTransform> transforms;
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;
1075 btAlignedObjectArray<btVector3> rayorg;
1076 btAlignedObjectArray<btVector3> raydir;
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;
1123 btAlignedObjectArray<const btDbvtNode*> leaves;
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;
1145 btAlignedObjectArray<const btDbvtNode*> leaves;
1146 btAlignedObjectArray<btVector3> vectors;
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);
1191 btAlignedObjectArray<btDbvtVolume> volumes;
1192 btAlignedObjectArray<bool> results;
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;
1218 btAlignedObjectArray<btVector3> vectors;
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;
1243 btAlignedObjectArray<btVector3> vectors;
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;
1270 btAlignedObjectArray<btVector3> vectors;
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;
1298 btAlignedObjectArray<btDbvtNode*> batch;
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);
1323 btAlignedObjectArray<btDbvtVolume> volumes;
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
btTransform::setOrigin
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:146
btAlignedObjectArray::reserve
void reserve(int _Count)
Definition: btAlignedObjectArray.h:287
btDbvt::collideKDOP
static DBVT_PREFIX void collideKDOP(const btDbvtNode *root, const btVector3 *normals, const btScalar *offsets, int count, DBVT_IPOLICY)
Definition: btDbvt.h:1176
Merge
DBVT_INLINE void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
Definition: btDbvt.h:700
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:264
btDbvtAabbMm::Mins
DBVT_INLINE const btVector3 & Mins() const
Definition: btDbvt.h:137
btDbvt::benchmark
static void benchmark()
Definition: btDbvt.h:294
btDbvt::~btDbvt
~btDbvt()
Definition: btDbvt.cpp:470
btDbvt::collideOCL
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
btAlignedObjectArray
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
Definition: btAlignedObjectArray.h:52
btDbvtAabbMm
Definition: btDbvt.h:132
fetchleaves
static void fetchleaves(btDbvt *pdbvt, btDbvtNode *root, tNodeArray &leaves, int depth=-1)
Definition: btDbvt.cpp:229
btAlignedObjectArray::findLinearSearch
int findLinearSearch(const T &key) const
Definition: btAlignedObjectArray.h:445
btDbvtNode::data
void * data
Definition: btDbvt.h:188
leftOfAxis
static bool leftOfAxis(const btDbvtNode *node, const btVector3 &org, const btVector3 &axis)
Definition: btDbvt.cpp:247
btDbvt::IClone
Definition: btDbvt.h:249
getmaxdepth
static void getmaxdepth(const btDbvtNode *node, int depth, int &maxdepth)
Definition: btDbvt.cpp:60
recursedeletenode
static void recursedeletenode(btDbvt *pdbvt, btDbvtNode *node)
Definition: btDbvt.cpp:80
split
static int split(btDbvtNode **leaves, int count, const btVector3 &org, const btVector3 &axis)
Definition: btDbvt.cpp:257
size
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btAssert
#define btAssert(x)
Definition: btScalar.h:133
btDbvt
The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes ...
Definition: btDbvt.h:198
btDbvtAabbMm::Center
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:134
btDbvt::insert
btDbvtNode * insert(const btDbvtVolume &box, void *data)
Definition: btDbvt.cpp:534
btClock
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
Definition: btQuickprof.h:22
btDbvt::m_root
btDbvtNode * m_root
Definition: btDbvt.h:263
btDbvt::IWriter::WriteNode
virtual void WriteNode(const btDbvtNode *, int index, int parent, int child0, int child1)=0
btClock::reset
void reset()
Resets the initial reference time.
Definition: btQuickprof.cpp:112
btDbvtAabbMm::Lengths
DBVT_INLINE btVector3 Lengths() const
Definition: btDbvt.h:135
btDbvt::rayTest
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
topdown
static btDbvtNode * topdown(btDbvt *pdbvt, btDbvtNode **leaves, int count, int bu_treshold)
Definition: btDbvt.cpp:351
Select
DBVT_INLINE int Select(const btDbvtAabbMm &o, const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:621
btDbvtNodeEnumerator::nodes
tConstNodeArray nodes
Definition: btDbvt.cpp:26
btDbvt::write
void write(IWriter *iwriter) const
Definition: btDbvt.cpp:618
btDbvtNodeEnumerator::Process
void Process(const btDbvtNode *n)
Definition: btDbvt.cpp:27
btDbvtAabbMm::Maxs
DBVT_INLINE const btVector3 & Maxs() const
Definition: btDbvt.h:138
btDbvt::update
void update(btDbvtNode *leaf, int lookahead=-1)
Definition: btDbvt.cpp:543
SIMD_PI
#define SIMD_PI
Definition: btScalar.h:506
btDbvt::sStkCLN::node
const btDbvtNode * node
Definition: btDbvt.h:224
tConstNodeArray
btAlignedObjectArray< const btDbvtNode * > tConstNodeArray
Definition: btDbvt.cpp:21
SIMD_INFINITY
#define SIMD_INFINITY
Definition: btScalar.h:524
btDbvt::countLeaves
static int countLeaves(const btDbvtNode *node)
Definition: btDbvt.cpp:683
btDbvt::clear
void clear()
Definition: btDbvt.cpp:476
btDbvt::optimizeIncremental
void optimizeIncremental(int passes)
Definition: btDbvt.cpp:513
createnode
static DBVT_INLINE btDbvtNode * createnode(btDbvt *pdbvt, btDbvtNode *parent, void *data)
Definition: btDbvt.cpp:93
btDbvtAabbMm::FromCE
static btDbvtAabbMm FromCE(const btVector3 &c, const btVector3 &e)
Definition: btDbvt.h:419
btVector3::x
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
btDbvt::m_opath
unsigned m_opath
Definition: btDbvt.h:267
merge
static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume &a, const btDbvtVolume &b)
Definition: btDbvt.cpp:37
btDbvtNode::childs
btDbvtNode * childs[2]
Definition: btDbvt.h:187
btDbvt::sStkCLN
Definition: btDbvt.h:222
btSwap
void btSwap(T &a, T &b)
Definition: btScalar.h:623
btDbvt::maxdepth
static int maxdepth(const btDbvtNode *node)
Definition: btDbvt.cpp:675
btDbvtAabbMm::FromMM
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:434
insertleaf
static void insertleaf(btDbvt *pdbvt, btDbvtNode *root, btDbvtNode *leaf)
Definition: btDbvt.cpp:137
btAlignedFree
#define btAlignedFree(ptr)
Definition: btAlignedAllocator.h:47
btTransform::setRotation
void setRotation(const btQuaternion &q)
Set the rotational element by btQuaternion.
Definition: btTransform.h:160
btVector3::y
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
btVector3::z
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
btDbvtAabbMm::Expand
DBVT_INLINE void Expand(const btVector3 &e)
Definition: btDbvt.h:469
btAlignedObjectArray::pop_back
void pop_back()
Definition: btAlignedObjectArray.h:192
btDbvt::m_stkStack
btAlignedObjectArray< sStkNN > m_stkStack
Definition: btDbvt.h:269
btDbvt::m_lkhd
int m_lkhd
Definition: btDbvt.h:265
btDbvt::optimizeTopDown
void optimizeTopDown(int bu_treshold=128)
Definition: btDbvt.cpp:501
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
ATTRIBUTE_ALIGNED16
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:84
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:149
btClock::getTimeMilliseconds
unsigned long long int getTimeMilliseconds()
Returns the time in ms since the last call to reset or since the btClock was created.
Definition: btQuickprof.cpp:136
btDbvt::ICollide
Definition: btDbvt.h:231
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
btDbvtNode::isleaf
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:184
btDbvt::IWriter::Prepare
virtual void Prepare(const btDbvtNode *root, int numnodes)=0
btDbvt::btDbvt
btDbvt()
Definition: btDbvt.cpp:460
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:210
btDbvtNode::volume
btDbvtVolume volume
Definition: btDbvt.h:182
btDbvtNode::isinternal
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:185
btDbvt::IWriter::WriteLeaf
virtual void WriteLeaf(const btDbvtNode *, int index, int parent)=0
removeleaf
static btDbvtNode * removeleaf(btDbvt *pdbvt, btDbvtNode *leaf)
Definition: btDbvt.cpp:187
btMax
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
btDbvtAabbMm::Contain
DBVT_INLINE bool Contain(const btDbvtAabbMm &a) const
Definition: btDbvt.h:493
DBVT_INLINE
#define DBVT_INLINE
Definition: btDbvt.h:54
btDbvtNodeEnumerator
Definition: btDbvt.cpp:24
Intersect
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:576
btAlignedAlloc
#define btAlignedAlloc(size, alignment)
Definition: btAlignedAllocator.h:46
bounds
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:298
indexof
static DBVT_INLINE int indexof(const btDbvtNode *node)
Definition: btDbvt.cpp:31
dot
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:888
tNodeArray
btAlignedObjectArray< btDbvtNode * > tNodeArray
btDbvt implementation by Nathanael Presson
Definition: btDbvt.cpp:20
btDbvt::collideTT
DBVT_PREFIX void collideTT(const btDbvtNode *root0, const btDbvtNode *root1, DBVT_IPOLICY)
Definition: btDbvt.h:777
btQuaternion
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:49
btDot
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
deletenode
static DBVT_INLINE void deletenode(btDbvt *pdbvt, btDbvtNode *node)
Definition: btDbvt.cpp:72
btDbvt.h
btDbvt::optimizeBottomUp
void optimizeBottomUp()
Definition: btDbvt.cpp:488
btDbvtNode
Definition: btDbvt.h:180
btDbvt::clone
void clone(btDbvt &dest, IClone *iclone=0) const
Definition: btDbvt.cpp:643
btDbvt::enumNodes
static DBVT_PREFIX void enumNodes(const btDbvtNode *root, DBVT_IPOLICY)
Definition: btDbvt.h:746
btDbvt::IWriter
Definition: btDbvt.h:241
btDbvtAabbMm::SignedExpand
DBVT_INLINE void SignedExpand(const btVector3 &e)
Definition: btDbvt.h:476
sort
static DBVT_INLINE btDbvtNode * sort(btDbvtNode *n, btDbvtNode *&r)
Definition: btDbvt.cpp:417
btDbvt::remove
void remove(btDbvtNode *leaf)
Definition: btDbvt.cpp:610
bottomup
static void bottomup(btDbvt *pdbvt, btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:317
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
btDbvt::m_free
btDbvtNode * m_free
Definition: btDbvt.h:264
btDbvt::IClone::CloneLeaf
virtual void CloneLeaf(btDbvtNode *)
Definition: btDbvt.h:252
btDbvt::m_leaves
int m_leaves
Definition: btDbvt.h:266
btDbvt::sStkCLN::parent
btDbvtNode * parent
Definition: btDbvt.h:225
btDbvt::extractLeaves
static void extractLeaves(const btDbvtNode *node, btAlignedObjectArray< const btDbvtNode *> &leaves)
Definition: btDbvt.cpp:692
NotEqual
DBVT_INLINE bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
Definition: btDbvt.h:729
btDbvtNode::parent
btDbvtNode * parent
Definition: btDbvt.h:183
btFabs
btScalar btFabs(btScalar x)
Definition: btScalar.h:477