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
43 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
44 : btTriangleMeshShape(meshInterface),
47 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
50 m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
51 //construct bvh from meshInterface
56 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
57 m_bvh = new (mem) btOptimizedBvh();
59 m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
66 void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
68 m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
70 m_localAabbMin.setMin(aabbMin);
71 m_localAabbMax.setMax(aabbMax);
74 void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
76 m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
81 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
85 m_bvh->~btOptimizedBvh();
90 void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
92 struct MyNodeOverlapCallback : public btNodeOverlapCallback
94 btStridingMeshInterface* m_meshInterface;
95 btTriangleCallback* m_callback;
97 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
98 : m_meshInterface(meshInterface),
103 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
105 btVector3 m_triangle[3];
106 const unsigned char* vertexbase;
110 const unsigned char* indexbase;
113 PHY_ScalarType indicestype;
115 m_meshInterface->getLockedReadOnlyVertexIndexBase(
126 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
128 const btVector3& meshScaling = m_meshInterface->getScaling();
129 for (int j = 2; j >= 0; j--)
132 switch (indicestype) {
133 case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
134 case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
135 case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
136 default: btAssert(0);
139 if (type == PHY_FLOAT)
141 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
143 m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
147 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
149 m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
153 /* Perform ray vs. triangle collision here */
154 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
155 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
159 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
161 m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
164 void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
166 struct MyNodeOverlapCallback : public btNodeOverlapCallback
168 btStridingMeshInterface* m_meshInterface;
169 btTriangleCallback* m_callback;
171 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
172 : m_meshInterface(meshInterface),
177 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
179 btVector3 m_triangle[3];
180 const unsigned char* vertexbase;
184 const unsigned char* indexbase;
187 PHY_ScalarType indicestype;
189 m_meshInterface->getLockedReadOnlyVertexIndexBase(
200 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
202 const btVector3& meshScaling = m_meshInterface->getScaling();
203 for (int j = 2; j >= 0; j--)
206 switch (indicestype) {
207 case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
208 case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
209 case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
210 default: btAssert(0);
213 if (type == PHY_FLOAT)
215 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
217 m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
221 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
223 m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
227 /* Perform ray vs. triangle collision here */
228 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
229 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
233 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
235 m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
238 //perform bvh tree traversal and report overlapping triangles to 'callback'
239 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
242 //brute force traverse all triangles
243 btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
246 //first get all the nodes
248 struct MyNodeOverlapCallback : public btNodeOverlapCallback
250 btStridingMeshInterface* m_meshInterface;
251 btTriangleCallback* m_callback;
252 btVector3 m_triangle[3];
255 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
256 : m_meshInterface(meshInterface),
257 m_callback(callback),
262 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
265 const unsigned char* vertexbase;
269 const unsigned char* indexbase;
272 PHY_ScalarType indicestype;
274 m_meshInterface->getLockedReadOnlyVertexIndexBase(
285 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
286 btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
288 const btVector3& meshScaling = m_meshInterface->getScaling();
289 for (int j = 2; j >= 0; j--)
291 int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
293 #ifdef DEBUG_TRIANGLE_MESH
294 printf("%d ,", graphicsindex);
295 #endif //DEBUG_TRIANGLE_MESH
296 if (type == PHY_FLOAT)
298 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
300 m_triangle[j] = btVector3(
301 graphicsbase[0] * meshScaling.getX(),
302 graphicsbase[1] * meshScaling.getY(),
303 graphicsbase[2] * meshScaling.getZ());
307 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
309 m_triangle[j] = btVector3(
310 btScalar(graphicsbase[0]) * meshScaling.getX(),
311 btScalar(graphicsbase[1]) * meshScaling.getY(),
312 btScalar(graphicsbase[2]) * meshScaling.getZ());
314 #ifdef DEBUG_TRIANGLE_MESH
315 printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
316 #endif //DEBUG_TRIANGLE_MESH
319 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
320 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
324 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
326 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);
369 ///fills the dataBuffer and returns the struct name (and 0 on failure)
370 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
372 btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
374 btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
376 m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
378 trimeshData->m_collisionMargin = float(m_collisionMargin);
380 if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
382 void* chunk = serializer->findPointer(m_bvh);
385 #ifdef BT_USE_DOUBLE_PRECISION
386 trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
387 trimeshData->m_quantizedFloatBvh = 0;
389 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
390 trimeshData->m_quantizedDoubleBvh = 0;
391 #endif //BT_USE_DOUBLE_PRECISION
395 #ifdef BT_USE_DOUBLE_PRECISION
396 trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
397 trimeshData->m_quantizedFloatBvh = 0;
399 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
400 trimeshData->m_quantizedDoubleBvh = 0;
401 #endif //BT_USE_DOUBLE_PRECISION
403 int sz = m_bvh->calculateSerializeBufferSizeNew();
404 btChunk* chunk = serializer->allocate(sz, 1);
405 const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
406 serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
411 trimeshData->m_quantizedFloatBvh = 0;
412 trimeshData->m_quantizedDoubleBvh = 0;
415 if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
417 void* chunk = serializer->findPointer(m_triangleInfoMap);
420 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
424 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
425 int sz = m_triangleInfoMap->calculateSerializeBufferSize();
426 btChunk* chunk = serializer->allocate(sz, 1);
427 const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
428 serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
433 trimeshData->m_triangleInfoMap = 0;
436 // Fill padding with zeros to appease msan.
437 memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
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);