diff --git a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp index 4acc4002e..43b06e080 100644 --- a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp +++ b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -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); + } } diff --git a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index ae3f845a7..f6195c808 100644 --- a/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -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";} diff --git a/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index 76d7d0f53..619927cc3 100644 --- a/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -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;im_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;iInternalProcessAllTriangles(&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() { } diff --git a/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index 05abd7885..e5fd5f29a 100644 --- a/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -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; diff --git a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index a0d58eac0..c8368d27e 100644 --- a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -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; +} \ No newline at end of file diff --git a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h index abf7cf256..d7b354b78 100644 --- a/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h +++ b/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -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