2015-06-11 23:34:41 -04:00

177 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TrueCraft.API
{
/// <summary>
/// Represents a ray; a line with a start and direction, but no end.
/// </summary>
// Mostly taken from the MonoXna project, which is licensed under the MIT license
public struct Ray : IEquatable<Ray>
{
#region Public Fields
/// <summary>
/// The direction of the ray.
/// </summary>
public readonly Vector3 Direction;
/// <summary>
/// The position of the ray (its origin).
/// </summary>
public readonly Vector3 Position;
#endregion
#region Public Constructors
/// <summary>
/// Creates a new ray from specified values.
/// </summary>
/// <param name="position">The position of the ray (its origin).</param>
/// <param name="direction">The direction of the ray.</param>
public Ray(Vector3 position, Vector3 direction)
{
this.Position = position;
this.Direction = direction;
}
#endregion
#region Public Methods
/// <summary>
/// Determines whether this and another object are equal.
/// </summary>
/// <param name="obj">The other object.</param>
/// <returns></returns>
public override bool Equals(object obj)
{
return (obj is Ray) && Equals((Ray)obj);
}
/// <summary>
/// Determines whether this and another ray are equal.
/// </summary>
/// <param name="other">The other ray.</param>
/// <returns></returns>
public bool Equals(Ray other)
{
return Position.Equals(other.Position) && Direction.Equals(other.Direction);
}
/// <summary>
/// Returns the hash code for this ray.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return Position.GetHashCode() ^ Direction.GetHashCode();
}
/// <summary>
/// Returns the distance along the ray where it intersects the specified bounding box, if it intersects at all.
/// </summary>
/// <param name="box">The bounding box to check intersection with.</param>
/// <returns></returns>
public double? Intersects(BoundingBox box)
{
//first test if start in box
if (Position.X >= box.Min.X
&& Position.X <= box.Max.X
&& Position.Y >= box.Min.Y
&& Position.Y <= box.Max.Y
&& Position.Z >= box.Min.Z
&& Position.Z <= box.Max.Z)
return 0.0f;// here we concidere cube is full and origine is in cube so intersect at origine
//Second we check each face
Vector3 maxT = new Vector3(-1.0f);
//Vector3 minT = new Vector3(-1.0f);
//calcul intersection with each faces
if (Position.X < box.Min.X && Direction.X != 0.0f)
maxT.X = (box.Min.X - Position.X) / Direction.X;
else if (Position.X > box.Max.X && Direction.X != 0.0f)
maxT.X = (box.Max.X - Position.X) / Direction.X;
if (Position.Y < box.Min.Y && Direction.Y != 0.0f)
maxT.Y = (box.Min.Y - Position.Y) / Direction.Y;
else if (Position.Y > box.Max.Y && Direction.Y != 0.0f)
maxT.Y = (box.Max.Y - Position.Y) / Direction.Y;
if (Position.Z < box.Min.Z && Direction.Z != 0.0f)
maxT.Z = (box.Min.Z - Position.Z) / Direction.Z;
else if (Position.Z > box.Max.Z && Direction.Z != 0.0f)
maxT.Z = (box.Max.Z - Position.Z) / Direction.Z;
//get the maximum maxT
if (maxT.X > maxT.Y && maxT.X > maxT.Z)
{
if (maxT.X < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
double coord = Position.Z + maxT.X * Direction.Z;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.Z || coord > box.Max.Z)
return null;
coord = Position.Y + maxT.X * Direction.Y;
if (coord < box.Min.Y || coord > box.Max.Y)
return null;
return maxT.X;
}
if (maxT.Y > maxT.X && maxT.Y > maxT.Z)
{
if (maxT.Y < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
double coord = Position.Z + maxT.Y * Direction.Z;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.Z || coord > box.Max.Z)
return null;
coord = Position.X + maxT.Y * Direction.X;
if (coord < box.Min.X || coord > box.Max.X)
return null;
return maxT.Y;
}
else //Z
{
if (maxT.Z < 0.0f)
return null;// ray go on opposite of face
//coordonate of hit point of face of cube
double coord = Position.X + maxT.Z * Direction.X;
// if hit point coord ( intersect face with ray) is out of other plane coord it miss
if (coord < box.Min.X || coord > box.Max.X)
return null;
coord = Position.Y + maxT.Z * Direction.Y;
if (coord < box.Min.Y || coord > box.Max.Y)
return null;
return maxT.Z;
}
}
public static bool operator !=(Ray a, Ray b)
{
return !a.Equals(b);
}
public static bool operator ==(Ray a, Ray b)
{
return a.Equals(b);
}
/// <summary>
/// Returns a string representation of this ray.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return string.Format("{{Position:{0} Direction:{1}}}", Position.ToString(), Direction.ToString());
}
#endregion
}
}