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