namespace DarkWynter.Engine.Physics { #region Using Statements using System; using System.Collections.Generic; using System.Threading; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; #endregion using Globals; /// /// BoundingVolume Class supports multiple bounding shapes to define an object in physical space. /// BoundingType is selected during initialization of the object. /// /// Collision Checking is handled by passing another Mass's BoundingVolume into the Intersect(BoundingVolume volume) method. /// No type-specific information is required during collision checks, b/c BoundingVolume handles this internally. /// public class BoundingVolume { /// /// Specifies which bounding object the BoundingVolume is using internally. /// Enums_Engine.BoundingType Type; // Bounding Objects : evenually split into seperate classes BoundingSphere sphere; BoundingBox box; BoundingFrustum frustum; Ray ray; Vector4 quad; // Bounding Object Properties : also seperate classes /// /// The Center of the bounding volume. Used by Sphere and Box /// public Vector3 center; /// /// The Radius of the bounding volume. Used by Sphere /// public float radius; /// /// The Scale of the bounding volume. Used by Box /// public Vector3 scale; #region Constructors /// /// Default /// public BoundingVolume() { center = new Vector3(0.0f); radius = 0.0f; } /// /// Support for Sphere intersections with volumes /// /// The Bounding Sphere to be used in our Bounding volume public BoundingVolume(BoundingSphere Sphere) { center = Sphere.Center; radius = Sphere.Radius; sphere = new BoundingSphere(Sphere.Center, Sphere.Radius); Type = Enums_Engine.BoundingType.Sphere; } /// /// Support for Box intersections with volumes /// /// Set this volume's parameters before or while passing in. public BoundingVolume(BoundingBox Box) { box = Box; Type = Enums_Engine.BoundingType.Box; } /// /// Support for Frustum intersections with volumes /// /// Set this volume's parameters before or while passing in. public BoundingVolume(BoundingFrustum Frustum) { frustum = Frustum; Type = Enums_Engine.BoundingType.Frustum; } /// /// Support for Ray intersections with volumes /// /// Set this volume's parameters before or while passing in. public BoundingVolume(Ray Ray) { ray = Ray; Type = Enums_Engine.BoundingType.Ray; } /// /// Support for Sphere intersections with volumes /// /// The Bounding Sphere to be used in our Bounding volume public BoundingVolume(Vector2 startPoint, Vector2 endPoint) { // Quad center (+/-) radius quad = new Vector4(); quad.X = startPoint.X; quad.Y = startPoint.Y; quad.Z = endPoint.X; quad.W = endPoint.Y; Type = Enums_Engine.BoundingType.Quad; } #endregion /// /// Returns true if "this" BoundingVolume intersects the parameter BoundingVolume. /// /// BoundingVolume that we check for collision with. /// True if the two volumes intersect public bool Intersects(BoundingVolume volume) { // If Intersection between "this" and "volume" if ( IntersectSphere(volume) || IntersectBox(volume) || IntersectFrustum(volume) || IntersectQuad(volume) || IntersectRay(volume) ) return true; // Nothing has returned yet, so no collision occured.. return false; } #region Type Intersection Mux/Demux private bool IntersectSphere(BoundingVolume volume) { // Check this.Sphere if (this.Type == Enums_Engine.BoundingType.Sphere) { if (volume.Type == Enums_Engine.BoundingType.Sphere) { // .. with volume.Sphere if (this.sphere.Intersects(volume.sphere)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Box) { // .. with volume.Box if (this.sphere.Intersects(volume.box)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Frustum) { // .. with volume.Frustum if (this.sphere.Intersects(volume.frustum)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Ray) { // .. with volume.Ray if (volume.ray.Intersects(this.sphere).HasValue) { return true; } } } return false; } private bool IntersectBox(BoundingVolume volume) { // If a box, check against other types... if (this.Type == Enums_Engine.BoundingType.Box) { if (volume.Type == Enums_Engine.BoundingType.Sphere) { if (this.box.Intersects(volume.sphere)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Box) { if (this.box.Intersects(volume.box)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Frustum) { if (this.box.Intersects(volume.frustum)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Ray) { if (volume.ray.Intersects(this.box).HasValue) { return true; } } } return false; } private bool IntersectFrustum(BoundingVolume volume) { // Check this.Frustum if (this.Type == Enums_Engine.BoundingType.Frustum) { if (volume.Type == Enums_Engine.BoundingType.Sphere) { // .. with volume.Sphere if (this.frustum.Intersects(volume.sphere)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Box) { // .. with volume.Box if (this.frustum.Intersects(volume.box)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Frustum) { // .. with volume.Frustum if (this.frustum.Intersects(volume.frustum)) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Ray) { // .. with volume.Ray if (volume.ray.Intersects(this.frustum).HasValue) { return true; } } } return false; } private bool IntersectRay(BoundingVolume volume) { // Check this.Ray if (this.Type == Enums_Engine.BoundingType.Ray) { if (volume.Type == Enums_Engine.BoundingType.Sphere) { // .. with volume.Sphere if (this.ray.Intersects(volume.sphere).HasValue) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Box) { // .. with volume.Box if (this.ray.Intersects(volume.box).HasValue) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Frustum) { // .. with volume.Frustum if (this.ray.Intersects(volume.frustum).HasValue) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Ray) { // XNA does not support Ray-Ray intersections return true; } return false; } return false; } private bool IntersectQuad(BoundingVolume volume) { // Check this.Sphere if (this.Type == Enums_Engine.BoundingType.Quad) { if (volume.Type == Enums_Engine.BoundingType.Sphere) { // Intersect quad with sphere if (false) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Box) { if (false) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Frustum) { if (false) { return true; } } else if (volume.Type == Enums_Engine.BoundingType.Ray) { if (false) { return true; } } } return false; } #endregion #region Positional Updates /// /// Update the position of our bounding volume /// /// The current position of the object public void UpdateSphere(Vector3 currentPosition) { sphere.Center = currentPosition; sphere.Radius = radius; } /// /// Update the position of our bounding volume /// /// The current position of the object /// Box Orientation /// Vector3 scale of the box public void UpdateBox(Vector3 currentPosition, Quaternion rotation, Vector3 boxScale) { box.Min = currentPosition - boxScale; box.Max = currentPosition + boxScale; // CLEAN: Add Rotational Math to support non-axis aligned boxes. // Needs to be multiplied by the rotation } /// /// Update the position of our bounding volume /// /// The current position of the object /// The last position of the object private void UpdateFrustum(Vector3 currentPosition, Vector3 lastPosition) { // Frustum cannot be assigned to; Create new if neccessary } /// /// Update the position of our bounding volume /// /// The current position of the object /// The current orientation of the Ray public void UpdateRay(Vector3 currentPosition, Vector3 currentDirection) { ray.Position = currentPosition; ray.Direction += currentDirection; } /// /// Update the position of our bounding volume /// /// The current position of the object public void UpdateQuad(Vector2 startPoint, Vector2 endPoint) { // Quad center (+/-) radius quad.X = startPoint.X; quad.Y = startPoint.Y; quad.Z = endPoint.X; quad.W = endPoint.Y; } /// /// Draw our bounding volume if desired. /// public void Draw() { } #endregion } }