Back to index

supertuxkart  0.5+dfsg1
btBvhTriangleMeshShape.cpp
Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 //#define DISABLE_BVH
00017 
00018 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
00019 #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
00020 
00023 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
00024 :btTriangleMeshShape(meshInterface),
00025 m_bvh(0),
00026 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
00027 m_ownsBvh(false)
00028 {
00029        //construct bvh from meshInterface
00030 #ifndef DISABLE_BVH
00031 
00032        btVector3 bvhAabbMin,bvhAabbMax;
00033        meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
00034        
00035        if (buildBvh)
00036        {
00037               void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00038               m_bvh = new (mem) btOptimizedBvh();
00039               m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
00040               m_ownsBvh = true;
00041        }
00042 
00043 #endif //DISABLE_BVH
00044 
00045 }
00046 
00047 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
00048 :btTriangleMeshShape(meshInterface),
00049 m_bvh(0),
00050 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
00051 m_ownsBvh(false)
00052 {
00053        //construct bvh from meshInterface
00054 #ifndef DISABLE_BVH
00055 
00056        if (buildBvh)
00057        {
00058               void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00059               m_bvh = new (mem) btOptimizedBvh();
00060               
00061               m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
00062               m_ownsBvh = true;
00063        }
00064 
00065 #endif //DISABLE_BVH
00066 
00067 }
00068 
00069 void   btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00070 {
00071        m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
00072        
00073        m_localAabbMin.setMin(aabbMin);
00074        m_localAabbMax.setMax(aabbMax);
00075 }
00076 
00077 
00078 void   btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00079 {
00080        m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
00081        
00082        recalcLocalAabb();
00083 }
00084 
00085 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
00086 {
00087        if (m_ownsBvh)
00088        {
00089               m_bvh->~btOptimizedBvh();
00090               btAlignedFree(m_bvh);
00091        }
00092 }
00093 
00094 void   btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
00095 {
00096        struct MyNodeOverlapCallback : public btNodeOverlapCallback
00097        {
00098               btStridingMeshInterface*    m_meshInterface;
00099               btTriangleCallback* m_callback;
00100 
00101               MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00102                      :m_meshInterface(meshInterface),
00103                      m_callback(callback)
00104               {
00105               }
00106                             
00107               virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00108               {
00109                      btVector3 m_triangle[3];
00110                      const unsigned char *vertexbase;
00111                      int numverts;
00112                      PHY_ScalarType type;
00113                      int stride;
00114                      const unsigned char *indexbase;
00115                      int indexstride;
00116                      int numfaces;
00117                      PHY_ScalarType indicestype;
00118 
00119                      m_meshInterface->getLockedReadOnlyVertexIndexBase(
00120                             &vertexbase,
00121                             numverts,
00122                             type,
00123                             stride,
00124                             &indexbase,
00125                             indexstride,
00126                             numfaces,
00127                             indicestype,
00128                             nodeSubPart);
00129 
00130                      int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
00131                      btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00132        
00133                      const btVector3& meshScaling = m_meshInterface->getScaling();
00134                      for (int j=2;j>=0;j--)
00135                      {
00136                             int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
00137 
00138                             btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
00139 
00140                             m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());        
00141                      }
00142 
00143                      /* Perform ray vs. triangle collision here */
00144                      m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00145                      m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00146               }
00147        };
00148 
00149        MyNodeOverlapCallback       myNodeCallback(callback,m_meshInterface);
00150 
00151        m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
00152 }
00153 
00154 void   btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
00155 {
00156        struct MyNodeOverlapCallback : public btNodeOverlapCallback
00157        {
00158               btStridingMeshInterface*    m_meshInterface;
00159               btTriangleCallback* m_callback;
00160 
00161               MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00162                      :m_meshInterface(meshInterface),
00163                      m_callback(callback)
00164               {
00165               }
00166                             
00167               virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00168               {
00169                      btVector3 m_triangle[3];
00170                      const unsigned char *vertexbase;
00171                      int numverts;
00172                      PHY_ScalarType type;
00173                      int stride;
00174                      const unsigned char *indexbase;
00175                      int indexstride;
00176                      int numfaces;
00177                      PHY_ScalarType indicestype;
00178 
00179                      m_meshInterface->getLockedReadOnlyVertexIndexBase(
00180                             &vertexbase,
00181                             numverts,
00182                             type,
00183                             stride,
00184                             &indexbase,
00185                             indexstride,
00186                             numfaces,
00187                             indicestype,
00188                             nodeSubPart);
00189 
00190                      int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
00191                      btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00192        
00193                      const btVector3& meshScaling = m_meshInterface->getScaling();
00194                      for (int j=2;j>=0;j--)
00195                      {
00196                             int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
00197 
00198                             btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
00199 
00200                             m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());        
00201                      }
00202 
00203                      /* Perform ray vs. triangle collision here */
00204                      m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00205                      m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00206               }
00207        };
00208 
00209        MyNodeOverlapCallback       myNodeCallback(callback,m_meshInterface);
00210 
00211        m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
00212 }
00213 
00214 //perform bvh tree traversal and report overlapping triangles to 'callback'
00215 void   btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00216 {
00217 
00218 #ifdef DISABLE_BVH
00219        //brute force traverse all triangles
00220        btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
00221 #else
00222 
00223        //first get all the nodes
00224 
00225        
00226        struct MyNodeOverlapCallback : public btNodeOverlapCallback
00227        {
00228               btStridingMeshInterface*    m_meshInterface;
00229               btTriangleCallback*         m_callback;
00230               btVector3                          m_triangle[3];
00231 
00232 
00233               MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00234                      :m_meshInterface(meshInterface),
00235                      m_callback(callback)
00236               {
00237               }
00238                             
00239               virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00240               {
00241                      const unsigned char *vertexbase;
00242                      int numverts;
00243                      PHY_ScalarType type;
00244                      int stride;
00245                      const unsigned char *indexbase;
00246                      int indexstride;
00247                      int numfaces;
00248                      PHY_ScalarType indicestype;
00249                      
00250 
00251                      m_meshInterface->getLockedReadOnlyVertexIndexBase(
00252                             &vertexbase,
00253                             numverts,
00254                             type,
00255                             stride,
00256                             &indexbase,
00257                             indexstride,
00258                             numfaces,
00259                             indicestype,
00260                             nodeSubPart);
00261 
00262                      int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
00263                      btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00264        
00265                      const btVector3& meshScaling = m_meshInterface->getScaling();
00266                      for (int j=2;j>=0;j--)
00267                      {
00268                             
00269                             int graphicsindex = indicestype==PHY_SHORT?((short*)gfxbase)[j]:gfxbase[j];
00270 
00271 
00272 #ifdef DEBUG_TRIANGLE_MESH
00273                             printf("%d ,",graphicsindex);
00274 #endif //DEBUG_TRIANGLE_MESH
00275                             btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
00276 
00277                             m_triangle[j] = btVector3(
00278                                    graphicsbase[0]*meshScaling.getX(),
00279                                    graphicsbase[1]*meshScaling.getY(),
00280                                    graphicsbase[2]*meshScaling.getZ());
00281 #ifdef DEBUG_TRIANGLE_MESH
00282                             printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
00283 #endif //DEBUG_TRIANGLE_MESH
00284                      }
00285 
00286                      m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00287                      m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00288               }
00289 
00290        };
00291 
00292        MyNodeOverlapCallback       myNodeCallback(callback,m_meshInterface);
00293 
00294        m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
00295 
00296 
00297 #endif//DISABLE_BVH
00298 
00299 
00300 }
00301 
00302 
00303 void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
00304 {
00305        if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
00306        {
00307               btTriangleMeshShape::setLocalScaling(scaling);
00308               if (m_ownsBvh)
00309               {
00310                      m_bvh->~btOptimizedBvh();
00311                      btAlignedFree(m_bvh);
00312               }
00314               void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00315               m_bvh = new(mem) btOptimizedBvh();
00316               //rebuild the bvh...
00317               m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
00318 
00319        }
00320 }