allow incremental refitting of the quantized aabb tree

This commit is contained in:
ejcoumans
2007-04-10 21:40:43 +00:00
parent 853bafb7ae
commit 2cf026aae3
6 changed files with 153 additions and 55 deletions

View File

@@ -28,12 +28,36 @@ btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInte
#ifndef DISABLE_BVH
m_bvh = new btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression);
btVector3 bvhAabbMin,bvhAabbMax;
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
#endif //DISABLE_BVH
}
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression)
{
//construct bvh from meshInterface
#ifndef DISABLE_BVH
m_bvh = new btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
#endif //DISABLE_BVH
}
void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
{
m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
m_localAabbMin.setMin(aabbMin);
m_localAabbMax.setMax(aabbMax);
}
void btBvhTriangleMeshShape::refitTree()
{
m_bvh->refit( m_meshInterface );
@@ -140,8 +164,12 @@ void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
btTriangleMeshShape::setLocalScaling(scaling);
delete m_bvh;
///rescale aabb, instead of calculating?
m_localAabbMin*=scaling;
m_localAabbMax*=scaling;
m_bvh = new btOptimizedBvh();
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression);
//rebuild the bvh...
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
}
}

View File

@@ -32,6 +32,9 @@ public:
btBvhTriangleMeshShape() :btTriangleMeshShape(0) {};
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression);
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual ~btBvhTriangleMeshShape();
@@ -48,6 +51,9 @@ public:
void refitTree();
///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
//debugging
virtual char* getName()const {return "BVHTRIANGLEMESH";}

View File

@@ -29,7 +29,7 @@ btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false),
}
void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression)
void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
{
m_useQuantization = useQuantizedAabbCompression;
@@ -114,7 +114,8 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
if (m_useQuantization)
{
initQuantizationValues(triangles);
//initialize quantization values
setQuantizationValues(bvhAabbMin,bvhAabbMax);
QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
@@ -158,15 +159,53 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
}
void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
{
if (m_useQuantization)
//incrementally initialize quantization values
btAssert(m_useQuantization);
btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
///we should update all quantization values, using updateBvhNodes(meshInterface);
///but we only update chunks that overlap the given aabb
unsigned short quantizedQueryAabbMin[3];
unsigned short quantizedQueryAabbMax[3];
quantizeWithClamp(&quantizedQueryAabbMin[0],aabbMin);
quantizeWithClamp(&quantizedQueryAabbMax[0],aabbMax);
int i;
for (i=0;i<this->m_SubtreeHeaders.size();i++)
{
int nodeSubPart=0;
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
initQuantizationValues(meshInterface);
bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
if (overlap)
{
updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize);
//get access info to trianglemesh data
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
}
}
void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode)
{
btAssert(m_useQuantization);
int nodeSubPart=0;
//get access info to trianglemesh data
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
@@ -180,9 +219,9 @@ void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
btVector3 triangleVerts[3];
btVector3 aabbMin,aabbMax;
const btVector3& meshScaling = meshInterface->getScaling();
int numNodes = m_curNodeIndex;
int i;
for (i=numNodes-1;i>=0;i--)
for (i=endNode-1;i>=firstNode;i--)
{
@@ -250,61 +289,47 @@ void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
{
m_bvhAabbMin = bvhAabbMin;
m_bvhAabbMax = bvhAabbMax;
btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize;
}
void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
{
if (m_useQuantization)
{
//calculate new aabb
btVector3 aabbMin,aabbMax;
meshInterface->calculateAabbBruteForce(aabbMin,aabbMax);
setQuantizationValues(aabbMin,aabbMax);
updateBvhNodes(meshInterface,0,m_curNodeIndex);
///now update all subtree headers
int i;
for (i=0;i<m_SubtreeHeaders.size();i++)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
} else
{
}
}
void btOptimizedBvh::initQuantizationValues(btStridingMeshInterface* triangles)
{
struct AabbCalculationCallback : public btInternalTriangleIndexCallback
{
btVector3 m_aabbMin;
btVector3 m_aabbMax;
AabbCalculationCallback()
{
m_aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
m_aabbMin.setMin(triangle[0]);
m_aabbMax.setMax(triangle[0]);
m_aabbMin.setMin(triangle[1]);
m_aabbMax.setMax(triangle[1]);
m_aabbMin.setMin(triangle[2]);
m_aabbMax.setMax(triangle[2]);
}
};
//first calculate the total aabb for all triangles
AabbCalculationCallback aabbCallback;
btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
triangles->InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
//initialize quantization values
m_bvhAabbMin = aabbCallback.m_aabbMin;
m_bvhAabbMax = aabbCallback.m_aabbMax;
btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize;
}
btOptimizedBvh::~btOptimizedBvh()
{
}

View File

@@ -201,9 +201,7 @@ ATTRIBUTE_ALIGNED16(class) btOptimizedBvh
}
void initQuantizationValues(btStridingMeshInterface* triangles);
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
@@ -287,7 +285,7 @@ public:
virtual ~btOptimizedBvh();
void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression);
void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
@@ -305,6 +303,11 @@ public:
void refit(btStridingMeshInterface* triangles);
void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode);
QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;

View File

@@ -83,3 +83,37 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
}
}
void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
{
struct AabbCalculationCallback : public btInternalTriangleIndexCallback
{
btVector3 m_aabbMin;
btVector3 m_aabbMax;
AabbCalculationCallback()
{
m_aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
m_aabbMin.setMin(triangle[0]);
m_aabbMax.setMax(triangle[0]);
m_aabbMin.setMin(triangle[1]);
m_aabbMax.setMax(triangle[1]);
m_aabbMin.setMin(triangle[2]);
m_aabbMax.setMax(triangle[2]);
}
};
//first calculate the total aabb for all triangles
AabbCalculationCallback aabbCallback;
aabbMin.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
aabbMax.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30));
InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
aabbMin = aabbCallback.m_aabbMin;
aabbMax = aabbCallback.m_aabbMax;
}

View File

@@ -49,6 +49,8 @@ class btStridingMeshInterface
void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
///brute force method to calculate aabb
void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
/// get read and write access to a subpart of a triangle mesh
/// this subpart has a continuous array of vertices and indices