2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
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:
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.
15 ///btDbvt implementation by Nathanael Presson
20 typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
21 typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
24 struct btDbvtNodeEnumerator : btDbvt::ICollide
26 tConstNodeArray nodes;
27 void Process(const btDbvtNode* n) { nodes.push_back(n); }
31 static DBVT_INLINE int indexof(const btDbvtNode* node)
33 return (node->parent->childs[1] == node);
37 static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume& a,
38 const btDbvtVolume& b)
41 ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
42 btDbvtVolume* ptr = (btDbvtVolume*)locals;
43 btDbvtVolume& res = *ptr;
51 // volume+edge lengths
52 static DBVT_INLINE btScalar size(const btDbvtVolume& a)
54 const btVector3 edges = a.Lengths();
55 return (edges.x() * edges.y() * edges.z() +
56 edges.x() + edges.y() + edges.z());
60 static void getmaxdepth(const btDbvtNode* node, int depth, int& maxdepth)
62 if (node->isinternal())
64 getmaxdepth(node->childs[0], depth + 1, maxdepth);
65 getmaxdepth(node->childs[1], depth + 1, maxdepth);
68 maxdepth = btMax(maxdepth, depth);
72 static DBVT_INLINE void deletenode(btDbvt* pdbvt,
75 btAlignedFree(pdbvt->m_free);
80 static void recursedeletenode(btDbvt* pdbvt,
83 if (node == 0) return;
86 recursedeletenode(pdbvt, node->childs[0]);
87 recursedeletenode(pdbvt, node->childs[1]);
89 if (node == pdbvt->m_root) pdbvt->m_root = 0;
90 deletenode(pdbvt, node);
94 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
101 node = pdbvt->m_free;
106 node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
108 node->parent = parent;
115 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
117 const btDbvtVolume& volume,
120 btDbvtNode* node = createnode(pdbvt, parent, data);
121 node->volume = volume;
126 static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
128 const btDbvtVolume& volume0,
129 const btDbvtVolume& volume1,
132 btDbvtNode* node = createnode(pdbvt, parent, data);
133 Merge(volume0, volume1, node->volume);
138 static void insertleaf(btDbvt* pdbvt,
144 pdbvt->m_root = leaf;
153 root = root->childs[Select(leaf->volume,
154 root->childs[0]->volume,
155 root->childs[1]->volume)];
156 } while (!root->isleaf());
158 btDbvtNode* prev = root->parent;
159 btDbvtNode* node = createnode(pdbvt, prev, leaf->volume, root->volume, 0);
162 prev->childs[indexof(root)] = node;
163 node->childs[0] = root;
165 node->childs[1] = leaf;
169 if (!prev->volume.Contain(node->volume))
170 Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
174 } while (0 != (prev = node->parent));
178 node->childs[0] = root;
180 node->childs[1] = leaf;
182 pdbvt->m_root = node;
188 static btDbvtNode* removeleaf(btDbvt* pdbvt,
191 if (leaf == pdbvt->m_root)
198 btDbvtNode* parent = leaf->parent;
199 btDbvtNode* prev = parent->parent;
200 btDbvtNode* sibling = parent->childs[1 - indexof(leaf)];
203 prev->childs[indexof(parent)] = sibling;
204 sibling->parent = prev;
205 deletenode(pdbvt, parent);
208 const btDbvtVolume pb = prev->volume;
209 Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
210 if (NotEqual(pb, prev->volume))
217 return (prev ? prev : pdbvt->m_root);
221 pdbvt->m_root = sibling;
223 deletenode(pdbvt, parent);
224 return (pdbvt->m_root);
230 static void fetchleaves(btDbvt* pdbvt,
235 if (root->isinternal() && depth)
237 fetchleaves(pdbvt, root->childs[0], leaves, depth - 1);
238 fetchleaves(pdbvt, root->childs[1], leaves, depth - 1);
239 deletenode(pdbvt, root);
243 leaves.push_back(root);
248 static bool leftOfAxis(const btDbvtNode* node,
249 const btVector3& org,
250 const btVector3& axis)
252 return btDot(axis, node->volume.Center() - org) <= 0;
255 // Partitions leaves such that leaves[0, n) are on the
256 // left of axis, and leaves[n, count) are on the right
257 // of axis. returns N.
258 static int split(btDbvtNode** leaves,
260 const btVector3& org,
261 const btVector3& axis)
267 while (begin != end && leftOfAxis(leaves[begin], org, axis))
277 while (begin != end && !leftOfAxis(leaves[end - 1], org, axis))
287 // swap out of place nodes
289 btDbvtNode* temp = leaves[begin];
290 leaves[begin] = leaves[end];
299 static btDbvtVolume bounds(btDbvtNode** leaves,
303 ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
304 btDbvtVolume* ptr = (btDbvtVolume*)locals;
305 btDbvtVolume& volume = *ptr;
306 volume = leaves[0]->volume;
308 btDbvtVolume volume = leaves[0]->volume;
310 for (int i = 1, ni = count; i < ni; ++i)
312 Merge(volume, leaves[i]->volume, volume);
318 static void bottomup(btDbvt* pdbvt,
324 btScalar minsize = SIMD_INFINITY;
325 int minidx[2] = {-1, -1};
326 for (int i = 0; i < count; ++i)
328 for (int j = i + 1; j < count; ++j)
330 const btScalar sz = size(merge(leaves[i]->volume, leaves[j]->volume));
339 btDbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
340 btDbvtNode* p = createnode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
345 leaves[minidx[0]] = p;
346 leaves[minidx[1]] = leaves[count - 1];
352 static btDbvtNode* topdown(btDbvt* pdbvt,
357 static const btVector3 axis[] = {btVector3(1, 0, 0),
360 btAssert(bu_treshold > 2);
363 if (count > bu_treshold)
365 const btDbvtVolume vol = bounds(leaves, count);
366 const btVector3 org = vol.Center();
369 int bestmidp = count;
370 int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
372 for (i = 0; i < count; ++i)
374 const btVector3 x = leaves[i]->volume.Center() - org;
375 for (int j = 0; j < 3; ++j)
377 ++splitcount[j][btDot(x, axis[j]) > 0 ? 1 : 0];
380 for (i = 0; i < 3; ++i)
382 if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
384 const int midp = (int)btFabs(btScalar(splitcount[i][0] - splitcount[i][1]));
394 partition = split(leaves, count, org, axis[bestaxis]);
395 btAssert(partition != 0 && partition != count);
399 partition = count / 2 + 1;
401 btDbvtNode* node = createnode(pdbvt, 0, vol, 0);
402 node->childs[0] = topdown(pdbvt, &leaves[0], partition, bu_treshold);
403 node->childs[1] = topdown(pdbvt, &leaves[partition], count - partition, bu_treshold);
404 node->childs[0]->parent = node;
405 node->childs[1]->parent = node;
410 bottomup(pdbvt, leaves, count);
418 static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n, btDbvtNode*& r)
420 btDbvtNode* p = n->parent;
421 btAssert(n->isinternal());
424 const int i = indexof(n);
426 btDbvtNode* s = p->childs[j];
427 btDbvtNode* q = p->parent;
428 btAssert(n == p->childs[i]);
430 q->childs[indexof(p)] = n;
436 p->childs[0] = n->childs[0];
437 p->childs[1] = n->childs[1];
438 n->childs[0]->parent = p;
439 n->childs[1]->parent = p;
442 btSwap(p->volume, n->volume);
449 static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
451 while(n&&(count--)) n=n->parent;
480 recursedeletenode(this, m_root);
481 btAlignedFree(m_free);
489 void btDbvt::optimizeBottomUp()
494 leaves.reserve(m_leaves);
495 fetchleaves(this, m_root, leaves);
496 bottomup(this, &leaves[0], leaves.size());
502 void btDbvt::optimizeTopDown(int bu_treshold)
507 leaves.reserve(m_leaves);
508 fetchleaves(this, m_root, leaves);
509 m_root = topdown(this, &leaves[0], leaves.size(), bu_treshold);
514 void btDbvt::optimizeIncremental(int passes)
516 if (passes < 0) passes = m_leaves;
517 if (m_root && (passes > 0))
521 btDbvtNode* node = m_root;
523 while (node->isinternal())
525 node = sort(node, m_root)->childs[(m_opath >> bit) & 1];
526 bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
535 btDbvtNode* btDbvt::insert(const btDbvtVolume& volume, void* data)
537 btDbvtNode* leaf = createnode(this, 0, volume, data);
538 insertleaf(this, m_root, leaf);
544 void btDbvt::update(btDbvtNode* leaf, int lookahead)
546 btDbvtNode* root = removeleaf(this, leaf);
551 for (int i = 0; (i < lookahead) && root->parent; ++i)
559 insertleaf(this, root, leaf);
563 void btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume)
565 btDbvtNode* root = removeleaf(this, leaf);
570 for (int i = 0; (i < m_lkhd) && root->parent; ++i)
578 leaf->volume = volume;
579 insertleaf(this, root, leaf);
583 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin)
585 if (leaf->volume.Contain(volume)) return (false);
586 volume.Expand(btVector3(margin, margin, margin));
587 volume.SignedExpand(velocity);
588 update(leaf, volume);
593 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity)
595 if (leaf->volume.Contain(volume)) return (false);
596 volume.SignedExpand(velocity);
597 update(leaf, volume);
602 bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin)
604 if (leaf->volume.Contain(volume)) return (false);
605 volume.Expand(btVector3(margin, margin, margin));
606 update(leaf, volume);
611 void btDbvt::remove(btDbvtNode* leaf)
613 removeleaf(this, leaf);
614 deletenode(this, leaf);
619 void btDbvt::write(IWriter* iwriter) const
621 btDbvtNodeEnumerator nodes;
622 nodes.nodes.reserve(m_leaves * 2);
623 enumNodes(m_root, nodes);
624 iwriter->Prepare(m_root, nodes.nodes.size());
625 for (int i = 0; i < nodes.nodes.size(); ++i)
627 const btDbvtNode* n = nodes.nodes[i];
629 if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
632 const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
633 const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
634 iwriter->WriteNode(n, i, p, c0, c1);
638 iwriter->WriteLeaf(n, i, p);
644 void btDbvt::clone(btDbvt& dest, IClone* iclone) const
649 btAlignedObjectArray<sStkCLN> stack;
650 stack.reserve(m_leaves);
651 stack.push_back(sStkCLN(m_root, 0));
654 const int i = stack.size() - 1;
655 const sStkCLN e = stack[i];
656 btDbvtNode* n = createnode(&dest, e.parent, e.node->volume, e.node->data);
659 e.parent->childs[i & 1] = n;
662 if (e.node->isinternal())
664 stack.push_back(sStkCLN(e.node->childs[0], n));
665 stack.push_back(sStkCLN(e.node->childs[1], n));
669 iclone->CloneLeaf(n);
671 } while (stack.size() > 0);
676 int btDbvt::maxdepth(const btDbvtNode* node)
679 if (node) getmaxdepth(node, 1, depth);
684 int btDbvt::countLeaves(const btDbvtNode* node)
686 if (node->isinternal())
687 return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
693 void btDbvt::extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves)
695 if (node->isinternal())
697 extractLeaves(node->childs[0], leaves);
698 extractLeaves(node->childs[1], leaves);
702 leaves.push_back(node);
707 #if DBVT_ENABLE_BENCHMARK
711 #include "LinearMath/btQuickProf.h"
716 /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"
717 /GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
718 /Fo"..\..\out\release8\build\libbulletcollision\\"
719 /Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
720 /W3 /nologo /c /Wp64 /Zi /errorReport:prompt
723 World scale: 100.000000
724 Extents base: 1.000000
725 Extents range: 4.000000
727 sizeof(btDbvtVolume): 32 bytes
728 sizeof(btDbvtNode): 44 bytes
729 [1] btDbvtVolume intersections: 3499 ms (-1%)
730 [2] btDbvtVolume merges: 1934 ms (0%)
731 [3] btDbvt::collideTT: 5485 ms (-21%)
732 [4] btDbvt::collideTT self: 2814 ms (-20%)
733 [5] btDbvt::collideTT xform: 7379 ms (-1%)
734 [6] btDbvt::collideTT xform,self: 7270 ms (-2%)
735 [7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
736 [8] insert/remove: 2093 ms (0%),(1001983 ir/s)
737 [9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
738 [10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
739 [11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
740 [12] btDbvtVolume notequal: 3659 ms (0%)
741 [13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
742 [14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
743 [15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
744 [16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
745 [17] btDbvtVolume select: 3419 ms (0%)
748 struct btDbvtBenchmark
750 struct NilPolicy : btDbvt::ICollide
752 NilPolicy() : m_pcount(0), m_depth(-SIMD_INFINITY), m_checksort(true) {}
753 void Process(const btDbvtNode*, const btDbvtNode*) { ++m_pcount; }
754 void Process(const btDbvtNode*) { ++m_pcount; }
755 void Process(const btDbvtNode*, btScalar depth)
760 if (depth >= m_depth)
763 printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
770 struct P14 : btDbvt::ICollide
774 const btDbvtNode* leaf;
777 void Process(const btDbvtNode* leaf, btScalar depth)
783 static int sortfnc(const Node& a, const Node& b)
785 if (a.depth < b.depth) return (+1);
786 if (a.depth > b.depth) return (-1);
789 btAlignedObjectArray<Node> m_nodes;
791 struct P15 : btDbvt::ICollide
795 const btDbvtNode* leaf;
798 void Process(const btDbvtNode* leaf)
802 n.depth = dot(leaf->volume.Center(), m_axis);
804 static int sortfnc(const Node& a, const Node& b)
806 if (a.depth < b.depth) return (+1);
807 if (a.depth > b.depth) return (-1);
810 btAlignedObjectArray<Node> m_nodes;
813 static btScalar RandUnit()
815 return (rand() / (btScalar)RAND_MAX);
817 static btVector3 RandVector3()
819 return (btVector3(RandUnit(), RandUnit(), RandUnit()));
821 static btVector3 RandVector3(btScalar cs)
823 return (RandVector3() * cs - btVector3(cs, cs, cs) / 2);
825 static btDbvtVolume RandVolume(btScalar cs, btScalar eb, btScalar es)
827 return (btDbvtVolume::FromCE(RandVector3(cs), btVector3(eb, eb, eb) + RandVector3() * es));
829 static btTransform RandTransform(btScalar cs)
832 t.setOrigin(RandVector3(cs));
833 t.setRotation(btQuaternion(RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2).normalized());
836 static void RandTree(btScalar cs, btScalar eb, btScalar es, int leaves, btDbvt& dbvt)
839 for (int i = 0; i < leaves; ++i)
841 dbvt.insert(RandVolume(cs, eb, es), 0);
846 void btDbvt::benchmark()
848 static const btScalar cfgVolumeCenterScale = 100;
849 static const btScalar cfgVolumeExentsBase = 1;
850 static const btScalar cfgVolumeExentsScale = 4;
851 static const int cfgLeaves = 8192;
852 static const bool cfgEnable = true;
854 //[1] btDbvtVolume intersections
855 bool cfgBenchmark1_Enable = cfgEnable;
856 static const int cfgBenchmark1_Iterations = 8;
857 static const int cfgBenchmark1_Reference = 3499;
858 //[2] btDbvtVolume merges
859 bool cfgBenchmark2_Enable = cfgEnable;
860 static const int cfgBenchmark2_Iterations = 4;
861 static const int cfgBenchmark2_Reference = 1945;
862 //[3] btDbvt::collideTT
863 bool cfgBenchmark3_Enable = cfgEnable;
864 static const int cfgBenchmark3_Iterations = 512;
865 static const int cfgBenchmark3_Reference = 5485;
866 //[4] btDbvt::collideTT self
867 bool cfgBenchmark4_Enable = cfgEnable;
868 static const int cfgBenchmark4_Iterations = 512;
869 static const int cfgBenchmark4_Reference = 2814;
870 //[5] btDbvt::collideTT xform
871 bool cfgBenchmark5_Enable = cfgEnable;
872 static const int cfgBenchmark5_Iterations = 512;
873 static const btScalar cfgBenchmark5_OffsetScale = 2;
874 static const int cfgBenchmark5_Reference = 7379;
875 //[6] btDbvt::collideTT xform,self
876 bool cfgBenchmark6_Enable = cfgEnable;
877 static const int cfgBenchmark6_Iterations = 512;
878 static const btScalar cfgBenchmark6_OffsetScale = 2;
879 static const int cfgBenchmark6_Reference = 7270;
880 //[7] btDbvt::rayTest
881 bool cfgBenchmark7_Enable = cfgEnable;
882 static const int cfgBenchmark7_Passes = 32;
883 static const int cfgBenchmark7_Iterations = 65536;
884 static const int cfgBenchmark7_Reference = 6307;
886 bool cfgBenchmark8_Enable = cfgEnable;
887 static const int cfgBenchmark8_Passes = 32;
888 static const int cfgBenchmark8_Iterations = 65536;
889 static const int cfgBenchmark8_Reference = 2105;
890 //[9] updates (teleport)
891 bool cfgBenchmark9_Enable = cfgEnable;
892 static const int cfgBenchmark9_Passes = 32;
893 static const int cfgBenchmark9_Iterations = 65536;
894 static const int cfgBenchmark9_Reference = 1879;
895 //[10] updates (jitter)
896 bool cfgBenchmark10_Enable = cfgEnable;
897 static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
898 static const int cfgBenchmark10_Passes = 32;
899 static const int cfgBenchmark10_Iterations = 65536;
900 static const int cfgBenchmark10_Reference = 1244;
901 //[11] optimize (incremental)
902 bool cfgBenchmark11_Enable = cfgEnable;
903 static const int cfgBenchmark11_Passes = 64;
904 static const int cfgBenchmark11_Iterations = 65536;
905 static const int cfgBenchmark11_Reference = 2510;
906 //[12] btDbvtVolume notequal
907 bool cfgBenchmark12_Enable = cfgEnable;
908 static const int cfgBenchmark12_Iterations = 32;
909 static const int cfgBenchmark12_Reference = 3677;
910 //[13] culling(OCL+fullsort)
911 bool cfgBenchmark13_Enable = cfgEnable;
912 static const int cfgBenchmark13_Iterations = 1024;
913 static const int cfgBenchmark13_Reference = 2231;
914 //[14] culling(OCL+qsort)
915 bool cfgBenchmark14_Enable = cfgEnable;
916 static const int cfgBenchmark14_Iterations = 8192;
917 static const int cfgBenchmark14_Reference = 3500;
918 //[15] culling(KDOP+qsort)
919 bool cfgBenchmark15_Enable = cfgEnable;
920 static const int cfgBenchmark15_Iterations = 8192;
921 static const int cfgBenchmark15_Reference = 1151;
922 //[16] insert/remove batch
923 bool cfgBenchmark16_Enable = cfgEnable;
924 static const int cfgBenchmark16_BatchCount = 256;
925 static const int cfgBenchmark16_Passes = 16384;
926 static const int cfgBenchmark16_Reference = 5138;
928 bool cfgBenchmark17_Enable = cfgEnable;
929 static const int cfgBenchmark17_Iterations = 4;
930 static const int cfgBenchmark17_Reference = 3390;
933 printf("Benchmarking dbvt...\r\n");
934 printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
935 printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
936 printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
937 printf("\tLeaves: %u\r\n", cfgLeaves);
938 printf("\tsizeof(btDbvtVolume): %u bytes\r\n", sizeof(btDbvtVolume));
939 printf("\tsizeof(btDbvtNode): %u bytes\r\n", sizeof(btDbvtNode));
940 if (cfgBenchmark1_Enable)
943 btAlignedObjectArray<btDbvtVolume> volumes;
944 btAlignedObjectArray<bool> results;
945 volumes.resize(cfgLeaves);
946 results.resize(cfgLeaves);
947 for (int i = 0; i < cfgLeaves; ++i)
949 volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
951 printf("[1] btDbvtVolume intersections: ");
953 for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
955 for (int j = 0; j < cfgLeaves; ++j)
957 for (int k = 0; k < cfgLeaves; ++k)
959 results[k] = Intersect(volumes[j], volumes[k]);
963 const int time = (int)wallclock.getTimeMilliseconds();
964 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
966 if (cfgBenchmark2_Enable)
969 btAlignedObjectArray<btDbvtVolume> volumes;
970 btAlignedObjectArray<btDbvtVolume> results;
971 volumes.resize(cfgLeaves);
972 results.resize(cfgLeaves);
973 for (int i = 0; i < cfgLeaves; ++i)
975 volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
977 printf("[2] btDbvtVolume merges: ");
979 for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
981 for (int j = 0; j < cfgLeaves; ++j)
983 for (int k = 0; k < cfgLeaves; ++k)
985 Merge(volumes[j], volumes[k], results[k]);
989 const int time = (int)wallclock.getTimeMilliseconds();
990 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
992 if (cfgBenchmark3_Enable)
996 btDbvtBenchmark::NilPolicy policy;
997 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
998 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
999 dbvt[0].optimizeTopDown();
1000 dbvt[1].optimizeTopDown();
1001 printf("[3] btDbvt::collideTT: ");
1003 for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
1005 btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
1007 const int time = (int)wallclock.getTimeMilliseconds();
1008 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
1010 if (cfgBenchmark4_Enable)
1014 btDbvtBenchmark::NilPolicy policy;
1015 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1016 dbvt.optimizeTopDown();
1017 printf("[4] btDbvt::collideTT self: ");
1019 for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
1021 btDbvt::collideTT(dbvt.m_root, dbvt.m_root, policy);
1023 const int time = (int)wallclock.getTimeMilliseconds();
1024 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
1026 if (cfgBenchmark5_Enable)
1030 btAlignedObjectArray<btTransform> transforms;
1031 btDbvtBenchmark::NilPolicy policy;
1032 transforms.resize(cfgBenchmark5_Iterations);
1033 for (int i = 0; i < transforms.size(); ++i)
1035 transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
1037 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
1038 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
1039 dbvt[0].optimizeTopDown();
1040 dbvt[1].optimizeTopDown();
1041 printf("[5] btDbvt::collideTT xform: ");
1043 for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
1045 btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
1047 const int time = (int)wallclock.getTimeMilliseconds();
1048 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
1050 if (cfgBenchmark6_Enable)
1054 btAlignedObjectArray<btTransform> transforms;
1055 btDbvtBenchmark::NilPolicy policy;
1056 transforms.resize(cfgBenchmark6_Iterations);
1057 for (int i = 0; i < transforms.size(); ++i)
1059 transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
1061 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1062 dbvt.optimizeTopDown();
1063 printf("[6] btDbvt::collideTT xform,self: ");
1065 for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
1067 btDbvt::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
1069 const int time = (int)wallclock.getTimeMilliseconds();
1070 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
1072 if (cfgBenchmark7_Enable)
1076 btAlignedObjectArray<btVector3> rayorg;
1077 btAlignedObjectArray<btVector3> raydir;
1078 btDbvtBenchmark::NilPolicy policy;
1079 rayorg.resize(cfgBenchmark7_Iterations);
1080 raydir.resize(cfgBenchmark7_Iterations);
1081 for (int i = 0; i < rayorg.size(); ++i)
1083 rayorg[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
1084 raydir[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
1086 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1087 dbvt.optimizeTopDown();
1088 printf("[7] btDbvt::rayTest: ");
1090 for (int i = 0; i < cfgBenchmark7_Passes; ++i)
1092 for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
1094 btDbvt::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
1097 const int time = (int)wallclock.getTimeMilliseconds();
1098 unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
1099 printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
1101 if (cfgBenchmark8_Enable)
1105 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1106 dbvt.optimizeTopDown();
1107 printf("[8] insert/remove: ");
1109 for (int i = 0; i < cfgBenchmark8_Passes; ++i)
1111 for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
1113 dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
1116 const int time = (int)wallclock.getTimeMilliseconds();
1117 const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
1118 printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
1120 if (cfgBenchmark9_Enable)
1124 btAlignedObjectArray<const btDbvtNode*> leaves;
1125 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1126 dbvt.optimizeTopDown();
1127 dbvt.extractLeaves(dbvt.m_root, leaves);
1128 printf("[9] updates (teleport): ");
1130 for (int i = 0; i < cfgBenchmark9_Passes; ++i)
1132 for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
1134 dbvt.update(const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]),
1135 btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
1138 const int time = (int)wallclock.getTimeMilliseconds();
1139 const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
1140 printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
1142 if (cfgBenchmark10_Enable)
1146 btAlignedObjectArray<const btDbvtNode*> leaves;
1147 btAlignedObjectArray<btVector3> vectors;
1148 vectors.resize(cfgBenchmark10_Iterations);
1149 for (int i = 0; i < vectors.size(); ++i)
1151 vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)) * cfgBenchmark10_Scale;
1153 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1154 dbvt.optimizeTopDown();
1155 dbvt.extractLeaves(dbvt.m_root, leaves);
1156 printf("[10] updates (jitter): ");
1159 for (int i = 0; i < cfgBenchmark10_Passes; ++i)
1161 for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
1163 const btVector3& d = vectors[j];
1164 btDbvtNode* l = const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]);
1165 btDbvtVolume v = btDbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
1169 const int time = (int)wallclock.getTimeMilliseconds();
1170 const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
1171 printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
1173 if (cfgBenchmark11_Enable)
1177 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1178 dbvt.optimizeTopDown();
1179 printf("[11] optimize (incremental): ");
1181 for (int i = 0; i < cfgBenchmark11_Passes; ++i)
1183 dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
1185 const int time = (int)wallclock.getTimeMilliseconds();
1186 const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
1187 printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
1189 if (cfgBenchmark12_Enable)
1192 btAlignedObjectArray<btDbvtVolume> volumes;
1193 btAlignedObjectArray<bool> results;
1194 volumes.resize(cfgLeaves);
1195 results.resize(cfgLeaves);
1196 for (int i = 0; i < cfgLeaves; ++i)
1198 volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
1200 printf("[12] btDbvtVolume notequal: ");
1202 for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
1204 for (int j = 0; j < cfgLeaves; ++j)
1206 for (int k = 0; k < cfgLeaves; ++k)
1208 results[k] = NotEqual(volumes[j], volumes[k]);
1212 const int time = (int)wallclock.getTimeMilliseconds();
1213 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
1215 if (cfgBenchmark13_Enable)
1219 btAlignedObjectArray<btVector3> vectors;
1220 btDbvtBenchmark::NilPolicy policy;
1221 vectors.resize(cfgBenchmark13_Iterations);
1222 for (int i = 0; i < vectors.size(); ++i)
1224 vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1226 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1227 dbvt.optimizeTopDown();
1228 printf("[13] culling(OCL+fullsort): ");
1230 for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
1232 static const btScalar offset = 0;
1233 policy.m_depth = -SIMD_INFINITY;
1234 dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
1236 const int time = (int)wallclock.getTimeMilliseconds();
1237 const int t = cfgBenchmark13_Iterations;
1238 printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
1240 if (cfgBenchmark14_Enable)
1244 btAlignedObjectArray<btVector3> vectors;
1245 btDbvtBenchmark::P14 policy;
1246 vectors.resize(cfgBenchmark14_Iterations);
1247 for (int i = 0; i < vectors.size(); ++i)
1249 vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1251 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1252 dbvt.optimizeTopDown();
1253 policy.m_nodes.reserve(cfgLeaves);
1254 printf("[14] culling(OCL+qsort): ");
1256 for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
1258 static const btScalar offset = 0;
1259 policy.m_nodes.resize(0);
1260 dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
1261 policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
1263 const int time = (int)wallclock.getTimeMilliseconds();
1264 const int t = cfgBenchmark14_Iterations;
1265 printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
1267 if (cfgBenchmark15_Enable)
1271 btAlignedObjectArray<btVector3> vectors;
1272 btDbvtBenchmark::P15 policy;
1273 vectors.resize(cfgBenchmark15_Iterations);
1274 for (int i = 0; i < vectors.size(); ++i)
1276 vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
1278 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1279 dbvt.optimizeTopDown();
1280 policy.m_nodes.reserve(cfgLeaves);
1281 printf("[15] culling(KDOP+qsort): ");
1283 for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
1285 static const btScalar offset = 0;
1286 policy.m_nodes.resize(0);
1287 policy.m_axis = vectors[i];
1288 dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
1289 policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
1291 const int time = (int)wallclock.getTimeMilliseconds();
1292 const int t = cfgBenchmark15_Iterations;
1293 printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
1295 if (cfgBenchmark16_Enable)
1299 btAlignedObjectArray<btDbvtNode*> batch;
1300 btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
1301 dbvt.optimizeTopDown();
1302 batch.reserve(cfgBenchmark16_BatchCount);
1303 printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
1305 for (int i = 0; i < cfgBenchmark16_Passes; ++i)
1307 for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
1309 batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
1311 for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
1313 dbvt.remove(batch[j]);
1317 const int time = (int)wallclock.getTimeMilliseconds();
1318 const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
1319 printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
1321 if (cfgBenchmark17_Enable)
1324 btAlignedObjectArray<btDbvtVolume> volumes;
1325 btAlignedObjectArray<int> results;
1326 btAlignedObjectArray<int> indices;
1327 volumes.resize(cfgLeaves);
1328 results.resize(cfgLeaves);
1329 indices.resize(cfgLeaves);
1330 for (int i = 0; i < cfgLeaves; ++i)
1333 volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
1335 for (int i = 0; i < cfgLeaves; ++i)
1337 btSwap(indices[i], indices[rand() % cfgLeaves]);
1339 printf("[17] btDbvtVolume select: ");
1341 for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
1343 for (int j = 0; j < cfgLeaves; ++j)
1345 for (int k = 0; k < cfgLeaves; ++k)
1347 const int idx = indices[k];
1348 results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
1352 const int time = (int)wallclock.getTimeMilliseconds();
1353 printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);