public bool GetPointOnTetrahedronClosestToOrigin(ref RaySimplex simplex, out Vector3 point)
{
//Thanks to the fact that D is new and that we know that the origin is within the extruded
//triangular prism of ABC (and on the "D" side of ABC),
//we can immediately ignore voronoi regions:
//A, B, C, AC, AB, BC, ABC
//and only consider:
//D, DA, DB, DC, DAC, DCB, DBA
//There is some overlap of calculations in this method, since DAC, DCB, and DBA are tested fully.
//When this method is being called, we don't care about the state of 'this' simplex. It's just a temporary shifted simplex.
//The one that needs to be updated is the simplex being passed in.
var minimumSimplex = new RaySimplex();
point = new Vector3();
float minimumDistance = float.MaxValue;
RaySimplex candidate;
float candidateDistance;
Vector3 candidatePoint;
if (TryTetrahedronTriangle(ref A, ref C, ref D,
ref simplex.A, ref simplex.C, ref simplex.D,
ref B, out candidate, out candidatePoint))
{
point = candidatePoint;
minimumSimplex = candidate;
minimumDistance = candidatePoint.LengthSquared();
}
if (TryTetrahedronTriangle(ref C, ref B, ref D,
ref simplex.C, ref simplex.B, ref simplex.D,
ref A, out candidate, out candidatePoint) &&
(candidateDistance = candidatePoint.LengthSquared()) < minimumDistance)
{
point = candidatePoint;
minimumSimplex = candidate;
minimumDistance = candidateDistance;
}
if (TryTetrahedronTriangle(ref B, ref A, ref D,
ref simplex.B, ref simplex.A, ref simplex.D,
ref C, out candidate, out candidatePoint) &&
(candidateDistance = candidatePoint.LengthSquared()) < minimumDistance)
{
point = candidatePoint;
minimumSimplex = candidate;
minimumDistance = candidateDistance;
}
if (TryTetrahedronTriangle(ref A, ref B, ref C,
ref simplex.A, ref simplex.B, ref simplex.C,
ref D, out candidate, out candidatePoint) &&
(candidateDistance = candidatePoint.LengthSquared()) < minimumDistance)
{
point = candidatePoint;
minimumSimplex = candidate;
minimumDistance = candidateDistance;
}
if (minimumDistance < float.MaxValue)
{
simplex = minimumSimplex;
return false;
}
return true;
}