Assuming I have two rays (or, alternately, two position vectors and 2 corresponding speed vectors), what is the fastest / most resource-efficient (i.e. no for loops etc.) way to find the shortest possible line segment connecting the two rays, OR the Closest Point of Approach (for the 2+2 vectors)?
Thanks in advance!
Nobody answered, and I figured on my own. Sample solution in case somebody else is interested:
public static float ClosestTimeOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2)
{
//float t = 0;
var dv = vel1 - vel2;
var dv2 = Vector3.Dot(dv, dv);
if (dv2 < 0.0000001f) // the tracks are almost parallel
{
return 0.0f; // any time is ok. Use time 0.
}
var w0 = pos1 - pos2;
return (-Vector3.Dot(w0, dv)/dv2);
}
public static float ClosestDistOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2, out Vector3 p1, out Vector3 p2)
{
var t = ClosestTimeOfApproach(pos1,vel1,pos2,vel2);
p1 = pos1 + (t * vel1);
p2 = pos2 + (t*vel2);
return Vector3.Distance(p1, p2); // distance at CPA
}
public static Vector3 ClosestPointOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2)
{
var t = ClosestTimeOfApproach(pos1, vel1, pos2, vel2);
if (t<0) // don't detect approach points in the past, only in the future;
{
return (pos1);
}
return (pos1 + (t * vel1));
}
Found this post that helped me when I couldn’t get this solution to work.
The answer links to these resources (the function ClosestPointsOnTwoLines helped me out the most with my problem):
http://wiki.unity3d.com/index.php/3d_Math_functions?_ga=2.104569024.1350420062.1572253629-1502904723.1553610781
Hope it helps
I had the same problem but i wanted to find the closest points between two lines and i came up with the following solution:
// Piece wise mult
Vector3 PWMult(Vector3 left, Vector3 right)
{
return new Vector3(left.x*right.x,left.y*right.y,left.z*right.z);
}
// Vector Sum
float VSum(Vector3 vec)
{
return vec.x+vec.y+vec.z;
}
/// <summary>
/// returns the t values for the points where the rays are closest.
/// </summary>
/// <returns> Vector2 wher x is t value for ray1 and y is t value for ray 2</returns>
public static Vector2 ClosestPointRays(Vector3 origin1, Vector3 vel1, Vector3 origin2, Vector3 vel2)
{
float t1 = VSum(PWMult(origin2 - origin1, vel1 * Vector3.Dot(vel2, vel2) - vel2 * Vector3.Dot(vel2, vel1))) / VSum(PWMult(vel1, vel1) * Vector3.Dot(vel2, vel2) - PWMult(vel2, vel1) * Vector3.Dot(vel2, vel1));
float t2 = VSum(PWMult(origin1 - origin2, vel2 * Vector3.Dot(vel1, vel1) - vel1 * Vector3.Dot(vel1, vel2))) / VSum(PWMult(vel2, vel2) * Vector3.Dot(vel1, vel1) - PWMult(vel1, vel2) * Vector3.Dot(vel1, vel2));
return new Vector2(t1,t2);
}
I used origin and velocity instead of the builtin ray because it normalizes it’s direction and I would need to rescale the values otherwise.
I tested it myself (using it to attach spider strings to other strings) so i can confirm that it worked.
From this it is easy to find the distance of the closest points and so on.