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 bool b3LeftOfAxis( const b3DbvtNode* node,
|
||||||
static void b3Split( const b3NodeArray& leaves,
|
|
||||||
b3NodeArray& left,
|
|
||||||
b3NodeArray& right,
|
|
||||||
const b3Vector3& org,
|
const b3Vector3& org,
|
||||||
const b3Vector3& axis)
|
const b3Vector3& axis)
|
||||||
{
|
{
|
||||||
left.resize(0);
|
return b3Dot(axis,node->volume.Center()-org) <= 0;
|
||||||
right.resize(0);
|
}
|
||||||
for(int i=0,ni=leaves.size();i<ni;++i)
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
int begin=0;
|
||||||
|
int end=count;
|
||||||
|
for(;;)
|
||||||
{
|
{
|
||||||
if(b3Dot(axis,leaves[i]->volume.Center()-org)<0)
|
while(begin!=end && b3LeftOfAxis(leaves[begin],org,axis))
|
||||||
left.push_back(leaves[i]);
|
{
|
||||||
else
|
++begin;
|
||||||
right.push_back(leaves[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#if B3_DBVT_MERGE_IMPL==B3_DBVT_IMPL_SSE
|
||||||
B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
|
B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
|
||||||
@@ -255,7 +288,7 @@ static b3DbvtVolume b3Bounds( const b3NodeArray& leaves)
|
|||||||
#else
|
#else
|
||||||
b3DbvtVolume volume=leaves[0]->volume;
|
b3DbvtVolume volume=leaves[0]->volume;
|
||||||
#endif
|
#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);
|
b3Merge(volume,leaves[i]->volume,volume);
|
||||||
}
|
}
|
||||||
@@ -264,15 +297,16 @@ static b3DbvtVolume b3Bounds( const b3NodeArray& leaves)
|
|||||||
|
|
||||||
//
|
//
|
||||||
static void b3BottomUp( b3DynamicBvh* pdbvt,
|
static void b3BottomUp( b3DynamicBvh* pdbvt,
|
||||||
b3NodeArray& leaves)
|
b3DbvtNode** leaves,
|
||||||
|
int count)
|
||||||
{
|
{
|
||||||
while(leaves.size()>1)
|
while(count>1)
|
||||||
{
|
{
|
||||||
b3Scalar minsize=B3_INFINITY;
|
b3Scalar minsize=B3_INFINITY;
|
||||||
int minidx[2]={-1,-1};
|
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));
|
const b3Scalar sz=b3Size(b3Merge(leaves[i]->volume,leaves[j]->volume));
|
||||||
if(sz<minsize)
|
if(sz<minsize)
|
||||||
@@ -290,31 +324,33 @@ static void b3BottomUp( b3DynamicBvh* pdbvt,
|
|||||||
n[0]->parent = p;
|
n[0]->parent = p;
|
||||||
n[1]->parent = p;
|
n[1]->parent = p;
|
||||||
leaves[minidx[0]] = p;
|
leaves[minidx[0]] = p;
|
||||||
leaves.swap(minidx[1],leaves.size()-1);
|
leaves[minidx[1]] = leaves[count-1];
|
||||||
leaves.pop_back();
|
--count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
|
static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
|
||||||
b3NodeArray& leaves,
|
b3DbvtNode** leaves,
|
||||||
|
int count,
|
||||||
int bu_treshold)
|
int bu_treshold)
|
||||||
{
|
{
|
||||||
static const b3Vector3 axis[]={b3MakeVector3(1,0,0),
|
static const b3Vector3 axis[]={b3MakeVector3(1,0,0),
|
||||||
b3MakeVector3(0,1,0),
|
b3MakeVector3(0,1,0),
|
||||||
b3MakeVector3(0,0,1)};
|
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();
|
const b3Vector3 org=vol.Center();
|
||||||
b3NodeArray sets[2];
|
int partition;
|
||||||
int bestaxis=-1;
|
int bestaxis=-1;
|
||||||
int bestmidp=leaves.size();
|
int bestmidp=count;
|
||||||
int splitcount[3][2]={{0,0},{0,0},{0,0}};
|
int splitcount[3][2]={{0,0},{0,0},{0,0}};
|
||||||
int i;
|
int i;
|
||||||
for( i=0;i<leaves.size();++i)
|
for( i=0;i<count;++i)
|
||||||
{
|
{
|
||||||
const b3Vector3 x=leaves[i]->volume.Center()-org;
|
const b3Vector3 x=leaves[i]->volume.Center()-org;
|
||||||
for(int j=0;j<3;++j)
|
for(int j=0;j<3;++j)
|
||||||
@@ -336,29 +372,23 @@ static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
|
|||||||
}
|
}
|
||||||
if(bestaxis>=0)
|
if(bestaxis>=0)
|
||||||
{
|
{
|
||||||
sets[0].reserve(splitcount[bestaxis][0]);
|
partition=b3Split(leaves,count,org,axis[bestaxis]);
|
||||||
sets[1].reserve(splitcount[bestaxis][1]);
|
b3Assert(partition!=0 && partition!=count);
|
||||||
b3Split(leaves,sets[0],sets[1],org,axis[bestaxis]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sets[0].reserve(leaves.size()/2+1);
|
partition=count/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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
b3DbvtNode* node=b3CreateNode(pdbvt,0,vol,0);
|
b3DbvtNode* node=b3CreateNode(pdbvt,0,vol,0);
|
||||||
node->childs[0]=b3TopDown(pdbvt,sets[0],bu_treshold);
|
node->childs[0]=b3TopDown(pdbvt,&leaves[0],partition,bu_treshold);
|
||||||
node->childs[1]=b3TopDown(pdbvt,sets[1],bu_treshold);
|
node->childs[1]=b3TopDown(pdbvt,&leaves[partition],count-partition,bu_treshold);
|
||||||
node->childs[0]->parent=node;
|
node->childs[0]->parent=node;
|
||||||
node->childs[1]->parent=node;
|
node->childs[1]->parent=node;
|
||||||
return(node);
|
return(node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b3BottomUp(pdbvt,leaves);
|
b3BottomUp(pdbvt,leaves,count);
|
||||||
return(leaves[0]);
|
return(leaves[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,7 +472,7 @@ void b3DynamicBvh::optimizeBottomUp()
|
|||||||
b3NodeArray leaves;
|
b3NodeArray leaves;
|
||||||
leaves.reserve(m_leaves);
|
leaves.reserve(m_leaves);
|
||||||
b3FetchLeaves(this,m_root,leaves);
|
b3FetchLeaves(this,m_root,leaves);
|
||||||
b3BottomUp(this,leaves);
|
b3BottomUp(this,&leaves[0],leaves.size());
|
||||||
m_root=leaves[0];
|
m_root=leaves[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +485,7 @@ void b3DynamicBvh::optimizeTopDown(int bu_treshold)
|
|||||||
b3NodeArray leaves;
|
b3NodeArray leaves;
|
||||||
leaves.reserve(m_leaves);
|
leaves.reserve(m_leaves);
|
||||||
b3FetchLeaves(this,m_root,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,
|
static bool leftOfAxis( const btDbvtNode* node,
|
||||||
tNodeArray& left,
|
|
||||||
tNodeArray& right,
|
|
||||||
const btVector3& org,
|
const btVector3& org,
|
||||||
const btVector3& axis)
|
const btVector3& axis)
|
||||||
{
|
{
|
||||||
left.resize(0);
|
return btDot(axis, node->volume.Center() - org) <= 0;
|
||||||
right.resize(0);
|
}
|
||||||
for(int i=0,ni=leaves.size();i<ni;++i)
|
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
int begin=0;
|
||||||
|
int end=count;
|
||||||
|
for(;;)
|
||||||
{
|
{
|
||||||
if(btDot(axis,leaves[i]->volume.Center()-org)<0)
|
while(begin!=end && leftOfAxis(leaves[begin],org,axis))
|
||||||
left.push_back(leaves[i]);
|
{
|
||||||
else
|
++begin;
|
||||||
right.push_back(leaves[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
|
||||||
ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
|
ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
|
||||||
@@ -257,7 +292,7 @@ static btDbvtVolume bounds( const tNodeArray& leaves)
|
|||||||
#else
|
#else
|
||||||
btDbvtVolume volume=leaves[0]->volume;
|
btDbvtVolume volume=leaves[0]->volume;
|
||||||
#endif
|
#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);
|
Merge(volume,leaves[i]->volume,volume);
|
||||||
}
|
}
|
||||||
@@ -266,15 +301,16 @@ static btDbvtVolume bounds( const tNodeArray& leaves)
|
|||||||
|
|
||||||
//
|
//
|
||||||
static void bottomup( btDbvt* pdbvt,
|
static void bottomup( btDbvt* pdbvt,
|
||||||
tNodeArray& leaves)
|
btDbvtNode** leaves,
|
||||||
|
int count)
|
||||||
{
|
{
|
||||||
while(leaves.size()>1)
|
while(count>1)
|
||||||
{
|
{
|
||||||
btScalar minsize=SIMD_INFINITY;
|
btScalar minsize=SIMD_INFINITY;
|
||||||
int minidx[2]={-1,-1};
|
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));
|
const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
|
||||||
if(sz<minsize)
|
if(sz<minsize)
|
||||||
@@ -292,31 +328,33 @@ static void bottomup( btDbvt* pdbvt,
|
|||||||
n[0]->parent = p;
|
n[0]->parent = p;
|
||||||
n[1]->parent = p;
|
n[1]->parent = p;
|
||||||
leaves[minidx[0]] = p;
|
leaves[minidx[0]] = p;
|
||||||
leaves.swap(minidx[1],leaves.size()-1);
|
leaves[minidx[1]] = leaves[count-1];
|
||||||
leaves.pop_back();
|
--count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
static btDbvtNode* topdown(btDbvt* pdbvt,
|
static btDbvtNode* topdown(btDbvt* pdbvt,
|
||||||
tNodeArray& leaves,
|
btDbvtNode** leaves,
|
||||||
|
int count,
|
||||||
int bu_treshold)
|
int bu_treshold)
|
||||||
{
|
{
|
||||||
static const btVector3 axis[]={btVector3(1,0,0),
|
static const btVector3 axis[]={btVector3(1,0,0),
|
||||||
btVector3(0,1,0),
|
btVector3(0,1,0),
|
||||||
btVector3(0,0,1)};
|
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();
|
const btVector3 org=vol.Center();
|
||||||
tNodeArray sets[2];
|
int partition;
|
||||||
int bestaxis=-1;
|
int bestaxis=-1;
|
||||||
int bestmidp=leaves.size();
|
int bestmidp=count;
|
||||||
int splitcount[3][2]={{0,0},{0,0},{0,0}};
|
int splitcount[3][2]={{0,0},{0,0},{0,0}};
|
||||||
int i;
|
int i;
|
||||||
for( i=0;i<leaves.size();++i)
|
for( i=0;i<count;++i)
|
||||||
{
|
{
|
||||||
const btVector3 x=leaves[i]->volume.Center()-org;
|
const btVector3 x=leaves[i]->volume.Center()-org;
|
||||||
for(int j=0;j<3;++j)
|
for(int j=0;j<3;++j)
|
||||||
@@ -338,29 +376,23 @@ static btDbvtNode* topdown(btDbvt* pdbvt,
|
|||||||
}
|
}
|
||||||
if(bestaxis>=0)
|
if(bestaxis>=0)
|
||||||
{
|
{
|
||||||
sets[0].reserve(splitcount[bestaxis][0]);
|
partition=split(leaves,count,org,axis[bestaxis]);
|
||||||
sets[1].reserve(splitcount[bestaxis][1]);
|
btAssert(partition!=0 && partition!=count);
|
||||||
split(leaves,sets[0],sets[1],org,axis[bestaxis]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sets[0].reserve(leaves.size()/2+1);
|
partition=count/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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
btDbvtNode* node=createnode(pdbvt,0,vol,0);
|
btDbvtNode* node=createnode(pdbvt,0,vol,0);
|
||||||
node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
|
node->childs[0]=topdown(pdbvt,&leaves[0],partition,bu_treshold);
|
||||||
node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
|
node->childs[1]=topdown(pdbvt,&leaves[partition],count-partition,bu_treshold);
|
||||||
node->childs[0]->parent=node;
|
node->childs[0]->parent=node;
|
||||||
node->childs[1]->parent=node;
|
node->childs[1]->parent=node;
|
||||||
return(node);
|
return(node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bottomup(pdbvt,leaves);
|
bottomup(pdbvt,leaves,count);
|
||||||
return(leaves[0]);
|
return(leaves[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,7 +476,7 @@ void btDbvt::optimizeBottomUp()
|
|||||||
tNodeArray leaves;
|
tNodeArray leaves;
|
||||||
leaves.reserve(m_leaves);
|
leaves.reserve(m_leaves);
|
||||||
fetchleaves(this,m_root,leaves);
|
fetchleaves(this,m_root,leaves);
|
||||||
bottomup(this,leaves);
|
bottomup(this,&leaves[0],leaves.size());
|
||||||
m_root=leaves[0];
|
m_root=leaves[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +489,7 @@ void btDbvt::optimizeTopDown(int bu_treshold)
|
|||||||
tNodeArray leaves;
|
tNodeArray leaves;
|
||||||
leaves.reserve(m_leaves);
|
leaves.reserve(m_leaves);
|
||||||
fetchleaves(this,m_root,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