/// <summary> /// Intersects a segment and a sphere. /// </summary> public static bool IntersectSegmentSphere(Vector3 p0, Vector3 p1, Sphere s, out Vector3 hitPos) { Vector3 dir = p1 - p0; float length = dir.magnitude; if (Mathf.Approximately(length, 0.0f)) { hitPos = p0; return IntersectPointSphere(p0, s); } dir = dir / length; // Normalize // Perform ray/sphere intersection, and verify t to guarantee // collision occurred within boundaries of segment. float t; if (IntersectRaySphere(p0, dir, s, out t, out hitPos)) { if (t <= length) { return true; } } return false; }
/// <summary> /// Intersects ray r = p + td, |d| = 1, with sphere s and, if intersecting, /// returns t value of intersection and intersection point q /// </summary> public static bool IntersectRaySphere(Vector3 p, Vector3 d, Sphere s, out float t, out Vector3 q) { // Ref: Real-Time Collision Detection Vector3 m = p - s.Center; float b = Vector3.Dot(m, d); float c = Vector3.Dot(m, m) - s.Radius * s.Radius; // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) if (c > 0.0f && b > 0.0f) { t = 0.0f; q = Vector3.zero; return false; } float discr = b * b - c; // A negative discriminant corresponds to ray missing sphere if (discr < 0.0f) { t = 0.0f; q = Vector3.zero; return false; } // Ray now found to intersect sphere, compute smallest t value of intersection t = -b - Mathf.Sqrt(discr); // If t is negative, ray started inside sphere so clamp t to zero if (t < 0.0f) { t = 0.0f; } q = p + t * d; return true; }
/// <summary> /// Intersects a ray and sphere: r = p + td /// </summary> public static bool IntersectRaySphere(Vector3 p, Vector3 d, Sphere s) { // Ref: Real-Time Collision Detection Vector3 m = p - s.Center; float c = Vector3.Dot(m, m) - s.Radius * s.Radius; // If there is definitely at least one real root, there must be an intersection if (c <= 0.0f) { return true; } float b = Vector3.Dot(m, d); // Early exit if ray origin outside sphere and ray pointing away from sphere if (b > 0.0f) { return false; } float disc = b * b - c; // A negative discriminant corresponds to ray missing sphere if (disc < 0.0f) { return false; } // Now ray must hit sphere return true; }
/// <summary> /// Given a point p and a sphere, /// return whether the point intersects the sphere. /// </summary> public static bool IntersectPointSphere(Vector3 p, Sphere s) { float r2 = s.Radius * s.Radius; float distSqr = Vector3.SqrMagnitude(p - s.Center); return distSqr <= r2; }