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
}
}