(61d00a474) v0.9.7.1
This commit is contained in:
538
Libraries/XNATypes/BoundingBox.cs
Normal file
538
Libraries/XNATypes/BoundingBox.cs
Normal file
@@ -0,0 +1,538 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
[DataContract]
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct BoundingBox : IEquatable<BoundingBox>
|
||||
{
|
||||
|
||||
#region Public Fields
|
||||
|
||||
[DataMember]
|
||||
public Vector3 Min;
|
||||
|
||||
[DataMember]
|
||||
public Vector3 Max;
|
||||
|
||||
public const int CornerCount = 8;
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public BoundingBox(Vector3 min, Vector3 max)
|
||||
{
|
||||
this.Min = min;
|
||||
this.Max = max;
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public ContainmentType Contains(BoundingBox box)
|
||||
{
|
||||
//test if all corner is in the same side of a face by just checking min and max
|
||||
if (box.Max.X < Min.X
|
||||
|| box.Min.X > Max.X
|
||||
|| box.Max.Y < Min.Y
|
||||
|| box.Min.Y > Max.Y
|
||||
|| box.Max.Z < Min.Z
|
||||
|| box.Min.Z > Max.Z)
|
||||
return ContainmentType.Disjoint;
|
||||
|
||||
|
||||
if (box.Min.X >= Min.X
|
||||
&& box.Max.X <= Max.X
|
||||
&& box.Min.Y >= Min.Y
|
||||
&& box.Max.Y <= Max.Y
|
||||
&& box.Min.Z >= Min.Z
|
||||
&& box.Max.Z <= Max.Z)
|
||||
return ContainmentType.Contains;
|
||||
|
||||
return ContainmentType.Intersects;
|
||||
}
|
||||
|
||||
public void Contains(ref BoundingBox box, out ContainmentType result)
|
||||
{
|
||||
result = Contains(box);
|
||||
}
|
||||
|
||||
public ContainmentType Contains(BoundingFrustum frustum)
|
||||
{
|
||||
//TODO: bad done here need a fix.
|
||||
//Because question is not frustum contain box but reverse and this is not the same
|
||||
int i;
|
||||
ContainmentType contained;
|
||||
Vector3[] corners = frustum.GetCorners();
|
||||
|
||||
// First we check if frustum is in box
|
||||
for (i = 0; i < corners.Length; i++)
|
||||
{
|
||||
this.Contains(ref corners[i], out contained);
|
||||
if (contained == ContainmentType.Disjoint)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == corners.Length) // This means we checked all the corners and they were all contain or instersect
|
||||
return ContainmentType.Contains;
|
||||
|
||||
if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects
|
||||
return ContainmentType.Intersects;
|
||||
|
||||
|
||||
// If we get here, it means the first (and only) point we checked was actually contained in the frustum.
|
||||
// So we assume that all other points will also be contained. If one of the points is disjoint, we can
|
||||
// exit immediately saying that the result is Intersects
|
||||
i++;
|
||||
for (; i < corners.Length; i++)
|
||||
{
|
||||
this.Contains(ref corners[i], out contained);
|
||||
if (contained != ContainmentType.Contains)
|
||||
return ContainmentType.Intersects;
|
||||
|
||||
}
|
||||
|
||||
// If we get here, then we know all the points were actually contained, therefore result is Contains
|
||||
return ContainmentType.Contains;
|
||||
}
|
||||
|
||||
public ContainmentType Contains(BoundingSphere sphere)
|
||||
{
|
||||
if (sphere.Center.X - Min.X >= sphere.Radius
|
||||
&& sphere.Center.Y - Min.Y >= sphere.Radius
|
||||
&& sphere.Center.Z - Min.Z >= sphere.Radius
|
||||
&& Max.X - sphere.Center.X >= sphere.Radius
|
||||
&& Max.Y - sphere.Center.Y >= sphere.Radius
|
||||
&& Max.Z - sphere.Center.Z >= sphere.Radius)
|
||||
return ContainmentType.Contains;
|
||||
|
||||
double dmin = 0;
|
||||
|
||||
double e = sphere.Center.X - Min.X;
|
||||
if (e < 0)
|
||||
{
|
||||
if (e < -sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = sphere.Center.X - Max.X;
|
||||
if (e > 0)
|
||||
{
|
||||
if (e > sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
}
|
||||
|
||||
e = sphere.Center.Y - Min.Y;
|
||||
if (e < 0)
|
||||
{
|
||||
if (e < -sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = sphere.Center.Y - Max.Y;
|
||||
if (e > 0)
|
||||
{
|
||||
if (e > sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
}
|
||||
|
||||
e = sphere.Center.Z - Min.Z;
|
||||
if (e < 0)
|
||||
{
|
||||
if (e < -sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = sphere.Center.Z - Max.Z;
|
||||
if (e > 0)
|
||||
{
|
||||
if (e > sphere.Radius)
|
||||
{
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
dmin += e * e;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmin <= sphere.Radius * sphere.Radius)
|
||||
return ContainmentType.Intersects;
|
||||
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
|
||||
{
|
||||
result = this.Contains(sphere);
|
||||
}
|
||||
|
||||
public ContainmentType Contains(Vector3 point)
|
||||
{
|
||||
ContainmentType result;
|
||||
this.Contains(ref point, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Contains(ref Vector3 point, out ContainmentType result)
|
||||
{
|
||||
//first we get if point is out of box
|
||||
if (point.X < this.Min.X
|
||||
|| point.X > this.Max.X
|
||||
|| point.Y < this.Min.Y
|
||||
|| point.Y > this.Max.Y
|
||||
|| point.Z < this.Min.Z
|
||||
|| point.Z > this.Max.Z)
|
||||
{
|
||||
result = ContainmentType.Disjoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ContainmentType.Contains;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Vector3 MaxVector3 = new Vector3(float.MaxValue);
|
||||
private static readonly Vector3 MinVector3 = new Vector3(float.MinValue);
|
||||
|
||||
/// <summary>
|
||||
/// Create a bounding box from the given list of points.
|
||||
/// </summary>
|
||||
/// <param name="points">The list of Vector3 instances defining the point cloud to bound</param>
|
||||
/// <returns>A bounding box that encapsulates the given point cloud.</returns>
|
||||
/// <exception cref="System.ArgumentException">Thrown if the given list has no points.</exception>
|
||||
public static BoundingBox CreateFromPoints(IEnumerable<Vector3> points)
|
||||
{
|
||||
if (points == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
var empty = true;
|
||||
var minVec = MaxVector3;
|
||||
var maxVec = MinVector3;
|
||||
foreach (var ptVector in points)
|
||||
{
|
||||
minVec.X = (minVec.X < ptVector.X) ? minVec.X : ptVector.X;
|
||||
minVec.Y = (minVec.Y < ptVector.Y) ? minVec.Y : ptVector.Y;
|
||||
minVec.Z = (minVec.Z < ptVector.Z) ? minVec.Z : ptVector.Z;
|
||||
|
||||
maxVec.X = (maxVec.X > ptVector.X) ? maxVec.X : ptVector.X;
|
||||
maxVec.Y = (maxVec.Y > ptVector.Y) ? maxVec.Y : ptVector.Y;
|
||||
maxVec.Z = (maxVec.Z > ptVector.Z) ? maxVec.Z : ptVector.Z;
|
||||
|
||||
empty = false;
|
||||
}
|
||||
if (empty)
|
||||
throw new ArgumentException();
|
||||
|
||||
return new BoundingBox(minVec, maxVec);
|
||||
}
|
||||
|
||||
public static BoundingBox CreateFromSphere(BoundingSphere sphere)
|
||||
{
|
||||
BoundingBox result;
|
||||
CreateFromSphere(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result)
|
||||
{
|
||||
var corner = new Vector3(sphere.Radius);
|
||||
result.Min = sphere.Center - corner;
|
||||
result.Max = sphere.Center + corner;
|
||||
}
|
||||
|
||||
public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional)
|
||||
{
|
||||
BoundingBox result;
|
||||
CreateMerged(ref original, ref additional, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result)
|
||||
{
|
||||
result.Min.X = Math.Min(original.Min.X, additional.Min.X);
|
||||
result.Min.Y = Math.Min(original.Min.Y, additional.Min.Y);
|
||||
result.Min.Z = Math.Min(original.Min.Z, additional.Min.Z);
|
||||
result.Max.X = Math.Max(original.Max.X, additional.Max.X);
|
||||
result.Max.Y = Math.Max(original.Max.Y, additional.Max.Y);
|
||||
result.Max.Z = Math.Max(original.Max.Z, additional.Max.Z);
|
||||
}
|
||||
|
||||
public bool Equals(BoundingBox other)
|
||||
{
|
||||
return (this.Min == other.Min) && (this.Max == other.Max);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is BoundingBox) ? this.Equals((BoundingBox)obj) : false;
|
||||
}
|
||||
|
||||
public Vector3[] GetCorners()
|
||||
{
|
||||
return new Vector3[] {
|
||||
new Vector3(this.Min.X, this.Max.Y, this.Max.Z),
|
||||
new Vector3(this.Max.X, this.Max.Y, this.Max.Z),
|
||||
new Vector3(this.Max.X, this.Min.Y, this.Max.Z),
|
||||
new Vector3(this.Min.X, this.Min.Y, this.Max.Z),
|
||||
new Vector3(this.Min.X, this.Max.Y, this.Min.Z),
|
||||
new Vector3(this.Max.X, this.Max.Y, this.Min.Z),
|
||||
new Vector3(this.Max.X, this.Min.Y, this.Min.Z),
|
||||
new Vector3(this.Min.X, this.Min.Y, this.Min.Z)
|
||||
};
|
||||
}
|
||||
|
||||
public void GetCorners(Vector3[] corners)
|
||||
{
|
||||
if (corners == null)
|
||||
{
|
||||
throw new ArgumentNullException("corners");
|
||||
}
|
||||
if (corners.Length < 8)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("corners", "Not Enought Corners");
|
||||
}
|
||||
corners[0].X = this.Min.X;
|
||||
corners[0].Y = this.Max.Y;
|
||||
corners[0].Z = this.Max.Z;
|
||||
corners[1].X = this.Max.X;
|
||||
corners[1].Y = this.Max.Y;
|
||||
corners[1].Z = this.Max.Z;
|
||||
corners[2].X = this.Max.X;
|
||||
corners[2].Y = this.Min.Y;
|
||||
corners[2].Z = this.Max.Z;
|
||||
corners[3].X = this.Min.X;
|
||||
corners[3].Y = this.Min.Y;
|
||||
corners[3].Z = this.Max.Z;
|
||||
corners[4].X = this.Min.X;
|
||||
corners[4].Y = this.Max.Y;
|
||||
corners[4].Z = this.Min.Z;
|
||||
corners[5].X = this.Max.X;
|
||||
corners[5].Y = this.Max.Y;
|
||||
corners[5].Z = this.Min.Z;
|
||||
corners[6].X = this.Max.X;
|
||||
corners[6].Y = this.Min.Y;
|
||||
corners[6].Z = this.Min.Z;
|
||||
corners[7].X = this.Min.X;
|
||||
corners[7].Y = this.Min.Y;
|
||||
corners[7].Z = this.Min.Z;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Min.GetHashCode() + this.Max.GetHashCode();
|
||||
}
|
||||
|
||||
public bool Intersects(BoundingBox box)
|
||||
{
|
||||
bool result;
|
||||
Intersects(ref box, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Intersects(ref BoundingBox box, out bool result)
|
||||
{
|
||||
if ((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X))
|
||||
{
|
||||
if ((this.Max.Y < box.Min.Y) || (this.Min.Y > box.Max.Y))
|
||||
{
|
||||
result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
result = (this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z);
|
||||
return;
|
||||
}
|
||||
|
||||
result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
public bool Intersects(BoundingFrustum frustum)
|
||||
{
|
||||
return frustum.Intersects(this);
|
||||
}
|
||||
|
||||
public bool Intersects(BoundingSphere sphere)
|
||||
{
|
||||
if (sphere.Center.X - Min.X > sphere.Radius
|
||||
&& sphere.Center.Y - Min.Y > sphere.Radius
|
||||
&& sphere.Center.Z - Min.Z > sphere.Radius
|
||||
&& Max.X - sphere.Center.X > sphere.Radius
|
||||
&& Max.Y - sphere.Center.Y > sphere.Radius
|
||||
&& Max.Z - sphere.Center.Z > sphere.Radius)
|
||||
return true;
|
||||
|
||||
double dmin = 0;
|
||||
|
||||
if (sphere.Center.X - Min.X <= sphere.Radius)
|
||||
dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
|
||||
else if (Max.X - sphere.Center.X <= sphere.Radius)
|
||||
dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
|
||||
|
||||
if (sphere.Center.Y - Min.Y <= sphere.Radius)
|
||||
dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
|
||||
else if (Max.Y - sphere.Center.Y <= sphere.Radius)
|
||||
dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
|
||||
|
||||
if (sphere.Center.Z - Min.Z <= sphere.Radius)
|
||||
dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
|
||||
else if (Max.Z - sphere.Center.Z <= sphere.Radius)
|
||||
dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
|
||||
|
||||
if (dmin <= sphere.Radius * sphere.Radius)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Intersects(ref BoundingSphere sphere, out bool result)
|
||||
{
|
||||
result = Intersects(sphere);
|
||||
}
|
||||
|
||||
public PlaneIntersectionType Intersects(Plane plane)
|
||||
{
|
||||
PlaneIntersectionType result;
|
||||
Intersects(ref plane, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
|
||||
{
|
||||
// See http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
|
||||
|
||||
Vector3 positiveVertex;
|
||||
Vector3 negativeVertex;
|
||||
|
||||
if (plane.Normal.X >= 0)
|
||||
{
|
||||
positiveVertex.X = Max.X;
|
||||
negativeVertex.X = Min.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
positiveVertex.X = Min.X;
|
||||
negativeVertex.X = Max.X;
|
||||
}
|
||||
|
||||
if (plane.Normal.Y >= 0)
|
||||
{
|
||||
positiveVertex.Y = Max.Y;
|
||||
negativeVertex.Y = Min.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
positiveVertex.Y = Min.Y;
|
||||
negativeVertex.Y = Max.Y;
|
||||
}
|
||||
|
||||
if (plane.Normal.Z >= 0)
|
||||
{
|
||||
positiveVertex.Z = Max.Z;
|
||||
negativeVertex.Z = Min.Z;
|
||||
}
|
||||
else
|
||||
{
|
||||
positiveVertex.Z = Min.Z;
|
||||
negativeVertex.Z = Max.Z;
|
||||
}
|
||||
|
||||
// Inline Vector3.Dot(plane.Normal, negativeVertex) + plane.D;
|
||||
var distance = plane.Normal.X * negativeVertex.X + plane.Normal.Y * negativeVertex.Y + plane.Normal.Z * negativeVertex.Z + plane.D;
|
||||
if (distance > 0)
|
||||
{
|
||||
result = PlaneIntersectionType.Front;
|
||||
return;
|
||||
}
|
||||
|
||||
// Inline Vector3.Dot(plane.Normal, positiveVertex) + plane.D;
|
||||
distance = plane.Normal.X * positiveVertex.X + plane.Normal.Y * positiveVertex.Y + plane.Normal.Z * positiveVertex.Z + plane.D;
|
||||
if (distance < 0)
|
||||
{
|
||||
result = PlaneIntersectionType.Back;
|
||||
return;
|
||||
}
|
||||
|
||||
result = PlaneIntersectionType.Intersecting;
|
||||
}
|
||||
|
||||
public Nullable<float> Intersects(Ray ray)
|
||||
{
|
||||
return ray.Intersects(this);
|
||||
}
|
||||
|
||||
public void Intersects(ref Ray ray, out Nullable<float> result)
|
||||
{
|
||||
result = Intersects(ray);
|
||||
}
|
||||
|
||||
public static bool operator ==(BoundingBox a, BoundingBox b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator !=(BoundingBox a, BoundingBox b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
"Min( ", this.Min.DebugDisplayString, " ) \r\n",
|
||||
"Max( ",this.Max.DebugDisplayString, " )"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{{Min:" + this.Min.ToString() + " Max:" + this.Max.ToString() + "}}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deconstruction method for <see cref="BoundingBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public void Deconstruct(out Vector3 min, out Vector3 max)
|
||||
{
|
||||
min = Min;
|
||||
max = Max;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
578
Libraries/XNATypes/BoundingFrustum.cs
Normal file
578
Libraries/XNATypes/BoundingFrustum.cs
Normal file
@@ -0,0 +1,578 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a viewing frustum for intersection operations.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public class BoundingFrustum : IEquatable<BoundingFrustum>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private Matrix _matrix;
|
||||
private readonly Vector3[] _corners = new Vector3[CornerCount];
|
||||
private readonly Plane[] _planes = new Plane[PlaneCount];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// The number of planes in the frustum.
|
||||
/// </summary>
|
||||
public const int PlaneCount = 6;
|
||||
|
||||
/// <summary>
|
||||
/// The number of corner points in the frustum.
|
||||
/// </summary>
|
||||
public const int CornerCount = 8;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Matrix"/> of the frustum.
|
||||
/// </summary>
|
||||
public Matrix Matrix
|
||||
{
|
||||
get { return this._matrix; }
|
||||
set
|
||||
{
|
||||
this._matrix = value;
|
||||
this.CreatePlanes(); // FIXME: The odds are the planes will be used a lot more often than the matrix
|
||||
this.CreateCorners(); // is updated, so this should help performance. I hope ;)
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the near plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Near
|
||||
{
|
||||
get { return this._planes[0]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the far plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Far
|
||||
{
|
||||
get { return this._planes[1]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the left plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Left
|
||||
{
|
||||
get { return this._planes[2]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the right plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Right
|
||||
{
|
||||
get { return this._planes[3]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the top plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Top
|
||||
{
|
||||
get { return this._planes[4]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bottom plane of the frustum.
|
||||
/// </summary>
|
||||
public Plane Bottom
|
||||
{
|
||||
get { return this._planes[5]; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
"Near( ", this._planes[0].DebugDisplayString, " ) \r\n",
|
||||
"Far( ", this._planes[1].DebugDisplayString, " ) \r\n",
|
||||
"Left( ", this._planes[2].DebugDisplayString, " ) \r\n",
|
||||
"Right( ", this._planes[3].DebugDisplayString, " ) \r\n",
|
||||
"Top( ", this._planes[4].DebugDisplayString, " ) \r\n",
|
||||
"Bottom( ", this._planes[5].DebugDisplayString, " ) "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the frustum by extracting the view planes from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="value">Combined matrix which usually is (View * Projection).</param>
|
||||
public BoundingFrustum(Matrix value)
|
||||
{
|
||||
this._matrix = value;
|
||||
this.CreatePlanes();
|
||||
this.CreateCorners();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="BoundingFrustum"/> instances are equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="BoundingFrustum"/> instance on the left of the equal sign.</param>
|
||||
/// <param name="b"><see cref="BoundingFrustum"/> instance on the right of the equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator ==(BoundingFrustum a, BoundingFrustum b)
|
||||
{
|
||||
if (Equals(a, null))
|
||||
return (Equals(b, null));
|
||||
|
||||
if (Equals(b, null))
|
||||
return (Equals(a, null));
|
||||
|
||||
return a._matrix == (b._matrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="BoundingFrustum"/> instances are not equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="BoundingFrustum"/> instance on the left of the not equal sign.</param>
|
||||
/// <param name="b"><see cref="BoundingFrustum"/> instance on the right of the not equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator !=(BoundingFrustum a, BoundingFrustum b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
#region Contains
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">A <see cref="BoundingBox"/> for testing.</param>
|
||||
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.</returns>
|
||||
public ContainmentType Contains(BoundingBox box)
|
||||
{
|
||||
var result = default(ContainmentType);
|
||||
this.Contains(ref box, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">A <see cref="BoundingBox"/> for testing.</param>
|
||||
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingBox"/> as an output parameter.</param>
|
||||
public void Contains(ref BoundingBox box, out ContainmentType result)
|
||||
{
|
||||
var intersects = false;
|
||||
for (var i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
var planeIntersectionType = default(PlaneIntersectionType);
|
||||
box.Intersects(ref this._planes[i], out planeIntersectionType);
|
||||
switch (planeIntersectionType)
|
||||
{
|
||||
case PlaneIntersectionType.Front:
|
||||
result = ContainmentType.Disjoint;
|
||||
return;
|
||||
case PlaneIntersectionType.Intersecting:
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = intersects ? ContainmentType.Intersects : ContainmentType.Contains;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="frustum">A <see cref="BoundingFrustum"/> for testing.</param>
|
||||
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingFrustum"/>.</returns>
|
||||
public ContainmentType Contains(BoundingFrustum frustum)
|
||||
{
|
||||
if (this == frustum) // We check to see if the two frustums are equal
|
||||
return ContainmentType.Contains;// If they are, there's no need to go any further.
|
||||
|
||||
var intersects = false;
|
||||
for (var i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
PlaneIntersectionType planeIntersectionType;
|
||||
frustum.Intersects(ref _planes[i], out planeIntersectionType);
|
||||
switch (planeIntersectionType)
|
||||
{
|
||||
case PlaneIntersectionType.Front:
|
||||
return ContainmentType.Disjoint;
|
||||
case PlaneIntersectionType.Intersecting:
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return intersects ? ContainmentType.Intersects : ContainmentType.Contains;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.
|
||||
/// </summary>
|
||||
/// <param name="sphere">A <see cref="BoundingSphere"/> for testing.</param>
|
||||
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.</returns>
|
||||
public ContainmentType Contains(BoundingSphere sphere)
|
||||
{
|
||||
var result = default(ContainmentType);
|
||||
this.Contains(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/>.
|
||||
/// </summary>
|
||||
/// <param name="sphere">A <see cref="BoundingSphere"/> for testing.</param>
|
||||
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="BoundingSphere"/> as an output parameter.</param>
|
||||
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
|
||||
{
|
||||
var intersects = false;
|
||||
for (var i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
var planeIntersectionType = default(PlaneIntersectionType);
|
||||
|
||||
// TODO: we might want to inline this for performance reasons
|
||||
sphere.Intersects(ref this._planes[i], out planeIntersectionType);
|
||||
switch (planeIntersectionType)
|
||||
{
|
||||
case PlaneIntersectionType.Front:
|
||||
result = ContainmentType.Disjoint;
|
||||
return;
|
||||
case PlaneIntersectionType.Intersecting:
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = intersects ? ContainmentType.Intersects : ContainmentType.Contains;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.
|
||||
/// </summary>
|
||||
/// <param name="point">A <see cref="Vector3"/> for testing.</param>
|
||||
/// <returns>Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.</returns>
|
||||
public ContainmentType Contains(Vector3 point)
|
||||
{
|
||||
var result = default(ContainmentType);
|
||||
this.Contains(ref point, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Containment test between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/>.
|
||||
/// </summary>
|
||||
/// <param name="point">A <see cref="Vector3"/> for testing.</param>
|
||||
/// <param name="result">Result of testing for containment between this <see cref="BoundingFrustum"/> and specified <see cref="Vector3"/> as an output parameter.</param>
|
||||
public void Contains(ref Vector3 point, out ContainmentType result)
|
||||
{
|
||||
for (var i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
// TODO: we might want to inline this for performance reasons
|
||||
if (PlaneHelper.ClassifyPoint(ref point, ref this._planes[i]) > 0)
|
||||
{
|
||||
result = ContainmentType.Disjoint;
|
||||
return;
|
||||
}
|
||||
}
|
||||
result = ContainmentType.Contains;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="BoundingFrustum"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public bool Equals(BoundingFrustum other)
|
||||
{
|
||||
return (this == other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="Object"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is BoundingFrustum) && this == ((BoundingFrustum)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of internal corners array.
|
||||
/// </summary>
|
||||
/// <returns>The array of corners.</returns>
|
||||
public Vector3[] GetCorners()
|
||||
{
|
||||
return (Vector3[])this._corners.Clone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of internal corners array.
|
||||
/// </summary>
|
||||
/// <param name="corners">The array which values will be replaced to corner values of this instance. It must have size of <see cref="BoundingFrustum.CornerCount"/>.</param>
|
||||
public void GetCorners(Vector3[] corners)
|
||||
{
|
||||
if (corners == null) throw new ArgumentNullException("corners");
|
||||
if (corners.Length < CornerCount) throw new ArgumentOutOfRangeException("corners");
|
||||
|
||||
this._corners.CopyTo(corners, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash code of this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <returns>Hash code of this <see cref="BoundingFrustum"/>.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this._matrix.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">A <see cref="BoundingBox"/> for intersection test.</param>
|
||||
/// <returns><c>true</c> if specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(BoundingBox box)
|
||||
{
|
||||
var result = false;
|
||||
this.Intersects(ref box, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">A <see cref="BoundingBox"/> for intersection test.</param>
|
||||
/// <param name="result"><c>true</c> if specified <see cref="BoundingBox"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise as an output parameter.</param>
|
||||
public void Intersects(ref BoundingBox box, out bool result)
|
||||
{
|
||||
var containment = default(ContainmentType);
|
||||
this.Contains(ref box, out containment);
|
||||
result = containment != ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingFrustum"/> intersects with this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="frustum">An other <see cref="BoundingFrustum"/> for intersection test.</param>
|
||||
/// <returns><c>true</c> if other <see cref="BoundingFrustum"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(BoundingFrustum frustum)
|
||||
{
|
||||
return Contains(frustum) != ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="sphere">A <see cref="BoundingSphere"/> for intersection test.</param>
|
||||
/// <returns><c>true</c> if specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(BoundingSphere sphere)
|
||||
{
|
||||
var result = default(bool);
|
||||
this.Intersects(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="sphere">A <see cref="BoundingSphere"/> for intersection test.</param>
|
||||
/// <param name="result"><c>true</c> if specified <see cref="BoundingSphere"/> intersects with this <see cref="BoundingFrustum"/>; <c>false</c> otherwise as an output parameter.</param>
|
||||
public void Intersects(ref BoundingSphere sphere, out bool result)
|
||||
{
|
||||
var containment = default(ContainmentType);
|
||||
this.Contains(ref sphere, out containment);
|
||||
result = containment != ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets type of intersection between specified <see cref="Plane"/> and this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="plane">A <see cref="Plane"/> for intersection test.</param>
|
||||
/// <returns>A plane intersection type.</returns>
|
||||
public PlaneIntersectionType Intersects(Plane plane)
|
||||
{
|
||||
PlaneIntersectionType result;
|
||||
Intersects(ref plane, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets type of intersection between specified <see cref="Plane"/> and this <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="plane">A <see cref="Plane"/> for intersection test.</param>
|
||||
/// <param name="result">A plane intersection type as an output parameter.</param>
|
||||
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
|
||||
{
|
||||
result = plane.Intersects(ref _corners[0]);
|
||||
for (int i = 1; i < _corners.Length; i++)
|
||||
if (plane.Intersects(ref _corners[i]) != result)
|
||||
result = PlaneIntersectionType.Intersecting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the distance of intersection of <see cref="Ray"/> and this <see cref="BoundingFrustum"/> or null if no intersection happens.
|
||||
/// </summary>
|
||||
/// <param name="ray">A <see cref="Ray"/> for intersection test.</param>
|
||||
/// <returns>Distance at which ray intersects with this <see cref="BoundingFrustum"/> or null if no intersection happens.</returns>
|
||||
public float? Intersects(Ray ray)
|
||||
{
|
||||
float? result;
|
||||
Intersects(ref ray, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the distance of intersection of <see cref="Ray"/> and this <see cref="BoundingFrustum"/> or null if no intersection happens.
|
||||
/// </summary>
|
||||
/// <param name="ray">A <see cref="Ray"/> for intersection test.</param>
|
||||
/// <param name="result">Distance at which ray intersects with this <see cref="BoundingFrustum"/> or null if no intersection happens as an output parameter.</param>
|
||||
public void Intersects(ref Ray ray, out float? result)
|
||||
{
|
||||
ContainmentType ctype;
|
||||
this.Contains(ref ray.Position, out ctype);
|
||||
|
||||
switch (ctype)
|
||||
{
|
||||
case ContainmentType.Disjoint:
|
||||
result = null;
|
||||
return;
|
||||
case ContainmentType.Contains:
|
||||
result = 0.0f;
|
||||
return;
|
||||
case ContainmentType.Intersects:
|
||||
throw new NotImplementedException();
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> representation of this <see cref="BoundingFrustum"/> in the format:
|
||||
/// {Near:[nearPlane] Far:[farPlane] Left:[leftPlane] Right:[rightPlane] Top:[topPlane] Bottom:[bottomPlane]}
|
||||
/// </summary>
|
||||
/// <returns><see cref="String"/> representation of this <see cref="BoundingFrustum"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return "{Near: " + this._planes[0] +
|
||||
" Far:" + this._planes[1] +
|
||||
" Left:" + this._planes[2] +
|
||||
" Right:" + this._planes[3] +
|
||||
" Top:" + this._planes[4] +
|
||||
" Bottom:" + this._planes[5] +
|
||||
"}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void CreateCorners()
|
||||
{
|
||||
IntersectionPoint(ref this._planes[0], ref this._planes[2], ref this._planes[4], out this._corners[0]);
|
||||
IntersectionPoint(ref this._planes[0], ref this._planes[3], ref this._planes[4], out this._corners[1]);
|
||||
IntersectionPoint(ref this._planes[0], ref this._planes[3], ref this._planes[5], out this._corners[2]);
|
||||
IntersectionPoint(ref this._planes[0], ref this._planes[2], ref this._planes[5], out this._corners[3]);
|
||||
IntersectionPoint(ref this._planes[1], ref this._planes[2], ref this._planes[4], out this._corners[4]);
|
||||
IntersectionPoint(ref this._planes[1], ref this._planes[3], ref this._planes[4], out this._corners[5]);
|
||||
IntersectionPoint(ref this._planes[1], ref this._planes[3], ref this._planes[5], out this._corners[6]);
|
||||
IntersectionPoint(ref this._planes[1], ref this._planes[2], ref this._planes[5], out this._corners[7]);
|
||||
}
|
||||
|
||||
private void CreatePlanes()
|
||||
{
|
||||
this._planes[0] = new Plane(-this._matrix.M13, -this._matrix.M23, -this._matrix.M33, -this._matrix.M43);
|
||||
this._planes[1] = new Plane(this._matrix.M13 - this._matrix.M14, this._matrix.M23 - this._matrix.M24, this._matrix.M33 - this._matrix.M34, this._matrix.M43 - this._matrix.M44);
|
||||
this._planes[2] = new Plane(-this._matrix.M14 - this._matrix.M11, -this._matrix.M24 - this._matrix.M21, -this._matrix.M34 - this._matrix.M31, -this._matrix.M44 - this._matrix.M41);
|
||||
this._planes[3] = new Plane(this._matrix.M11 - this._matrix.M14, this._matrix.M21 - this._matrix.M24, this._matrix.M31 - this._matrix.M34, this._matrix.M41 - this._matrix.M44);
|
||||
this._planes[4] = new Plane(this._matrix.M12 - this._matrix.M14, this._matrix.M22 - this._matrix.M24, this._matrix.M32 - this._matrix.M34, this._matrix.M42 - this._matrix.M44);
|
||||
this._planes[5] = new Plane(-this._matrix.M14 - this._matrix.M12, -this._matrix.M24 - this._matrix.M22, -this._matrix.M34 - this._matrix.M32, -this._matrix.M44 - this._matrix.M42);
|
||||
|
||||
this.NormalizePlane(ref this._planes[0]);
|
||||
this.NormalizePlane(ref this._planes[1]);
|
||||
this.NormalizePlane(ref this._planes[2]);
|
||||
this.NormalizePlane(ref this._planes[3]);
|
||||
this.NormalizePlane(ref this._planes[4]);
|
||||
this.NormalizePlane(ref this._planes[5]);
|
||||
}
|
||||
|
||||
private static void IntersectionPoint(ref Plane a, ref Plane b, ref Plane c, out Vector3 result)
|
||||
{
|
||||
// Formula used
|
||||
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
|
||||
//P = -------------------------------------------------------------------------
|
||||
// N1 . ( N2 * N3 )
|
||||
//
|
||||
// Note: N refers to the normal, d refers to the displacement. '.' means dot product. '*' means cross product
|
||||
|
||||
Vector3 v1, v2, v3;
|
||||
Vector3 cross;
|
||||
|
||||
Vector3.Cross(ref b.Normal, ref c.Normal, out cross);
|
||||
|
||||
float f;
|
||||
Vector3.Dot(ref a.Normal, ref cross, out f);
|
||||
f *= -1.0f;
|
||||
|
||||
Vector3.Cross(ref b.Normal, ref c.Normal, out cross);
|
||||
Vector3.Multiply(ref cross, a.D, out v1);
|
||||
//v1 = (a.D * (Vector3.Cross(b.Normal, c.Normal)));
|
||||
|
||||
|
||||
Vector3.Cross(ref c.Normal, ref a.Normal, out cross);
|
||||
Vector3.Multiply(ref cross, b.D, out v2);
|
||||
//v2 = (b.D * (Vector3.Cross(c.Normal, a.Normal)));
|
||||
|
||||
|
||||
Vector3.Cross(ref a.Normal, ref b.Normal, out cross);
|
||||
Vector3.Multiply(ref cross, c.D, out v3);
|
||||
//v3 = (c.D * (Vector3.Cross(a.Normal, b.Normal)));
|
||||
|
||||
result.X = (v1.X + v2.X + v3.X) / f;
|
||||
result.Y = (v1.Y + v2.Y + v3.Y) / f;
|
||||
result.Z = (v1.Z + v2.Z + v3.Z) / f;
|
||||
}
|
||||
|
||||
private void NormalizePlane(ref Plane p)
|
||||
{
|
||||
float factor = 1f / p.Normal.Length();
|
||||
p.Normal.X *= factor;
|
||||
p.Normal.Y *= factor;
|
||||
p.Normal.Z *= factor;
|
||||
p.D *= factor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
640
Libraries/XNATypes/BoundingSphere.cs
Normal file
640
Libraries/XNATypes/BoundingSphere.cs
Normal file
@@ -0,0 +1,640 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a sphere in 3D-space for bounding operations.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct BoundingSphere : IEquatable<BoundingSphere>
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// The sphere center.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Vector3 Center;
|
||||
|
||||
/// <summary>
|
||||
/// The sphere radius.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public float Radius;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
"Center( ", this.Center.DebugDisplayString, " ) \r\n",
|
||||
"Radius( ", this.Radius.ToString(), " )"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a bounding sphere with the specified center and radius.
|
||||
/// </summary>
|
||||
/// <param name="center">The sphere center.</param>
|
||||
/// <param name="radius">The sphere radius.</param>
|
||||
public BoundingSphere(Vector3 center, float radius)
|
||||
{
|
||||
this.Center = center;
|
||||
this.Radius = radius;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
#region Contains
|
||||
|
||||
/// <summary>
|
||||
/// Test if a bounding box is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="box">The box for testing.</param>
|
||||
/// <returns>The containment type.</returns>
|
||||
public ContainmentType Contains(BoundingBox box)
|
||||
{
|
||||
//check if all corner is in sphere
|
||||
bool inside = true;
|
||||
foreach (Vector3 corner in box.GetCorners())
|
||||
{
|
||||
if (this.Contains(corner) == ContainmentType.Disjoint)
|
||||
{
|
||||
inside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inside)
|
||||
return ContainmentType.Contains;
|
||||
|
||||
//check if the distance from sphere center to cube face < radius
|
||||
double dmin = 0;
|
||||
|
||||
if (Center.X < box.Min.X)
|
||||
dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X);
|
||||
|
||||
else if (Center.X > box.Max.X)
|
||||
dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X);
|
||||
|
||||
if (Center.Y < box.Min.Y)
|
||||
dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y);
|
||||
|
||||
else if (Center.Y > box.Max.Y)
|
||||
dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y);
|
||||
|
||||
if (Center.Z < box.Min.Z)
|
||||
dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z);
|
||||
|
||||
else if (Center.Z > box.Max.Z)
|
||||
dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z);
|
||||
|
||||
if (dmin <= Radius * Radius)
|
||||
return ContainmentType.Intersects;
|
||||
|
||||
//else disjoint
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a bounding box is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="box">The box for testing.</param>
|
||||
/// <param name="result">The containment type as an output parameter.</param>
|
||||
public void Contains(ref BoundingBox box, out ContainmentType result)
|
||||
{
|
||||
result = this.Contains(box);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a frustum is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="frustum">The frustum for testing.</param>
|
||||
/// <returns>The containment type.</returns>
|
||||
public ContainmentType Contains(BoundingFrustum frustum)
|
||||
{
|
||||
//check if all corner is in sphere
|
||||
bool inside = true;
|
||||
|
||||
Vector3[] corners = frustum.GetCorners();
|
||||
foreach (Vector3 corner in corners)
|
||||
{
|
||||
if (this.Contains(corner) == ContainmentType.Disjoint)
|
||||
{
|
||||
inside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inside)
|
||||
return ContainmentType.Contains;
|
||||
|
||||
//check if the distance from sphere center to frustrum face < radius
|
||||
double dmin = 0;
|
||||
//TODO : calcul dmin
|
||||
|
||||
if (dmin <= Radius * Radius)
|
||||
return ContainmentType.Intersects;
|
||||
|
||||
//else disjoint
|
||||
return ContainmentType.Disjoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a frustum is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="frustum">The frustum for testing.</param>
|
||||
/// <param name="result">The containment type as an output parameter.</param>
|
||||
public void Contains(ref BoundingFrustum frustum,out ContainmentType result)
|
||||
{
|
||||
result = this.Contains(frustum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a sphere is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="sphere">The other sphere for testing.</param>
|
||||
/// <returns>The containment type.</returns>
|
||||
public ContainmentType Contains(BoundingSphere sphere)
|
||||
{
|
||||
ContainmentType result;
|
||||
Contains(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a sphere is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="sphere">The other sphere for testing.</param>
|
||||
/// <param name="result">The containment type as an output parameter.</param>
|
||||
public void Contains(ref BoundingSphere sphere, out ContainmentType result)
|
||||
{
|
||||
float sqDistance;
|
||||
Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance);
|
||||
|
||||
if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius))
|
||||
result = ContainmentType.Disjoint;
|
||||
|
||||
else if (sqDistance <= (Radius - sphere.Radius) * (Radius - sphere.Radius))
|
||||
result = ContainmentType.Contains;
|
||||
|
||||
else
|
||||
result = ContainmentType.Intersects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a point is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="point">The vector in 3D-space for testing.</param>
|
||||
/// <returns>The containment type.</returns>
|
||||
public ContainmentType Contains(Vector3 point)
|
||||
{
|
||||
ContainmentType result;
|
||||
Contains(ref point, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if a point is fully inside, outside, or just intersecting the sphere.
|
||||
/// </summary>
|
||||
/// <param name="point">The vector in 3D-space for testing.</param>
|
||||
/// <param name="result">The containment type as an output parameter.</param>
|
||||
public void Contains(ref Vector3 point, out ContainmentType result)
|
||||
{
|
||||
float sqRadius = Radius * Radius;
|
||||
float sqDistance;
|
||||
Vector3.DistanceSquared(ref point, ref Center, out sqDistance);
|
||||
|
||||
if (sqDistance > sqRadius)
|
||||
result = ContainmentType.Disjoint;
|
||||
|
||||
else if (sqDistance < sqRadius)
|
||||
result = ContainmentType.Contains;
|
||||
|
||||
else
|
||||
result = ContainmentType.Intersects;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CreateFromBoundingBox
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">The box to create the sphere from.</param>
|
||||
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
|
||||
public static BoundingSphere CreateFromBoundingBox(BoundingBox box)
|
||||
{
|
||||
BoundingSphere result;
|
||||
CreateFromBoundingBox(ref box, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="box">The box to create the sphere from.</param>
|
||||
/// <param name="result">The new <see cref="BoundingSphere"/> as an output parameter.</param>
|
||||
public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result)
|
||||
{
|
||||
// Find the center of the box.
|
||||
Vector3 center = new Vector3((box.Min.X + box.Max.X) / 2.0f,
|
||||
(box.Min.Y + box.Max.Y) / 2.0f,
|
||||
(box.Min.Z + box.Max.Z) / 2.0f);
|
||||
|
||||
// Find the distance between the center and one of the corners of the box.
|
||||
float radius = Vector3.Distance(center, box.Max);
|
||||
|
||||
result = new BoundingSphere(center, radius);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified <see cref="BoundingFrustum"/>.
|
||||
/// </summary>
|
||||
/// <param name="frustum">The frustum to create the sphere from.</param>
|
||||
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
|
||||
public static BoundingSphere CreateFromFrustum(BoundingFrustum frustum)
|
||||
{
|
||||
return CreateFromPoints(frustum.GetCorners());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified list of points in 3D-space.
|
||||
/// </summary>
|
||||
/// <param name="points">List of point to create the sphere from.</param>
|
||||
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
|
||||
public static BoundingSphere CreateFromPoints(IEnumerable<Vector3> points)
|
||||
{
|
||||
if (points == null )
|
||||
throw new ArgumentNullException("points");
|
||||
|
||||
// From "Real-Time Collision Detection" (Page 89)
|
||||
|
||||
var minx = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
|
||||
var maxx = -minx;
|
||||
var miny = minx;
|
||||
var maxy = -minx;
|
||||
var minz = minx;
|
||||
var maxz = -minx;
|
||||
|
||||
// Find the most extreme points along the principle axis.
|
||||
var numPoints = 0;
|
||||
foreach (var pt in points)
|
||||
{
|
||||
++numPoints;
|
||||
|
||||
if (pt.X < minx.X)
|
||||
minx = pt;
|
||||
if (pt.X > maxx.X)
|
||||
maxx = pt;
|
||||
if (pt.Y < miny.Y)
|
||||
miny = pt;
|
||||
if (pt.Y > maxy.Y)
|
||||
maxy = pt;
|
||||
if (pt.Z < minz.Z)
|
||||
minz = pt;
|
||||
if (pt.Z > maxz.Z)
|
||||
maxz = pt;
|
||||
}
|
||||
|
||||
if (numPoints == 0)
|
||||
throw new ArgumentException("You should have at least one point in points.");
|
||||
|
||||
var sqDistX = Vector3.DistanceSquared(maxx, minx);
|
||||
var sqDistY = Vector3.DistanceSquared(maxy, miny);
|
||||
var sqDistZ = Vector3.DistanceSquared(maxz, minz);
|
||||
|
||||
// Pick the pair of most distant points.
|
||||
var min = minx;
|
||||
var max = maxx;
|
||||
if (sqDistY > sqDistX && sqDistY > sqDistZ)
|
||||
{
|
||||
max = maxy;
|
||||
min = miny;
|
||||
}
|
||||
if (sqDistZ > sqDistX && sqDistZ > sqDistY)
|
||||
{
|
||||
max = maxz;
|
||||
min = minz;
|
||||
}
|
||||
|
||||
var center = (min + max) * 0.5f;
|
||||
var radius = Vector3.Distance(max, center);
|
||||
|
||||
// Test every point and expand the sphere.
|
||||
// The current bounding sphere is just a good approximation and may not enclose all points.
|
||||
// From: Mathematics for 3D Game Programming and Computer Graphics, Eric Lengyel, Third Edition.
|
||||
// Page 218
|
||||
float sqRadius = radius * radius;
|
||||
foreach (var pt in points)
|
||||
{
|
||||
Vector3 diff = (pt-center);
|
||||
float sqDist = diff.LengthSquared();
|
||||
if (sqDist > sqRadius)
|
||||
{
|
||||
float distance = (float)Math.Sqrt(sqDist); // equal to diff.Length();
|
||||
Vector3 direction = diff / distance;
|
||||
Vector3 G = center - radius * direction;
|
||||
center = (G + pt) / 2;
|
||||
radius = Vector3.Distance(pt, center);
|
||||
sqRadius = radius * radius;
|
||||
}
|
||||
}
|
||||
|
||||
return new BoundingSphere(center, radius);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain two spheres.
|
||||
/// </summary>
|
||||
/// <param name="original">First sphere.</param>
|
||||
/// <param name="additional">Second sphere.</param>
|
||||
/// <returns>The new <see cref="BoundingSphere"/>.</returns>
|
||||
public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional)
|
||||
{
|
||||
BoundingSphere result;
|
||||
CreateMerged(ref original, ref additional, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the smallest <see cref="BoundingSphere"/> that can contain two spheres.
|
||||
/// </summary>
|
||||
/// <param name="original">First sphere.</param>
|
||||
/// <param name="additional">Second sphere.</param>
|
||||
/// <param name="result">The new <see cref="BoundingSphere"/> as an output parameter.</param>
|
||||
public static void CreateMerged(ref BoundingSphere original, ref BoundingSphere additional, out BoundingSphere result)
|
||||
{
|
||||
Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center);
|
||||
float distance = ocenterToaCenter.Length();
|
||||
if (distance <= original.Radius + additional.Radius)//intersect
|
||||
{
|
||||
if (distance <= original.Radius - additional.Radius)//original contain additional
|
||||
{
|
||||
result = original;
|
||||
return;
|
||||
}
|
||||
if (distance <= additional.Radius - original.Radius)//additional contain original
|
||||
{
|
||||
result = additional;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//else find center of new sphere and radius
|
||||
float leftRadius = Math.Max(original.Radius - distance, additional.Radius);
|
||||
float Rightradius = Math.Max(original.Radius + distance, additional.Radius);
|
||||
ocenterToaCenter = ocenterToaCenter + (((leftRadius - Rightradius) / (2 * ocenterToaCenter.Length())) * ocenterToaCenter);//oCenterToResultCenter
|
||||
|
||||
result = new BoundingSphere();
|
||||
result.Center = original.Center + ocenterToaCenter;
|
||||
result.Radius = (leftRadius + Rightradius) / 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="BoundingSphere"/>.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="BoundingSphere"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public bool Equals(BoundingSphere other)
|
||||
{
|
||||
return this.Center == other.Center && this.Radius == other.Radius;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="Object"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="Object"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is BoundingSphere)
|
||||
return this.Equals((BoundingSphere)obj);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash code of this <see cref="BoundingSphere"/>.
|
||||
/// </summary>
|
||||
/// <returns>Hash code of this <see cref="BoundingSphere"/>.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Center.GetHashCode() + this.Radius.GetHashCode();
|
||||
}
|
||||
|
||||
#region Intersects
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="box">The box for testing.</param>
|
||||
/// <returns><c>true</c> if <see cref="BoundingBox"/> intersects with this sphere; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(BoundingBox box)
|
||||
{
|
||||
return box.Intersects(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="BoundingBox"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="box">The box for testing.</param>
|
||||
/// <param name="result"><c>true</c> if <see cref="BoundingBox"/> intersects with this sphere; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Intersects(ref BoundingBox box, out bool result)
|
||||
{
|
||||
box.Intersects(ref this, out result);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO : Make the public bool Intersects(BoundingFrustum frustum) overload
|
||||
|
||||
public bool Intersects(BoundingFrustum frustum)
|
||||
{
|
||||
if (frustum == null)
|
||||
throw new NullReferenceException();
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the other <see cref="BoundingSphere"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="sphere">The other sphere for testing.</param>
|
||||
/// <returns><c>true</c> if other <see cref="BoundingSphere"/> intersects with this sphere; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(BoundingSphere sphere)
|
||||
{
|
||||
bool result;
|
||||
Intersects(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the other <see cref="BoundingSphere"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="sphere">The other sphere for testing.</param>
|
||||
/// <param name="result"><c>true</c> if other <see cref="BoundingSphere"/> intersects with this sphere; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Intersects(ref BoundingSphere sphere, out bool result)
|
||||
{
|
||||
float sqDistance;
|
||||
Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance);
|
||||
|
||||
if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius))
|
||||
result = false;
|
||||
else
|
||||
result = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="Plane"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="plane">The plane for testing.</param>
|
||||
/// <returns>Type of intersection.</returns>
|
||||
public PlaneIntersectionType Intersects(Plane plane)
|
||||
{
|
||||
var result = default(PlaneIntersectionType);
|
||||
// TODO: we might want to inline this for performance reasons
|
||||
this.Intersects(ref plane, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="Plane"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="plane">The plane for testing.</param>
|
||||
/// <param name="result">Type of intersection as an output parameter.</param>
|
||||
public void Intersects(ref Plane plane, out PlaneIntersectionType result)
|
||||
{
|
||||
var distance = default(float);
|
||||
// TODO: we might want to inline this for performance reasons
|
||||
Vector3.Dot(ref plane.Normal, ref this.Center, out distance);
|
||||
distance += plane.D;
|
||||
if (distance > this.Radius)
|
||||
result = PlaneIntersectionType.Front;
|
||||
else if (distance < -this.Radius)
|
||||
result = PlaneIntersectionType.Back;
|
||||
else
|
||||
result = PlaneIntersectionType.Intersecting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="Ray"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray for testing.</param>
|
||||
/// <returns>Distance of ray intersection or <c>null</c> if there is no intersection.</returns>
|
||||
public float? Intersects(Ray ray)
|
||||
{
|
||||
return ray.Intersects(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not a specified <see cref="Ray"/> intersects with this sphere.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray for testing.</param>
|
||||
/// <param name="result">Distance of ray intersection or <c>null</c> if there is no intersection as an output parameter.</param>
|
||||
public void Intersects(ref Ray ray, out float? result)
|
||||
{
|
||||
ray.Intersects(ref this, out result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> representation of this <see cref="BoundingSphere"/> in the format:
|
||||
/// {Center:[<see cref="Center"/>] Radius:[<see cref="Radius"/>]}
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="String"/> representation of this <see cref="BoundingSphere"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return "{Center:" + this.Center + " Radius:" + this.Radius + "}";
|
||||
}
|
||||
|
||||
#region Transform
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BoundingSphere"/> that contains a transformation of translation and scale from this sphere by the specified <see cref="Matrix"/>.
|
||||
/// </summary>
|
||||
/// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
|
||||
/// <returns>Transformed <see cref="BoundingSphere"/>.</returns>
|
||||
public BoundingSphere Transform(Matrix matrix)
|
||||
{
|
||||
BoundingSphere sphere = new BoundingSphere();
|
||||
sphere.Center = Vector3.Transform(this.Center, matrix);
|
||||
sphere.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
|
||||
return sphere;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BoundingSphere"/> that contains a transformation of translation and scale from this sphere by the specified <see cref="Matrix"/>.
|
||||
/// </summary>
|
||||
/// <param name="matrix">The transformation <see cref="Matrix"/>.</param>
|
||||
/// <param name="result">Transformed <see cref="BoundingSphere"/> as an output parameter.</param>
|
||||
public void Transform(ref Matrix matrix, out BoundingSphere result)
|
||||
{
|
||||
result.Center = Vector3.Transform(this.Center, matrix);
|
||||
result.Radius = this.Radius * ((float)Math.Sqrt((double)Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)))));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Deconstruction method for <see cref="BoundingSphere"/>.
|
||||
/// </summary>
|
||||
/// <param name="center"></param>
|
||||
/// <param name="radius"></param>
|
||||
public void Deconstruct(out Vector3 center, out float radius)
|
||||
{
|
||||
center = Center;
|
||||
radius = Radius;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="BoundingSphere"/> instances are equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="BoundingSphere"/> instance on the left of the equal sign.</param>
|
||||
/// <param name="b"><see cref="BoundingSphere"/> instance on the right of the equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator == (BoundingSphere a, BoundingSphere b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="BoundingSphere"/> instances are not equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="BoundingSphere"/> instance on the left of the not equal sign.</param>
|
||||
/// <param name="b"><see cref="BoundingSphere"/> instance on the right of the not equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator != (BoundingSphere a, BoundingSphere b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1821
Libraries/XNATypes/Color.cs
Normal file
1821
Libraries/XNATypes/Color.cs
Normal file
File diff suppressed because it is too large
Load Diff
25
Libraries/XNATypes/ContainmentType.cs
Normal file
25
Libraries/XNATypes/ContainmentType.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how the bounding volumes intersects or contain one another.
|
||||
/// </summary>
|
||||
public enum ContainmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that there is no overlap between two bounding volumes.
|
||||
/// </summary>
|
||||
Disjoint,
|
||||
/// <summary>
|
||||
/// Indicates that one bounding volume completely contains another volume.
|
||||
/// </summary>
|
||||
Contains,
|
||||
/// <summary>
|
||||
/// Indicates that bounding volumes partially overlap one another.
|
||||
/// </summary>
|
||||
Intersects
|
||||
}
|
||||
}
|
||||
320
Libraries/XNATypes/MathHelper.cs
Normal file
320
Libraries/XNATypes/MathHelper.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains commonly used precalculated values and mathematical operations.
|
||||
/// </summary>
|
||||
public static class MathHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the mathematical constant e(2.71828175).
|
||||
/// </summary>
|
||||
public const float E = (float)Math.E;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the log base ten of e(0.4342945).
|
||||
/// </summary>
|
||||
public const float Log10E = 0.4342945f;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the log base two of e(1.442695).
|
||||
/// </summary>
|
||||
public const float Log2E = 1.442695f;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the value of pi(3.14159274).
|
||||
/// </summary>
|
||||
public const float Pi = (float)Math.PI;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the value of pi divided by two(1.57079637).
|
||||
/// </summary>
|
||||
public const float PiOver2 = (float)(Math.PI / 2.0);
|
||||
|
||||
/// <summary>
|
||||
/// Represents the value of pi divided by four(0.7853982).
|
||||
/// </summary>
|
||||
public const float PiOver4 = (float)(Math.PI / 4.0);
|
||||
|
||||
/// <summary>
|
||||
/// Represents the value of pi times two(6.28318548).
|
||||
/// </summary>
|
||||
public const float TwoPi = (float)(Math.PI * 2.0);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Cartesian coordinate for one axis of a point that is defined by a given triangle and two normalized barycentric (areal) coordinates.
|
||||
/// </summary>
|
||||
/// <param name="value1">The coordinate on one axis of vertex 1 of the defining triangle.</param>
|
||||
/// <param name="value2">The coordinate on the same axis of vertex 2 of the defining triangle.</param>
|
||||
/// <param name="value3">The coordinate on the same axis of vertex 3 of the defining triangle.</param>
|
||||
/// <param name="amount1">The normalized barycentric (areal) coordinate b2, equal to the weighting factor for vertex 2, the coordinate of which is specified in value2.</param>
|
||||
/// <param name="amount2">The normalized barycentric (areal) coordinate b3, equal to the weighting factor for vertex 3, the coordinate of which is specified in value3.</param>
|
||||
/// <returns>Cartesian coordinate of the specified point with respect to the axis being used.</returns>
|
||||
public static float Barycentric(float value1, float value2, float value3, float amount1, float amount2)
|
||||
{
|
||||
return value1 + (value2 - value1) * amount1 + (value3 - value1) * amount2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a Catmull-Rom interpolation using the specified positions.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first position in the interpolation.</param>
|
||||
/// <param name="value2">The second position in the interpolation.</param>
|
||||
/// <param name="value3">The third position in the interpolation.</param>
|
||||
/// <param name="value4">The fourth position in the interpolation.</param>
|
||||
/// <param name="amount">Weighting factor.</param>
|
||||
/// <returns>A position that is the result of the Catmull-Rom interpolation.</returns>
|
||||
public static float CatmullRom(float value1, float value2, float value3, float value4, float amount)
|
||||
{
|
||||
// Using formula from http://www.mvps.org/directx/articles/catmull/
|
||||
// Internally using doubles not to lose precission
|
||||
double amountSquared = amount * amount;
|
||||
double amountCubed = amountSquared * amount;
|
||||
return (float)(0.5 * (2.0 * value2 +
|
||||
(value3 - value1) * amount +
|
||||
(2.0 * value1 - 5.0 * value2 + 4.0 * value3 - value4) * amountSquared +
|
||||
(3.0 * value2 - value1 - 3.0 * value3 + value4) * amountCubed));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restricts a value to be within a specified range.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum value. If <c>value</c> is less than <c>min</c>, <c>min</c> will be returned.</param>
|
||||
/// <param name="max">The maximum value. If <c>value</c> is greater than <c>max</c>, <c>max</c> will be returned.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static float Clamp(float value, float min, float max)
|
||||
{
|
||||
// First we check to see if we're greater than the max
|
||||
value = (value > max) ? max : value;
|
||||
|
||||
// Then we check to see if we're less than the min.
|
||||
value = (value < min) ? min : value;
|
||||
|
||||
// There's no check to see if min > max.
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restricts a value to be within a specified range.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum value. If <c>value</c> is less than <c>min</c>, <c>min</c> will be returned.</param>
|
||||
/// <param name="max">The maximum value. If <c>value</c> is greater than <c>max</c>, <c>max</c> will be returned.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static int Clamp(int value, int min, int max)
|
||||
{
|
||||
value = (value > max) ? max : value;
|
||||
value = (value < min) ? min : value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the absolute value of the difference of two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <returns>Distance between the two values.</returns>
|
||||
public static float Distance(float value1, float value2)
|
||||
{
|
||||
return Math.Abs(value1 - value2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a Hermite spline interpolation.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source position.</param>
|
||||
/// <param name="tangent1">Source tangent.</param>
|
||||
/// <param name="value2">Source position.</param>
|
||||
/// <param name="tangent2">Source tangent.</param>
|
||||
/// <param name="amount">Weighting factor.</param>
|
||||
/// <returns>The result of the Hermite spline interpolation.</returns>
|
||||
public static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount)
|
||||
{
|
||||
// All transformed to double not to lose precission
|
||||
// Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
|
||||
double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
|
||||
double sCubed = s * s * s;
|
||||
double sSquared = s * s;
|
||||
|
||||
if (amount == 0f)
|
||||
result = value1;
|
||||
else if (amount == 1f)
|
||||
result = value2;
|
||||
else
|
||||
result = (2 * v1 - 2 * v2 + t2 + t1) * sCubed +
|
||||
(3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared +
|
||||
t1 * s +
|
||||
v1;
|
||||
return (float)result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Destination value.</param>
|
||||
/// <param name="amount">Value between 0 and 1 indicating the weight of value2.</param>
|
||||
/// <returns>Interpolated value.</returns>
|
||||
/// <remarks>This method performs the linear interpolation based on the following formula:
|
||||
/// <code>value1 + (value2 - value1) * amount</code>.
|
||||
/// Passing amount a value of 0 will cause value1 to be returned, a value of 1 will cause value2 to be returned.
|
||||
/// See <see cref="MathHelper.LerpPrecise"/> for a less efficient version with more precision around edge cases.
|
||||
/// </remarks>
|
||||
public static float Lerp(float value1, float value2, float amount)
|
||||
{
|
||||
return value1 + (value2 - value1) * amount;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Linearly interpolates between two values.
|
||||
/// This method is a less efficient, more precise version of <see cref="MathHelper.Lerp"/>.
|
||||
/// See remarks for more info.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Destination value.</param>
|
||||
/// <param name="amount">Value between 0 and 1 indicating the weight of value2.</param>
|
||||
/// <returns>Interpolated value.</returns>
|
||||
/// <remarks>This method performs the linear interpolation based on the following formula:
|
||||
/// <code>((1 - amount) * value1) + (value2 * amount)</code>.
|
||||
/// Passing amount a value of 0 will cause value1 to be returned, a value of 1 will cause value2 to be returned.
|
||||
/// This method does not have the floating point precision issue that <see cref="MathHelper.Lerp"/> has.
|
||||
/// i.e. If there is a big gap between value1 and value2 in magnitude (e.g. value1=10000000000000000, value2=1),
|
||||
/// right at the edge of the interpolation range (amount=1), <see cref="MathHelper.Lerp"/> will return 0 (whereas it should return 1).
|
||||
/// This also holds for value1=10^17, value2=10; value1=10^18,value2=10^2... so on.
|
||||
/// For an in depth explanation of the issue, see below references:
|
||||
/// Relevant Wikipedia Article: https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support
|
||||
/// Relevant StackOverflow Answer: http://stackoverflow.com/questions/4353525/floating-point-linear-interpolation#answer-23716956
|
||||
/// </remarks>
|
||||
public static float LerpPrecise(float value1, float value2, float amount)
|
||||
{
|
||||
return ((1 - amount) * value1) + (value2 * amount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the greater of two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <returns>The greater value.</returns>
|
||||
public static float Max(float value1, float value2)
|
||||
{
|
||||
return value1 > value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the greater of two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <returns>The greater value.</returns>
|
||||
public static int Max(int value1, int value2)
|
||||
{
|
||||
return value1 > value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the lesser of two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <returns>The lesser value.</returns>
|
||||
public static float Min(float value1, float value2)
|
||||
{
|
||||
return value1 < value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the lesser of two values.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <returns>The lesser value.</returns>
|
||||
public static int Min(int value1, int value2)
|
||||
{
|
||||
return value1 < value2 ? value1 : value2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates between two values using a cubic equation.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source value.</param>
|
||||
/// <param name="value2">Source value.</param>
|
||||
/// <param name="amount">Weighting value.</param>
|
||||
/// <returns>Interpolated value.</returns>
|
||||
public static float SmoothStep(float value1, float value2, float amount)
|
||||
{
|
||||
// It is expected that 0 < amount < 1
|
||||
// If amount < 0, return value1
|
||||
// If amount > 1, return value2
|
||||
float result = MathHelper.Clamp(amount, 0f, 1f);
|
||||
result = MathHelper.Hermite(value1, 0f, value2, 0f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts radians to degrees.
|
||||
/// </summary>
|
||||
/// <param name="radians">The angle in radians.</param>
|
||||
/// <returns>The angle in degrees.</returns>
|
||||
/// <remarks>
|
||||
/// This method uses double precission internally,
|
||||
/// though it returns single float
|
||||
/// Factor = 180 / pi
|
||||
/// </remarks>
|
||||
public static float ToDegrees(float radians)
|
||||
{
|
||||
return (float)(radians * 57.295779513082320876798154814105);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts degrees to radians.
|
||||
/// </summary>
|
||||
/// <param name="degrees">The angle in degrees.</param>
|
||||
/// <returns>The angle in radians.</returns>
|
||||
/// <remarks>
|
||||
/// This method uses double precission internally,
|
||||
/// though it returns single float
|
||||
/// Factor = pi / 180
|
||||
/// </remarks>
|
||||
public static float ToRadians(float degrees)
|
||||
{
|
||||
return (float)(degrees * 0.017453292519943295769236907684886);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reduces a given angle to a value between π and -π.
|
||||
/// </summary>
|
||||
/// <param name="angle">The angle to reduce, in radians.</param>
|
||||
/// <returns>The new angle, in radians.</returns>
|
||||
public static float WrapAngle(float angle)
|
||||
{
|
||||
if ((angle > -Pi) && (angle <= Pi))
|
||||
return angle;
|
||||
angle %= TwoPi;
|
||||
if (angle <= -Pi)
|
||||
return angle + TwoPi;
|
||||
if (angle > Pi)
|
||||
return angle - TwoPi;
|
||||
return angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if value is powered by two.
|
||||
/// </summary>
|
||||
/// <param name="value">A value.</param>
|
||||
/// <returns><c>true</c> if <c>value</c> is powered by two; otherwise <c>false</c>.</returns>
|
||||
public static bool IsPowerOfTwo(int value)
|
||||
{
|
||||
return (value > 0) && ((value & (value - 1)) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
2474
Libraries/XNATypes/Matrix.cs
Normal file
2474
Libraries/XNATypes/Matrix.cs
Normal file
File diff suppressed because it is too large
Load Diff
296
Libraries/XNATypes/Plane.cs
Normal file
296
Libraries/XNATypes/Plane.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
internal class PlaneHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a value indicating what side (positive/negative) of a plane a point is
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check with</param>
|
||||
/// <param name="plane">The plane to check against</param>
|
||||
/// <returns>Greater than zero if on the positive side, less than zero if on the negative size, 0 otherwise</returns>
|
||||
public static float ClassifyPoint(ref Vector3 point, ref Plane plane)
|
||||
{
|
||||
return point.X * plane.Normal.X + point.Y * plane.Normal.Y + point.Z * plane.Normal.Z + plane.D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the perpendicular distance from a point to a plane
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check</param>
|
||||
/// <param name="plane">The place to check</param>
|
||||
/// <returns>The perpendicular distance from the point to the plane</returns>
|
||||
public static float PerpendicularDistance(ref Vector3 point, ref Plane plane)
|
||||
{
|
||||
// dist = (ax + by + cz + d) / sqrt(a*a + b*b + c*c)
|
||||
return (float)Math.Abs((plane.Normal.X * point.X + plane.Normal.Y * point.Y + plane.Normal.Z * point.Z)
|
||||
/ Math.Sqrt(plane.Normal.X * plane.Normal.X + plane.Normal.Y * plane.Normal.Y + plane.Normal.Z * plane.Normal.Z));
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct Plane : IEquatable<Plane>
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
[DataMember]
|
||||
public float D;
|
||||
|
||||
[DataMember]
|
||||
public Vector3 Normal;
|
||||
|
||||
#endregion Public Fields
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Plane(Vector4 value)
|
||||
: this(new Vector3(value.X, value.Y, value.Z), value.W)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Plane(Vector3 normal, float d)
|
||||
{
|
||||
Normal = normal;
|
||||
D = d;
|
||||
}
|
||||
|
||||
public Plane(Vector3 a, Vector3 b, Vector3 c)
|
||||
{
|
||||
Vector3 ab = b - a;
|
||||
Vector3 ac = c - a;
|
||||
|
||||
Vector3 cross = Vector3.Cross(ab, ac);
|
||||
Vector3.Normalize(ref cross, out Normal);
|
||||
D = -(Vector3.Dot(Normal, a));
|
||||
}
|
||||
|
||||
public Plane(float a, float b, float c, float d)
|
||||
: this(new Vector3(a, b, c), d)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public float Dot(Vector4 value)
|
||||
{
|
||||
return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W));
|
||||
}
|
||||
|
||||
public void Dot(ref Vector4 value, out float result)
|
||||
{
|
||||
result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + (this.D * value.W);
|
||||
}
|
||||
|
||||
public float DotCoordinate(Vector3 value)
|
||||
{
|
||||
return ((((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D);
|
||||
}
|
||||
|
||||
public void DotCoordinate(ref Vector3 value, out float result)
|
||||
{
|
||||
result = (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z)) + this.D;
|
||||
}
|
||||
|
||||
public float DotNormal(Vector3 value)
|
||||
{
|
||||
return (((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z));
|
||||
}
|
||||
|
||||
public void DotNormal(ref Vector3 value, out float result)
|
||||
{
|
||||
result = ((this.Normal.X * value.X) + (this.Normal.Y * value.Y)) + (this.Normal.Z * value.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a normalized plane by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="plane">The normalized plane to transform.</param>
|
||||
/// <param name="matrix">The transformation matrix.</param>
|
||||
/// <returns>The transformed plane.</returns>
|
||||
public static Plane Transform(Plane plane, Matrix matrix)
|
||||
{
|
||||
Plane result;
|
||||
Transform(ref plane, ref matrix, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a normalized plane by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="plane">The normalized plane to transform.</param>
|
||||
/// <param name="matrix">The transformation matrix.</param>
|
||||
/// <param name="result">The transformed plane.</param>
|
||||
public static void Transform(ref Plane plane, ref Matrix matrix, out Plane result)
|
||||
{
|
||||
// See "Transforming Normals" in http://www.glprogramming.com/red/appendixf.html
|
||||
// for an explanation of how this works.
|
||||
|
||||
Matrix transformedMatrix;
|
||||
Matrix.Invert(ref matrix, out transformedMatrix);
|
||||
Matrix.Transpose(ref transformedMatrix, out transformedMatrix);
|
||||
|
||||
var vector = new Vector4(plane.Normal, plane.D);
|
||||
|
||||
Vector4 transformedVector;
|
||||
Vector4.Transform(ref vector, ref transformedMatrix, out transformedVector);
|
||||
|
||||
result = new Plane(transformedVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a normalized plane by a quaternion rotation.
|
||||
/// </summary>
|
||||
/// <param name="plane">The normalized plane to transform.</param>
|
||||
/// <param name="rotation">The quaternion rotation.</param>
|
||||
/// <returns>The transformed plane.</returns>
|
||||
public static Plane Transform(Plane plane, Quaternion rotation)
|
||||
{
|
||||
Plane result;
|
||||
Transform(ref plane, ref rotation, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a normalized plane by a quaternion rotation.
|
||||
/// </summary>
|
||||
/// <param name="plane">The normalized plane to transform.</param>
|
||||
/// <param name="rotation">The quaternion rotation.</param>
|
||||
/// <param name="result">The transformed plane.</param>
|
||||
public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result)
|
||||
{
|
||||
Vector3.Transform(ref plane.Normal, ref rotation, out result.Normal);
|
||||
result.D = plane.D;
|
||||
}
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
float length = Normal.Length();
|
||||
float factor = 1f / length;
|
||||
Vector3.Multiply(ref Normal, factor, out Normal);
|
||||
D = D * factor;
|
||||
}
|
||||
|
||||
public static Plane Normalize(Plane value)
|
||||
{
|
||||
Plane ret;
|
||||
Normalize(ref value, out ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Normalize(ref Plane value, out Plane result)
|
||||
{
|
||||
float length = value.Normal.Length();
|
||||
float factor = 1f / length;
|
||||
Vector3.Multiply(ref value.Normal, factor, out result.Normal);
|
||||
result.D = value.D * factor;
|
||||
}
|
||||
|
||||
public static bool operator !=(Plane plane1, Plane plane2)
|
||||
{
|
||||
return !plane1.Equals(plane2);
|
||||
}
|
||||
|
||||
public static bool operator ==(Plane plane1, Plane plane2)
|
||||
{
|
||||
return plane1.Equals(plane2);
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
return (other is Plane) ? this.Equals((Plane)other) : false;
|
||||
}
|
||||
|
||||
public bool Equals(Plane other)
|
||||
{
|
||||
return ((Normal == other.Normal) && (D == other.D));
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Normal.GetHashCode() ^ D.GetHashCode();
|
||||
}
|
||||
|
||||
public PlaneIntersectionType Intersects(BoundingBox box)
|
||||
{
|
||||
return box.Intersects(this);
|
||||
}
|
||||
|
||||
public void Intersects(ref BoundingBox box, out PlaneIntersectionType result)
|
||||
{
|
||||
box.Intersects (ref this, out result);
|
||||
}
|
||||
|
||||
public PlaneIntersectionType Intersects(BoundingFrustum frustum)
|
||||
{
|
||||
return frustum.Intersects(this);
|
||||
}
|
||||
|
||||
public PlaneIntersectionType Intersects(BoundingSphere sphere)
|
||||
{
|
||||
return sphere.Intersects(this);
|
||||
}
|
||||
|
||||
public void Intersects(ref BoundingSphere sphere, out PlaneIntersectionType result)
|
||||
{
|
||||
sphere.Intersects(ref this, out result);
|
||||
}
|
||||
|
||||
internal PlaneIntersectionType Intersects(ref Vector3 point)
|
||||
{
|
||||
float distance;
|
||||
DotCoordinate(ref point, out distance);
|
||||
|
||||
if (distance > 0)
|
||||
return PlaneIntersectionType.Front;
|
||||
|
||||
if (distance < 0)
|
||||
return PlaneIntersectionType.Back;
|
||||
|
||||
return PlaneIntersectionType.Intersecting;
|
||||
}
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
this.Normal.DebugDisplayString, " ",
|
||||
this.D.ToString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{Normal:" + Normal + " D:" + D + "}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deconstruction method for <see cref="Plane"/>.
|
||||
/// </summary>
|
||||
/// <param name="normal"></param>
|
||||
/// <param name="d"></param>
|
||||
public void Deconstruct(out Vector3 normal, out float d)
|
||||
{
|
||||
normal = Normal;
|
||||
d = D;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
25
Libraries/XNATypes/PlaneIntersectionType.cs
Normal file
25
Libraries/XNATypes/PlaneIntersectionType.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the intersection between a <see cref="Plane"/> and a bounding volume.
|
||||
/// </summary>
|
||||
public enum PlaneIntersectionType
|
||||
{
|
||||
/// <summary>
|
||||
/// There is no intersection, the bounding volume is in the negative half space of the plane.
|
||||
/// </summary>
|
||||
Front,
|
||||
/// <summary>
|
||||
/// There is no intersection, the bounding volume is in the positive half space of the plane.
|
||||
/// </summary>
|
||||
Back,
|
||||
/// <summary>
|
||||
/// The plane is intersected.
|
||||
/// </summary>
|
||||
Intersecting
|
||||
}
|
||||
}
|
||||
219
Libraries/XNATypes/Point.cs
Normal file
219
Libraries/XNATypes/Point.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a 2D-point.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct Point : IEquatable<Point>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static readonly Point zeroPoint = new Point();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// The x coordinate of this <see cref="Point"/>.
|
||||
/// </summary>
|
||||
public int X;
|
||||
|
||||
/// <summary>
|
||||
/// The y coordinate of this <see cref="Point"/>.
|
||||
/// </summary>
|
||||
public int Y;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="Point"/> with coordinates 0, 0.
|
||||
/// </summary>
|
||||
public static Point Zero
|
||||
{
|
||||
get { return zeroPoint; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
this.X.ToString(), " ",
|
||||
this.Y.ToString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a point with X and Y from two values.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate in 2d-space.</param>
|
||||
/// <param name="y">The y coordinate in 2d-space.</param>
|
||||
public Point(int x, int y)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a point with X and Y set to the same value.
|
||||
/// </summary>
|
||||
/// <param name="value">The x and y coordinates in 2d-space.</param>
|
||||
public Point(int value)
|
||||
{
|
||||
this.X = value;
|
||||
this.Y = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Adds two points.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source <see cref="Point"/> on the left of the add sign.</param>
|
||||
/// <param name="value2">Source <see cref="Point"/> on the right of the add sign.</param>
|
||||
/// <returns>Sum of the points.</returns>
|
||||
public static Point operator +(Point value1, Point value2)
|
||||
{
|
||||
return new Point(value1.X + value2.X, value1.Y + value2.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts a <see cref="Point"/> from a <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source <see cref="Point"/> on the left of the sub sign.</param>
|
||||
/// <param name="value2">Source <see cref="Point"/> on the right of the sub sign.</param>
|
||||
/// <returns>Result of the subtraction.</returns>
|
||||
public static Point operator -(Point value1, Point value2)
|
||||
{
|
||||
return new Point(value1.X - value2.X, value1.Y - value2.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies the components of two points by each other.
|
||||
/// </summary>
|
||||
/// <param name="value1">Source <see cref="Point"/> on the left of the mul sign.</param>
|
||||
/// <param name="value2">Source <see cref="Point"/> on the right of the mul sign.</param>
|
||||
/// <returns>Result of the multiplication.</returns>
|
||||
public static Point operator *(Point value1, Point value2)
|
||||
{
|
||||
return new Point(value1.X * value2.X, value1.Y * value2.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the components of a <see cref="Point"/> by the components of another <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <param name="source">Source <see cref="Point"/> on the left of the div sign.</param>
|
||||
/// <param name="divisor">Divisor <see cref="Point"/> on the right of the div sign.</param>
|
||||
/// <returns>The result of dividing the points.</returns>
|
||||
public static Point operator /(Point source, Point divisor)
|
||||
{
|
||||
return new Point(source.X / divisor.X, source.Y / divisor.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="Point"/> instances are equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="Point"/> instance on the left of the equal sign.</param>
|
||||
/// <param name="b"><see cref="Point"/> instance on the right of the equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator ==(Point a, Point b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="Point"/> instances are not equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="Point"/> instance on the left of the not equal sign.</param>
|
||||
/// <param name="b"><see cref="Point"/> instance on the right of the not equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator !=(Point a, Point b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="Object"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="Object"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Point) && Equals((Point)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="Point"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public bool Equals(Point other)
|
||||
{
|
||||
return ((X == other.X) && (Y == other.Y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash code of this <see cref="Point"/>.
|
||||
/// </summary>
|
||||
/// <returns>Hash code of this <see cref="Point"/>.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 17;
|
||||
hash = hash * 23 + X.GetHashCode();
|
||||
hash = hash * 23 + Y.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> representation of this <see cref="Point"/> in the format:
|
||||
/// {X:[<see cref="X"/>] Y:[<see cref="Y"/>]}
|
||||
/// </summary>
|
||||
/// <returns><see cref="String"/> representation of this <see cref="Point"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return "{X:" + X + " Y:" + Y + "}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Vector2"/> representation for this object.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Vector2"/> representation for this object.</returns>
|
||||
public Vector2 ToVector2()
|
||||
{
|
||||
return new Vector2(X, Y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1169
Libraries/XNATypes/Quaternion.cs
Normal file
1169
Libraries/XNATypes/Quaternion.cs
Normal file
File diff suppressed because it is too large
Load Diff
272
Libraries/XNATypes/Ray.cs
Normal file
272
Libraries/XNATypes/Ray.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
[DataContract]
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct Ray : IEquatable<Ray>
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
[DataMember]
|
||||
public Vector3 Direction;
|
||||
|
||||
[DataMember]
|
||||
public Vector3 Position;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public Ray(Vector3 position, Vector3 direction)
|
||||
{
|
||||
this.Position = position;
|
||||
this.Direction = direction;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Ray) ? this.Equals((Ray)obj) : false;
|
||||
}
|
||||
|
||||
|
||||
public bool Equals(Ray other)
|
||||
{
|
||||
return this.Position.Equals(other.Position) && this.Direction.Equals(other.Direction);
|
||||
}
|
||||
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Position.GetHashCode() ^ Direction.GetHashCode();
|
||||
}
|
||||
|
||||
// adapted from http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
|
||||
public float? Intersects(BoundingBox box)
|
||||
{
|
||||
const float Epsilon = 1e-6f;
|
||||
|
||||
float? tMin = null, tMax = null;
|
||||
|
||||
if (Math.Abs(Direction.X) < Epsilon)
|
||||
{
|
||||
if (Position.X < box.Min.X || Position.X > box.Max.X)
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
tMin = (box.Min.X - Position.X) / Direction.X;
|
||||
tMax = (box.Max.X - Position.X) / Direction.X;
|
||||
|
||||
if (tMin > tMax)
|
||||
{
|
||||
var temp = tMin;
|
||||
tMin = tMax;
|
||||
tMax = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.Abs(Direction.Y) < Epsilon)
|
||||
{
|
||||
if (Position.Y < box.Min.Y || Position.Y > box.Max.Y)
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tMinY = (box.Min.Y - Position.Y) / Direction.Y;
|
||||
var tMaxY = (box.Max.Y - Position.Y) / Direction.Y;
|
||||
|
||||
if (tMinY > tMaxY)
|
||||
{
|
||||
var temp = tMinY;
|
||||
tMinY = tMaxY;
|
||||
tMaxY = temp;
|
||||
}
|
||||
|
||||
if ((tMin.HasValue && tMin > tMaxY) || (tMax.HasValue && tMinY > tMax))
|
||||
return null;
|
||||
|
||||
if (!tMin.HasValue || tMinY > tMin) tMin = tMinY;
|
||||
if (!tMax.HasValue || tMaxY < tMax) tMax = tMaxY;
|
||||
}
|
||||
|
||||
if (Math.Abs(Direction.Z) < Epsilon)
|
||||
{
|
||||
if (Position.Z < box.Min.Z || Position.Z > box.Max.Z)
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tMinZ = (box.Min.Z - Position.Z) / Direction.Z;
|
||||
var tMaxZ = (box.Max.Z - Position.Z) / Direction.Z;
|
||||
|
||||
if (tMinZ > tMaxZ)
|
||||
{
|
||||
var temp = tMinZ;
|
||||
tMinZ = tMaxZ;
|
||||
tMaxZ = temp;
|
||||
}
|
||||
|
||||
if ((tMin.HasValue && tMin > tMaxZ) || (tMax.HasValue && tMinZ > tMax))
|
||||
return null;
|
||||
|
||||
if (!tMin.HasValue || tMinZ > tMin) tMin = tMinZ;
|
||||
if (!tMax.HasValue || tMaxZ < tMax) tMax = tMaxZ;
|
||||
}
|
||||
|
||||
// having a positive tMin and a negative tMax means the ray is inside the box
|
||||
// we expect the intesection distance to be 0 in that case
|
||||
if ((tMin.HasValue && tMin < 0) && tMax > 0) return 0;
|
||||
|
||||
// a negative tMin means that the intersection point is behind the ray's origin
|
||||
// we discard these as not hitting the AABB
|
||||
if (tMin < 0) return null;
|
||||
|
||||
return tMin;
|
||||
}
|
||||
|
||||
|
||||
public void Intersects(ref BoundingBox box, out float? result)
|
||||
{
|
||||
result = Intersects(box);
|
||||
}
|
||||
|
||||
/*
|
||||
public float? Intersects(BoundingFrustum frustum)
|
||||
{
|
||||
if (frustum == null)
|
||||
{
|
||||
throw new ArgumentNullException("frustum");
|
||||
}
|
||||
|
||||
return frustum.Intersects(this);
|
||||
}
|
||||
*/
|
||||
|
||||
public float? Intersects(BoundingSphere sphere)
|
||||
{
|
||||
float? result;
|
||||
Intersects(ref sphere, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public float? Intersects(Plane plane)
|
||||
{
|
||||
float? result;
|
||||
Intersects(ref plane, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Intersects(ref Plane plane, out float? result)
|
||||
{
|
||||
var den = Vector3.Dot(Direction, plane.Normal);
|
||||
if (Math.Abs(den) < 0.00001f)
|
||||
{
|
||||
result = null;
|
||||
return;
|
||||
}
|
||||
|
||||
result = (-plane.D - Vector3.Dot(plane.Normal, Position)) / den;
|
||||
|
||||
if (result < 0.0f)
|
||||
{
|
||||
if (result < -0.00001f)
|
||||
{
|
||||
result = null;
|
||||
return;
|
||||
}
|
||||
|
||||
result = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void Intersects(ref BoundingSphere sphere, out float? result)
|
||||
{
|
||||
// Find the vector between where the ray starts the the sphere's centre
|
||||
Vector3 difference = sphere.Center - this.Position;
|
||||
|
||||
float differenceLengthSquared = difference.LengthSquared();
|
||||
float sphereRadiusSquared = sphere.Radius * sphere.Radius;
|
||||
|
||||
float distanceAlongRay;
|
||||
|
||||
// If the distance between the ray start and the sphere's centre is less than
|
||||
// the radius of the sphere, it means we've intersected. N.B. checking the LengthSquared is faster.
|
||||
if (differenceLengthSquared < sphereRadiusSquared)
|
||||
{
|
||||
result = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3.Dot(ref this.Direction, ref difference, out distanceAlongRay);
|
||||
// If the ray is pointing away from the sphere then we don't ever intersect
|
||||
if (distanceAlongRay < 0)
|
||||
{
|
||||
result = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Next we kinda use Pythagoras to check if we are within the bounds of the sphere
|
||||
// if x = radius of sphere
|
||||
// if y = distance between ray position and sphere centre
|
||||
// if z = the distance we've travelled along the ray
|
||||
// if x^2 + z^2 - y^2 < 0, we do not intersect
|
||||
float dist = sphereRadiusSquared + distanceAlongRay * distanceAlongRay - differenceLengthSquared;
|
||||
|
||||
result = (dist < 0) ? null : distanceAlongRay - (float?)Math.Sqrt(dist);
|
||||
}
|
||||
|
||||
|
||||
public static bool operator !=(Ray a, Ray b)
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
|
||||
public static bool operator ==(Ray a, Ray b)
|
||||
{
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
"Pos( ", this.Position.DebugDisplayString, " ) \r\n",
|
||||
"Dir( ", this.Direction.DebugDisplayString, " )"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{{Position:" + Position.ToString() + " Direction:" + Direction.ToString() + "}}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deconstruction method for <see cref="Ray"/>.
|
||||
/// </summary>
|
||||
/// <param name="position">Receives the start position of the ray.</param>
|
||||
/// <param name="direction">Receives the direction of the ray.</param>
|
||||
public void Deconstruct(out Vector3 position, out Vector3 direction)
|
||||
{
|
||||
position = Position;
|
||||
direction = Direction;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
532
Libraries/XNATypes/Rectangle.cs
Normal file
532
Libraries/XNATypes/Rectangle.cs
Normal file
@@ -0,0 +1,532 @@
|
||||
// MIT License - Copyright (C) The Mono.Xna Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a 2D-rectangle.
|
||||
/// </summary>
|
||||
|
||||
[DebuggerDisplay("{DebugDisplayString,nq}")]
|
||||
public struct Rectangle : IEquatable<Rectangle>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static Rectangle emptyRectangle = new Rectangle();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// The x coordinate of the top-left corner of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
|
||||
public int X;
|
||||
|
||||
/// <summary>
|
||||
/// The y coordinate of the top-left corner of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
|
||||
public int Y;
|
||||
|
||||
/// <summary>
|
||||
/// The width of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
|
||||
public int Width;
|
||||
|
||||
/// <summary>
|
||||
/// The height of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
|
||||
public int Height;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="Rectangle"/> with X=0, Y=0, Width=0, Height=0.
|
||||
/// </summary>
|
||||
public static Rectangle Empty
|
||||
{
|
||||
get { return emptyRectangle; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the x coordinate of the left edge of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public int Left
|
||||
{
|
||||
get { return this.X; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the x coordinate of the right edge of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public int Right
|
||||
{
|
||||
get { return (this.X + this.Width); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the y coordinate of the top edge of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public int Top
|
||||
{
|
||||
get { return this.Y; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the y coordinate of the bottom edge of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public int Bottom
|
||||
{
|
||||
get { return (this.Y + this.Height); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this <see cref="Rectangle"/> has a <see cref="Width"/> and
|
||||
/// <see cref="Height"/> of 0, and a <see cref="Location"/> of (0, 0).
|
||||
/// </summary>
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((((this.Width == 0) && (this.Height == 0)) && (this.X == 0)) && (this.Y == 0));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The top-left coordinates of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public Point Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Point(this.X, this.Y);
|
||||
}
|
||||
set
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The width-height coordinates of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
public Point Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Point(this.Width,this.Height);
|
||||
}
|
||||
set
|
||||
{
|
||||
Width = value.X;
|
||||
Height = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Point"/> located in the center of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see cref="Width"/> or <see cref="Height"/> is an odd number,
|
||||
/// the center point will be rounded down.
|
||||
/// </remarks>
|
||||
public Point Center
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Point(this.X + (this.Width / 2), this.Y + (this.Height / 2));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Properties
|
||||
|
||||
internal string DebugDisplayString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Concat(
|
||||
this.X, " ",
|
||||
this.Y, " ",
|
||||
this.Width, " ",
|
||||
this.Height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="Rectangle"/> struct, with the specified
|
||||
/// position, width, and height.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate of the top-left corner of the created <see cref="Rectangle"/>.</param>
|
||||
/// <param name="y">The y coordinate of the top-left corner of the created <see cref="Rectangle"/>.</param>
|
||||
/// <param name="width">The width of the created <see cref="Rectangle"/>.</param>
|
||||
/// <param name="height">The height of the created <see cref="Rectangle"/>.</param>
|
||||
public Rectangle(int x, int y, int width, int height)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="Rectangle"/> struct, with the specified
|
||||
/// location and size.
|
||||
/// </summary>
|
||||
/// <param name="location">The x and y coordinates of the top-left corner of the created <see cref="Rectangle"/>.</param>
|
||||
/// <param name="size">The width and height of the created <see cref="Rectangle"/>.</param>
|
||||
public Rectangle(Point location,Point size)
|
||||
{
|
||||
this.X = location.X;
|
||||
this.Y = location.Y;
|
||||
this.Width = size.X;
|
||||
this.Height = size.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="Rectangle"/> instances are equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="Rectangle"/> instance on the left of the equal sign.</param>
|
||||
/// <param name="b"><see cref="Rectangle"/> instance on the right of the equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator ==(Rectangle a, Rectangle b)
|
||||
{
|
||||
return ((a.X == b.X) && (a.Y == b.Y) && (a.Width == b.Width) && (a.Height == b.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether two <see cref="Rectangle"/> instances are not equal.
|
||||
/// </summary>
|
||||
/// <param name="a"><see cref="Rectangle"/> instance on the left of the not equal sign.</param>
|
||||
/// <param name="b"><see cref="Rectangle"/> instance on the right of the not equal sign.</param>
|
||||
/// <returns><c>true</c> if the instances are not equal; <c>false</c> otherwise.</returns>
|
||||
public static bool operator !=(Rectangle a, Rectangle b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate of the point to check for containment.</param>
|
||||
/// <param name="y">The y coordinate of the point to check for containment.</param>
|
||||
/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="Rectangle"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Contains(int x, int y)
|
||||
{
|
||||
return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate of the point to check for containment.</param>
|
||||
/// <param name="y">The y coordinate of the point to check for containment.</param>
|
||||
/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="Rectangle"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Contains(float x, float y)
|
||||
{
|
||||
return ((((this.X <= x) && (x < (this.X + this.Width))) && (this.Y <= y)) && (y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The coordinates to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <returns><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="Rectangle"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Contains(Point value)
|
||||
{
|
||||
return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The coordinates to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <param name="result"><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="Rectangle"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Contains(ref Point value, out bool result)
|
||||
{
|
||||
result = ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The coordinates to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <returns><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="Rectangle"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Contains(Vector2 value)
|
||||
{
|
||||
return ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The coordinates to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <param name="result"><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="Rectangle"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Contains(ref Vector2 value, out bool result)
|
||||
{
|
||||
result = ((((this.X <= value.X) && (value.X < (this.X + this.Width))) && (this.Y <= value.Y)) && (value.Y < (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Rectangle"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Rectangle"/> to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <returns><c>true</c> if the provided <see cref="Rectangle"/>'s bounds lie entirely inside this <see cref="Rectangle"/>; <c>false</c> otherwise.</returns>
|
||||
public bool Contains(Rectangle value)
|
||||
{
|
||||
return ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the provided <see cref="Rectangle"/> lies within the bounds of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Rectangle"/> to check for inclusion in this <see cref="Rectangle"/>.</param>
|
||||
/// <param name="result"><c>true</c> if the provided <see cref="Rectangle"/>'s bounds lie entirely inside this <see cref="Rectangle"/>; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Contains(ref Rectangle value,out bool result)
|
||||
{
|
||||
result = ((((this.X <= value.X) && ((value.X + value.Width) <= (this.X + this.Width))) && (this.Y <= value.Y)) && ((value.Y + value.Height) <= (this.Y + this.Height)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="Object"/>.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="Object"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Rectangle) && this == ((Rectangle)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares whether current instance is equal to specified <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="Rectangle"/> to compare.</param>
|
||||
/// <returns><c>true</c> if the instances are equal; <c>false</c> otherwise.</returns>
|
||||
public bool Equals(Rectangle other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hash code of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <returns>Hash code of this <see cref="Rectangle"/>.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 17;
|
||||
hash = hash * 23 + X.GetHashCode();
|
||||
hash = hash * 23 + Y.GetHashCode();
|
||||
hash = hash * 23 + Width.GetHashCode();
|
||||
hash = hash * 23 + Height.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the edges of this <see cref="Rectangle"/> by specified horizontal and vertical amounts.
|
||||
/// </summary>
|
||||
/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
|
||||
/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
|
||||
public void Inflate(int horizontalAmount, int verticalAmount)
|
||||
{
|
||||
X -= horizontalAmount;
|
||||
Y -= verticalAmount;
|
||||
Width += horizontalAmount * 2;
|
||||
Height += verticalAmount * 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the edges of this <see cref="Rectangle"/> by specified horizontal and vertical amounts.
|
||||
/// </summary>
|
||||
/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
|
||||
/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
|
||||
public void Inflate(float horizontalAmount, float verticalAmount)
|
||||
{
|
||||
X -= (int)horizontalAmount;
|
||||
Y -= (int)verticalAmount;
|
||||
Width += (int)horizontalAmount * 2;
|
||||
Height += (int)verticalAmount * 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the edges of this <see cref="Rectangle"/> by specified horizontal and vertical amounts.
|
||||
/// </summary>
|
||||
/// <param name="amount">Value to adjust the edges.</param>
|
||||
public void Inflate(Vector2 amount)
|
||||
{
|
||||
Inflate(amount.X, amount.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the other <see cref="Rectangle"/> intersects with this rectangle.
|
||||
/// </summary>
|
||||
/// <param name="value">The other rectangle for testing.</param>
|
||||
/// <returns><c>true</c> if other <see cref="Rectangle"/> intersects with this rectangle; <c>false</c> otherwise.</returns>
|
||||
public bool Intersects(Rectangle value)
|
||||
{
|
||||
return value.Left < Right &&
|
||||
Left < value.Right &&
|
||||
value.Top < Bottom &&
|
||||
Top < value.Bottom;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the other <see cref="Rectangle"/> intersects with this rectangle.
|
||||
/// </summary>
|
||||
/// <param name="value">The other rectangle for testing.</param>
|
||||
/// <param name="result"><c>true</c> if other <see cref="Rectangle"/> intersects with this rectangle; <c>false</c> otherwise. As an output parameter.</param>
|
||||
public void Intersects(ref Rectangle value, out bool result)
|
||||
{
|
||||
result = value.Left < Right &&
|
||||
Left < value.Right &&
|
||||
value.Top < Bottom &&
|
||||
Top < value.Bottom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Rectangle"/> that contains overlapping region of two other rectangles.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first <see cref="Rectangle"/>.</param>
|
||||
/// <param name="value2">The second <see cref="Rectangle"/>.</param>
|
||||
/// <returns>Overlapping region of the two rectangles.</returns>
|
||||
public static Rectangle Intersect(Rectangle value1, Rectangle value2)
|
||||
{
|
||||
Rectangle rectangle;
|
||||
Intersect(ref value1, ref value2, out rectangle);
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Rectangle"/> that contains overlapping region of two other rectangles.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first <see cref="Rectangle"/>.</param>
|
||||
/// <param name="value2">The second <see cref="Rectangle"/>.</param>
|
||||
/// <param name="result">Overlapping region of the two rectangles as an output parameter.</param>
|
||||
public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
|
||||
{
|
||||
if (value1.Intersects(value2))
|
||||
{
|
||||
int right_side = Math.Min(value1.X + value1.Width, value2.X + value2.Width);
|
||||
int left_side = Math.Max(value1.X, value2.X);
|
||||
int top_side = Math.Max(value1.Y, value2.Y);
|
||||
int bottom_side = Math.Min(value1.Y + value1.Height, value2.Y + value2.Height);
|
||||
result = new Rectangle(left_side, top_side, right_side - left_side, bottom_side - top_side);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="Location"/> of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="offsetX">The x coordinate to add to this <see cref="Rectangle"/>.</param>
|
||||
/// <param name="offsetY">The y coordinate to add to this <see cref="Rectangle"/>.</param>
|
||||
public void Offset(int offsetX, int offsetY)
|
||||
{
|
||||
X += offsetX;
|
||||
Y += offsetY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="Location"/> of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="offsetX">The x coordinate to add to this <see cref="Rectangle"/>.</param>
|
||||
/// <param name="offsetY">The y coordinate to add to this <see cref="Rectangle"/>.</param>
|
||||
public void Offset(float offsetX, float offsetY)
|
||||
{
|
||||
X += (int)offsetX;
|
||||
Y += (int)offsetY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="Location"/> of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="amount">The x and y components to add to this <see cref="Rectangle"/>.</param>
|
||||
public void Offset(Point amount)
|
||||
{
|
||||
X += amount.X;
|
||||
Y += amount.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="Location"/> of this <see cref="Rectangle"/>.
|
||||
/// </summary>
|
||||
/// <param name="amount">The x and y components to add to this <see cref="Rectangle"/>.</param>
|
||||
public void Offset(Vector2 amount)
|
||||
{
|
||||
X += (int)amount.X;
|
||||
Y += (int)amount.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="String"/> representation of this <see cref="Rectangle"/> in the format:
|
||||
/// {X:[<see cref="X"/>] Y:[<see cref="Y"/>] Width:[<see cref="Width"/>] Height:[<see cref="Height"/>]}
|
||||
/// </summary>
|
||||
/// <returns><see cref="String"/> representation of this <see cref="Rectangle"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return "{X:" + X + " Y:" + Y + " Width:" + Width + " Height:" + Height + "}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Rectangle"/> that completely contains two other rectangles.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first <see cref="Rectangle"/>.</param>
|
||||
/// <param name="value2">The second <see cref="Rectangle"/>.</param>
|
||||
/// <returns>The union of the two rectangles.</returns>
|
||||
public static Rectangle Union(Rectangle value1, Rectangle value2)
|
||||
{
|
||||
int x = Math.Min(value1.X, value2.X);
|
||||
int y = Math.Min(value1.Y, value2.Y);
|
||||
return new Rectangle(x, y,
|
||||
Math.Max(value1.Right, value2.Right) - x,
|
||||
Math.Max(value1.Bottom, value2.Bottom) - y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="Rectangle"/> that completely contains two other rectangles.
|
||||
/// </summary>
|
||||
/// <param name="value1">The first <see cref="Rectangle"/>.</param>
|
||||
/// <param name="value2">The second <see cref="Rectangle"/>.</param>
|
||||
/// <param name="result">The union of the two rectangles as an output parameter.</param>
|
||||
public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
|
||||
{
|
||||
result.X = Math.Min(value1.X, value2.X);
|
||||
result.Y = Math.Min(value1.Y, value2.Y);
|
||||
result.Width = Math.Max(value1.Right, value2.Right) - result.X;
|
||||
result.Height = Math.Max(value1.Bottom, value2.Bottom) - result.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1162
Libraries/XNATypes/Vector2.cs
Normal file
1162
Libraries/XNATypes/Vector2.cs
Normal file
File diff suppressed because it is too large
Load Diff
1373
Libraries/XNATypes/Vector3.cs
Normal file
1373
Libraries/XNATypes/Vector3.cs
Normal file
File diff suppressed because it is too large
Load Diff
1297
Libraries/XNATypes/Vector4.cs
Normal file
1297
Libraries/XNATypes/Vector4.cs
Normal file
File diff suppressed because it is too large
Load Diff
10
Libraries/XNATypes/XNATypes.csproj
Normal file
10
Libraries/XNATypes/XNATypes.csproj
Normal file
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<Authors></Authors>
|
||||
<Company />
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user