2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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)
40 #if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
41 ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
42 btDbvtVolume& res=*(btDbvtVolume*)locals;
50 // volume+edge lengths
51 static DBVT_INLINE btScalar size(const btDbvtVolume& a)
53 const btVector3 edges=a.Lengths();
54 return( edges.x()*edges.y()*edges.z()+
55 edges.x()+edges.y()+edges.z());
59 static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
61 if(node->isinternal())
63 getmaxdepth(node->childs[0],depth+1,maxdepth);
64 getmaxdepth(node->childs[1],depth+1,maxdepth);
65 } else maxdepth=btMax(maxdepth,depth);
69 static DBVT_INLINE void deletenode( btDbvt* pdbvt,
72 btAlignedFree(pdbvt->m_free);
77 static void recursedeletenode( btDbvt* pdbvt,
82 recursedeletenode(pdbvt,node->childs[0]);
83 recursedeletenode(pdbvt,node->childs[1]);
85 if(node==pdbvt->m_root) pdbvt->m_root=0;
86 deletenode(pdbvt,node);
90 static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
96 { node=pdbvt->m_free;pdbvt->m_free=0; }
98 { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
99 node->parent = parent;
106 static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
108 const btDbvtVolume& volume,
111 btDbvtNode* node=createnode(pdbvt,parent,data);
117 static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
119 const btDbvtVolume& volume0,
120 const btDbvtVolume& volume1,
123 btDbvtNode* node=createnode(pdbvt,parent,data);
124 Merge(volume0,volume1,node->volume);
129 static void insertleaf( btDbvt* pdbvt,
135 pdbvt->m_root = leaf;
143 root=root->childs[Select( leaf->volume,
144 root->childs[0]->volume,
145 root->childs[1]->volume)];
146 } while(!root->isleaf());
148 btDbvtNode* prev=root->parent;
149 btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
152 prev->childs[indexof(root)] = node;
153 node->childs[0] = root;root->parent=node;
154 node->childs[1] = leaf;leaf->parent=node;
156 if(!prev->volume.Contain(node->volume))
157 Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
161 } while(0!=(prev=node->parent));
165 node->childs[0] = root;root->parent=node;
166 node->childs[1] = leaf;leaf->parent=node;
167 pdbvt->m_root = node;
173 static btDbvtNode* removeleaf( btDbvt* pdbvt,
176 if(leaf==pdbvt->m_root)
183 btDbvtNode* parent=leaf->parent;
184 btDbvtNode* prev=parent->parent;
185 btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
188 prev->childs[indexof(parent)]=sibling;
189 sibling->parent=prev;
190 deletenode(pdbvt,parent);
193 const btDbvtVolume pb=prev->volume;
194 Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
195 if(NotEqual(pb,prev->volume))
200 return(prev?prev:pdbvt->m_root);
204 pdbvt->m_root=sibling;
206 deletenode(pdbvt,parent);
207 return(pdbvt->m_root);
213 static void fetchleaves(btDbvt* pdbvt,
218 if(root->isinternal()&&depth)
220 fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
221 fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
222 deletenode(pdbvt,root);
226 leaves.push_back(root);
231 static void split( const tNodeArray& leaves,
234 const btVector3& org,
235 const btVector3& axis)
239 for(int i=0,ni=leaves.size();i<ni;++i)
241 if(btDot(axis,leaves[i]->volume.Center()-org)<0)
242 left.push_back(leaves[i]);
244 right.push_back(leaves[i]);
249 static btDbvtVolume bounds( const tNodeArray& leaves)
251 #if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
252 ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
253 btDbvtVolume& volume=*(btDbvtVolume*)locals;
254 volume=leaves[0]->volume;
256 btDbvtVolume volume=leaves[0]->volume;
258 for(int i=1,ni=leaves.size();i<ni;++i)
260 Merge(volume,leaves[i]->volume,volume);
266 static void bottomup( btDbvt* pdbvt,
269 while(leaves.size()>1)
271 btScalar minsize=SIMD_INFINITY;
272 int minidx[2]={-1,-1};
273 for(int i=0;i<leaves.size();++i)
275 for(int j=i+1;j<leaves.size();++j)
277 const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
286 btDbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
287 btDbvtNode* p = createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
292 leaves[minidx[0]] = p;
293 leaves.swap(minidx[1],leaves.size()-1);
299 static btDbvtNode* topdown(btDbvt* pdbvt,
303 static const btVector3 axis[]={btVector3(1,0,0),
308 if(leaves.size()>bu_treshold)
310 const btDbvtVolume vol=bounds(leaves);
311 const btVector3 org=vol.Center();
314 int bestmidp=leaves.size();
315 int splitcount[3][2]={{0,0},{0,0},{0,0}};
317 for( i=0;i<leaves.size();++i)
319 const btVector3 x=leaves[i]->volume.Center()-org;
322 ++splitcount[j][btDot(x,axis[j])>0?1:0];
327 if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
329 const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
339 sets[0].reserve(splitcount[bestaxis][0]);
340 sets[1].reserve(splitcount[bestaxis][1]);
341 split(leaves,sets[0],sets[1],org,axis[bestaxis]);
345 sets[0].reserve(leaves.size()/2+1);
346 sets[1].reserve(leaves.size()/2);
347 for(int i=0,ni=leaves.size();i<ni;++i)
349 sets[i&1].push_back(leaves[i]);
352 btDbvtNode* node=createnode(pdbvt,0,vol,0);
353 node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
354 node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
355 node->childs[0]->parent=node;
356 node->childs[1]->parent=node;
361 bottomup(pdbvt,leaves);
369 static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
371 btDbvtNode* p=n->parent;
372 btAssert(n->isinternal());
375 const int i=indexof(n);
377 btDbvtNode* s=p->childs[j];
378 btDbvtNode* q=p->parent;
379 btAssert(n==p->childs[i]);
380 if(q) q->childs[indexof(p)]=n; else r=n;
384 p->childs[0]=n->childs[0];
385 p->childs[1]=n->childs[1];
386 n->childs[0]->parent=p;
387 n->childs[1]->parent=p;
390 btSwap(p->volume,n->volume);
397 static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
399 while(n&&(count--)) n=n->parent;
428 recursedeletenode(this,m_root);
429 btAlignedFree(m_free);
438 void btDbvt::optimizeBottomUp()
443 leaves.reserve(m_leaves);
444 fetchleaves(this,m_root,leaves);
445 bottomup(this,leaves);
451 void btDbvt::optimizeTopDown(int bu_treshold)
456 leaves.reserve(m_leaves);
457 fetchleaves(this,m_root,leaves);
458 m_root=topdown(this,leaves,bu_treshold);
463 void btDbvt::optimizeIncremental(int passes)
465 if(passes<0) passes=m_leaves;
466 if(m_root&&(passes>0))
469 btDbvtNode* node=m_root;
471 while(node->isinternal())
473 node=sort(node,m_root)->childs[(m_opath>>bit)&1];
474 bit=(bit+1)&(sizeof(unsigned)*8-1);
483 btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
485 btDbvtNode* leaf=createnode(this,0,volume,data);
486 insertleaf(this,m_root,leaf);
492 void btDbvt::update(btDbvtNode* leaf,int lookahead)
494 btDbvtNode* root=removeleaf(this,leaf);
499 for(int i=0;(i<lookahead)&&root->parent;++i)
505 insertleaf(this,root,leaf);
509 void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
511 btDbvtNode* root=removeleaf(this,leaf);
516 for(int i=0;(i<m_lkhd)&&root->parent;++i)
523 insertleaf(this,root,leaf);
527 bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
529 if(leaf->volume.Contain(volume)) return(false);
530 volume.Expand(btVector3(margin,margin,margin));
531 volume.SignedExpand(velocity);
537 bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
539 if(leaf->volume.Contain(volume)) return(false);
540 volume.SignedExpand(velocity);
546 bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
548 if(leaf->volume.Contain(volume)) return(false);
549 volume.Expand(btVector3(margin,margin,margin));
555 void btDbvt::remove(btDbvtNode* leaf)
557 removeleaf(this,leaf);
558 deletenode(this,leaf);
563 void btDbvt::write(IWriter* iwriter) const
565 btDbvtNodeEnumerator nodes;
566 nodes.nodes.reserve(m_leaves*2);
567 enumNodes(m_root,nodes);
568 iwriter->Prepare(m_root,nodes.nodes.size());
569 for(int i=0;i<nodes.nodes.size();++i)
571 const btDbvtNode* n=nodes.nodes[i];
573 if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
576 const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
577 const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
578 iwriter->WriteNode(n,i,p,c0,c1);
582 iwriter->WriteLeaf(n,i,p);
588 void btDbvt::clone(btDbvt& dest,IClone* iclone) const
593 btAlignedObjectArray<sStkCLN> stack;
594 stack.reserve(m_leaves);
595 stack.push_back(sStkCLN(m_root,0));
597 const int i=stack.size()-1;
598 const sStkCLN e=stack[i];
599 btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
602 e.parent->childs[i&1]=n;
605 if(e.node->isinternal())
607 stack.push_back(sStkCLN(e.node->childs[0],n));
608 stack.push_back(sStkCLN(e.node->childs[1],n));
612 iclone->CloneLeaf(n);
614 } while(stack.size()>0);
619 int btDbvt::maxdepth(const btDbvtNode* node)
622 if(node) getmaxdepth(node,1,depth);
627 int btDbvt::countLeaves(const btDbvtNode* node)
629 if(node->isinternal())
630 return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
636 void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
638 if(node->isinternal())
640 extractLeaves(node->childs[0],leaves);
641 extractLeaves(node->childs[1],leaves);
645 leaves.push_back(node);
650 #if DBVT_ENABLE_BENCHMARK
654 #include "LinearMath/btQuickProf.h"
659 /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"
660 /GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
661 /Fo"..\..\out\release8\build\libbulletcollision\\"
662 /Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
663 /W3 /nologo /c /Wp64 /Zi /errorReport:prompt
666 World scale: 100.000000
667 Extents base: 1.000000
668 Extents range: 4.000000
670 sizeof(btDbvtVolume): 32 bytes
671 sizeof(btDbvtNode): 44 bytes
672 [1] btDbvtVolume intersections: 3499 ms (-1%)
673 [2] btDbvtVolume merges: 1934 ms (0%)
674 [3] btDbvt::collideTT: 5485 ms (-21%)
675 [4] btDbvt::collideTT self: 2814 ms (-20%)
676 [5] btDbvt::collideTT xform: 7379 ms (-1%)
677 [6] btDbvt::collideTT xform,self: 7270 ms (-2%)
678 [7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
679 [8] insert/remove: 2093 ms (0%),(1001983 ir/s)
680 [9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
681 [10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
682 [11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
683 [12] btDbvtVolume notequal: 3659 ms (0%)
684 [13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
685 [14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
686 [15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
687 [16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
688 [17] btDbvtVolume select: 3419 ms (0%)
691 struct btDbvtBenchmark
693 struct NilPolicy : btDbvt::ICollide
695 NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
696 void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
697 void Process(const btDbvtNode*) { ++m_pcount; }
698 void Process(const btDbvtNode*,btScalar depth)
702 { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
708 struct P14 : btDbvt::ICollide
712 const btDbvtNode* leaf;
715 void Process(const btDbvtNode* leaf,btScalar depth)
721 static int sortfnc(const Node& a,const Node& b)
723 if(a.depth<b.depth) return(+1);
724 if(a.depth>b.depth) return(-1);
727 btAlignedObjectArray<Node> m_nodes;
729 struct P15 : btDbvt::ICollide
733 const btDbvtNode* leaf;
736 void Process(const btDbvtNode* leaf)
740 n.depth = dot(leaf->volume.Center(),m_axis);
742 static int sortfnc(const Node& a,const Node& b)
744 if(a.depth<b.depth) return(+1);
745 if(a.depth>b.depth) return(-1);
748 btAlignedObjectArray<Node> m_nodes;
751 static btScalar RandUnit()
753 return(rand()/(btScalar)RAND_MAX);
755 static btVector3 RandVector3()
757 return(btVector3(RandUnit(),RandUnit(),RandUnit()));
759 static btVector3 RandVector3(btScalar cs)
761 return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
763 static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
765 return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
767 static btTransform RandTransform(btScalar cs)
770 t.setOrigin(RandVector3(cs));
771 t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
774 static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
777 for(int i=0;i<leaves;++i)
779 dbvt.insert(RandVolume(cs,eb,es),0);
784 void btDbvt::benchmark()
786 static const btScalar cfgVolumeCenterScale = 100;
787 static const btScalar cfgVolumeExentsBase = 1;
788 static const btScalar cfgVolumeExentsScale = 4;
789 static const int cfgLeaves = 8192;
790 static const bool cfgEnable = true;
792 //[1] btDbvtVolume intersections
793 bool cfgBenchmark1_Enable = cfgEnable;
794 static const int cfgBenchmark1_Iterations = 8;
795 static const int cfgBenchmark1_Reference = 3499;
796 //[2] btDbvtVolume merges
797 bool cfgBenchmark2_Enable = cfgEnable;
798 static const int cfgBenchmark2_Iterations = 4;
799 static const int cfgBenchmark2_Reference = 1945;
800 //[3] btDbvt::collideTT
801 bool cfgBenchmark3_Enable = cfgEnable;
802 static const int cfgBenchmark3_Iterations = 512;
803 static const int cfgBenchmark3_Reference = 5485;
804 //[4] btDbvt::collideTT self
805 bool cfgBenchmark4_Enable = cfgEnable;
806 static const int cfgBenchmark4_Iterations = 512;
807 static const int cfgBenchmark4_Reference = 2814;
808 //[5] btDbvt::collideTT xform
809 bool cfgBenchmark5_Enable = cfgEnable;
810 static const int cfgBenchmark5_Iterations = 512;
811 static const btScalar cfgBenchmark5_OffsetScale = 2;
812 static const int cfgBenchmark5_Reference = 7379;
813 //[6] btDbvt::collideTT xform,self
814 bool cfgBenchmark6_Enable = cfgEnable;
815 static const int cfgBenchmark6_Iterations = 512;
816 static const btScalar cfgBenchmark6_OffsetScale = 2;
817 static const int cfgBenchmark6_Reference = 7270;
818 //[7] btDbvt::rayTest
819 bool cfgBenchmark7_Enable = cfgEnable;
820 static const int cfgBenchmark7_Passes = 32;
821 static const int cfgBenchmark7_Iterations = 65536;
822 static const int cfgBenchmark7_Reference = 6307;
824 bool cfgBenchmark8_Enable = cfgEnable;
825 static const int cfgBenchmark8_Passes = 32;
826 static const int cfgBenchmark8_Iterations = 65536;
827 static const int cfgBenchmark8_Reference = 2105;
828 //[9] updates (teleport)
829 bool cfgBenchmark9_Enable = cfgEnable;
830 static const int cfgBenchmark9_Passes = 32;
831 static const int cfgBenchmark9_Iterations = 65536;
832 static const int cfgBenchmark9_Reference = 1879;
833 //[10] updates (jitter)
834 bool cfgBenchmark10_Enable = cfgEnable;
835 static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
836 static const int cfgBenchmark10_Passes = 32;
837 static const int cfgBenchmark10_Iterations = 65536;
838 static const int cfgBenchmark10_Reference = 1244;
839 //[11] optimize (incremental)
840 bool cfgBenchmark11_Enable = cfgEnable;
841 static const int cfgBenchmark11_Passes = 64;
842 static const int cfgBenchmark11_Iterations = 65536;
843 static const int cfgBenchmark11_Reference = 2510;
844 //[12] btDbvtVolume notequal
845 bool cfgBenchmark12_Enable = cfgEnable;
846 static const int cfgBenchmark12_Iterations = 32;
847 static const int cfgBenchmark12_Reference = 3677;
848 //[13] culling(OCL+fullsort)
849 bool cfgBenchmark13_Enable = cfgEnable;
850 static const int cfgBenchmark13_Iterations = 1024;
851 static const int cfgBenchmark13_Reference = 2231;
852 //[14] culling(OCL+qsort)
853 bool cfgBenchmark14_Enable = cfgEnable;
854 static const int cfgBenchmark14_Iterations = 8192;
855 static const int cfgBenchmark14_Reference = 3500;
856 //[15] culling(KDOP+qsort)
857 bool cfgBenchmark15_Enable = cfgEnable;
858 static const int cfgBenchmark15_Iterations = 8192;
859 static const int cfgBenchmark15_Reference = 1151;
860 //[16] insert/remove batch
861 bool cfgBenchmark16_Enable = cfgEnable;
862 static const int cfgBenchmark16_BatchCount = 256;
863 static const int cfgBenchmark16_Passes = 16384;
864 static const int cfgBenchmark16_Reference = 5138;
866 bool cfgBenchmark17_Enable = cfgEnable;
867 static const int cfgBenchmark17_Iterations = 4;
868 static const int cfgBenchmark17_Reference = 3390;
871 printf("Benchmarking dbvt...\r\n");
872 printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
873 printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
874 printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
875 printf("\tLeaves: %u\r\n",cfgLeaves);
876 printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
877 printf("\tsizeof(btDbvtNode): %u bytes\r\n",sizeof(btDbvtNode));
878 if(cfgBenchmark1_Enable)
881 btAlignedObjectArray<btDbvtVolume> volumes;
882 btAlignedObjectArray<bool> results;
883 volumes.resize(cfgLeaves);
884 results.resize(cfgLeaves);
885 for(int i=0;i<cfgLeaves;++i)
887 volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
889 printf("[1] btDbvtVolume intersections: ");
891 for(int i=0;i<cfgBenchmark1_Iterations;++i)
893 for(int j=0;j<cfgLeaves;++j)
895 for(int k=0;k<cfgLeaves;++k)
897 results[k]=Intersect(volumes[j],volumes[k]);
901 const int time=(int)wallclock.getTimeMilliseconds();
902 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
904 if(cfgBenchmark2_Enable)
907 btAlignedObjectArray<btDbvtVolume> volumes;
908 btAlignedObjectArray<btDbvtVolume> results;
909 volumes.resize(cfgLeaves);
910 results.resize(cfgLeaves);
911 for(int i=0;i<cfgLeaves;++i)
913 volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
915 printf("[2] btDbvtVolume merges: ");
917 for(int i=0;i<cfgBenchmark2_Iterations;++i)
919 for(int j=0;j<cfgLeaves;++j)
921 for(int k=0;k<cfgLeaves;++k)
923 Merge(volumes[j],volumes[k],results[k]);
927 const int time=(int)wallclock.getTimeMilliseconds();
928 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
930 if(cfgBenchmark3_Enable)
934 btDbvtBenchmark::NilPolicy policy;
935 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
936 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
937 dbvt[0].optimizeTopDown();
938 dbvt[1].optimizeTopDown();
939 printf("[3] btDbvt::collideTT: ");
941 for(int i=0;i<cfgBenchmark3_Iterations;++i)
943 btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
945 const int time=(int)wallclock.getTimeMilliseconds();
946 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
948 if(cfgBenchmark4_Enable)
952 btDbvtBenchmark::NilPolicy policy;
953 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
954 dbvt.optimizeTopDown();
955 printf("[4] btDbvt::collideTT self: ");
957 for(int i=0;i<cfgBenchmark4_Iterations;++i)
959 btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
961 const int time=(int)wallclock.getTimeMilliseconds();
962 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
964 if(cfgBenchmark5_Enable)
968 btAlignedObjectArray<btTransform> transforms;
969 btDbvtBenchmark::NilPolicy policy;
970 transforms.resize(cfgBenchmark5_Iterations);
971 for(int i=0;i<transforms.size();++i)
973 transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
975 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
976 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
977 dbvt[0].optimizeTopDown();
978 dbvt[1].optimizeTopDown();
979 printf("[5] btDbvt::collideTT xform: ");
981 for(int i=0;i<cfgBenchmark5_Iterations;++i)
983 btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
985 const int time=(int)wallclock.getTimeMilliseconds();
986 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
988 if(cfgBenchmark6_Enable)
992 btAlignedObjectArray<btTransform> transforms;
993 btDbvtBenchmark::NilPolicy policy;
994 transforms.resize(cfgBenchmark6_Iterations);
995 for(int i=0;i<transforms.size();++i)
997 transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
999 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1000 dbvt.optimizeTopDown();
1001 printf("[6] btDbvt::collideTT xform,self: ");
1003 for(int i=0;i<cfgBenchmark6_Iterations;++i)
1005 btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
1007 const int time=(int)wallclock.getTimeMilliseconds();
1008 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
1010 if(cfgBenchmark7_Enable)
1014 btAlignedObjectArray<btVector3> rayorg;
1015 btAlignedObjectArray<btVector3> raydir;
1016 btDbvtBenchmark::NilPolicy policy;
1017 rayorg.resize(cfgBenchmark7_Iterations);
1018 raydir.resize(cfgBenchmark7_Iterations);
1019 for(int i=0;i<rayorg.size();++i)
1021 rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
1022 raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
1024 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1025 dbvt.optimizeTopDown();
1026 printf("[7] btDbvt::rayTest: ");
1028 for(int i=0;i<cfgBenchmark7_Passes;++i)
1030 for(int j=0;j<cfgBenchmark7_Iterations;++j)
1032 btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
1035 const int time=(int)wallclock.getTimeMilliseconds();
1036 unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
1037 printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
1039 if(cfgBenchmark8_Enable)
1043 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1044 dbvt.optimizeTopDown();
1045 printf("[8] insert/remove: ");
1047 for(int i=0;i<cfgBenchmark8_Passes;++i)
1049 for(int j=0;j<cfgBenchmark8_Iterations;++j)
1051 dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
1054 const int time=(int)wallclock.getTimeMilliseconds();
1055 const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
1056 printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
1058 if(cfgBenchmark9_Enable)
1062 btAlignedObjectArray<const btDbvtNode*> leaves;
1063 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1064 dbvt.optimizeTopDown();
1065 dbvt.extractLeaves(dbvt.m_root,leaves);
1066 printf("[9] updates (teleport): ");
1068 for(int i=0;i<cfgBenchmark9_Passes;++i)
1070 for(int j=0;j<cfgBenchmark9_Iterations;++j)
1072 dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
1073 btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
1076 const int time=(int)wallclock.getTimeMilliseconds();
1077 const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
1078 printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
1080 if(cfgBenchmark10_Enable)
1084 btAlignedObjectArray<const btDbvtNode*> leaves;
1085 btAlignedObjectArray<btVector3> vectors;
1086 vectors.resize(cfgBenchmark10_Iterations);
1087 for(int i=0;i<vectors.size();++i)
1089 vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
1091 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1092 dbvt.optimizeTopDown();
1093 dbvt.extractLeaves(dbvt.m_root,leaves);
1094 printf("[10] updates (jitter): ");
1097 for(int i=0;i<cfgBenchmark10_Passes;++i)
1099 for(int j=0;j<cfgBenchmark10_Iterations;++j)
1101 const btVector3& d=vectors[j];
1102 btDbvtNode* l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
1103 btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
1107 const int time=(int)wallclock.getTimeMilliseconds();
1108 const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
1109 printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
1111 if(cfgBenchmark11_Enable)
1115 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1116 dbvt.optimizeTopDown();
1117 printf("[11] optimize (incremental): ");
1119 for(int i=0;i<cfgBenchmark11_Passes;++i)
1121 dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
1123 const int time=(int)wallclock.getTimeMilliseconds();
1124 const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
1125 printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
1127 if(cfgBenchmark12_Enable)
1130 btAlignedObjectArray<btDbvtVolume> volumes;
1131 btAlignedObjectArray<bool> results;
1132 volumes.resize(cfgLeaves);
1133 results.resize(cfgLeaves);
1134 for(int i=0;i<cfgLeaves;++i)
1136 volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
1138 printf("[12] btDbvtVolume notequal: ");
1140 for(int i=0;i<cfgBenchmark12_Iterations;++i)
1142 for(int j=0;j<cfgLeaves;++j)
1144 for(int k=0;k<cfgLeaves;++k)
1146 results[k]=NotEqual(volumes[j],volumes[k]);
1150 const int time=(int)wallclock.getTimeMilliseconds();
1151 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
1153 if(cfgBenchmark13_Enable)
1157 btAlignedObjectArray<btVector3> vectors;
1158 btDbvtBenchmark::NilPolicy policy;
1159 vectors.resize(cfgBenchmark13_Iterations);
1160 for(int i=0;i<vectors.size();++i)
1162 vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
1164 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1165 dbvt.optimizeTopDown();
1166 printf("[13] culling(OCL+fullsort): ");
1168 for(int i=0;i<cfgBenchmark13_Iterations;++i)
1170 static const btScalar offset=0;
1171 policy.m_depth=-SIMD_INFINITY;
1172 dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
1174 const int time=(int)wallclock.getTimeMilliseconds();
1175 const int t=cfgBenchmark13_Iterations;
1176 printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
1178 if(cfgBenchmark14_Enable)
1182 btAlignedObjectArray<btVector3> vectors;
1183 btDbvtBenchmark::P14 policy;
1184 vectors.resize(cfgBenchmark14_Iterations);
1185 for(int i=0;i<vectors.size();++i)
1187 vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
1189 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1190 dbvt.optimizeTopDown();
1191 policy.m_nodes.reserve(cfgLeaves);
1192 printf("[14] culling(OCL+qsort): ");
1194 for(int i=0;i<cfgBenchmark14_Iterations;++i)
1196 static const btScalar offset=0;
1197 policy.m_nodes.resize(0);
1198 dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
1199 policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
1201 const int time=(int)wallclock.getTimeMilliseconds();
1202 const int t=cfgBenchmark14_Iterations;
1203 printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
1205 if(cfgBenchmark15_Enable)
1209 btAlignedObjectArray<btVector3> vectors;
1210 btDbvtBenchmark::P15 policy;
1211 vectors.resize(cfgBenchmark15_Iterations);
1212 for(int i=0;i<vectors.size();++i)
1214 vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
1216 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1217 dbvt.optimizeTopDown();
1218 policy.m_nodes.reserve(cfgLeaves);
1219 printf("[15] culling(KDOP+qsort): ");
1221 for(int i=0;i<cfgBenchmark15_Iterations;++i)
1223 static const btScalar offset=0;
1224 policy.m_nodes.resize(0);
1225 policy.m_axis=vectors[i];
1226 dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
1227 policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
1229 const int time=(int)wallclock.getTimeMilliseconds();
1230 const int t=cfgBenchmark15_Iterations;
1231 printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
1233 if(cfgBenchmark16_Enable)
1237 btAlignedObjectArray<btDbvtNode*> batch;
1238 btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
1239 dbvt.optimizeTopDown();
1240 batch.reserve(cfgBenchmark16_BatchCount);
1241 printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
1243 for(int i=0;i<cfgBenchmark16_Passes;++i)
1245 for(int j=0;j<cfgBenchmark16_BatchCount;++j)
1247 batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
1249 for(int j=0;j<cfgBenchmark16_BatchCount;++j)
1251 dbvt.remove(batch[j]);
1255 const int time=(int)wallclock.getTimeMilliseconds();
1256 const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
1257 printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
1259 if(cfgBenchmark17_Enable)
1262 btAlignedObjectArray<btDbvtVolume> volumes;
1263 btAlignedObjectArray<int> results;
1264 btAlignedObjectArray<int> indices;
1265 volumes.resize(cfgLeaves);
1266 results.resize(cfgLeaves);
1267 indices.resize(cfgLeaves);
1268 for(int i=0;i<cfgLeaves;++i)
1271 volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
1273 for(int i=0;i<cfgLeaves;++i)
1275 btSwap(indices[i],indices[rand()%cfgLeaves]);
1277 printf("[17] btDbvtVolume select: ");
1279 for(int i=0;i<cfgBenchmark17_Iterations;++i)
1281 for(int j=0;j<cfgLeaves;++j)
1283 for(int k=0;k<cfgLeaves;++k)
1285 const int idx=indices[k];
1286 results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
1290 const int time=(int)wallclock.getTimeMilliseconds();
1291 printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);