Bullet Collision Detection & Physics Library
btBvhTriangleMeshShape.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16//#define DISABLE_BVH
17
21
24btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
25 : btTriangleMeshShape(meshInterface),
26 m_bvh(0),
27 m_triangleInfoMap(0),
28 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
29 m_ownsBvh(false)
30{
32 //construct bvh from meshInterface
33#ifndef DISABLE_BVH
34
35 if (buildBvh)
36 {
38 }
39
40#endif //DISABLE_BVH
41}
42
43btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
44 : btTriangleMeshShape(meshInterface),
45 m_bvh(0),
46 m_triangleInfoMap(0),
47 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
48 m_ownsBvh(false)
49{
51 //construct bvh from meshInterface
52#ifndef DISABLE_BVH
53
54 if (buildBvh)
55 {
56 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
57 m_bvh = new (mem) btOptimizedBvh();
58
59 m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
60 m_ownsBvh = true;
61 }
62
63#endif //DISABLE_BVH
64}
65
67{
68 m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
69
70 m_localAabbMin.setMin(aabbMin);
71 m_localAabbMax.setMax(aabbMax);
72}
73
74void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
75{
76 m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
77
79}
80
82{
83 if (m_ownsBvh)
84 {
87 }
88}
89
90void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
91{
92 struct MyNodeOverlapCallback : public btNodeOverlapCallback
93 {
95 btTriangleCallback* m_callback;
96
97 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
98 : m_meshInterface(meshInterface),
99 m_callback(callback)
100 {
101 }
102
103 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
104 {
105 btVector3 m_triangle[3];
106 const unsigned char* vertexbase;
107 int numverts;
108 PHY_ScalarType type;
109 int stride;
110 const unsigned char* indexbase;
111 int indexstride;
112 int numfaces;
113 PHY_ScalarType indicestype;
114
116 &vertexbase,
117 numverts,
118 type,
119 stride,
120 &indexbase,
121 indexstride,
122 numfaces,
123 indicestype,
124 nodeSubPart);
125
126 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
127
128 const btVector3& meshScaling = m_meshInterface->getScaling();
129 for (int j = 2; j >= 0; j--)
130 {
131 int graphicsindex;
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);
137 }
138
139 if (type == PHY_FLOAT)
140 {
141 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
142
143 m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
144 }
145 else
146 {
147 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
148
149 m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
150 }
151 }
152
153 /* Perform ray vs. triangle collision here */
154 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
156 }
157 };
158
159 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
160
161 m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
162}
163
164void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
165{
166 struct MyNodeOverlapCallback : public btNodeOverlapCallback
167 {
169 btTriangleCallback* m_callback;
170
171 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
172 : m_meshInterface(meshInterface),
173 m_callback(callback)
174 {
175 }
176
177 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
178 {
179 btVector3 m_triangle[3];
180 const unsigned char* vertexbase;
181 int numverts;
182 PHY_ScalarType type;
183 int stride;
184 const unsigned char* indexbase;
185 int indexstride;
186 int numfaces;
187 PHY_ScalarType indicestype;
188
190 &vertexbase,
191 numverts,
192 type,
193 stride,
194 &indexbase,
195 indexstride,
196 numfaces,
197 indicestype,
198 nodeSubPart);
199
200 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
201
202 const btVector3& meshScaling = m_meshInterface->getScaling();
203 for (int j = 2; j >= 0; j--)
204 {
205 int graphicsindex;
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);
211 }
212
213 if (type == PHY_FLOAT)
214 {
215 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
216
217 m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
218 }
219 else
220 {
221 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
222
223 m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
224 }
225 }
226
227 /* Perform ray vs. triangle collision here */
228 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
230 }
231 };
232
233 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
234
235 m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
236}
237
238//perform bvh tree traversal and report overlapping triangles to 'callback'
239void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
240{
241#ifdef DISABLE_BVH
242 //brute force traverse all triangles
243 btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
244#else
245
246 //first get all the nodes
247
248 struct MyNodeOverlapCallback : public btNodeOverlapCallback
249 {
251 btTriangleCallback* m_callback;
252 btVector3 m_triangle[3];
253 int m_numOverlap;
254
255 MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
256 : m_meshInterface(meshInterface),
257 m_callback(callback),
258 m_numOverlap(0)
259 {
260 }
261
262 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
263 {
264 m_numOverlap++;
265 const unsigned char* vertexbase;
266 int numverts;
267 PHY_ScalarType type;
268 int stride;
269 const unsigned char* indexbase;
270 int indexstride;
271 int numfaces;
272 PHY_ScalarType indicestype;
273
275 &vertexbase,
276 numverts,
277 type,
278 stride,
279 &indexbase,
280 indexstride,
281 numfaces,
282 indicestype,
283 nodeSubPart);
284
285 unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
286 btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
287
288 const btVector3& meshScaling = m_meshInterface->getScaling();
289 for (int j = 2; j >= 0; j--)
290 {
291 int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
292
293#ifdef DEBUG_TRIANGLE_MESH
294 printf("%d ,", graphicsindex);
295#endif //DEBUG_TRIANGLE_MESH
296 if (type == PHY_FLOAT)
297 {
298 float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
299
300 m_triangle[j] = btVector3(
301 graphicsbase[0] * meshScaling.getX(),
302 graphicsbase[1] * meshScaling.getY(),
303 graphicsbase[2] * meshScaling.getZ());
304 }
305 else
306 {
307 double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
308
309 m_triangle[j] = btVector3(
310 btScalar(graphicsbase[0]) * meshScaling.getX(),
311 btScalar(graphicsbase[1]) * meshScaling.getY(),
312 btScalar(graphicsbase[2]) * meshScaling.getZ());
313 }
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
317 }
318
319 m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
321 }
322 };
323
324 MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
325
326 m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
327
328#endif //DISABLE_BVH
329}
330
332{
333 if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
334 {
337 }
338}
339
341{
342 if (m_ownsBvh)
343 {
346 }
348 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
349 m_bvh = new (mem) btOptimizedBvh();
350 //rebuild the bvh...
352 m_ownsBvh = true;
353}
354
356{
357 btAssert(!m_bvh);
359
360 m_bvh = bvh;
361 m_ownsBvh = false;
362 // update the scaling without rebuilding the bvh
363 if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
364 {
366 }
367}
368
370const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
371{
372 btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
373
374 btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
375
376 m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
377
378 trimeshData->m_collisionMargin = float(m_collisionMargin);
379
380 if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
381 {
382 void* chunk = serializer->findPointer(m_bvh);
383 if (chunk)
384 {
385#ifdef BT_USE_DOUBLE_PRECISION
386 trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
387 trimeshData->m_quantizedFloatBvh = 0;
388#else
389 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
390 trimeshData->m_quantizedDoubleBvh = 0;
391#endif //BT_USE_DOUBLE_PRECISION
392 }
393 else
394 {
395#ifdef BT_USE_DOUBLE_PRECISION
397 trimeshData->m_quantizedFloatBvh = 0;
398#else
399 trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
400 trimeshData->m_quantizedDoubleBvh = 0;
401#endif //BT_USE_DOUBLE_PRECISION
402
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);
407 }
408 }
409 else
410 {
411 trimeshData->m_quantizedFloatBvh = 0;
412 trimeshData->m_quantizedDoubleBvh = 0;
413 }
414
416 {
417 void* chunk = serializer->findPointer(m_triangleInfoMap);
418 if (chunk)
419 {
420 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
421 }
422 else
423 {
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);
429 }
430 }
431 else
432 {
433 trimeshData->m_triangleInfoMap = 0;
434 }
435
436 // Fill padding with zeros to appease msan.
437 memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
438
439 return "btTriangleMeshShapeData";
440}
441
443{
444 if (m_bvh)
445 {
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);
450 }
451}
452
454{
456 {
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);
461 }
462}
#define btAlignedFree(ptr)
#define btAlignedAlloc(size, alignment)
@ TRIANGLE_MESH_SHAPE_PROXYTYPE
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
@ PHY_INTEGER
#define btQuantizedBvhData
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:153
@ BT_SERIALIZE_NO_TRIANGLEINFOMAP
Definition: btSerializer.h:60
@ BT_SERIALIZE_NO_BVH
Definition: btSerializer.h:59
#define BT_TRIANLGE_INFO_MAP
Definition: btSerializer.h:116
#define BT_QUANTIZED_BVH_CODE
Definition: btSerializer.h:115
virtual void serializeSingleBvh(btSerializer *serializer) const
void performRaycast(btTriangleCallback *callback, const btVector3 &raySource, const btVector3 &rayTarget)
void refitTree(const btVector3 &aabbMin, const btVector3 &aabbMax)
void setOptimizedBvh(btOptimizedBvh *bvh, const btVector3 &localScaling=btVector3(1, 1, 1))
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
void partialRefitTree(const btVector3 &aabbMin, const btVector3 &aabbMax)
for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more...
void performConvexcast(btTriangleCallback *callback, const btVector3 &boxSource, const btVector3 &boxTarget, const btVector3 &boxMin, const btVector3 &boxMax)
btTriangleInfoMap * m_triangleInfoMap
virtual void setLocalScaling(const btVector3 &scaling)
virtual void serializeSingleTriangleInfoMap(btSerializer *serializer) const
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
btBvhTriangleMeshShape(btStridingMeshInterface *meshInterface, bool useQuantizedAabbCompression, bool buildBvh=true)
Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization...
void * m_oldPtr
Definition: btSerializer.h:52
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
btScalar m_collisionMargin
The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes,...
virtual ~btOptimizedBvh()
void refitPartial(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
void reportAabbOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
‍***************************************** expert/internal use only *************************
void reportRayOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget) const
void reportBoxCastOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget, const btVector3 &aabbMin, const btVector3 &aabbMax) const
virtual int calculateSerializeBufferSizeNew() const
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
Data buffer MUST be 16 byte aligned.
virtual btChunk * allocate(size_t size, int numElements)=0
virtual void * getUniquePointer(void *oldPtr)=0
virtual int getSerializationFlags() const =0
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
virtual void * findPointer(void *oldPtr)=0
The btStridingMeshInterface is the interface class for high performance generic access to triangle me...
const btVector3 & getScaling() const
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int &numverts, PHY_ScalarType &type, int &stride, const unsigned char **indexbase, int &indexstride, int &numfaces, PHY_ScalarType &indicestype, int subpart=0) const =0
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
virtual void unLockReadOnlyVertexBase(int subpart) const =0
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly...
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
virtual void setLocalScaling(const btVector3 &scaling)
btStridingMeshInterface * m_meshInterface
virtual const btVector3 & getLocalScaling() const
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:609
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:626
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
virtual int calculateSerializeBufferSize() const
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btStridingMeshInterfaceData m_meshInterface
btQuantizedBvhDoubleData * m_quantizedDoubleBvh
btQuantizedBvhFloatData * m_quantizedFloatBvh
btCollisionShapeData m_collisionShapeData
btTriangleInfoMapData * m_triangleInfoMap