Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @ 2898

Last change on this file since 2898 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 11.1 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
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
18#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
19#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
20
21///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
22///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
23btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
24:btTriangleMeshShape(meshInterface),
25m_bvh(0),
26m_useQuantizedAabbCompression(useQuantizedAabbCompression),
27m_ownsBvh(false)
28{
29        m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
30        //construct bvh from meshInterface
31#ifndef DISABLE_BVH
32
33        btVector3 bvhAabbMin,bvhAabbMax;
34        if(meshInterface->hasPremadeAabb())
35        {
36                meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax);
37        }
38        else
39        {
40                meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
41        }
42       
43        if (buildBvh)
44        {
45                void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
46                m_bvh = new (mem) btOptimizedBvh();
47                m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
48                m_ownsBvh = true;
49        }
50
51#endif //DISABLE_BVH
52
53}
54
55btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
56:btTriangleMeshShape(meshInterface),
57m_bvh(0),
58m_useQuantizedAabbCompression(useQuantizedAabbCompression),
59m_ownsBvh(false)
60{
61        m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
62        //construct bvh from meshInterface
63#ifndef DISABLE_BVH
64
65        if (buildBvh)
66        {
67                void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
68                m_bvh = new (mem) btOptimizedBvh();
69               
70                m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
71                m_ownsBvh = true;
72        }
73
74#endif //DISABLE_BVH
75
76}
77
78void    btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
79{
80        m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
81       
82        m_localAabbMin.setMin(aabbMin);
83        m_localAabbMax.setMax(aabbMax);
84}
85
86
87void    btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
88{
89        m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
90       
91        recalcLocalAabb();
92}
93
94btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
95{
96        if (m_ownsBvh)
97        {
98                m_bvh->~btOptimizedBvh();
99                btAlignedFree(m_bvh);
100        }
101}
102
103void    btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
104{
105        struct  MyNodeOverlapCallback : public btNodeOverlapCallback
106        {
107                btStridingMeshInterface*        m_meshInterface;
108                btTriangleCallback* m_callback;
109
110                MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
111                        :m_meshInterface(meshInterface),
112                        m_callback(callback)
113                {
114                }
115                               
116                virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
117                {
118                        btVector3 m_triangle[3];
119                        const unsigned char *vertexbase;
120                        int numverts;
121                        PHY_ScalarType type;
122                        int stride;
123                        const unsigned char *indexbase;
124                        int indexstride;
125                        int numfaces;
126                        PHY_ScalarType indicestype;
127
128                        m_meshInterface->getLockedReadOnlyVertexIndexBase(
129                                &vertexbase,
130                                numverts,
131                                type,
132                                stride,
133                                &indexbase,
134                                indexstride,
135                                numfaces,
136                                indicestype,
137                                nodeSubPart);
138
139                        unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
140                        btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
141       
142                        const btVector3& meshScaling = m_meshInterface->getScaling();
143                        for (int j=2;j>=0;j--)
144                        {
145                                int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
146                               
147                                if (type == PHY_FLOAT)
148                                {
149                                        float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
150                                       
151                                        m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());           
152                                }
153                                else
154                                {
155                                        double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
156                                       
157                                        m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());             
158                                }
159                        }
160
161                        /* Perform ray vs. triangle collision here */
162                        m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
163                        m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
164                }
165        };
166
167        MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
168
169        m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
170}
171
172void    btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
173{
174        struct  MyNodeOverlapCallback : public btNodeOverlapCallback
175        {
176                btStridingMeshInterface*        m_meshInterface;
177                btTriangleCallback* m_callback;
178
179                MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
180                        :m_meshInterface(meshInterface),
181                        m_callback(callback)
182                {
183                }
184                               
185                virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
186                {
187                        btVector3 m_triangle[3];
188                        const unsigned char *vertexbase;
189                        int numverts;
190                        PHY_ScalarType type;
191                        int stride;
192                        const unsigned char *indexbase;
193                        int indexstride;
194                        int numfaces;
195                        PHY_ScalarType indicestype;
196
197                        m_meshInterface->getLockedReadOnlyVertexIndexBase(
198                                &vertexbase,
199                                numverts,
200                                type,
201                                stride,
202                                &indexbase,
203                                indexstride,
204                                numfaces,
205                                indicestype,
206                                nodeSubPart);
207
208                        unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
209                        btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
210       
211                        const btVector3& meshScaling = m_meshInterface->getScaling();
212                        for (int j=2;j>=0;j--)
213                        {
214                                int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
215
216                                if (type == PHY_FLOAT)
217                                {
218                                        float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
219
220                                        m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());           
221                                }
222                                else
223                                {
224                                        double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
225                                       
226                                        m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());             
227                                }
228                        }
229
230                        /* Perform ray vs. triangle collision here */
231                        m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
232                        m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
233                }
234        };
235
236        MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
237
238        m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
239}
240
241//perform bvh tree traversal and report overlapping triangles to 'callback'
242void    btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
243{
244
245#ifdef DISABLE_BVH
246        //brute force traverse all triangles
247        btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
248#else
249
250        //first get all the nodes
251
252       
253        struct  MyNodeOverlapCallback : public btNodeOverlapCallback
254        {
255                btStridingMeshInterface*        m_meshInterface;
256                btTriangleCallback*             m_callback;
257                btVector3                               m_triangle[3];
258
259
260                MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
261                        :m_meshInterface(meshInterface),
262                        m_callback(callback)
263                {
264                }
265                               
266                virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
267                {
268                        const unsigned char *vertexbase;
269                        int numverts;
270                        PHY_ScalarType type;
271                        int stride;
272                        const unsigned char *indexbase;
273                        int indexstride;
274                        int numfaces;
275                        PHY_ScalarType indicestype;
276                       
277
278                        m_meshInterface->getLockedReadOnlyVertexIndexBase(
279                                &vertexbase,
280                                numverts,
281                                type,
282                                stride,
283                                &indexbase,
284                                indexstride,
285                                numfaces,
286                                indicestype,
287                                nodeSubPart);
288
289                        unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
290                        btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
291       
292                        const btVector3& meshScaling = m_meshInterface->getScaling();
293                        for (int j=2;j>=0;j--)
294                        {
295                               
296                                int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
297
298
299#ifdef DEBUG_TRIANGLE_MESH
300                                printf("%d ,",graphicsindex);
301#endif //DEBUG_TRIANGLE_MESH
302                                if (type == PHY_FLOAT)
303                                {
304                                        float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
305                                       
306                                        m_triangle[j] = btVector3(
307                                                                                                                                                graphicsbase[0]*meshScaling.getX(),
308                                                                                                                                                graphicsbase[1]*meshScaling.getY(),
309                                                                                                                                                graphicsbase[2]*meshScaling.getZ());
310                                }
311                                else
312                                {
313                                        double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
314
315                                        m_triangle[j] = btVector3(
316                                                btScalar(graphicsbase[0])*meshScaling.getX(),
317                                                btScalar(graphicsbase[1])*meshScaling.getY(),
318                                                btScalar(graphicsbase[2])*meshScaling.getZ());
319                                }
320#ifdef DEBUG_TRIANGLE_MESH
321                                printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
322#endif //DEBUG_TRIANGLE_MESH
323                        }
324
325                        m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
326                        m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
327                }
328
329        };
330
331        MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
332
333        m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
334
335
336#endif//DISABLE_BVH
337
338
339}
340
341void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
342{
343   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
344   {
345      btTriangleMeshShape::setLocalScaling(scaling);
346      if (m_ownsBvh)
347      {
348         m_bvh->~btOptimizedBvh();
349         btAlignedFree(m_bvh);
350      }
351      ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
352      void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
353      m_bvh = new(mem) btOptimizedBvh();
354      //rebuild the bvh...
355      m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
356      m_ownsBvh = true;
357   }
358}
359
360void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
361{
362   btAssert(!m_bvh);
363   btAssert(!m_ownsBvh);
364
365   m_bvh = bvh;
366   m_ownsBvh = false;
367   // update the scaling without rebuilding the bvh
368   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
369   {
370      btTriangleMeshShape::setLocalScaling(scaling);
371   }
372}
373
374
Note: See TracBrowser for help on using the repository browser.