Bullet Collision Detection & Physics Library
btBvhTriangleMeshShape.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
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:
10 
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.
14 */
15 
16 //#define DISABLE_BVH
17 
21 
24 btBvhTriangleMeshShape::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 
43 btBvhTriangleMeshShape::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 
66 void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
67 {
68  m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
69 
70  m_localAabbMin.setMin(aabbMin);
71  m_localAabbMax.setMax(aabbMax);
72 }
73 
74 void 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 
90 void 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 
164 void 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'
239 void 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 
370 const 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
396  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
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 {
455  if (m_triangleInfoMap)
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 int getSerializationFlags() const =0
virtual void * findPointer(void *oldPtr)=0
virtual void * getUniquePointer(void *oldPtr)=0
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
The btStridingMeshInterface is the interface class for high performance generic access to triangle me...
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
const btVector3 & getScaling() const
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
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 & getX() const
Return the x value.
Definition: btVector3.h:561
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
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
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