/* * Finds the point on a line segment closest to a given point. * * Solves the equation system that minimizes the point-line distance. * https://math.stackexchange.com/questions/846054/closest-points-on-two-line-segments */ public static Vect3 FindClosestLinePoint(Vect3 lineStart, Vect3 lineEnd, Vect3 point) { Vect3 lineVector = lineEnd - lineStart; double lineVectorSquared = Vect3.Dot(lineVector, lineVector); double pointToLineVectorDotProduct = Vect3.Dot((point - lineStart), lineVector); double vectorScalingFactor = pointToLineVectorDotProduct / lineVectorSquared; // Clamps the result to the line segment distance [0,1] // 0 is lineStart, 1 applies the entire lineVector from lineStart towards lineEnd. vectorScalingFactor = vectorScalingFactor < 0 ? 0 : vectorScalingFactor; vectorScalingFactor = vectorScalingFactor > 1 ? 1 : vectorScalingFactor; return(lineStart + lineVector * vectorScalingFactor); }
/* * Calculates Line/Face intersections using the Möller-Trumbore intersection algorithm. * * https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm */ public static bool rayIntersectsTriangle(Vect3 rayOrigin, Vect3 rayVector, Vect3 vertex0, Vect3 vertex1, Vect3 vertex2) { double EPSILON = 1e-6; Vect3 edge1 = vertex1 - vertex0; Vect3 edge2 = vertex2 - vertex0; double a, f, u, v; Vect3 h = Vect3.Cross(rayVector, edge2); a = Vect3.Dot(edge1, h); if (a > -EPSILON && a < EPSILON) { return(false); // This ray is parallel to this triangle. } f = 1.0 / a; Vect3 s = rayOrigin - vertex0; u = f * Vect3.Dot(s, h); if (u < 0.0 || u > 1.0) { return(false); } Vect3 q = Vect3.Cross(s, edge1); v = f * Vect3.Dot(rayVector, q); if (v < 0.0 || u + v > 1.0) { return(false); } double t = f * Vect3.Dot(edge2, q); return(t > EPSILON); }