2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
18 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
19 #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
20 #include "LinearMath/btSerializer.h"
22 ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
23 ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
24 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
25 :btTriangleMeshShape(meshInterface),
28 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
31 m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
32 //construct bvh from meshInterface
44 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
45 :btTriangleMeshShape(meshInterface),
48 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
51 m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
52 //construct bvh from meshInterface
57 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
58 m_bvh = new (mem) btOptimizedBvh();
60 m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
68 void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
70 m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
72 m_localAabbMin.setMin(aabbMin);
73 m_localAabbMax.setMax(aabbMax);
77 void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
79 m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
84 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
88 m_bvh->~btOptimizedBvh();
93 void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
95 struct MyNodeOverlapCallback : public btNodeOverlapCallback
97 btStridingMeshInterface* m_meshInterface;
98 btTriangleCallback* m_callback;
100 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
101 :m_meshInterface(meshInterface),
106 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
108 btVector3 m_triangle[3];
109 const unsigned char *vertexbase;
113 const unsigned char *indexbase;
116 PHY_ScalarType indicestype;
118 m_meshInterface->getLockedReadOnlyVertexIndexBase(
129 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
130 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
132 const btVector3& meshScaling = m_meshInterface->getScaling();
133 for (int j=2;j>=0;j--)
135 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
137 if (type == PHY_FLOAT)
139 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
141 m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
145 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
147 m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
151 /* Perform ray vs. triangle collision here */
152 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
153 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
157 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
159 m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
162 void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
164 struct MyNodeOverlapCallback : public btNodeOverlapCallback
166 btStridingMeshInterface* m_meshInterface;
167 btTriangleCallback* m_callback;
169 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
170 :m_meshInterface(meshInterface),
175 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
177 btVector3 m_triangle[3];
178 const unsigned char *vertexbase;
182 const unsigned char *indexbase;
185 PHY_ScalarType indicestype;
187 m_meshInterface->getLockedReadOnlyVertexIndexBase(
198 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
199 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
201 const btVector3& meshScaling = m_meshInterface->getScaling();
202 for (int j=2;j>=0;j--)
204 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
206 if (type == PHY_FLOAT)
208 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
210 m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
214 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
216 m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
220 /* Perform ray vs. triangle collision here */
221 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
222 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
226 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
228 m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
231 //perform bvh tree traversal and report overlapping triangles to 'callback'
232 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
236 //brute force traverse all triangles
237 btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
240 //first get all the nodes
243 struct MyNodeOverlapCallback : public btNodeOverlapCallback
245 btStridingMeshInterface* m_meshInterface;
246 btTriangleCallback* m_callback;
247 btVector3 m_triangle[3];
250 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
251 :m_meshInterface(meshInterface),
256 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
258 const unsigned char *vertexbase;
262 const unsigned char *indexbase;
265 PHY_ScalarType indicestype;
268 m_meshInterface->getLockedReadOnlyVertexIndexBase(
279 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
280 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
282 const btVector3& meshScaling = m_meshInterface->getScaling();
283 for (int j=2;j>=0;j--)
286 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
289 #ifdef DEBUG_TRIANGLE_MESH
290 printf("%d ,",graphicsindex);
291 #endif //DEBUG_TRIANGLE_MESH
292 if (type == PHY_FLOAT)
294 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
296 m_triangle[j] = btVector3(
297 graphicsbase[0]*meshScaling.getX(),
298 graphicsbase[1]*meshScaling.getY(),
299 graphicsbase[2]*meshScaling.getZ());
303 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
305 m_triangle[j] = btVector3(
306 btScalar(graphicsbase[0])*meshScaling.getX(),
307 btScalar(graphicsbase[1])*meshScaling.getY(),
308 btScalar(graphicsbase[2])*meshScaling.getZ());
310 #ifdef DEBUG_TRIANGLE_MESH
311 printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
312 #endif //DEBUG_TRIANGLE_MESH
315 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
316 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
321 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
323 m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
331 void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
333 if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
335 btTriangleMeshShape::setLocalScaling(scaling);
340 void btBvhTriangleMeshShape::buildOptimizedBvh()
344 m_bvh->~btOptimizedBvh();
345 btAlignedFree(m_bvh);
347 ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
348 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
349 m_bvh = new(mem) btOptimizedBvh();
351 m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
355 void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
358 btAssert(!m_ownsBvh);
362 // update the scaling without rebuilding the bvh
363 if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
365 btTriangleMeshShape::setLocalScaling(scaling);
371 ///fills the dataBuffer and returns the struct name (and 0 on failure)
372 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
374 btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
376 btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
378 m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
380 trimeshData->m_collisionMargin = float(m_collisionMargin);
384 if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
386 void* chunk = serializer->findPointer(m_bvh);
389 #ifdef BT_USE_DOUBLE_PRECISION
390 trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
391 trimeshData->m_quantizedFloatBvh = 0;
393 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
394 trimeshData->m_quantizedDoubleBvh= 0;
395 #endif //BT_USE_DOUBLE_PRECISION
399 #ifdef BT_USE_DOUBLE_PRECISION
400 trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
401 trimeshData->m_quantizedFloatBvh = 0;
403 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
404 trimeshData->m_quantizedDoubleBvh= 0;
405 #endif //BT_USE_DOUBLE_PRECISION
407 int sz = m_bvh->calculateSerializeBufferSizeNew();
408 btChunk* chunk = serializer->allocate(sz,1);
409 const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
410 serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
414 trimeshData->m_quantizedFloatBvh = 0;
415 trimeshData->m_quantizedDoubleBvh = 0;
420 if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
422 void* chunk = serializer->findPointer(m_triangleInfoMap);
425 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
428 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
429 int sz = m_triangleInfoMap->calculateSerializeBufferSize();
430 btChunk* chunk = serializer->allocate(sz,1);
431 const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
432 serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
436 trimeshData->m_triangleInfoMap = 0;
439 return "btTriangleMeshShapeData";
442 void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
446 int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
447 btChunk* chunk = serializer->allocate(len,1);
448 const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
449 serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
453 void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
455 if (m_triangleInfoMap)
457 int len = m_triangleInfoMap->calculateSerializeBufferSize();
458 btChunk* chunk = serializer->allocate(len,1);
459 const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
460 serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);