/// <summary> /// Determines whether there is an intersection between a <see cref="Ray" /> and a <see /// cref="Plane" />. /// </summary> /// <param name="ray"> The ray to test. </param> /// <param name="plane"> The plane to test </param> /// <param name="point"> /// When the method completes, contains the point of intersection, or <see cref="Vector3" /> /// if there was no intersection. /// </param> /// <returns> Whether the two objects intersected. </returns> public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out Vector3 point) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 175 float distance; if (!RayIntersectsPlane(ref ray, ref plane, out distance)) { point = Vector3.Zero; return false; } point = ray.Position + (ray.Direction * distance); return true; }
/// <summary> /// Determines whether the specified <see cref="Vector4" /> is equal to this instance. /// </summary> /// <param name="value"> The <see cref="Vector4" /> to compare with this instance. </param> /// <returns> /// <c>true</c> if the specified <see cref="Vector4" /> is equal to this instance; /// otherwise, <c>false</c>. /// </returns> public bool Equals(Plane value) { return this.Normal == value.Normal && Math.Abs(this.D - value.D) < MathHelpers.ZeroTolerance; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a triangle. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="vertex1"> The first vertex of the triangle to test. </param> /// <param name="vertex2"> The second vertex of the triagnle to test. </param> /// <param name="vertex3"> The third vertex of the triangle to test. </param> /// <returns> Whether the two objects intersected. </returns> public static PlaneIntersectionType PlaneIntersectsTriangle(ref Plane plane, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 207 PlaneIntersectionType test1 = PlaneIntersectsPoint(ref plane, ref vertex1); PlaneIntersectionType test2 = PlaneIntersectsPoint(ref plane, ref vertex2); PlaneIntersectionType test3 = PlaneIntersectsPoint(ref plane, ref vertex3); if (test1 == PlaneIntersectionType.Front && test2 == PlaneIntersectionType.Front && test3 == PlaneIntersectionType.Front) return PlaneIntersectionType.Front; if (test1 == PlaneIntersectionType.Back && test2 == PlaneIntersectionType.Back && test3 == PlaneIntersectionType.Back) return PlaneIntersectionType.Back; return PlaneIntersectionType.Intersecting; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Ray" /> and a <see /// cref="Plane" />. /// </summary> /// <param name="ray"> The ray to test. </param> /// <param name="plane"> The plane to test. </param> /// <param name="distance"> /// When the method completes, contains the distance of the intersection, or 0 if there was /// no intersection. /// </param> /// <returns> Whether the two objects intersect. </returns> public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out float distance) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 175 float direction = plane.Normal.Dot(ray.Direction); if (Math.Abs(direction) < MathHelpers.ZeroTolerance) { distance = 0f; return false; } float position = plane.Normal.Dot(ray.Position); distance = (plane.D - position) / direction; if (distance < 0f) { if (distance < -MathHelpers.ZeroTolerance) { distance = 0; return false; } distance = 0f; } return true; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a point. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="point"> The point to test. </param> /// <returns> Whether the two objects intersected. </returns> public static PlaneIntersectionType PlaneIntersectsPoint(ref Plane plane, ref Vector3 point) { float distance = plane.Normal.Dot(point); distance += plane.D; if (distance > 0f) return PlaneIntersectionType.Front; if (distance < 0f) return PlaneIntersectionType.Back; return PlaneIntersectionType.Intersecting; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a <see /// cref="BoundingSphere" />. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="sphere"> The sphere to test. </param> /// <returns> Whether the two objects intersected. </returns> public static PlaneIntersectionType PlaneIntersectsSphere(ref Plane plane, ref BoundingSphere sphere) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 160 float distance = plane.Normal.Dot(sphere.Center); distance += plane.D; if (distance > sphere.Radius) return PlaneIntersectionType.Front; if (distance < -sphere.Radius) return PlaneIntersectionType.Back; return PlaneIntersectionType.Intersecting; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a <see /// cref="Plane" />. /// </summary> /// <param name="plane1"> The first plane to test. </param> /// <param name="plane2"> The second plane to test. </param> /// <param name="line"> /// When the method completes, contains the line of intersection as a <see cref="Ray" />, or /// a zero ray if there was no intersection. /// </param> /// <returns> Whether the two objects intersected. </returns> /// <remarks> /// Although a ray is set to have an origin, the ray returned by this method is really a /// line in three dimensions which has no real origin. The ray is considered valid when both /// the positive direction is used and when the negative direction is used. /// </remarks> public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2, out Ray line) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 207 Vector3 direction = plane1.Normal.Cross(plane2.Normal); // If direction is the zero vector, the planes are parallel and possibly coincident. It // is not an intersection. The dot product will tell us. float denominator = direction.Dot(direction); // We assume the planes are normalized, therefore the denominator only serves as a // parallel and coincident check. Otherwise we need to deivide the point by the denominator. if (Math.Abs(denominator) < MathHelpers.ZeroTolerance) { line = new Ray(); return false; } Vector3 temp = plane1.D * plane2.Normal - plane2.D * plane1.Normal; Vector3 point = temp.Cross(direction); line.Position = point; line.Direction = direction; line.Direction.Normalize(); return true; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a <see /// cref="Plane" />. /// </summary> /// <param name="plane1"> The first plane to test. </param> /// <param name="plane2"> The second plane to test. </param> /// <returns> Whether the two objects intersected. </returns> public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2) { Vector3 direction = plane1.Normal.Cross(plane2.Normal); // If direction is the zero vector, the planes are parallel and possibly coincident. It // is not an intersection. The dot product will tell us. float denominator = direction.Dot(direction); if (Math.Abs(denominator) < MathHelpers.ZeroTolerance) return false; return true; }
/// <summary> /// Determines whether there is an intersection between a <see cref="Plane" /> and a <see /// cref="BoundingBox" />. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="box"> The box to test. </param> /// <returns> Whether the two objects intersected. </returns> public static PlaneIntersectionType PlaneIntersectsBox(ref Plane plane, ref BoundingBox box) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 161 Vector3 min; Vector3 max; max.X = (plane.Normal.X >= 0.0f) ? box.Minimum.X : box.Maximum.X; max.Y = (plane.Normal.Y >= 0.0f) ? box.Minimum.Y : box.Maximum.Y; max.Z = (plane.Normal.Z >= 0.0f) ? box.Minimum.Z : box.Maximum.Z; min.X = (plane.Normal.X >= 0.0f) ? box.Maximum.X : box.Minimum.X; min.Y = (plane.Normal.Y >= 0.0f) ? box.Maximum.Y : box.Minimum.Y; min.Z = (plane.Normal.Z >= 0.0f) ? box.Maximum.Z : box.Minimum.Z; float distance = plane.Normal.Dot(max); if (distance + plane.D > 0.0f) return PlaneIntersectionType.Front; distance = Vector3.Dot(plane.Normal, min); if (distance + plane.D < 0.0f) return PlaneIntersectionType.Back; return PlaneIntersectionType.Intersecting; }
/// <summary> /// Determines the distance between a <see cref="Plane" /> and a point. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="point"> The point to test. </param> /// <returns> The distance between the two objects. </returns> public static float DistancePlanePoint(ref Plane plane, ref Vector3 point) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 127 float dot = plane.Normal.Dot(point); return dot - plane.D; }
/// <summary> /// Determines the closest point between a <see cref="Plane" /> and a point. /// </summary> /// <param name="plane"> The plane to test. </param> /// <param name="point"> The point to test. </param> /// <param name="result"> /// When the method completes, contains the closest point between the two objects. /// </param> public static void ClosestPointPlanePoint(ref Plane plane, ref Vector3 point, out Vector3 result) { // Source: Real-Time Collision Detection by Christer Ericson // Reference: Page 126 float dot = plane.Normal.Dot(point); float t = dot - plane.D; result = point - (t * plane.Normal); }