forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			316 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			316 lines
		
	
	
		
			8.2 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. | ||
|  | */ | ||
|  | 
 | ||
|  | #include "btConvexTriangleMeshShape.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btCollisionMargin.h"
 | ||
|  | 
 | ||
|  | #include "LinearMath/btQuaternion.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) | ||
|  | : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface) | ||
|  | { | ||
|  | 	m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; | ||
|  | 	if ( calcAabb ) | ||
|  | 		recalcLocalAabb(); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | ///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
 | ||
|  | ///but then we are duplicating
 | ||
|  | class LocalSupportVertexCallback: public btInternalTriangleIndexCallback | ||
|  | { | ||
|  | 
 | ||
|  | 	btVector3 m_supportVertexLocal; | ||
|  | public: | ||
|  | 
 | ||
|  | 	btScalar m_maxDot; | ||
|  | 	btVector3 m_supportVecLocal; | ||
|  | 
 | ||
|  | 	LocalSupportVertexCallback(const btVector3& supportVecLocal) | ||
|  | 		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), | ||
|  | 		m_maxDot(btScalar(-BT_LARGE_FLOAT)), | ||
|  |                 m_supportVecLocal(supportVecLocal) | ||
|  | 	{ | ||
|  | 	} | ||
|  | 
 | ||
|  | 	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex) | ||
|  | 	{ | ||
|  | 		(void)triangleIndex; | ||
|  | 		(void)partId; | ||
|  | 
 | ||
|  | 		for (int i=0;i<3;i++) | ||
|  | 		{ | ||
|  | 			btScalar dot = m_supportVecLocal.dot(triangle[i]); | ||
|  | 			if (dot > m_maxDot) | ||
|  | 			{ | ||
|  | 				m_maxDot = dot; | ||
|  | 				m_supportVertexLocal = triangle[i]; | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	btVector3	GetSupportVertexLocal() | ||
|  | 	{ | ||
|  | 		return m_supportVertexLocal; | ||
|  | 	} | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | btVector3	btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const | ||
|  | { | ||
|  | 	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); | ||
|  | 
 | ||
|  | 	btVector3 vec = vec0; | ||
|  | 	btScalar lenSqr = vec.length2(); | ||
|  | 	if (lenSqr < btScalar(0.0001)) | ||
|  | 	{ | ||
|  | 		vec.setValue(1,0,0); | ||
|  | 	} else | ||
|  | 	{ | ||
|  | 		btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); | ||
|  | 		vec *= rlen; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	LocalSupportVertexCallback	supportCallback(vec); | ||
|  | 	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||
|  | 	m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); | ||
|  | 	supVec = supportCallback.GetSupportVertexLocal(); | ||
|  | 
 | ||
|  | 	return supVec; | ||
|  | } | ||
|  | 
 | ||
|  | void	btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const | ||
|  | { | ||
|  | 	//use 'w' component of supportVerticesOut?
 | ||
|  | 	{ | ||
|  | 		for (int i=0;i<numVectors;i++) | ||
|  | 		{ | ||
|  | 			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT); | ||
|  | 		} | ||
|  | 	} | ||
|  | 	 | ||
|  | 	///@todo: could do the batch inside the callback!
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 	for (int j=0;j<numVectors;j++) | ||
|  | 	{ | ||
|  | 		const btVector3& vec = vectors[j]; | ||
|  | 		LocalSupportVertexCallback	supportCallback(vec); | ||
|  | 		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||
|  | 		m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); | ||
|  | 		supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); | ||
|  | 	} | ||
|  | 	 | ||
|  | } | ||
|  | 	 | ||
|  | 
 | ||
|  | 
 | ||
|  | btVector3	btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const | ||
|  | { | ||
|  | 	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); | ||
|  | 
 | ||
|  | 	if ( getMargin()!=btScalar(0.) ) | ||
|  | 	{ | ||
|  | 		btVector3 vecnorm = vec; | ||
|  | 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) | ||
|  | 		{ | ||
|  | 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); | ||
|  | 		}  | ||
|  | 		vecnorm.normalize(); | ||
|  | 		supVertex+= getMargin() * vecnorm; | ||
|  | 	} | ||
|  | 	return supVertex; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
 | ||
|  | //Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
 | ||
|  | int	btConvexTriangleMeshShape::getNumVertices() const | ||
|  | { | ||
|  | 	//cache this?
 | ||
|  | 	return 0; | ||
|  | 	 | ||
|  | } | ||
|  | 
 | ||
|  | int btConvexTriangleMeshShape::getNumEdges() const | ||
|  | { | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const | ||
|  | { | ||
|  | 	btAssert(0);	 | ||
|  | } | ||
|  | 
 | ||
|  | void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const | ||
|  | { | ||
|  | 	btAssert(0); | ||
|  | } | ||
|  | 
 | ||
|  | int	btConvexTriangleMeshShape::getNumPlanes() const | ||
|  | { | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int  ) const | ||
|  | { | ||
|  | 	btAssert(0); | ||
|  | } | ||
|  | 
 | ||
|  | //not yet
 | ||
|  | bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const | ||
|  | { | ||
|  | 	btAssert(0); | ||
|  | 	return false; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | void	btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) | ||
|  | { | ||
|  | 	m_stridingMesh->setScaling(scaling); | ||
|  | 	 | ||
|  | 	recalcLocalAabb(); | ||
|  | 	 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | const btVector3& btConvexTriangleMeshShape::getLocalScaling() const | ||
|  | { | ||
|  | 	return m_stridingMesh->getScaling(); | ||
|  | } | ||
|  | 
 | ||
|  | void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const | ||
|  | { | ||
|  |    class CenterCallback: public btInternalTriangleIndexCallback | ||
|  |    { | ||
|  |       bool first; | ||
|  |       btVector3 ref; | ||
|  |       btVector3 sum; | ||
|  |       btScalar volume; | ||
|  | 
 | ||
|  |    public: | ||
|  | 
 | ||
|  |       CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) | ||
|  |       { | ||
|  |       } | ||
|  | 
 | ||
|  |       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) | ||
|  |       { | ||
|  |          (void) triangleIndex; | ||
|  |          (void) partId; | ||
|  |          if (first) | ||
|  |          { | ||
|  |             ref = triangle[0]; | ||
|  |             first = false; | ||
|  |          } | ||
|  |          else | ||
|  |          { | ||
|  |             btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); | ||
|  |             sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); | ||
|  |             volume += vol; | ||
|  |          } | ||
|  |       } | ||
|  |        | ||
|  |       btVector3 getCenter() | ||
|  |       { | ||
|  |          return (volume > 0) ? sum / volume : ref; | ||
|  |       } | ||
|  | 
 | ||
|  |       btScalar getVolume() | ||
|  |       { | ||
|  |          return volume * btScalar(1. / 6); | ||
|  |       } | ||
|  | 
 | ||
|  |    }; | ||
|  | 
 | ||
|  |    class InertiaCallback: public btInternalTriangleIndexCallback | ||
|  |    { | ||
|  |       btMatrix3x3 sum; | ||
|  |       btVector3 center; | ||
|  | 
 | ||
|  |    public: | ||
|  | 
 | ||
|  |       InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) | ||
|  |       { | ||
|  |       } | ||
|  | 
 | ||
|  |       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) | ||
|  |       { | ||
|  |          (void) triangleIndex; | ||
|  |          (void) partId; | ||
|  |          btMatrix3x3 i; | ||
|  |          btVector3 a = triangle[0] - center; | ||
|  |          btVector3 b = triangle[1] - center; | ||
|  |          btVector3 c = triangle[2] - center; | ||
|  |          btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); | ||
|  |          for (int j = 0; j < 3; j++) | ||
|  |          { | ||
|  |             for (int k = 0; k <= j; k++) | ||
|  |             { | ||
|  |                i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) | ||
|  |                   + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); | ||
|  |             } | ||
|  |          } | ||
|  |          btScalar i00 = -i[0][0]; | ||
|  |          btScalar i11 = -i[1][1]; | ||
|  |          btScalar i22 = -i[2][2]; | ||
|  |          i[0][0] = i11 + i22;  | ||
|  |          i[1][1] = i22 + i00;  | ||
|  |          i[2][2] = i00 + i11; | ||
|  |          sum[0] += i[0]; | ||
|  |          sum[1] += i[1]; | ||
|  |          sum[2] += i[2]; | ||
|  |       } | ||
|  |        | ||
|  |       btMatrix3x3& getInertia() | ||
|  |       { | ||
|  |          return sum; | ||
|  |       } | ||
|  | 
 | ||
|  |    }; | ||
|  | 
 | ||
|  |    CenterCallback centerCallback; | ||
|  |    btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); | ||
|  |    m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); | ||
|  |    btVector3 center = centerCallback.getCenter(); | ||
|  |    principal.setOrigin(center); | ||
|  |    volume = centerCallback.getVolume(); | ||
|  | 
 | ||
|  |    InertiaCallback inertiaCallback(center); | ||
|  |    m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); | ||
|  | 
 | ||
|  |    btMatrix3x3& i = inertiaCallback.getInertia(); | ||
|  |    i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); | ||
|  |    inertia.setValue(i[0][0], i[1][1], i[2][2]); | ||
|  |    inertia /= volume; | ||
|  | } | ||
|  | 
 |