/// <summary> /// Calculates the squared distance between a given point and a given ray. /// </summary> /// <param name="point">A <see cref="Vector2F"/> instance.</param> /// <param name="ray">A <see cref="Ray"/> instance.</param> /// <returns>The squared distance between the point and the ray.</returns> public static float SquaredDistance(Vector2F point, Ray ray) { Vector2F diff = point - ray.Origin; float t = Vector2F.DotProduct(diff, ray.Direction); if (t <= 0.0f) { t = 0.0f; } else { t /= ray.Direction.GetLengthSquared(); diff -= t * ray.Direction; } return(diff.GetLengthSquared()); }
/// <summary> /// Find the intersection of a ray and a sphere. /// Only works with unit rays (normalized direction)!!! /// </summary> /// <remarks> /// This is the optimized Ray-Sphere intersection algorithms described in "Real-Time Rendering". /// </remarks> /// <param name="ray">The ray to test.</param> /// <param name="t"> /// If intersection accurs, the function outputs the distance from the ray's origin /// to the closest intersection point to this parameter. /// </param> /// <returns>Returns True if the ray intersects the sphere. otherwise, <see langword="false"/>.</returns> public bool FindIntersections(Ray ray, ref float t) { // Only gives correct result for unit rays. //Debug.Assert(MathUtils.ApproxEquals(1.0f, ray.Direction.GetLength()), "Ray direction should be normalized!"); // Calculates a vector from the ray origin to the sphere center. Vector2F diff = this.center - ray.Origin; // Compute the projection of diff onto the ray direction float d = Vector2F.DotProduct(diff, ray.Direction); float diffSquared = diff.GetLengthSquared(); float radiusSquared = this.radius * this.radius; // First rejection test : // if d<0 and the ray origin is outside the sphere than the sphere is behind the ray if ((d < 0.0f) && (diffSquared > radiusSquared)) { return(false); } // Compute the distance from the sphere center to the projection float mSquared = diffSquared - d * d; // Second rejection test: // if mSquared > radiusSquared than the ray misses the sphere if (mSquared > radiusSquared) { return(false); } float q = (float)System.Math.Sqrt(radiusSquared - mSquared); // We are interested only in the first intersection point: if (diffSquared > radiusSquared) { // If the origin is outside the sphere t = d - q is the first intersection point t = d - q; } else { // If the origin is inside the sphere t = d + q is the first intersection point t = d + q; } return(true); }
/// <summary> /// Calculates the squared distance between a point and a solid oriented box. /// </summary> /// <param name="point">A <see cref="Vector2F"/> instance.</param> /// <param name="obb">An <see cref="OrientedBox"/> instance.</param> /// <param name="closestPoint">The closest point in box coordinates.</param> /// <returns>The squared distance between a point and a solid oriented box.</returns> /// <remarks> /// Treating the oriented box as solid means that any point inside the box has /// distance zero from the box. /// </remarks> public static float SquaredDistancePointSolidOrientedBox(Vector2F point, OrientedBox obb, out Vector2F closestPoint) { Vector2F diff = point - obb.Center; Vector2F closest = new Vector2F( Vector2F.DotProduct(diff, obb.Axis1), Vector2F.DotProduct(diff, obb.Axis2)); float sqrDist = 0.0f; float delta = 0.0f; if (closest.X < -obb.Extent1) { delta = closest.X + obb.Extent1; sqrDist += delta * delta; closest.X = -obb.Extent1; } else if (closest.X > obb.Extent1) { delta = closest.X - obb.Extent1; sqrDist += delta * delta; closest.X = obb.Extent1; } if (closest.Y < -obb.Extent2) { delta = closest.Y + obb.Extent2; sqrDist += delta * delta; closest.Y = -obb.Extent2; } else if (closest.Y > obb.Extent2) { delta = closest.Y - obb.Extent2; sqrDist += delta * delta; closest.Y = obb.Extent2; } closestPoint = closest; return(sqrDist); }