Blender V2.61 - r43446
|
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