Blender V2.61 - r43446

btBvhTriangleMeshShape.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
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 #include "LinearMath/btSerializer.h"
00021 
00024 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
00025 :btTriangleMeshShape(meshInterface),
00026 m_bvh(0),
00027 m_triangleInfoMap(0),
00028 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
00029 m_ownsBvh(false)
00030 {
00031     m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
00032     //construct bvh from meshInterface
00033 #ifndef DISABLE_BVH
00034 
00035     if (buildBvh)
00036     {
00037         buildOptimizedBvh();
00038     }
00039 
00040 #endif //DISABLE_BVH
00041 
00042 }
00043 
00044 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
00045 :btTriangleMeshShape(meshInterface),
00046 m_bvh(0),
00047 m_triangleInfoMap(0),
00048 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
00049 m_ownsBvh(false)
00050 {
00051     m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
00052     //construct bvh from meshInterface
00053 #ifndef DISABLE_BVH
00054 
00055     if (buildBvh)
00056     {
00057         void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00058         m_bvh = new (mem) btOptimizedBvh();
00059         
00060         m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
00061         m_ownsBvh = true;
00062     }
00063 
00064 #endif //DISABLE_BVH
00065 
00066 }
00067 
00068 void    btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00069 {
00070     m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
00071     
00072     m_localAabbMin.setMin(aabbMin);
00073     m_localAabbMax.setMax(aabbMax);
00074 }
00075 
00076 
00077 void    btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00078 {
00079     m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
00080     
00081     recalcLocalAabb();
00082 }
00083 
00084 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
00085 {
00086     if (m_ownsBvh)
00087     {
00088         m_bvh->~btOptimizedBvh();
00089         btAlignedFree(m_bvh);
00090     }
00091 }
00092 
00093 void    btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
00094 {
00095     struct  MyNodeOverlapCallback : public btNodeOverlapCallback
00096     {
00097         btStridingMeshInterface*    m_meshInterface;
00098         btTriangleCallback* m_callback;
00099 
00100         MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00101             :m_meshInterface(meshInterface),
00102             m_callback(callback)
00103         {
00104         }
00105                 
00106         virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00107         {
00108             btVector3 m_triangle[3];
00109             const unsigned char *vertexbase;
00110             int numverts;
00111             PHY_ScalarType type;
00112             int stride;
00113             const unsigned char *indexbase;
00114             int indexstride;
00115             int numfaces;
00116             PHY_ScalarType indicestype;
00117 
00118             m_meshInterface->getLockedReadOnlyVertexIndexBase(
00119                 &vertexbase,
00120                 numverts,
00121                 type,
00122                 stride,
00123                 &indexbase,
00124                 indexstride,
00125                 numfaces,
00126                 indicestype,
00127                 nodeSubPart);
00128 
00129             unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00130             btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00131     
00132             const btVector3& meshScaling = m_meshInterface->getScaling();
00133             for (int j=2;j>=0;j--)
00134             {
00135                 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00136                 
00137                 if (type == PHY_FLOAT)
00138                 {
00139                     float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00140                     
00141                     m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());        
00142                 }
00143                 else
00144                 {
00145                     double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00146                     
00147                     m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());      
00148                 }
00149             }
00150 
00151             /* Perform ray vs. triangle collision here */
00152             m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00153             m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00154         }
00155     };
00156 
00157     MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
00158 
00159     m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
00160 }
00161 
00162 void    btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
00163 {
00164     struct  MyNodeOverlapCallback : public btNodeOverlapCallback
00165     {
00166         btStridingMeshInterface*    m_meshInterface;
00167         btTriangleCallback* m_callback;
00168 
00169         MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00170             :m_meshInterface(meshInterface),
00171             m_callback(callback)
00172         {
00173         }
00174                 
00175         virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00176         {
00177             btVector3 m_triangle[3];
00178             const unsigned char *vertexbase;
00179             int numverts;
00180             PHY_ScalarType type;
00181             int stride;
00182             const unsigned char *indexbase;
00183             int indexstride;
00184             int numfaces;
00185             PHY_ScalarType indicestype;
00186 
00187             m_meshInterface->getLockedReadOnlyVertexIndexBase(
00188                 &vertexbase,
00189                 numverts,
00190                 type,
00191                 stride,
00192                 &indexbase,
00193                 indexstride,
00194                 numfaces,
00195                 indicestype,
00196                 nodeSubPart);
00197 
00198             unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00199             btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00200     
00201             const btVector3& meshScaling = m_meshInterface->getScaling();
00202             for (int j=2;j>=0;j--)
00203             {
00204                 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00205 
00206                 if (type == PHY_FLOAT)
00207                 {
00208                     float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00209 
00210                     m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());        
00211                 }
00212                 else
00213                 {
00214                     double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00215                     
00216                     m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());      
00217                 }
00218             }
00219 
00220             /* Perform ray vs. triangle collision here */
00221             m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00222             m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00223         }
00224     };
00225 
00226     MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
00227 
00228     m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
00229 }
00230 
00231 //perform bvh tree traversal and report overlapping triangles to 'callback'
00232 void    btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00233 {
00234 
00235 #ifdef DISABLE_BVH
00236     //brute force traverse all triangles
00237     btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
00238 #else
00239 
00240     //first get all the nodes
00241 
00242     
00243     struct  MyNodeOverlapCallback : public btNodeOverlapCallback
00244     {
00245         btStridingMeshInterface*    m_meshInterface;
00246         btTriangleCallback*     m_callback;
00247         btVector3               m_triangle[3];
00248 
00249 
00250         MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00251             :m_meshInterface(meshInterface),
00252             m_callback(callback)
00253         {
00254         }
00255                 
00256         virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00257         {
00258             const unsigned char *vertexbase;
00259             int numverts;
00260             PHY_ScalarType type;
00261             int stride;
00262             const unsigned char *indexbase;
00263             int indexstride;
00264             int numfaces;
00265             PHY_ScalarType indicestype;
00266             
00267 
00268             m_meshInterface->getLockedReadOnlyVertexIndexBase(
00269                 &vertexbase,
00270                 numverts,
00271                 type,
00272                 stride,
00273                 &indexbase,
00274                 indexstride,
00275                 numfaces,
00276                 indicestype,
00277                 nodeSubPart);
00278 
00279             unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00280             btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
00281     
00282             const btVector3& meshScaling = m_meshInterface->getScaling();
00283             for (int j=2;j>=0;j--)
00284             {
00285                 
00286                 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
00287 
00288 
00289 #ifdef DEBUG_TRIANGLE_MESH
00290                 printf("%d ,",graphicsindex);
00291 #endif //DEBUG_TRIANGLE_MESH
00292                 if (type == PHY_FLOAT)
00293                 {
00294                     float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00295                     
00296                     m_triangle[j] = btVector3(
00297                                                                         graphicsbase[0]*meshScaling.getX(),
00298                                                                         graphicsbase[1]*meshScaling.getY(),
00299                                                                         graphicsbase[2]*meshScaling.getZ());
00300                 }
00301                 else
00302                 {
00303                     double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00304 
00305                     m_triangle[j] = btVector3(
00306                         btScalar(graphicsbase[0])*meshScaling.getX(),
00307                         btScalar(graphicsbase[1])*meshScaling.getY(),
00308                         btScalar(graphicsbase[2])*meshScaling.getZ());
00309                 }
00310 #ifdef DEBUG_TRIANGLE_MESH
00311                 printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
00312 #endif //DEBUG_TRIANGLE_MESH
00313             }
00314 
00315             m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00316             m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00317         }
00318 
00319     };
00320 
00321     MyNodeOverlapCallback   myNodeCallback(callback,m_meshInterface);
00322 
00323     m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
00324 
00325 
00326 #endif//DISABLE_BVH
00327 
00328 
00329 }
00330 
00331 void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
00332 {
00333    if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
00334    {
00335       btTriangleMeshShape::setLocalScaling(scaling);
00336       buildOptimizedBvh();
00337    }
00338 }
00339 
00340 void   btBvhTriangleMeshShape::buildOptimizedBvh()
00341 {
00342     if (m_ownsBvh)
00343     {
00344         m_bvh->~btOptimizedBvh();
00345         btAlignedFree(m_bvh);
00346     }
00348     void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00349     m_bvh = new(mem) btOptimizedBvh();
00350     //rebuild the bvh...
00351     m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
00352     m_ownsBvh = true;
00353 }
00354 
00355 void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
00356 {
00357    btAssert(!m_bvh);
00358    btAssert(!m_ownsBvh);
00359 
00360    m_bvh = bvh;
00361    m_ownsBvh = false;
00362    // update the scaling without rebuilding the bvh
00363    if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
00364    {
00365       btTriangleMeshShape::setLocalScaling(scaling);
00366    }
00367 }
00368 
00369 
00370 
00372 const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
00373 {
00374     btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
00375 
00376     btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
00377 
00378     m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
00379 
00380     trimeshData->m_collisionMargin = float(m_collisionMargin);
00381 
00382     
00383 
00384     if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
00385     {
00386         void* chunk = serializer->findPointer(m_bvh);
00387         if (chunk)
00388         {
00389 #ifdef BT_USE_DOUBLE_PRECISION
00390             trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
00391             trimeshData->m_quantizedFloatBvh = 0;
00392 #else
00393             trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)chunk;
00394             trimeshData->m_quantizedDoubleBvh= 0;
00395 #endif //BT_USE_DOUBLE_PRECISION
00396         } else
00397         {
00398 
00399 #ifdef BT_USE_DOUBLE_PRECISION
00400             trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
00401             trimeshData->m_quantizedFloatBvh = 0;
00402 #else
00403             trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
00404             trimeshData->m_quantizedDoubleBvh= 0;
00405 #endif //BT_USE_DOUBLE_PRECISION
00406     
00407             int sz = m_bvh->calculateSerializeBufferSizeNew();
00408             btChunk* chunk = serializer->allocate(sz,1);
00409             const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
00410             serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
00411         }
00412     } else
00413     {
00414         trimeshData->m_quantizedFloatBvh = 0;
00415         trimeshData->m_quantizedDoubleBvh = 0;
00416     }
00417 
00418     
00419 
00420     if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
00421     {
00422         void* chunk = serializer->findPointer(m_triangleInfoMap);
00423         if (chunk)
00424         {
00425             trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
00426         } else
00427         {
00428             trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
00429             int sz = m_triangleInfoMap->calculateSerializeBufferSize();
00430             btChunk* chunk = serializer->allocate(sz,1);
00431             const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
00432             serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
00433         }
00434     } else
00435     {
00436         trimeshData->m_triangleInfoMap = 0;
00437     }
00438 
00439     return "btTriangleMeshShapeData";
00440 }
00441 
00442 void    btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
00443 {
00444     if (m_bvh)
00445     {
00446         int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
00447         btChunk* chunk = serializer->allocate(len,1);
00448         const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
00449         serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
00450     }
00451 }
00452 
00453 void    btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
00454 {
00455     if (m_triangleInfoMap)
00456     {
00457         int len = m_triangleInfoMap->calculateSerializeBufferSize();
00458         btChunk* chunk = serializer->allocate(len,1);
00459         const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
00460         serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
00461     }
00462 }
00463 
00464 
00465 
00466