forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			304 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			304 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /*
 | ||
|  | Bullet Continuous Collision Detection and Physics Library | ||
|  | Copyright (c) 2011 Advanced Micro Devices, Inc.  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. | ||
|  | */ | ||
|  | 
 | ||
|  | 
 | ||
|  | ///This file was written by Erwin Coumans
 | ||
|  | ///Separating axis rest based on work from Pierre Terdiman, see
 | ||
|  | ///And contact clipping based on work from Simon Hobbs
 | ||
|  | 
 | ||
|  | #include "btConvexPolyhedron.h"
 | ||
|  | #include "LinearMath/btHashMap.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | btConvexPolyhedron::btConvexPolyhedron() | ||
|  | { | ||
|  | 
 | ||
|  | } | ||
|  | btConvexPolyhedron::~btConvexPolyhedron() | ||
|  | { | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | inline bool IsAlmostZero(const btVector3& v) | ||
|  | { | ||
|  | 	if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6)	return false; | ||
|  | 	return true; | ||
|  | } | ||
|  | 
 | ||
|  | struct btInternalVertexPair | ||
|  | { | ||
|  | 	btInternalVertexPair(short int v0,short int v1) | ||
|  | 		:m_v0(v0), | ||
|  | 		m_v1(v1) | ||
|  | 	{ | ||
|  | 		if (m_v1>m_v0) | ||
|  | 			btSwap(m_v0,m_v1); | ||
|  | 	} | ||
|  | 	short int m_v0; | ||
|  | 	short int m_v1; | ||
|  | 	int getHash() const | ||
|  | 	{ | ||
|  | 		return m_v0+(m_v1<<16); | ||
|  | 	} | ||
|  | 	bool equals(const btInternalVertexPair& other) const | ||
|  | 	{ | ||
|  | 		return m_v0==other.m_v0 && m_v1==other.m_v1; | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | struct btInternalEdge | ||
|  | { | ||
|  | 	btInternalEdge() | ||
|  | 		:m_face0(-1), | ||
|  | 		m_face1(-1) | ||
|  | 	{ | ||
|  | 	} | ||
|  | 	short int m_face0; | ||
|  | 	short int m_face1; | ||
|  | }; | ||
|  | 
 | ||
|  | //
 | ||
|  | 
 | ||
|  | #ifdef TEST_INTERNAL_OBJECTS
 | ||
|  | bool btConvexPolyhedron::testContainment() const | ||
|  | { | ||
|  | 	for(int p=0;p<8;p++) | ||
|  | 	{ | ||
|  | 		btVector3 LocalPt; | ||
|  | 		if(p==0)		LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]); | ||
|  | 		else if(p==1)	LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]); | ||
|  | 		else if(p==2)	LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]); | ||
|  | 		else if(p==3)	LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]); | ||
|  | 		else if(p==4)	LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]); | ||
|  | 		else if(p==5)	LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]); | ||
|  | 		else if(p==6)	LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]); | ||
|  | 		else if(p==7)	LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]); | ||
|  | 
 | ||
|  | 		for(int i=0;i<m_faces.size();i++) | ||
|  | 		{ | ||
|  | 			const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]); | ||
|  | 			const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3]; | ||
|  | 			if(d>0.0f) | ||
|  | 				return false; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	return true; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | void	btConvexPolyhedron::initialize() | ||
|  | { | ||
|  | 
 | ||
|  | 	btHashMap<btInternalVertexPair,btInternalEdge> edges; | ||
|  | 
 | ||
|  | 	btScalar TotalArea = 0.0f; | ||
|  | 	 | ||
|  | 	m_localCenter.setValue(0, 0, 0); | ||
|  | 	for(int i=0;i<m_faces.size();i++) | ||
|  | 	{ | ||
|  | 		int numVertices = m_faces[i].m_indices.size(); | ||
|  | 		int NbTris = numVertices; | ||
|  | 		for(int j=0;j<NbTris;j++) | ||
|  | 		{ | ||
|  | 			int k = (j+1)%numVertices; | ||
|  | 			btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]); | ||
|  | 			btInternalEdge* edptr = edges.find(vp); | ||
|  | 			btVector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0]; | ||
|  | 			edge.normalize(); | ||
|  | 
 | ||
|  | 			bool found = false; | ||
|  | 
 | ||
|  | 			for (int p=0;p<m_uniqueEdges.size();p++) | ||
|  | 			{ | ||
|  | 				 | ||
|  | 				if (IsAlmostZero(m_uniqueEdges[p]-edge) ||  | ||
|  | 					IsAlmostZero(m_uniqueEdges[p]+edge)) | ||
|  | 				{ | ||
|  | 					found = true; | ||
|  | 					break; | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (!found) | ||
|  | 			{ | ||
|  | 				m_uniqueEdges.push_back(edge); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (edptr) | ||
|  | 			{ | ||
|  | 				btAssert(edptr->m_face0>=0); | ||
|  | 				btAssert(edptr->m_face1<0); | ||
|  | 				edptr->m_face1 = i; | ||
|  | 			} else | ||
|  | 			{ | ||
|  | 				btInternalEdge ed; | ||
|  | 				ed.m_face0 = i; | ||
|  | 				edges.insert(vp,ed); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | #ifdef USE_CONNECTED_FACES
 | ||
|  | 	for(int i=0;i<m_faces.size();i++) | ||
|  | 	{ | ||
|  | 		int numVertices = m_faces[i].m_indices.size(); | ||
|  | 		m_faces[i].m_connectedFaces.resize(numVertices); | ||
|  | 
 | ||
|  | 		for(int j=0;j<numVertices;j++) | ||
|  | 		{ | ||
|  | 			int k = (j+1)%numVertices; | ||
|  | 			btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]); | ||
|  | 			btInternalEdge* edptr = edges.find(vp); | ||
|  | 			btAssert(edptr); | ||
|  | 			btAssert(edptr->m_face0>=0); | ||
|  | 			btAssert(edptr->m_face1>=0); | ||
|  | 
 | ||
|  | 			int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0; | ||
|  | 			m_faces[i].m_connectedFaces[j] = connectedFace; | ||
|  | 		} | ||
|  | 	} | ||
|  | #endif//USE_CONNECTED_FACES
 | ||
|  | 
 | ||
|  | 	for(int i=0;i<m_faces.size();i++) | ||
|  | 	{ | ||
|  | 		int numVertices = m_faces[i].m_indices.size(); | ||
|  | 		int NbTris = numVertices-2; | ||
|  | 		 | ||
|  | 		const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]]; | ||
|  | 		for(int j=1;j<=NbTris;j++) | ||
|  | 		{ | ||
|  | 			int k = (j+1)%numVertices; | ||
|  | 			const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]]; | ||
|  | 			const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]]; | ||
|  | 			btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f; | ||
|  | 			btVector3 Center = (p0+p1+p2)/3.0f; | ||
|  | 			m_localCenter += Area * Center; | ||
|  | 			TotalArea += Area; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	m_localCenter /= TotalArea; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef TEST_INTERNAL_OBJECTS
 | ||
|  | 	if(1) | ||
|  | 	{ | ||
|  | 		m_radius = FLT_MAX; | ||
|  | 		for(int i=0;i<m_faces.size();i++) | ||
|  | 		{ | ||
|  | 			const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]); | ||
|  | 			const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]); | ||
|  | 			if(dist<m_radius) | ||
|  | 				m_radius = dist; | ||
|  | 		} | ||
|  | 
 | ||
|  | 	 | ||
|  | 		btScalar MinX = FLT_MAX; | ||
|  | 		btScalar MinY = FLT_MAX; | ||
|  | 		btScalar MinZ = FLT_MAX; | ||
|  | 		btScalar MaxX = -FLT_MAX; | ||
|  | 		btScalar MaxY = -FLT_MAX; | ||
|  | 		btScalar MaxZ = -FLT_MAX; | ||
|  | 		for(int i=0; i<m_vertices.size(); i++) | ||
|  | 		{ | ||
|  | 			const btVector3& pt = m_vertices[i]; | ||
|  | 			if(pt.x()<MinX)	MinX = pt.x(); | ||
|  | 			if(pt.x()>MaxX)	MaxX = pt.x(); | ||
|  | 			if(pt.y()<MinY)	MinY = pt.y(); | ||
|  | 			if(pt.y()>MaxY)	MaxY = pt.y(); | ||
|  | 			if(pt.z()<MinZ)	MinZ = pt.z(); | ||
|  | 			if(pt.z()>MaxZ)	MaxZ = pt.z(); | ||
|  | 		} | ||
|  | 		mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ); | ||
|  | 		mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ); | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | //		const btScalar r = m_radius / sqrtf(2.0f);
 | ||
|  | 		const btScalar r = m_radius / sqrtf(3.0f); | ||
|  | 		const int LargestExtent = mE.maxAxis(); | ||
|  | 		const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f; | ||
|  | 		m_extents[0] = m_extents[1] = m_extents[2] = r; | ||
|  | 		m_extents[LargestExtent] = mE[LargestExtent]*0.5f; | ||
|  | 		bool FoundBox = false; | ||
|  | 		for(int j=0;j<1024;j++) | ||
|  | 		{ | ||
|  | 			if(testContainment()) | ||
|  | 			{ | ||
|  | 				FoundBox = true; | ||
|  | 				break; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			m_extents[LargestExtent] -= Step; | ||
|  | 		} | ||
|  | 		if(!FoundBox) | ||
|  | 		{ | ||
|  | 			m_extents[0] = m_extents[1] = m_extents[2] = r; | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			// Refine the box
 | ||
|  | 			const btScalar Step = (m_radius - r)/1024.0f; | ||
|  | 			const int e0 = (1<<LargestExtent) & 3; | ||
|  | 			const int e1 = (1<<e0) & 3; | ||
|  | 
 | ||
|  | 			for(int j=0;j<1024;j++) | ||
|  | 			{ | ||
|  | 				const btScalar Saved0 = m_extents[e0]; | ||
|  | 				const btScalar Saved1 = m_extents[e1]; | ||
|  | 				m_extents[e0] += Step; | ||
|  | 				m_extents[e1] += Step; | ||
|  | 
 | ||
|  | 				if(!testContainment()) | ||
|  | 				{ | ||
|  | 					m_extents[e0] = Saved0; | ||
|  | 					m_extents[e1] = Saved1; | ||
|  | 					break; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const | ||
|  | { | ||
|  | 	minProj = FLT_MAX; | ||
|  | 	maxProj = -FLT_MAX; | ||
|  | 	int numVerts = m_vertices.size(); | ||
|  | 	for(int i=0;i<numVerts;i++) | ||
|  | 	{ | ||
|  | 		btVector3 pt = trans * m_vertices[i]; | ||
|  | 		btScalar dp = pt.dot(dir); | ||
|  | 		if(dp < minProj) | ||
|  | 		{ | ||
|  | 			minProj = dp; | ||
|  | 			witnesPtMin = pt; | ||
|  | 		} | ||
|  | 		if(dp > maxProj) | ||
|  | 		{ | ||
|  | 			maxProj = dp; | ||
|  | 			witnesPtMax = pt; | ||
|  | 		} | ||
|  | 	} | ||
|  | 	if(minProj>maxProj) | ||
|  | 	{ | ||
|  | 		btSwap(minProj,maxProj); | ||
|  | 		btSwap(witnesPtMin,witnesPtMax); | ||
|  | 	} | ||
|  | } |