00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
00232 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00233 {
00234
00235 #ifdef DISABLE_BVH
00236
00237 btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
00238 #else
00239
00240
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
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
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();
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