예제 #1
0
bool MFCollision_PlaneTriTest(const MFVector& plane, const MFVector& p0,  const MFVector& p1, const MFVector& p2, MFVector *pIntersectionPoint)
{
	float t0 = p0.DotH(plane);
	float t1 = p1.DotH(plane);
	float t2 = p2.DotH(plane);

	if(t0 <= 0.0f && t1 <= 0.0f && t2 <= 0)
		return false;

	if(t0 >= 0.0f && t1 >= 0.0f && t2 >= 0)
		return false;

	if(pIntersectionPoint)
	{
		// TODO: calculate point
	}

	return true;
}
예제 #2
0
bool MFCollision_SpherePlaneTest(const MFVector& spherePos, float radius, const MFVector& plane, MFCollisionResult *pResult)
{
	if(!pResult)
	{
		return spherePos.DotH(plane) < radius;
	}
	else
	{
		float d = spherePos.DotH(plane);

		pResult->bCollide = d < radius;

		if(pResult->bCollide)
		{
			pResult->depth = radius - d;
			pResult->normal = plane;
			pResult->intersectionPoint.Mad3(pResult->normal, -(d + pResult->depth*0.5f), spherePos);
		}

		return pResult->bCollide;
	}
}
예제 #3
0
bool MFCollision_RaySlabTest(const MFVector& rayPos, const MFVector& rayDir, const MFVector& plane, float slabHalfWidth, MFRayIntersectionResult *pResult)
{
	float a = plane.Dot3(rayDir);

	// if ray is parallel to plane
	if(a > -MFALMOST_ZERO && a < MFALMOST_ZERO)
	{
		// TODO: this is intentionally BROKEN
		// this is a near impossible case, and it adds a lot of junk to the function
/*
		if(MFAbs(rayPos.DotH(plane)) <= slabHalfWidth)
		{
			if(pResult)
			{
				pResult->time = 0.0f;
			}

			return true;
		}
*/
		return false;
	}

	// otherwise we can do the conventional test
	float inva = MFRcp(a);
	float t = -rayPos.DotH(plane);
	float t1 = (t + slabHalfWidth) * inva;
	float t2 = (t - slabHalfWidth) * inva;

	t = MFMin(t1, t2);
	t2 = MFMax(t1, t2);

	if(t > 1.0f || t2 < 0.0f)
		return false;

	if(pResult)
	{
		pResult->time = MFMax(t, 0.0f);
		pResult->surfaceNormal = a > 0.0f ? -plane : plane;
	}

	return true;
}
예제 #4
0
bool MFCollision_SweepSphereTriTest(const MFVector &sweepSpherePos, const MFVector &sweepSphereVelocity, float sweepSphereRadius, const MFCollisionTriangle &tri, MFSweepSphereResult *pResult)
{
	MFRayIntersectionResult result;

	// test the triangle surface
	if(!MFCollision_RaySlabTest(sweepSpherePos, sweepSphereVelocity, tri.plane, sweepSphereRadius, &result))
		return false;

	MFVector intersection = sweepSpherePos + sweepSphereVelocity * result.time;

	// test if intersection is inside the triangle
	float dot0, dot1, dot2;

	dot0 = intersection.DotH(tri.edgePlanes[0]);
//	if(dot0 > sphereRadius)
//		return false;

	dot1 = intersection.DotH(tri.edgePlanes[1]);
//	if(dot1 > sphereRadius)
//		return false;

	dot2 = intersection.DotH(tri.edgePlanes[2]);
//	if(dot2 > sphereRadius)
//		return false;

	// test if intersection is inside the triangle face
	if(dot0 >= 0.0f && dot1 >= 0.0f && dot2 >= 0.0f)
		goto collision;

	// test the 3 edges
	if(dot0 < 0.0f)
	{
		if(MFCollision_RayCapsuleTest(sweepSpherePos, sweepSphereVelocity, tri.verts[0], tri.verts[1]-tri.verts[0], sweepSphereRadius, &result))
			goto collision;
	}

	if(dot1 < 0.0f)
	{
		if(MFCollision_RayCapsuleTest(sweepSpherePos, sweepSphereVelocity, tri.verts[1], tri.verts[2]-tri.verts[1], sweepSphereRadius, &result))
			goto collision;
	}

	if(dot2 < 0.0f)
	{
		if(MFCollision_RayCapsuleTest(sweepSpherePos, sweepSphereVelocity, tri.verts[2], tri.verts[0]-tri.verts[2], sweepSphereRadius, &result))
			goto collision;
	}

	return false;

collision:
	if(result.time == 0.0f)
	{

		// this is for double sided collision.
		float dot = sweepSpherePos.DotH(tri.plane);
		float amountResolve = sweepSphereRadius - MFAbs(dot);
		pResult->intersectionReaction = result.surfaceNormal * amountResolve;
	}
	else
		pResult->intersectionReaction = MFVector::zero;

	pResult->surfaceNormal = result.surfaceNormal;
	pResult->time = result.time;
	return true;
}