Imported Upstream version 2.81
[platform/upstream/libbullet.git] / src / BulletCollision / CollisionShapes / btBvhTriangleMeshShape.cpp
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
18 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
19 #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
20 #include "LinearMath/btSerializer.h"
21
22 ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
23 ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
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 {
31         m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
32         //construct bvh from meshInterface
33 #ifndef DISABLE_BVH
34
35         if (buildBvh)
36         {
37                 buildOptimizedBvh();
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 {
51         m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
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
68 void    btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
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         
81         recalcLocalAabb();
82 }
83
84 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
85 {
86         if (m_ownsBvh)
87         {
88                 m_bvh->~btOptimizedBvh();
89                 btAlignedFree(m_bvh);
90         }
91 }
92
93 void    btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
94 {
95         struct  MyNodeOverlapCallback : public btNodeOverlapCallback
96         {
97                 btStridingMeshInterface*        m_meshInterface;
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         {
166                 btStridingMeshInterface*        m_meshInterface;
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         {
245                 btStridingMeshInterface*        m_meshInterface;
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
331 void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
332 {
333    if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
334    {
335       btTriangleMeshShape::setLocalScaling(scaling);
336           buildOptimizedBvh();
337    }
338 }
339
340 void   btBvhTriangleMeshShape::buildOptimizedBvh()
341 {
342         if (m_ownsBvh)
343         {
344                 m_bvh->~btOptimizedBvh();
345                 btAlignedFree(m_bvh);
346         }
347         ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
348         void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
349         m_bvh = new(mem) btOptimizedBvh();
350         //rebuild the bvh...
351         m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
352         m_ownsBvh = true;
353 }
354
355 void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
356 {
357    btAssert(!m_bvh);
358    btAssert(!m_ownsBvh);
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    {
365       btTriangleMeshShape::setLocalScaling(scaling);
366    }
367 }
368
369
370
371 ///fills the dataBuffer and returns the struct name (and 0 on failure)
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         
407                         int sz = m_bvh->calculateSerializeBufferSizeNew();
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
420         if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
421         {
422                 void* chunk = serializer->findPointer(m_triangleInfoMap);
423                 if (chunk)
424                 {
425                         trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
426                 } else
427                 {
428                         trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
429                         int sz = m_triangleInfoMap->calculateSerializeBufferSize();
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
442 void    btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
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
453 void    btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
454 {
455         if (m_triangleInfoMap)
456         {
457                 int len = m_triangleInfoMap->calculateSerializeBufferSize();
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