public static bool RayCastSphere(ref Ray ray, ref Vector3 spherePosition, float radius, float maximumLength, out RayHit hit)
{
Vector3 normalizedDirection;
float length = ray.Direction.Length();
Vector3.Divide(ref ray.Direction, length, out normalizedDirection);
maximumLength *= length;
hit = new RayHit();
Vector3 m;
Vector3.Subtract(ref ray.Position, ref spherePosition, out m);
float b = Vector3.Dot(m, normalizedDirection);
float c = m.LengthSquared() - radius * radius;
if (c > 0 && b > 0)
return false;
float discriminant = b * b - c;
if (discriminant < 0)
return false;
hit.T = -b - (float)Math.Sqrt(discriminant);
if (hit.T < 0)
hit.T = 0;
if (hit.T > maximumLength)
return false;
hit.T /= length;
Vector3.Multiply(ref normalizedDirection, hit.T, out hit.Location);
Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
Vector3.Subtract(ref hit.Location, ref spherePosition, out hit.Normal);
hit.Normal.Normalize();
return true;
}