diff --git a/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp b/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp index 16991bc04..0f04efe33 100644 --- a/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp +++ b/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp @@ -227,26 +227,59 @@ static void b3FetchLeaves(b3DynamicBvh* pdbvt, } } -// -static void b3Split( const b3NodeArray& leaves, - b3NodeArray& left, - b3NodeArray& right, +static bool b3LeftOfAxis( const b3DbvtNode* node, + const b3Vector3& org, + const b3Vector3& axis) +{ + return b3Dot(axis,node->volume.Center()-org) <= 0; +} + +// Partitions leaves such that leaves[0, n) are on the +// left of axis, and leaves[n, count) are on the right +// of axis. returns N. +static int b3Split( b3DbvtNode** leaves, + int count, const b3Vector3& org, const b3Vector3& axis) { - left.resize(0); - right.resize(0); - for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) - left.push_back(leaves[i]); - else - right.push_back(leaves[i]); + while(begin!=end && b3LeftOfAxis(leaves[begin],org,axis)) + { + ++begin; + } + + if(begin==end) + { + break; + } + + while(begin!=end && !b3LeftOfAxis(leaves[end-1],org,axis)) + { + --end; + } + + if(begin==end) + { + break; + } + + // swap out of place nodes + --end; + b3DbvtNode* temp=leaves[begin]; + leaves[begin]=leaves[end]; + leaves[end]=temp; + ++begin; } + + return begin; } // -static b3DbvtVolume b3Bounds( const b3NodeArray& leaves) +static b3DbvtVolume b3Bounds( b3DbvtNode** leaves, + int count) { #if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]); @@ -255,7 +288,7 @@ static b3DbvtVolume b3Bounds( const b3NodeArray& leaves) #else b3DbvtVolume volume=leaves[0]->volume; #endif - for(int i=1,ni=leaves.size();ivolume,volume); } @@ -264,15 +297,16 @@ static b3DbvtVolume b3Bounds( const b3NodeArray& leaves) // static void b3BottomUp( b3DynamicBvh* pdbvt, - b3NodeArray& leaves) + b3DbvtNode** leaves, + int count) { - while(leaves.size()>1) + while(count>1) { b3Scalar minsize=B3_INFINITY; int minidx[2]={-1,-1}; - for(int i=0;ivolume,leaves[j]->volume)); if(szparent = p; n[1]->parent = p; leaves[minidx[0]] = p; - leaves.swap(minidx[1],leaves.size()-1); - leaves.pop_back(); + leaves[minidx[1]] = leaves[count-1]; + --count; } } // static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt, - b3NodeArray& leaves, + b3DbvtNode** leaves, + int count, int bu_treshold) { static const b3Vector3 axis[]={b3MakeVector3(1,0,0), b3MakeVector3(0,1,0), b3MakeVector3(0,0,1)}; - if(leaves.size()>1) + b3Assert(bu_treshold>1); + if(count>1) { - if(leaves.size()>bu_treshold) + if(count>bu_treshold) { - const b3DbvtVolume vol=b3Bounds(leaves); + const b3DbvtVolume vol=b3Bounds(leaves,count); const b3Vector3 org=vol.Center(); - b3NodeArray sets[2]; + int partition; int bestaxis=-1; - int bestmidp=leaves.size(); + int bestmidp=count; int splitcount[3][2]={{0,0},{0,0},{0,0}}; int i; - for( i=0;ivolume.Center()-org; for(int j=0;j<3;++j) @@ -336,29 +372,23 @@ static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt, } if(bestaxis>=0) { - sets[0].reserve(splitcount[bestaxis][0]); - sets[1].reserve(splitcount[bestaxis][1]); - b3Split(leaves,sets[0],sets[1],org,axis[bestaxis]); + partition=b3Split(leaves,count,org,axis[bestaxis]); + b3Assert(partition!=0 && partition!=count); } else { - sets[0].reserve(leaves.size()/2+1); - sets[1].reserve(leaves.size()/2); - for(int i=0,ni=leaves.size();ichilds[0]=b3TopDown(pdbvt,sets[0],bu_treshold); - node->childs[1]=b3TopDown(pdbvt,sets[1],bu_treshold); + node->childs[0]=b3TopDown(pdbvt,&leaves[0],partition,bu_treshold); + node->childs[1]=b3TopDown(pdbvt,&leaves[partition],count-partition,bu_treshold); node->childs[0]->parent=node; node->childs[1]->parent=node; return(node); } else { - b3BottomUp(pdbvt,leaves); + b3BottomUp(pdbvt,leaves,count); return(leaves[0]); } } @@ -442,7 +472,7 @@ void b3DynamicBvh::optimizeBottomUp() b3NodeArray leaves; leaves.reserve(m_leaves); b3FetchLeaves(this,m_root,leaves); - b3BottomUp(this,leaves); + b3BottomUp(this,&leaves[0],leaves.size()); m_root=leaves[0]; } } @@ -455,7 +485,7 @@ void b3DynamicBvh::optimizeTopDown(int bu_treshold) b3NodeArray leaves; leaves.reserve(m_leaves); b3FetchLeaves(this,m_root,leaves); - m_root=b3TopDown(this,leaves,bu_treshold); + m_root=b3TopDown(this,&leaves[0],leaves.size(),bu_treshold); } } diff --git a/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp index 2ca20cdd8..d791d0741 100644 --- a/src/BulletCollision/BroadphaseCollision/btDbvt.cpp +++ b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -229,25 +229,60 @@ static void fetchleaves(btDbvt* pdbvt, } // -static void split( const tNodeArray& leaves, - tNodeArray& left, - tNodeArray& right, +static bool leftOfAxis( const btDbvtNode* node, + const btVector3& org, + const btVector3& axis) +{ + return btDot(axis, node->volume.Center() - org) <= 0; +} + + +// Partitions leaves such that leaves[0, n) are on the +// left of axis, and leaves[n, count) are on the right +// of axis. returns N. +static int split( btDbvtNode** leaves, + int count, const btVector3& org, const btVector3& axis) { - left.resize(0); - right.resize(0); - for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) - left.push_back(leaves[i]); - else - right.push_back(leaves[i]); + while(begin!=end && leftOfAxis(leaves[begin],org,axis)) + { + ++begin; + } + + if(begin==end) + { + break; + } + + while(begin!=end && !leftOfAxis(leaves[end-1],org,axis)) + { + --end; + } + + if(begin==end) + { + break; + } + + // swap out of place nodes + --end; + btDbvtNode* temp=leaves[begin]; + leaves[begin]=leaves[end]; + leaves[end]=temp; + ++begin; } + + return begin; } // -static btDbvtVolume bounds( const tNodeArray& leaves) +static btDbvtVolume bounds( btDbvtNode** leaves, + int count) { #if DBVT_MERGE_IMPL==DBVT_IMPL_SSE ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]); @@ -257,7 +292,7 @@ static btDbvtVolume bounds( const tNodeArray& leaves) #else btDbvtVolume volume=leaves[0]->volume; #endif - for(int i=1,ni=leaves.size();ivolume,volume); } @@ -266,15 +301,16 @@ static btDbvtVolume bounds( const tNodeArray& leaves) // static void bottomup( btDbvt* pdbvt, - tNodeArray& leaves) + btDbvtNode** leaves, + int count) { - while(leaves.size()>1) + while(count>1) { btScalar minsize=SIMD_INFINITY; int minidx[2]={-1,-1}; - for(int i=0;ivolume,leaves[j]->volume)); if(szparent = p; n[1]->parent = p; leaves[minidx[0]] = p; - leaves.swap(minidx[1],leaves.size()-1); - leaves.pop_back(); + leaves[minidx[1]] = leaves[count-1]; + --count; } } // static btDbvtNode* topdown(btDbvt* pdbvt, - tNodeArray& leaves, + btDbvtNode** leaves, + int count, int bu_treshold) { static const btVector3 axis[]={btVector3(1,0,0), btVector3(0,1,0), btVector3(0,0,1)}; - if(leaves.size()>1) + btAssert(bu_treshold>2); + if(count>1) { - if(leaves.size()>bu_treshold) + if(count>bu_treshold) { - const btDbvtVolume vol=bounds(leaves); + const btDbvtVolume vol=bounds(leaves,count); const btVector3 org=vol.Center(); - tNodeArray sets[2]; + int partition; int bestaxis=-1; - int bestmidp=leaves.size(); + int bestmidp=count; int splitcount[3][2]={{0,0},{0,0},{0,0}}; int i; - for( i=0;ivolume.Center()-org; for(int j=0;j<3;++j) @@ -338,29 +376,23 @@ static btDbvtNode* topdown(btDbvt* pdbvt, } if(bestaxis>=0) { - sets[0].reserve(splitcount[bestaxis][0]); - sets[1].reserve(splitcount[bestaxis][1]); - split(leaves,sets[0],sets[1],org,axis[bestaxis]); + partition=split(leaves,count,org,axis[bestaxis]); + btAssert(partition!=0 && partition!=count); } else { - sets[0].reserve(leaves.size()/2+1); - sets[1].reserve(leaves.size()/2); - for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); - node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); + node->childs[0]=topdown(pdbvt,&leaves[0],partition,bu_treshold); + node->childs[1]=topdown(pdbvt,&leaves[partition],count-partition,bu_treshold); node->childs[0]->parent=node; node->childs[1]->parent=node; return(node); } else { - bottomup(pdbvt,leaves); + bottomup(pdbvt,leaves,count); return(leaves[0]); } } @@ -444,7 +476,7 @@ void btDbvt::optimizeBottomUp() tNodeArray leaves; leaves.reserve(m_leaves); fetchleaves(this,m_root,leaves); - bottomup(this,leaves); + bottomup(this,&leaves[0],leaves.size()); m_root=leaves[0]; } } @@ -457,7 +489,7 @@ void btDbvt::optimizeTopDown(int bu_treshold) tNodeArray leaves; leaves.reserve(m_leaves); fetchleaves(this,m_root,leaves); - m_root=topdown(this,leaves,bu_treshold); + m_root=topdown(this,&leaves[0],leaves.size(),bu_treshold); } }