123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- //#define DISABLE_BVH
- #include "bullet/BulletCollision//CollisionShapes/btBvhTriangleMeshShape.h"
- #include "bullet/BulletCollision//CollisionShapes/btOptimizedBvh.h"
- #include "bullet/LinearMath/btSerializer.h"
- ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
- ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
- btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
- :btTriangleMeshShape(meshInterface),
- m_bvh(0),
- m_triangleInfoMap(0),
- m_useQuantizedAabbCompression(useQuantizedAabbCompression),
- m_ownsBvh(false)
- {
- m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- //construct bvh from meshInterface
- #ifndef DISABLE_BVH
- if (buildBvh)
- {
- buildOptimizedBvh();
- }
- #endif //DISABLE_BVH
- }
- btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
- :btTriangleMeshShape(meshInterface),
- m_bvh(0),
- m_triangleInfoMap(0),
- m_useQuantizedAabbCompression(useQuantizedAabbCompression),
- m_ownsBvh(false)
- {
- m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- //construct bvh from meshInterface
- #ifndef DISABLE_BVH
- if (buildBvh)
- {
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
- m_bvh = new (mem) btOptimizedBvh();
-
- m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
- m_ownsBvh = true;
- }
- #endif //DISABLE_BVH
- }
- void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
- {
- m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
-
- m_localAabbMin.setMin(aabbMin);
- m_localAabbMax.setMax(aabbMax);
- }
- void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
- {
- m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
-
- recalcLocalAabb();
- }
- btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
- {
- if (m_ownsBvh)
- {
- m_bvh->~btOptimizedBvh();
- btAlignedFree(m_bvh);
- }
- }
- void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
- {
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- btVector3 m_triangle[3];
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
- {
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
-
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
- }
- }
- /* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
- m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
- }
- void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
- {
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- btVector3 m_triangle[3];
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
- {
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
- m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
- }
- }
- /* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
- m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
- }
- //perform bvh tree traversal and report overlapping triangles to 'callback'
- void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
- {
- #ifdef DISABLE_BVH
- //brute force traverse all triangles
- btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
- #else
- //first get all the nodes
-
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
- btVector3 m_triangle[3];
- MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
- :m_meshInterface(meshInterface),
- m_callback(callback)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
- unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
- btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j=2;j>=0;j--)
- {
-
- int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
- #ifdef DEBUG_TRIANGLE_MESH
- printf("%d ,",graphicsindex);
- #endif //DEBUG_TRIANGLE_MESH
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
-
- m_triangle[j] = btVector3(
- graphicsbase[0]*meshScaling.getX(),
- graphicsbase[1]*meshScaling.getY(),
- graphicsbase[2]*meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
- m_triangle[j] = btVector3(
- btScalar(graphicsbase[0])*meshScaling.getX(),
- btScalar(graphicsbase[1])*meshScaling.getY(),
- btScalar(graphicsbase[2])*meshScaling.getZ());
- }
- #ifdef DEBUG_TRIANGLE_MESH
- printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
- #endif //DEBUG_TRIANGLE_MESH
- }
- m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
- MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
- m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
- #endif//DISABLE_BVH
- }
- void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
- {
- if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- buildOptimizedBvh();
- }
- }
- void btBvhTriangleMeshShape::buildOptimizedBvh()
- {
- if (m_ownsBvh)
- {
- m_bvh->~btOptimizedBvh();
- btAlignedFree(m_bvh);
- }
- ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
- m_bvh = new(mem) btOptimizedBvh();
- //rebuild the bvh...
- m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
- m_ownsBvh = true;
- }
- void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
- {
- btAssert(!m_bvh);
- btAssert(!m_ownsBvh);
- m_bvh = bvh;
- m_ownsBvh = false;
- // update the scaling without rebuilding the bvh
- if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- }
- }
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
- {
- btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
- btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
- m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
- trimeshData->m_collisionMargin = float(m_collisionMargin);
-
- if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
- {
- void* chunk = serializer->findPointer(m_bvh);
- if (chunk)
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
- trimeshData->m_quantizedFloatBvh = 0;
- #else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
- trimeshData->m_quantizedDoubleBvh= 0;
- #endif //BT_USE_DOUBLE_PRECISION
- } else
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
- trimeshData->m_quantizedFloatBvh = 0;
- #else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
- trimeshData->m_quantizedDoubleBvh= 0;
- #endif //BT_USE_DOUBLE_PRECISION
-
- int sz = m_bvh->calculateSerializeBufferSizeNew();
- btChunk* chunk = serializer->allocate(sz,1);
- const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
- }
- } else
- {
- trimeshData->m_quantizedFloatBvh = 0;
- trimeshData->m_quantizedDoubleBvh = 0;
- }
-
- if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
- {
- void* chunk = serializer->findPointer(m_triangleInfoMap);
- if (chunk)
- {
- trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
- } else
- {
- trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
- int sz = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(sz,1);
- const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
- }
- } else
- {
- trimeshData->m_triangleInfoMap = 0;
- }
- return "btTriangleMeshShapeData";
- }
- void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
- {
- if (m_bvh)
- {
- int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
- btChunk* chunk = serializer->allocate(len,1);
- const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
- }
- }
- void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
- {
- if (m_triangleInfoMap)
- {
- int len = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len,1);
- const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
- }
- }
|