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),
26m_bvh(0),
27m_triangleInfoMap(0),
28m_useQuantizedAabbCompression(useQuantizedAabbCompression),
29m_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
44btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
45:btTriangleMeshShape(meshInterface),
46m_bvh(0),
47m_triangleInfoMap(0),
48m_useQuantizedAabbCompression(useQuantizedAabbCompression),
49m_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
77void 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
93void 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
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);
154 }
155 };
156
157 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
158
159 m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
160}
161
162void 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
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);
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'
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
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);
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
373const 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
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{
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 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:292
#define SIMD_EPSILON
Definition: btScalar.h:521
#define btAssert(x)
Definition: btScalar.h:131
@ BT_SERIALIZE_NO_TRIANGLEINFOMAP
Definition: btSerializer.h:64
@ BT_SERIALIZE_NO_BVH
Definition: btSerializer.h:63
#define BT_TRIANLGE_INFO_MAP
Definition: btSerializer.h:124
#define BT_QUANTIZED_BVH_CODE
Definition: btSerializer.h:123
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:56
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:84
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:577
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
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:575
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
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:573
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