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
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
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
60 m_ownsBvh = true;
61 }
62
63#endif //DISABLE_BVH
64}
65
67{
69
72}
73
75{
77
79}
80
82{
83 if (m_ownsBvh)
84 {
87 }
88}
89
91{
93 {
94 btStridingMeshInterface* m_meshInterface;
96
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
115 m_meshInterface->getLockedReadOnlyVertexIndexBase(
116 &vertexbase,
117 numverts,
118 type,
119 stride,
120 &indexbase,
121 indexstride,
122 numfaces,
123 indicestype,
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);
155 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
156 }
157 };
158
160
162}
163
165{
167 {
168 btStridingMeshInterface* m_meshInterface;
170
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
189 m_meshInterface->getLockedReadOnlyVertexIndexBase(
190 &vertexbase,
191 numverts,
192 type,
193 stride,
194 &indexbase,
195 indexstride,
196 numfaces,
197 indicestype,
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);
229 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
230 }
231 };
232
234
236}
237
238//perform bvh tree traversal and report overlapping triangles to 'callback'
240{
241#ifdef DISABLE_BVH
242 //brute force traverse all triangles
244#else
245
246 //first get all the nodes
247
249 {
250 btStridingMeshInterface* m_meshInterface;
252 btVector3 m_triangle[3];
253 int m_numOverlap;
254
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
274 m_meshInterface->getLockedReadOnlyVertexIndexBase(
275 &vertexbase,
276 numverts,
277 type,
278 stride,
279 &indexbase,
280 indexstride,
281 numfaces,
282 indicestype,
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);
320 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
321 }
322 };
323
325
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
371{
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);
407 }
408 }
409 else
410 {
411 trimeshData->m_quantizedFloatBvh = 0;
412 trimeshData->m_quantizedDoubleBvh = 0;
413 }
414
415 if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
416 {
417 void* chunk = serializer->findPointer(m_triangleInfoMap);
418 if (chunk)
419 {
420 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
421 }
422 else
423 {
424 trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
426 btChunk* chunk = serializer->allocate(sz, 1);
427 const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
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{
456 {
458 btChunk* chunk = serializer->allocate(len, 1);
459 const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
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
const T & btMax(const T &a, const T &b)
Definition btMinMax.h:27
#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
@ BT_SERIALIZE_NO_BVH
#define BT_TRIANLGE_INFO_MAP
#define BT_QUANTIZED_BVH_CODE
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...
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.
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...
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
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