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  btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
128 
129  const btVector3& meshScaling = m_meshInterface->getScaling();
130  for (int j = 2; j >= 0; j--)
131  {
132  int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
133 
134  if (type == PHY_FLOAT)
135  {
136  float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
137 
138  m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
139  }
140  else
141  {
142  double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
143 
144  m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
145  }
146  }
147 
148  /* Perform ray vs. triangle collision here */
149  m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
151  }
152  };
153 
154  MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
155 
156  m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
157 }
158 
159 void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
160 {
161  struct MyNodeOverlapCallback : public btNodeOverlapCallback
162  {
164  btTriangleCallback* m_callback;
165 
166  MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
167  : m_meshInterface(meshInterface),
168  m_callback(callback)
169  {
170  }
171 
172  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
173  {
174  btVector3 m_triangle[3];
175  const unsigned char* vertexbase;
176  int numverts;
177  PHY_ScalarType type;
178  int stride;
179  const unsigned char* indexbase;
180  int indexstride;
181  int numfaces;
182  PHY_ScalarType indicestype;
183 
185  &vertexbase,
186  numverts,
187  type,
188  stride,
189  &indexbase,
190  indexstride,
191  numfaces,
192  indicestype,
193  nodeSubPart);
194 
195  unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
196  btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT);
197 
198  const btVector3& meshScaling = m_meshInterface->getScaling();
199  for (int j = 2; j >= 0; j--)
200  {
201  int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : gfxbase[j];
202 
203  if (type == PHY_FLOAT)
204  {
205  float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
206 
207  m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
208  }
209  else
210  {
211  double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
212 
213  m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
214  }
215  }
216 
217  /* Perform ray vs. triangle collision here */
218  m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
220  }
221  };
222 
223  MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
224 
225  m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
226 }
227 
228 //perform bvh tree traversal and report overlapping triangles to 'callback'
229 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
230 {
231 #ifdef DISABLE_BVH
232  //brute force traverse all triangles
233  btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
234 #else
235 
236  //first get all the nodes
237 
238  struct MyNodeOverlapCallback : public btNodeOverlapCallback
239  {
241  btTriangleCallback* m_callback;
242  btVector3 m_triangle[3];
243  int m_numOverlap;
244 
245  MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
246  : m_meshInterface(meshInterface),
247  m_callback(callback),
248  m_numOverlap(0)
249  {
250  }
251 
252  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
253  {
254  m_numOverlap++;
255  const unsigned char* vertexbase;
256  int numverts;
257  PHY_ScalarType type;
258  int stride;
259  const unsigned char* indexbase;
260  int indexstride;
261  int numfaces;
262  PHY_ScalarType indicestype;
263 
265  &vertexbase,
266  numverts,
267  type,
268  stride,
269  &indexbase,
270  indexstride,
271  numfaces,
272  indicestype,
273  nodeSubPart);
274 
275  unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
276  btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
277 
278  const btVector3& meshScaling = m_meshInterface->getScaling();
279  for (int j = 2; j >= 0; j--)
280  {
281  int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
282 
283 #ifdef DEBUG_TRIANGLE_MESH
284  printf("%d ,", graphicsindex);
285 #endif //DEBUG_TRIANGLE_MESH
286  if (type == PHY_FLOAT)
287  {
288  float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
289 
290  m_triangle[j] = btVector3(
291  graphicsbase[0] * meshScaling.getX(),
292  graphicsbase[1] * meshScaling.getY(),
293  graphicsbase[2] * meshScaling.getZ());
294  }
295  else
296  {
297  double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
298 
299  m_triangle[j] = btVector3(
300  btScalar(graphicsbase[0]) * meshScaling.getX(),
301  btScalar(graphicsbase[1]) * meshScaling.getY(),
302  btScalar(graphicsbase[2]) * meshScaling.getZ());
303  }
304 #ifdef DEBUG_TRIANGLE_MESH
305  printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
306 #endif //DEBUG_TRIANGLE_MESH
307  }
308 
309  m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
311  }
312  };
313 
314  MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
315 
316  m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
317 
318 #endif //DISABLE_BVH
319 }
320 
322 {
323  if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
324  {
327  }
328 }
329 
331 {
332  if (m_ownsBvh)
333  {
336  }
338  void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
339  m_bvh = new (mem) btOptimizedBvh();
340  //rebuild the bvh...
342  m_ownsBvh = true;
343 }
344 
346 {
347  btAssert(!m_bvh);
349 
350  m_bvh = bvh;
351  m_ownsBvh = false;
352  // update the scaling without rebuilding the bvh
353  if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
354  {
356  }
357 }
358 
360 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
361 {
362  btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
363 
364  btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
365 
366  m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
367 
368  trimeshData->m_collisionMargin = float(m_collisionMargin);
369 
370  if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
371  {
372  void* chunk = serializer->findPointer(m_bvh);
373  if (chunk)
374  {
375 #ifdef BT_USE_DOUBLE_PRECISION
376  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
377  trimeshData->m_quantizedFloatBvh = 0;
378 #else
379  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
380  trimeshData->m_quantizedDoubleBvh = 0;
381 #endif //BT_USE_DOUBLE_PRECISION
382  }
383  else
384  {
385 #ifdef BT_USE_DOUBLE_PRECISION
386  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
387  trimeshData->m_quantizedFloatBvh = 0;
388 #else
389  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
390  trimeshData->m_quantizedDoubleBvh = 0;
391 #endif //BT_USE_DOUBLE_PRECISION
392 
394  btChunk* chunk = serializer->allocate(sz, 1);
395  const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
396  serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
397  }
398  }
399  else
400  {
401  trimeshData->m_quantizedFloatBvh = 0;
402  trimeshData->m_quantizedDoubleBvh = 0;
403  }
404 
406  {
407  void* chunk = serializer->findPointer(m_triangleInfoMap);
408  if (chunk)
409  {
410  trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
411  }
412  else
413  {
416  btChunk* chunk = serializer->allocate(sz, 1);
417  const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
418  serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
419  }
420  }
421  else
422  {
423  trimeshData->m_triangleInfoMap = 0;
424  }
425 
426  // Fill padding with zeros to appease msan.
427  memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
428 
429  return "btTriangleMeshShapeData";
430 }
431 
433 {
434  if (m_bvh)
435  {
436  int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
437  btChunk* chunk = serializer->allocate(len, 1);
438  const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
439  serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, (void*)m_bvh);
440  }
441 }
442 
444 {
445  if (m_triangleInfoMap)
446  {
448  btChunk* chunk = serializer->allocate(len, 1);
449  const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
450  serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, (void*)m_triangleInfoMap);
451  }
452 }
#define SIMD_EPSILON
Definition: btScalar.h:523
void reportAabbOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
***************************************** expert/internal use only ************************* ...
void performRaycast(btTriangleCallback *callback, const btVector3 &raySource, const btVector3 &rayTarget)
btCollisionShapeData m_collisionShapeData
btStridingMeshInterface * m_meshInterface
#define BT_QUANTIZED_BVH_CODE
Definition: btSerializer.h:115
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
virtual void * getUniquePointer(void *oldPtr)=0
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
#define btAssert(x)
Definition: btScalar.h:133
btScalar m_collisionMargin
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btStridingMeshInterfaceData m_meshInterface
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
btTriangleInfoMapData * m_triangleInfoMap
The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly...
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
virtual void setLocalScaling(const btVector3 &scaling)
void reportBoxCastOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget, const btVector3 &aabbMin, const btVector3 &aabbMax) const
virtual void serializeSingleBvh(btSerializer *serializer) const
virtual int getSerializationFlags() const =0
virtual const btVector3 & getLocalScaling() const
btTriangleInfoMap * m_triangleInfoMap
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
virtual int calculateSerializeBufferSizeNew() const
#define btAlignedFree(ptr)
void setOptimizedBvh(btOptimizedBvh *bvh, const btVector3 &localScaling=btVector3(1, 1, 1))
The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
virtual void setLocalScaling(const btVector3 &scaling)
void performConvexcast(btTriangleCallback *callback, const btVector3 &boxSource, const btVector3 &boxTarget, const btVector3 &boxMin, const btVector3 &boxMax)
void reportRayOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget) const
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
btQuantizedBvhDoubleData * m_quantizedDoubleBvh
btBvhTriangleMeshShape(btStridingMeshInterface *meshInterface, bool useQuantizedAabbCompression, bool buildBvh=true)
Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization...
virtual void serializeSingleTriangleInfoMap(btSerializer *serializer) const
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
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...
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 processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
const btVector3 & getScaling() const
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
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
void refitTree(const btVector3 &aabbMin, const btVector3 &aabbMax)
#define btAlignedAlloc(size, alignment)
btQuantizedBvhFloatData * m_quantizedFloatBvh
#define BT_TRIANLGE_INFO_MAP
Definition: btSerializer.h:116
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
Data buffer MUST be 16 byte aligned.
virtual void unLockReadOnlyVertexBase(int subpart) const =0
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
virtual void * findPointer(void *oldPtr)=0
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
void * m_oldPtr
Definition: btSerializer.h:52
virtual btChunk * allocate(size_t size, int numElements)=0
virtual ~btOptimizedBvh()
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
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
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
#define btQuantizedBvhData
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
void refitPartial(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)