Merge pull request #1286 from mendsley/clean_vbt_allocations

Optimize Dbvt trees in place
This commit is contained in:
erwincoumans
2017-09-24 20:35:57 -07:00
committed by GitHub
2 changed files with 141 additions and 79 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}