Merge pull request #1286 from mendsley/clean_vbt_allocations
Optimize Dbvt trees in place
This commit is contained in:
@@ -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();i<ni;++i)
|
||||
int begin=0;
|
||||
int end=count;
|
||||
for(;;)
|
||||
{
|
||||
if(b3Dot(axis,leaves[i]->volume.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();i<ni;++i)
|
||||
for(int i=1,ni=count;i<ni;++i)
|
||||
{
|
||||
b3Merge(volume,leaves[i]->volume,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;i<leaves.size();++i)
|
||||
for(int i=0;i<count;++i)
|
||||
{
|
||||
for(int j=i+1;j<leaves.size();++j)
|
||||
for(int j=i+1;j<count;++j)
|
||||
{
|
||||
const b3Scalar sz=b3Size(b3Merge(leaves[i]->volume,leaves[j]->volume));
|
||||
if(sz<minsize)
|
||||
@@ -290,31 +324,33 @@ static void b3BottomUp( b3DynamicBvh* pdbvt,
|
||||
n[0]->parent = 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;i<leaves.size();++i)
|
||||
for( i=0;i<count;++i)
|
||||
{
|
||||
const b3Vector3 x=leaves[i]->volume.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();i<ni;++i)
|
||||
{
|
||||
sets[i&1].push_back(leaves[i]);
|
||||
}
|
||||
partition=count/2+1;
|
||||
}
|
||||
b3DbvtNode* node=b3CreateNode(pdbvt,0,vol,0);
|
||||
node->childs[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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();i<ni;++i)
|
||||
int begin=0;
|
||||
int end=count;
|
||||
for(;;)
|
||||
{
|
||||
if(btDot(axis,leaves[i]->volume.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();i<ni;++i)
|
||||
for(int i=1,ni=count;i<ni;++i)
|
||||
{
|
||||
Merge(volume,leaves[i]->volume,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;i<leaves.size();++i)
|
||||
for(int i=0;i<count;++i)
|
||||
{
|
||||
for(int j=i+1;j<leaves.size();++j)
|
||||
for(int j=i+1;j<count;++j)
|
||||
{
|
||||
const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
|
||||
if(sz<minsize)
|
||||
@@ -292,31 +328,33 @@ static void bottomup( btDbvt* pdbvt,
|
||||
n[0]->parent = 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;i<leaves.size();++i)
|
||||
for( i=0;i<count;++i)
|
||||
{
|
||||
const btVector3 x=leaves[i]->volume.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();i<ni;++i)
|
||||
{
|
||||
sets[i&1].push_back(leaves[i]);
|
||||
}
|
||||
partition=count/2+1;
|
||||
}
|
||||
btDbvtNode* node=createnode(pdbvt,0,vol,0);
|
||||
node->childs[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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user