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
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 m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
00030
00031 #ifndef DISABLE_BVH
00032
00033 if (buildBvh)
00034 {
00035 buildOptimizedBvh();
00036 }
00037
00038 #endif //DISABLE_BVH
00039
00040 }
00041
00042 btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
00043 :btTriangleMeshShape(meshInterface),
00044 m_bvh(0),
00045 m_useQuantizedAabbCompression(useQuantizedAabbCompression),
00046 m_ownsBvh(false)
00047 {
00048 m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
00049
00050 #ifndef DISABLE_BVH
00051
00052 if (buildBvh)
00053 {
00054 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00055 m_bvh = new (mem) btOptimizedBvh();
00056
00057 m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
00058 m_ownsBvh = true;
00059 }
00060
00061 #endif //DISABLE_BVH
00062
00063 }
00064
00065 void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00066 {
00067 m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
00068
00069 m_localAabbMin.setMin(aabbMin);
00070 m_localAabbMax.setMax(aabbMax);
00071 }
00072
00073
00074 void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
00075 {
00076 m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
00077
00078 recalcLocalAabb();
00079 }
00080
00081 btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
00082 {
00083 if (m_ownsBvh)
00084 {
00085 m_bvh->~btOptimizedBvh();
00086 btAlignedFree(m_bvh);
00087 }
00088 }
00089
00090 void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
00091 {
00092 struct MyNodeOverlapCallback : public btNodeOverlapCallback
00093 {
00094 btStridingMeshInterface* m_meshInterface;
00095 btTriangleCallback* m_callback;
00096
00097 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00098 :m_meshInterface(meshInterface),
00099 m_callback(callback)
00100 {
00101 }
00102
00103 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00104 {
00105 btVector3 m_triangle[3];
00106 const unsigned char *vertexbase;
00107 int numverts;
00108 PHY_ScalarType type;
00109 int stride;
00110 const unsigned char *indexbase;
00111 int indexstride;
00112 int numfaces;
00113 PHY_ScalarType indicestype;
00114
00115 m_meshInterface->getLockedReadOnlyVertexIndexBase(
00116 &vertexbase,
00117 numverts,
00118 type,
00119 stride,
00120 &indexbase,
00121 indexstride,
00122 numfaces,
00123 indicestype,
00124 nodeSubPart);
00125
00126 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00127 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00128
00129 const btVector3& meshScaling = m_meshInterface->getScaling();
00130 for (int j=2;j>=0;j--)
00131 {
00132 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00133
00134 if (type == PHY_FLOAT)
00135 {
00136 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00137
00138 m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
00139 }
00140 else
00141 {
00142 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00143
00144 m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
00145 }
00146 }
00147
00148
00149 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00150 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00151 }
00152 };
00153
00154 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
00155
00156 m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
00157 }
00158
00159 void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
00160 {
00161 struct MyNodeOverlapCallback : public btNodeOverlapCallback
00162 {
00163 btStridingMeshInterface* m_meshInterface;
00164 btTriangleCallback* m_callback;
00165
00166 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00167 :m_meshInterface(meshInterface),
00168 m_callback(callback)
00169 {
00170 }
00171
00172 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00173 {
00174 btVector3 m_triangle[3];
00175 const unsigned char *vertexbase;
00176 int numverts;
00177 PHY_ScalarType type;
00178 int stride;
00179 const unsigned char *indexbase;
00180 int indexstride;
00181 int numfaces;
00182 PHY_ScalarType indicestype;
00183
00184 m_meshInterface->getLockedReadOnlyVertexIndexBase(
00185 &vertexbase,
00186 numverts,
00187 type,
00188 stride,
00189 &indexbase,
00190 indexstride,
00191 numfaces,
00192 indicestype,
00193 nodeSubPart);
00194
00195 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00196 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00197
00198 const btVector3& meshScaling = m_meshInterface->getScaling();
00199 for (int j=2;j>=0;j--)
00200 {
00201 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00202
00203 if (type == PHY_FLOAT)
00204 {
00205 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00206
00207 m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
00208 }
00209 else
00210 {
00211 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00212
00213 m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
00214 }
00215 }
00216
00217
00218 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00219 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00220 }
00221 };
00222
00223 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
00224
00225 m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
00226 }
00227
00228
00229 void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00230 {
00231
00232 #ifdef DISABLE_BVH
00233
00234 btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
00235 #else
00236
00237
00238
00239
00240 struct MyNodeOverlapCallback : public btNodeOverlapCallback
00241 {
00242 btStridingMeshInterface* m_meshInterface;
00243 btTriangleCallback* m_callback;
00244 btVector3 m_triangle[3];
00245
00246
00247 MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
00248 :m_meshInterface(meshInterface),
00249 m_callback(callback)
00250 {
00251 }
00252
00253 virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
00254 {
00255 const unsigned char *vertexbase;
00256 int numverts;
00257 PHY_ScalarType type;
00258 int stride;
00259 const unsigned char *indexbase;
00260 int indexstride;
00261 int numfaces;
00262 PHY_ScalarType indicestype;
00263
00264
00265 m_meshInterface->getLockedReadOnlyVertexIndexBase(
00266 &vertexbase,
00267 numverts,
00268 type,
00269 stride,
00270 &indexbase,
00271 indexstride,
00272 numfaces,
00273 indicestype,
00274 nodeSubPart);
00275
00276 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00277 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00278
00279 const btVector3& meshScaling = m_meshInterface->getScaling();
00280 for (int j=2;j>=0;j--)
00281 {
00282
00283 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00284
00285
00286 #ifdef DEBUG_TRIANGLE_MESH
00287 printf("%d ,",graphicsindex);
00288 #endif //DEBUG_TRIANGLE_MESH
00289 if (type == PHY_FLOAT)
00290 {
00291 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00292
00293 m_triangle[j] = btVector3(
00294 graphicsbase[0]*meshScaling.getX(),
00295 graphicsbase[1]*meshScaling.getY(),
00296 graphicsbase[2]*meshScaling.getZ());
00297 }
00298 else
00299 {
00300 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00301
00302 m_triangle[j] = btVector3(
00303 btScalar(graphicsbase[0])*meshScaling.getX(),
00304 btScalar(graphicsbase[1])*meshScaling.getY(),
00305 btScalar(graphicsbase[2])*meshScaling.getZ());
00306 }
00307 #ifdef DEBUG_TRIANGLE_MESH
00308 printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
00309 #endif //DEBUG_TRIANGLE_MESH
00310 }
00311
00312 m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
00313 m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
00314 }
00315
00316 };
00317
00318 MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
00319
00320 m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
00321
00322
00323 #endif//DISABLE_BVH
00324
00325
00326 }
00327
00328 void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
00329 {
00330 if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
00331 {
00332 btTriangleMeshShape::setLocalScaling(scaling);
00333 buildOptimizedBvh();
00334 }
00335 }
00336
00337 void btBvhTriangleMeshShape::buildOptimizedBvh()
00338 {
00339 if (m_ownsBvh)
00340 {
00341 m_bvh->~btOptimizedBvh();
00342 btAlignedFree(m_bvh);
00343 }
00345 void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
00346 m_bvh = new(mem) btOptimizedBvh();
00347
00348 m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
00349 m_ownsBvh = true;
00350 }
00351
00352 void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
00353 {
00354 btAssert(!m_bvh);
00355 btAssert(!m_ownsBvh);
00356
00357 m_bvh = bvh;
00358 m_ownsBvh = false;
00359
00360 if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
00361 {
00362 btTriangleMeshShape::setLocalScaling(scaling);
00363 }
00364 }
00365
00366