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 
44 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
45 :btTriangleMeshShape(meshInterface),
46 m_bvh(0),
48 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
49 m_ownsBvh(false)
50 {
52  //construct bvh from meshInterface
53 #ifndef DISABLE_BVH
54 
55  if (buildBvh)
56  {
57  void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
58  m_bvh = new (mem) btOptimizedBvh();
59 
60  m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
61  m_ownsBvh = true;
62  }
63 
64 #endif //DISABLE_BVH
65 
66 }
67 
69 {
70  m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
71 
72  m_localAabbMin.setMin(aabbMin);
73  m_localAabbMax.setMax(aabbMax);
74 }
75 
76 
77 void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
78 {
79  m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
80 
82 }
83 
85 {
86  if (m_ownsBvh)
87  {
90  }
91 }
92 
93 void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
94 {
95  struct MyNodeOverlapCallback : public btNodeOverlapCallback
96  {
98  btTriangleCallback* m_callback;
99 
100  MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
101  :m_meshInterface(meshInterface),
102  m_callback(callback)
103  {
104  }
105 
106  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
107  {
108  btVector3 m_triangle[3];
109  const unsigned char *vertexbase;
110  int numverts;
111  PHY_ScalarType type;
112  int stride;
113  const unsigned char *indexbase;
114  int indexstride;
115  int numfaces;
116  PHY_ScalarType indicestype;
117 
118  m_meshInterface->getLockedReadOnlyVertexIndexBase(
119  &vertexbase,
120  numverts,
121  type,
122  stride,
123  &indexbase,
124  indexstride,
125  numfaces,
126  indicestype,
127  nodeSubPart);
128 
129  unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
130  btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
131 
132  const btVector3& meshScaling = m_meshInterface->getScaling();
133  for (int j=2;j>=0;j--)
134  {
135  int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
136 
137  if (type == PHY_FLOAT)
138  {
139  float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
140 
141  m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
142  }
143  else
144  {
145  double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
146 
147  m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
148  }
149  }
150 
151  /* Perform ray vs. triangle collision here */
152  m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
153  m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
154  }
155  };
156 
157  MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
158 
159  m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
160 }
161 
162 void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
163 {
164  struct MyNodeOverlapCallback : public btNodeOverlapCallback
165  {
167  btTriangleCallback* m_callback;
168 
169  MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
170  :m_meshInterface(meshInterface),
171  m_callback(callback)
172  {
173  }
174 
175  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
176  {
177  btVector3 m_triangle[3];
178  const unsigned char *vertexbase;
179  int numverts;
180  PHY_ScalarType type;
181  int stride;
182  const unsigned char *indexbase;
183  int indexstride;
184  int numfaces;
185  PHY_ScalarType indicestype;
186 
187  m_meshInterface->getLockedReadOnlyVertexIndexBase(
188  &vertexbase,
189  numverts,
190  type,
191  stride,
192  &indexbase,
193  indexstride,
194  numfaces,
195  indicestype,
196  nodeSubPart);
197 
198  unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
199  btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
200 
201  const btVector3& meshScaling = m_meshInterface->getScaling();
202  for (int j=2;j>=0;j--)
203  {
204  int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
205 
206  if (type == PHY_FLOAT)
207  {
208  float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
209 
210  m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
211  }
212  else
213  {
214  double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
215 
216  m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
217  }
218  }
219 
220  /* Perform ray vs. triangle collision here */
221  m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
222  m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
223  }
224  };
225 
226  MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
227 
228  m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
229 }
230 
231 //perform bvh tree traversal and report overlapping triangles to 'callback'
232 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
233 {
234 
235 #ifdef DISABLE_BVH
236  //brute force traverse all triangles
237  btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
238 #else
239 
240  //first get all the nodes
241 
242 
243  struct MyNodeOverlapCallback : public btNodeOverlapCallback
244  {
246  btTriangleCallback* m_callback;
247  btVector3 m_triangle[3];
248  int m_numOverlap;
249 
250  MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
251  :m_meshInterface(meshInterface),
252  m_callback(callback),
253  m_numOverlap(0)
254  {
255  }
256 
257  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
258  {
259  m_numOverlap++;
260  const unsigned char *vertexbase;
261  int numverts;
262  PHY_ScalarType type;
263  int stride;
264  const unsigned char *indexbase;
265  int indexstride;
266  int numfaces;
267  PHY_ScalarType indicestype;
268 
269 
270  m_meshInterface->getLockedReadOnlyVertexIndexBase(
271  &vertexbase,
272  numverts,
273  type,
274  stride,
275  &indexbase,
276  indexstride,
277  numfaces,
278  indicestype,
279  nodeSubPart);
280 
281  unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
282  btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
283 
284  const btVector3& meshScaling = m_meshInterface->getScaling();
285  for (int j=2;j>=0;j--)
286  {
287 
288  int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
289 
290 
291 #ifdef DEBUG_TRIANGLE_MESH
292  printf("%d ,",graphicsindex);
293 #endif //DEBUG_TRIANGLE_MESH
294  if (type == PHY_FLOAT)
295  {
296  float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
297 
298  m_triangle[j] = btVector3(
299  graphicsbase[0]*meshScaling.getX(),
300  graphicsbase[1]*meshScaling.getY(),
301  graphicsbase[2]*meshScaling.getZ());
302  }
303  else
304  {
305  double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
306 
307  m_triangle[j] = btVector3(
308  btScalar(graphicsbase[0])*meshScaling.getX(),
309  btScalar(graphicsbase[1])*meshScaling.getY(),
310  btScalar(graphicsbase[2])*meshScaling.getZ());
311  }
312 #ifdef DEBUG_TRIANGLE_MESH
313  printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
314 #endif //DEBUG_TRIANGLE_MESH
315  }
316 
317  m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
318  m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
319  }
320 
321  };
322 
323  MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
324 
325  m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
326 
327 #endif//DISABLE_BVH
328 
329 
330 }
331 
333 {
334  if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
335  {
338  }
339 }
340 
342 {
343  if (m_ownsBvh)
344  {
347  }
349  void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
350  m_bvh = new(mem) btOptimizedBvh();
351  //rebuild the bvh...
353  m_ownsBvh = true;
354 }
355 
357 {
358  btAssert(!m_bvh);
360 
361  m_bvh = bvh;
362  m_ownsBvh = false;
363  // update the scaling without rebuilding the bvh
364  if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
365  {
367  }
368 }
369 
370 
371 
373 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
374 {
375  btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
376 
377  btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
378 
379  m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
380 
381  trimeshData->m_collisionMargin = float(m_collisionMargin);
382 
383 
384 
385  if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
386  {
387  void* chunk = serializer->findPointer(m_bvh);
388  if (chunk)
389  {
390 #ifdef BT_USE_DOUBLE_PRECISION
391  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
392  trimeshData->m_quantizedFloatBvh = 0;
393 #else
394  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
395  trimeshData->m_quantizedDoubleBvh= 0;
396 #endif //BT_USE_DOUBLE_PRECISION
397  } else
398  {
399 
400 #ifdef BT_USE_DOUBLE_PRECISION
401  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
402  trimeshData->m_quantizedFloatBvh = 0;
403 #else
404  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
405  trimeshData->m_quantizedDoubleBvh= 0;
406 #endif //BT_USE_DOUBLE_PRECISION
407 
409  btChunk* chunk = serializer->allocate(sz,1);
410  const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
411  serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
412  }
413  } else
414  {
415  trimeshData->m_quantizedFloatBvh = 0;
416  trimeshData->m_quantizedDoubleBvh = 0;
417  }
418 
419 
420 
422  {
423  void* chunk = serializer->findPointer(m_triangleInfoMap);
424  if (chunk)
425  {
426  trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
427  } else
428  {
431  btChunk* chunk = serializer->allocate(sz,1);
432  const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
433  serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
434  }
435  } else
436  {
437  trimeshData->m_triangleInfoMap = 0;
438  }
439 
440  // Fill padding with zeros to appease msan.
441  memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
442 
443  return "btTriangleMeshShapeData";
444 }
445 
447 {
448  if (m_bvh)
449  {
450  int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
451  btChunk* chunk = serializer->allocate(len,1);
452  const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
453  serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
454  }
455 }
456 
458 {
459  if (m_triangleInfoMap)
460  {
462  btChunk* chunk = serializer->allocate(len,1);
463  const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
464  serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
465  }
466 }
467 
468 
469 
470 
#define SIMD_EPSILON
Definition: btScalar.h:521
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
Data buffer MUST be 16 byte aligned.
void performRaycast(btTriangleCallback *callback, const btVector3 &raySource, const btVector3 &rayTarget)
btCollisionShapeData m_collisionShapeData
btStridingMeshInterface * m_meshInterface
#define BT_QUANTIZED_BVH_CODE
Definition: btSerializer.h:125
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
virtual void * getUniquePointer(void *oldPtr)=0
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
#define btAssert(x)
Definition: btScalar.h:131
btScalar m_collisionMargin
const btVector3 & getScaling() const
btStridingMeshInterfaceData m_meshInterface
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
btTriangleInfoMapData * m_triangleInfoMap
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:577
The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly...
virtual void setLocalScaling(const btVector3 &scaling)
virtual int getSerializationFlags() const =0
btTriangleInfoMap * m_triangleInfoMap
void reportRayOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget) const
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:575
#define btAlignedFree(ptr)
void setOptimizedBvh(btOptimizedBvh *bvh, const btVector3 &localScaling=btVector3(1, 1, 1))
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:573
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)
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...
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
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 serializeSingleTriangleInfoMap(btSerializer *serializer) const
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
virtual int calculateSerializeBufferSize() const
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
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)
void reportBoxCastOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &raySource, const btVector3 &rayTarget, const btVector3 &aabbMin, const btVector3 &aabbMax) const
btQuantizedBvhFloatData * m_quantizedFloatBvh
#define BT_TRIANLGE_INFO_MAP
Definition: btSerializer.h:126
virtual void unLockReadOnlyVertexBase(int subpart) const =0
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:621
virtual void * findPointer(void *oldPtr)=0
virtual void serializeSingleBvh(btSerializer *serializer) const
void reportAabbOverlappingNodex(btNodeOverlapCallback *nodeCallback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
***************************************** expert/internal use only ************************* ...
void * m_oldPtr
Definition: btSerializer.h:56
virtual const btVector3 & getLocalScaling() const
virtual btChunk * allocate(size_t size, int numElements)=0
virtual ~btOptimizedBvh()
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:638
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
#define btQuantizedBvhData
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
virtual int calculateSerializeBufferSizeNew() const
void refitPartial(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)