471 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			471 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /*
 | ||
|  | 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 "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
 | ||
|  | #include "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]; | ||
|  | 		int m_numOverlap; | ||
|  | 
 | ||
|  | 		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) | ||
|  | 			:m_meshInterface(meshInterface), | ||
|  | 			m_callback(callback), | ||
|  | 			m_numOverlap(0) | ||
|  | 		{ | ||
|  | 		} | ||
|  | 				 | ||
|  | 		virtual void processNode(int nodeSubPart, int nodeTriangleIndex) | ||
|  | 		{ | ||
|  | 			m_numOverlap++; | ||
|  | 			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; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Fill padding with zeros to appease msan.
 | ||
|  | 	memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3)); | ||
|  | 
 | ||
|  | 	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); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |