allow incremental refitting of the quantized aabb tree
This commit is contained in:
@@ -28,12 +28,36 @@ btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInte
|
|||||||
#ifndef DISABLE_BVH
|
#ifndef DISABLE_BVH
|
||||||
|
|
||||||
m_bvh = new btOptimizedBvh();
|
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
|
#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()
|
void btBvhTriangleMeshShape::refitTree()
|
||||||
{
|
{
|
||||||
m_bvh->refit( m_meshInterface );
|
m_bvh->refit( m_meshInterface );
|
||||||
@@ -140,8 +164,12 @@ void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
|
|||||||
{
|
{
|
||||||
btTriangleMeshShape::setLocalScaling(scaling);
|
btTriangleMeshShape::setLocalScaling(scaling);
|
||||||
delete m_bvh;
|
delete m_bvh;
|
||||||
|
///rescale aabb, instead of calculating?
|
||||||
|
m_localAabbMin*=scaling;
|
||||||
|
m_localAabbMax*=scaling;
|
||||||
m_bvh = new btOptimizedBvh();
|
m_bvh = new btOptimizedBvh();
|
||||||
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression);
|
|
||||||
//rebuild the bvh...
|
//rebuild the bvh...
|
||||||
|
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ public:
|
|||||||
btBvhTriangleMeshShape() :btTriangleMeshShape(0) {};
|
btBvhTriangleMeshShape() :btTriangleMeshShape(0) {};
|
||||||
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression);
|
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();
|
virtual ~btBvhTriangleMeshShape();
|
||||||
|
|
||||||
|
|
||||||
@@ -48,6 +51,9 @@ public:
|
|||||||
|
|
||||||
void refitTree();
|
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
|
//debugging
|
||||||
virtual char* getName()const {return "BVHTRIANGLEMESH";}
|
virtual char* getName()const {return "BVHTRIANGLEMESH";}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
m_useQuantization = useQuantizedAabbCompression;
|
||||||
|
|
||||||
@@ -114,7 +114,8 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
|
|||||||
if (m_useQuantization)
|
if (m_useQuantization)
|
||||||
{
|
{
|
||||||
|
|
||||||
initQuantizationValues(triangles);
|
//initialize quantization values
|
||||||
|
setQuantizationValues(bvhAabbMin,bvhAabbMax);
|
||||||
|
|
||||||
QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
|
QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
|
||||||
|
|
||||||
@@ -158,13 +159,51 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
|
|
||||||
{
|
|
||||||
if (m_useQuantization)
|
|
||||||
{
|
|
||||||
int nodeSubPart=0;
|
|
||||||
|
|
||||||
initQuantizationValues(meshInterface);
|
void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
|
||||||
|
{
|
||||||
|
//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++)
|
||||||
|
{
|
||||||
|
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
|
||||||
|
|
||||||
|
bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
|
||||||
|
if (overlap)
|
||||||
|
{
|
||||||
|
updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize);
|
||||||
|
|
||||||
|
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
|
//get access info to trianglemesh data
|
||||||
const unsigned char *vertexbase;
|
const unsigned char *vertexbase;
|
||||||
@@ -180,9 +219,9 @@ void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
|
|||||||
btVector3 triangleVerts[3];
|
btVector3 triangleVerts[3];
|
||||||
btVector3 aabbMin,aabbMax;
|
btVector3 aabbMin,aabbMax;
|
||||||
const btVector3& meshScaling = meshInterface->getScaling();
|
const btVector3& meshScaling = meshInterface->getScaling();
|
||||||
int numNodes = m_curNodeIndex;
|
|
||||||
int i;
|
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);
|
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
|
///now update all subtree headers
|
||||||
|
|
||||||
|
int i;
|
||||||
for (i=0;i<m_SubtreeHeaders.size();i++)
|
for (i=0;i<m_SubtreeHeaders.size();i++)
|
||||||
{
|
{
|
||||||
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
|
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
|
||||||
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
|
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} 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()
|
btOptimizedBvh::~btOptimizedBvh()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
|
||||||
{
|
{
|
||||||
@@ -287,7 +285,7 @@ public:
|
|||||||
|
|
||||||
virtual ~btOptimizedBvh();
|
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;
|
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
@@ -305,6 +303,11 @@ public:
|
|||||||
|
|
||||||
void refit(btStridingMeshInterface* triangles);
|
void refit(btStridingMeshInterface* triangles);
|
||||||
|
|
||||||
|
void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
|
||||||
|
|
||||||
|
void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode);
|
||||||
|
|
||||||
|
|
||||||
QuantizedNodeArray& getQuantizedNodeArray()
|
QuantizedNodeArray& getQuantizedNodeArray()
|
||||||
{
|
{
|
||||||
return m_quantizedContiguousNodes;
|
return m_quantizedContiguousNodes;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -49,6 +49,8 @@ class btStridingMeshInterface
|
|||||||
|
|
||||||
void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
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
|
/// get read and write access to a subpart of a triangle mesh
|
||||||
/// this subpart has a continuous array of vertices and indices
|
/// this subpart has a continuous array of vertices and indices
|
||||||
|
|||||||
Reference in New Issue
Block a user