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),
47 m_triangleInfoMap(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 
249 
250  MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
251  :m_meshInterface(meshInterface),
252  m_callback(callback)
253  {
254  }
255 
256  virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
257  {
258  const unsigned char *vertexbase;
259  int numverts;
260  PHY_ScalarType type;
261  int stride;
262  const unsigned char *indexbase;
263  int indexstride;
264  int numfaces;
265  PHY_ScalarType indicestype;
266 
267 
268  m_meshInterface->getLockedReadOnlyVertexIndexBase(
269  &vertexbase,
270  numverts,
271  type,
272  stride,
273  &indexbase,
274  indexstride,
275  numfaces,
276  indicestype,
277  nodeSubPart);
278 
279  unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
280  btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
281 
282  const btVector3& meshScaling = m_meshInterface->getScaling();
283  for (int j=2;j>=0;j--)
284  {
285 
286  int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
287 
288 
289 #ifdef DEBUG_TRIANGLE_MESH
290  printf("%d ,",graphicsindex);
291 #endif //DEBUG_TRIANGLE_MESH
292  if (type == PHY_FLOAT)
293  {
294  float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
295 
296  m_triangle[j] = btVector3(
297  graphicsbase[0]*meshScaling.getX(),
298  graphicsbase[1]*meshScaling.getY(),
299  graphicsbase[2]*meshScaling.getZ());
300  }
301  else
302  {
303  double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
304 
305  m_triangle[j] = btVector3(
306  btScalar(graphicsbase[0])*meshScaling.getX(),
307  btScalar(graphicsbase[1])*meshScaling.getY(),
308  btScalar(graphicsbase[2])*meshScaling.getZ());
309  }
310 #ifdef DEBUG_TRIANGLE_MESH
311  printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
312 #endif //DEBUG_TRIANGLE_MESH
313  }
314 
315  m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
316  m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
317  }
318 
319  };
320 
321  MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
322 
323  m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
324 
325 
326 #endif//DISABLE_BVH
327 
328 
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 
369 
370 
372 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
373 {
374  btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
375 
376  btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
377 
378  m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
379 
380  trimeshData->m_collisionMargin = float(m_collisionMargin);
381 
382 
383 
384  if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
385  {
386  void* chunk = serializer->findPointer(m_bvh);
387  if (chunk)
388  {
389 #ifdef BT_USE_DOUBLE_PRECISION
390  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
391  trimeshData->m_quantizedFloatBvh = 0;
392 #else
393  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
394  trimeshData->m_quantizedDoubleBvh= 0;
395 #endif //BT_USE_DOUBLE_PRECISION
396  } else
397  {
398 
399 #ifdef BT_USE_DOUBLE_PRECISION
400  trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
401  trimeshData->m_quantizedFloatBvh = 0;
402 #else
403  trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
404  trimeshData->m_quantizedDoubleBvh= 0;
405 #endif //BT_USE_DOUBLE_PRECISION
406 
408  btChunk* chunk = serializer->allocate(sz,1);
409  const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
410  serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
411  }
412  } else
413  {
414  trimeshData->m_quantizedFloatBvh = 0;
415  trimeshData->m_quantizedDoubleBvh = 0;
416  }
417 
418 
419 
421  {
422  void* chunk = serializer->findPointer(m_triangleInfoMap);
423  if (chunk)
424  {
425  trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
426  } else
427  {
430  btChunk* chunk = serializer->allocate(sz,1);
431  const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
432  serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
433  }
434  } else
435  {
436  trimeshData->m_triangleInfoMap = 0;
437  }
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 }
463 
464 
465 
466 
#define SIMD_EPSILON
Definition: btScalar.h:494
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:123
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:113
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:565
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:563
#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:561
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:124
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:609
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:626
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:278
#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)