571 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			571 lines
		
	
	
		
			15 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 "btPolyhedralContactClipping.h"
 | 
						|
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
 | 
						|
 | 
						|
#include <float.h> //for FLT_MAX
 | 
						|
 | 
						|
int gExpectedNbTests=0;
 | 
						|
int gActualNbTests = 0;
 | 
						|
bool gUseInternalObject = true;
 | 
						|
 | 
						|
// Clips a face to the back of a plane
 | 
						|
void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS)
 | 
						|
{
 | 
						|
	
 | 
						|
	int ve;
 | 
						|
	btScalar ds, de;
 | 
						|
	int numVerts = pVtxIn.size();
 | 
						|
	if (numVerts < 2)
 | 
						|
		return;
 | 
						|
 | 
						|
	btVector3 firstVertex=pVtxIn[pVtxIn.size()-1];
 | 
						|
	btVector3 endVertex = pVtxIn[0];
 | 
						|
	
 | 
						|
	ds = planeNormalWS.dot(firstVertex)+planeEqWS;
 | 
						|
 | 
						|
	for (ve = 0; ve < numVerts; ve++)
 | 
						|
	{
 | 
						|
		endVertex=pVtxIn[ve];
 | 
						|
 | 
						|
		de = planeNormalWS.dot(endVertex)+planeEqWS;
 | 
						|
 | 
						|
		if (ds<0)
 | 
						|
		{
 | 
						|
			if (de<0)
 | 
						|
			{
 | 
						|
				// Start < 0, end < 0, so output endVertex
 | 
						|
				ppVtxOut.push_back(endVertex);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				// Start < 0, end >= 0, so output intersection
 | 
						|
				ppVtxOut.push_back( 	firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			if (de<0)
 | 
						|
			{
 | 
						|
				// Start >= 0, end < 0 so output intersection and end
 | 
						|
				ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
 | 
						|
				ppVtxOut.push_back(endVertex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		firstVertex = endVertex;
 | 
						|
		ds = de;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
 | 
						|
{
 | 
						|
	btScalar Min0,Max0;
 | 
						|
	btScalar Min1,Max1;
 | 
						|
	btVector3 witnesPtMinA,witnesPtMaxA;
 | 
						|
	btVector3 witnesPtMinB,witnesPtMaxB;
 | 
						|
 | 
						|
	hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA);
 | 
						|
	hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB);
 | 
						|
 | 
						|
	if(Max0<Min1 || Max1<Min0)
 | 
						|
		return false;
 | 
						|
 | 
						|
	btScalar d0 = Max0 - Min1;
 | 
						|
	btAssert(d0>=0.0f);
 | 
						|
	btScalar d1 = Max1 - Min0;
 | 
						|
	btAssert(d1>=0.0f);
 | 
						|
	if (d0<d1)
 | 
						|
	{
 | 
						|
		depth = d0;
 | 
						|
		witnessPointA = witnesPtMaxA;
 | 
						|
		witnessPointB = witnesPtMinB;
 | 
						|
 | 
						|
	} else
 | 
						|
	{
 | 
						|
		depth = d1;
 | 
						|
		witnessPointA = witnesPtMinA;
 | 
						|
		witnessPointB = witnesPtMaxB;
 | 
						|
	}
 | 
						|
	
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static int gActualSATPairTests=0;
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TEST_INTERNAL_OBJECTS
 | 
						|
 | 
						|
inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
 | 
						|
{
 | 
						|
	// This version is ~11.000 cycles (4%) faster overall in one of the tests.
 | 
						|
//	IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
 | 
						|
//	IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
 | 
						|
//	IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
 | 
						|
	p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
 | 
						|
	p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
 | 
						|
	p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
 | 
						|
}
 | 
						|
 | 
						|
void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr)
 | 
						|
{
 | 
						|
	const btMatrix3x3& rot = tr.getBasis();
 | 
						|
	const btVector3& r0 = rot[0];
 | 
						|
	const btVector3& r1 = rot[1];
 | 
						|
	const btVector3& r2 = rot[2];
 | 
						|
 | 
						|
	const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z();
 | 
						|
	const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z();
 | 
						|
	const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z();
 | 
						|
 | 
						|
	out.setValue(x, y, z);
 | 
						|
}
 | 
						|
 | 
						|
 bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
 | 
						|
{
 | 
						|
	const btScalar dp = delta_c.dot(axis);
 | 
						|
 | 
						|
	btVector3 localAxis0;
 | 
						|
	InverseTransformPoint3x3(localAxis0, axis,trans0);
 | 
						|
	btVector3 localAxis1;
 | 
						|
	InverseTransformPoint3x3(localAxis1, axis,trans1);
 | 
						|
 | 
						|
	btScalar p0[3];
 | 
						|
	BoxSupport(convex0.m_extents, localAxis0, p0);
 | 
						|
	btScalar p1[3];
 | 
						|
	BoxSupport(convex1.m_extents, localAxis1, p1);
 | 
						|
 | 
						|
	const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z();
 | 
						|
	const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z();
 | 
						|
 | 
						|
	const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius;
 | 
						|
	const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius;
 | 
						|
 | 
						|
	const btScalar MinMaxRadius = MaxRadius + MinRadius;
 | 
						|
	const btScalar d0 = MinMaxRadius + dp;
 | 
						|
	const btScalar d1 = MinMaxRadius - dp;
 | 
						|
 | 
						|
	const btScalar depth = d0<d1 ? d0:d1;
 | 
						|
	if(depth>dmin)
 | 
						|
		return false;
 | 
						|
	return true;
 | 
						|
}
 | 
						|
#endif //TEST_INTERNAL_OBJECTS
 | 
						|
 | 
						|
 
 | 
						|
 
 | 
						|
 SIMD_FORCE_INLINE void btSegmentsClosestPoints(
 | 
						|
	btVector3& ptsVector,
 | 
						|
	btVector3& offsetA,
 | 
						|
	btVector3& offsetB,
 | 
						|
	btScalar& tA, btScalar& tB,
 | 
						|
	const btVector3& translation,
 | 
						|
	const btVector3& dirA, btScalar hlenA,
 | 
						|
	const btVector3& dirB, btScalar hlenB )
 | 
						|
{
 | 
						|
	// compute the parameters of the closest points on each line segment
 | 
						|
 | 
						|
	btScalar dirA_dot_dirB = btDot(dirA,dirB);
 | 
						|
	btScalar dirA_dot_trans = btDot(dirA,translation);
 | 
						|
	btScalar dirB_dot_trans = btDot(dirB,translation);
 | 
						|
 | 
						|
	btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
 | 
						|
 | 
						|
	if ( denom == 0.0f ) {
 | 
						|
		tA = 0.0f;
 | 
						|
	} else {
 | 
						|
		tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
 | 
						|
		if ( tA < -hlenA )
 | 
						|
			tA = -hlenA;
 | 
						|
		else if ( tA > hlenA )
 | 
						|
			tA = hlenA;
 | 
						|
	}
 | 
						|
 | 
						|
	tB = tA * dirA_dot_dirB - dirB_dot_trans;
 | 
						|
 | 
						|
	if ( tB < -hlenB ) {
 | 
						|
		tB = -hlenB;
 | 
						|
		tA = tB * dirA_dot_dirB + dirA_dot_trans;
 | 
						|
 | 
						|
		if ( tA < -hlenA )
 | 
						|
			tA = -hlenA;
 | 
						|
		else if ( tA > hlenA )
 | 
						|
			tA = hlenA;
 | 
						|
	} else if ( tB > hlenB ) {
 | 
						|
		tB = hlenB;
 | 
						|
		tA = tB * dirA_dot_dirB + dirA_dot_trans;
 | 
						|
 | 
						|
		if ( tA < -hlenA )
 | 
						|
			tA = -hlenA;
 | 
						|
		else if ( tA > hlenA )
 | 
						|
			tA = hlenA;
 | 
						|
	}
 | 
						|
 | 
						|
	// compute the closest points relative to segment centers.
 | 
						|
 | 
						|
	offsetA = dirA * tA;
 | 
						|
	offsetB = dirB * tB;
 | 
						|
 | 
						|
	ptsVector = translation - offsetA + offsetB;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
bool btPolyhedralContactClipping::findSeparatingAxis(	const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
 | 
						|
{
 | 
						|
	gActualSATPairTests++;
 | 
						|
 | 
						|
//#ifdef TEST_INTERNAL_OBJECTS
 | 
						|
	const btVector3 c0 = transA * hullA.m_localCenter;
 | 
						|
	const btVector3 c1 = transB * hullB.m_localCenter;
 | 
						|
	const btVector3 DeltaC2 = c0 - c1;
 | 
						|
//#endif
 | 
						|
 | 
						|
	btScalar dmin = FLT_MAX;
 | 
						|
	int curPlaneTests=0;
 | 
						|
 | 
						|
	int numFacesA = hullA.m_faces.size();
 | 
						|
	// Test normals from hullA
 | 
						|
	for(int i=0;i<numFacesA;i++)
 | 
						|
	{
 | 
						|
		const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
 | 
						|
		btVector3 faceANormalWS = transA.getBasis() * Normal;
 | 
						|
		if (DeltaC2.dot(faceANormalWS)<0)
 | 
						|
			faceANormalWS*=-1.f;
 | 
						|
 | 
						|
		curPlaneTests++;
 | 
						|
#ifdef TEST_INTERNAL_OBJECTS
 | 
						|
		gExpectedNbTests++;
 | 
						|
		if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
 | 
						|
			continue;
 | 
						|
		gActualNbTests++;
 | 
						|
#endif
 | 
						|
 | 
						|
		btScalar d;
 | 
						|
		btVector3 wA,wB;
 | 
						|
		if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d,wA,wB))
 | 
						|
			return false;
 | 
						|
 | 
						|
		if(d<dmin)
 | 
						|
		{
 | 
						|
			dmin = d;
 | 
						|
			sep = faceANormalWS;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	int numFacesB = hullB.m_faces.size();
 | 
						|
	// Test normals from hullB
 | 
						|
	for(int i=0;i<numFacesB;i++)
 | 
						|
	{
 | 
						|
		const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
 | 
						|
		btVector3 WorldNormal = transB.getBasis() * Normal;
 | 
						|
		if (DeltaC2.dot(WorldNormal)<0)
 | 
						|
			WorldNormal *=-1.f;
 | 
						|
 | 
						|
		curPlaneTests++;
 | 
						|
#ifdef TEST_INTERNAL_OBJECTS
 | 
						|
		gExpectedNbTests++;
 | 
						|
		if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
 | 
						|
			continue;
 | 
						|
		gActualNbTests++;
 | 
						|
#endif
 | 
						|
 | 
						|
		btScalar d;
 | 
						|
		btVector3 wA,wB;
 | 
						|
		if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d,wA,wB))
 | 
						|
			return false;
 | 
						|
 | 
						|
		if(d<dmin)
 | 
						|
		{
 | 
						|
			dmin = d;
 | 
						|
			sep = WorldNormal;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
 | 
						|
	int edgeA=-1;
 | 
						|
	int edgeB=-1;
 | 
						|
	btVector3 worldEdgeA;
 | 
						|
	btVector3 worldEdgeB;
 | 
						|
	btVector3 witnessPointA(0,0,0),witnessPointB(0,0,0);
 | 
						|
	
 | 
						|
 | 
						|
	int curEdgeEdge = 0;
 | 
						|
	// Test edges
 | 
						|
	for(int e0=0;e0<hullA.m_uniqueEdges.size();e0++)
 | 
						|
	{
 | 
						|
		const btVector3 edge0 = hullA.m_uniqueEdges[e0];
 | 
						|
		const btVector3 WorldEdge0 = transA.getBasis() * edge0;
 | 
						|
		for(int e1=0;e1<hullB.m_uniqueEdges.size();e1++)
 | 
						|
		{
 | 
						|
			const btVector3 edge1 = hullB.m_uniqueEdges[e1];
 | 
						|
			const btVector3 WorldEdge1 = transB.getBasis() * edge1;
 | 
						|
 | 
						|
			btVector3 Cross = WorldEdge0.cross(WorldEdge1);
 | 
						|
			curEdgeEdge++;
 | 
						|
			if(!IsAlmostZero(Cross))
 | 
						|
			{
 | 
						|
				Cross = Cross.normalize();
 | 
						|
				if (DeltaC2.dot(Cross)<0)
 | 
						|
					Cross *= -1.f;
 | 
						|
 | 
						|
 | 
						|
#ifdef TEST_INTERNAL_OBJECTS
 | 
						|
				gExpectedNbTests++;
 | 
						|
				if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
 | 
						|
					continue;
 | 
						|
				gActualNbTests++;
 | 
						|
#endif
 | 
						|
 | 
						|
				btScalar dist;
 | 
						|
				btVector3 wA,wB;
 | 
						|
				if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist,wA,wB))
 | 
						|
					return false;
 | 
						|
 | 
						|
				if(dist<dmin)
 | 
						|
				{
 | 
						|
					dmin = dist;
 | 
						|
					sep = Cross;
 | 
						|
					edgeA=e0;
 | 
						|
					edgeB=e1;
 | 
						|
					worldEdgeA = WorldEdge0;
 | 
						|
					worldEdgeB = WorldEdge1;
 | 
						|
					witnessPointA=wA;
 | 
						|
					witnessPointB=wB;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	if (edgeA>=0&&edgeB>=0)
 | 
						|
	{
 | 
						|
//		printf("edge-edge\n");
 | 
						|
		//add an edge-edge contact
 | 
						|
 | 
						|
		btVector3 ptsVector;
 | 
						|
		btVector3 offsetA;
 | 
						|
		btVector3 offsetB;
 | 
						|
		btScalar tA;
 | 
						|
		btScalar tB;
 | 
						|
 | 
						|
		btVector3 translation = witnessPointB-witnessPointA;
 | 
						|
 | 
						|
		btVector3 dirA = worldEdgeA;
 | 
						|
		btVector3 dirB = worldEdgeB;
 | 
						|
		
 | 
						|
		btScalar hlenB = 1e30f;
 | 
						|
		btScalar hlenA = 1e30f;
 | 
						|
 | 
						|
		btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB,
 | 
						|
			translation,
 | 
						|
			dirA, hlenA,
 | 
						|
			dirB,hlenB);
 | 
						|
 | 
						|
		btScalar nlSqrt = ptsVector.length2();
 | 
						|
		if (nlSqrt>SIMD_EPSILON)
 | 
						|
		{
 | 
						|
			btScalar nl = btSqrt(nlSqrt);
 | 
						|
			ptsVector *= 1.f/nl;
 | 
						|
			if (ptsVector.dot(DeltaC2)<0.f)
 | 
						|
			{
 | 
						|
				ptsVector*=-1.f;
 | 
						|
			}
 | 
						|
			btVector3 ptOnB = witnessPointB + offsetB;
 | 
						|
			btScalar distance = nl;
 | 
						|
			resultOut.addContactPoint(ptsVector, ptOnB,-distance);
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	if((DeltaC2.dot(sep))<0.0f)
 | 
						|
		sep = -sep;
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void	btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA,  const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
 | 
						|
{
 | 
						|
	worldVertsB2.resize(0);
 | 
						|
	btVertexArray* pVtxIn = &worldVertsB1;
 | 
						|
	btVertexArray* pVtxOut = &worldVertsB2;
 | 
						|
	pVtxOut->reserve(pVtxIn->size());
 | 
						|
 | 
						|
	int closestFaceA=-1;
 | 
						|
	{
 | 
						|
		btScalar dmin = FLT_MAX;
 | 
						|
		for(int face=0;face<hullA.m_faces.size();face++)
 | 
						|
		{
 | 
						|
			const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
 | 
						|
			const btVector3 faceANormalWS = transA.getBasis() * Normal;
 | 
						|
		
 | 
						|
			btScalar d = faceANormalWS.dot(separatingNormal);
 | 
						|
			if (d < dmin)
 | 
						|
			{
 | 
						|
				dmin = d;
 | 
						|
				closestFaceA = face;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (closestFaceA<0)
 | 
						|
		return;
 | 
						|
 | 
						|
	const btFace& polyA = hullA.m_faces[closestFaceA];
 | 
						|
 | 
						|
		// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
 | 
						|
	int numVerticesA = polyA.m_indices.size();
 | 
						|
	for(int e0=0;e0<numVerticesA;e0++)
 | 
						|
	{
 | 
						|
		const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
 | 
						|
		const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0+1)%numVerticesA]];
 | 
						|
		const btVector3 edge0 = a - b;
 | 
						|
		const btVector3 WorldEdge0 = transA.getBasis() * edge0;
 | 
						|
		btVector3 worldPlaneAnormal1 = transA.getBasis()* btVector3(polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
 | 
						|
 | 
						|
		btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1);//.cross(WorldEdge0);
 | 
						|
		btVector3 worldA1 = transA*a;
 | 
						|
		btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
 | 
						|
		
 | 
						|
//int otherFace=0;
 | 
						|
#ifdef BLA1
 | 
						|
		int otherFace = polyA.m_connectedFaces[e0];
 | 
						|
		btVector3 localPlaneNormal (hullA.m_faces[otherFace].m_plane[0],hullA.m_faces[otherFace].m_plane[1],hullA.m_faces[otherFace].m_plane[2]);
 | 
						|
		btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
 | 
						|
 | 
						|
		btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
 | 
						|
		btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
 | 
						|
#else 
 | 
						|
		btVector3 planeNormalWS = planeNormalWS1;
 | 
						|
		btScalar planeEqWS=planeEqWS1;
 | 
						|
		
 | 
						|
#endif
 | 
						|
		//clip face
 | 
						|
 | 
						|
		clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
 | 
						|
		btSwap(pVtxIn,pVtxOut);
 | 
						|
		pVtxOut->resize(0);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//#define ONLY_REPORT_DEEPEST_POINT
 | 
						|
 | 
						|
	btVector3 point;
 | 
						|
	
 | 
						|
 | 
						|
	// only keep points that are behind the witness face
 | 
						|
	{
 | 
						|
		btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
 | 
						|
		btScalar localPlaneEq = polyA.m_plane[3];
 | 
						|
		btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
 | 
						|
		btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
 | 
						|
		for (int i=0;i<pVtxIn->size();i++)
 | 
						|
		{
 | 
						|
			btVector3 vtx = pVtxIn->at(i);
 | 
						|
			btScalar depth = planeNormalWS.dot(vtx)+planeEqWS;
 | 
						|
			if (depth <=minDist)
 | 
						|
			{
 | 
						|
//				printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
 | 
						|
				depth = minDist;
 | 
						|
			}
 | 
						|
 | 
						|
			if (depth <=maxDist)
 | 
						|
			{
 | 
						|
				btVector3 point = pVtxIn->at(i);
 | 
						|
#ifdef ONLY_REPORT_DEEPEST_POINT
 | 
						|
				curMaxDist = depth;
 | 
						|
#else
 | 
						|
#if 0
 | 
						|
				if (depth<-3)
 | 
						|
				{
 | 
						|
					printf("error in btPolyhedralContactClipping depth = %f\n", depth);
 | 
						|
					printf("likely wrong separatingNormal passed in\n");
 | 
						|
				} 
 | 
						|
#endif				
 | 
						|
				resultOut.addContactPoint(separatingNormal,point,depth);
 | 
						|
#endif
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
#ifdef ONLY_REPORT_DEEPEST_POINT
 | 
						|
	if (curMaxDist<maxDist)
 | 
						|
	{
 | 
						|
		resultOut.addContactPoint(separatingNormal,point,curMaxDist);
 | 
						|
	}
 | 
						|
#endif //ONLY_REPORT_DEEPEST_POINT
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void	btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut)
 | 
						|
{
 | 
						|
 | 
						|
	btVector3 separatingNormal = separatingNormal1.normalized();
 | 
						|
//	const btVector3 c0 = transA * hullA.m_localCenter;
 | 
						|
//	const btVector3 c1 = transB * hullB.m_localCenter;
 | 
						|
	//const btVector3 DeltaC2 = c0 - c1;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
	int closestFaceB=-1;
 | 
						|
	btScalar dmax = -FLT_MAX;
 | 
						|
	{
 | 
						|
		for(int face=0;face<hullB.m_faces.size();face++)
 | 
						|
		{
 | 
						|
			const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
 | 
						|
			const btVector3 WorldNormal = transB.getBasis() * Normal;
 | 
						|
			btScalar d = WorldNormal.dot(separatingNormal);
 | 
						|
			if (d > dmax)
 | 
						|
			{
 | 
						|
				dmax = d;
 | 
						|
				closestFaceB = face;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	worldVertsB1.resize(0);
 | 
						|
				{
 | 
						|
					const btFace& polyB = hullB.m_faces[closestFaceB];
 | 
						|
					const int numVertices = polyB.m_indices.size();
 | 
						|
					for(int e0=0;e0<numVertices;e0++)
 | 
						|
					{
 | 
						|
						const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
 | 
						|
						worldVertsB1.push_back(transB*b);
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
	
 | 
						|
	if (closestFaceB>=0)
 | 
						|
		clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut);
 | 
						|
 | 
						|
}
 |