Adding Math

This commit is contained in:
Marc Hernandez 2019-06-26 00:03:48 -07:00
parent 335ca7e368
commit a2dc2bed3c
52 changed files with 31323 additions and 0 deletions

View File

@ -6,6 +6,18 @@ using System.Reflection;
namespace lib namespace lib
{ {
public class DescAttribute : Attribute
{
public string Desc { get; private set; }
public DescAttribute( string desc )
{
Desc = desc;
}
}
[Serializable] [Serializable]
public class ResRefConfig<T> : res.Ref<T> where T: Config public class ResRefConfig<T> : res.Ref<T> where T: Config
{ {

View File

@ -66,6 +66,56 @@
<Compile Include="Config.cs" /> <Compile Include="Config.cs" />
<Compile Include="Helpers.cs" /> <Compile Include="Helpers.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="math\AngleSingle.cs" />
<Compile Include="math\AngleType.cs" />
<Compile Include="math\BoundingBox.cs" />
<Compile Include="math\BoundingBoxExt.cs" />
<Compile Include="math\BoundingFrustum.cs" />
<Compile Include="math\BoundingSphere.cs" />
<Compile Include="math\CollisionHelper.cs" />
<Compile Include="math\Color.cs" />
<Compile Include="math\Color.Palette.cs" />
<Compile Include="math\Color3.cs" />
<Compile Include="math\Color4.cs" />
<Compile Include="math\ColorBGRA.cs" />
<Compile Include="math\ColorExtensions.cs" />
<Compile Include="math\ColorHSV.cs" />
<Compile Include="math\ContainmentType.cs" />
<Compile Include="math\DataStyleAttribute.cs" />
<Compile Include="math\Double2.cs" />
<Compile Include="math\Double3.cs" />
<Compile Include="math\Double4.cs" />
<Compile Include="math\GuillotinePacker.cs" />
<Compile Include="math\Half.cs" />
<Compile Include="math\Half2.cs" />
<Compile Include="math\Half3.cs" />
<Compile Include="math\Half4.cs" />
<Compile Include="math\HalfUtils.cs" />
<Compile Include="math\Int2.cs" />
<Compile Include="math\Int3.cs" />
<Compile Include="math\Int4.cs" />
<Compile Include="math\MathUtil.cs" />
<Compile Include="math\Matrix.cs" />
<Compile Include="math\Module.cs" />
<Compile Include="math\NamespaceDoc.cs" />
<Compile Include="math\Plane.cs" />
<Compile Include="math\PlaneIntersectionType.cs" />
<Compile Include="math\Point.cs" />
<Compile Include="math\Properties\AssemblyInfo.cs" />
<Compile Include="math\Quaternion.cs" />
<Compile Include="math\RandomSeed.cs" />
<Compile Include="math\Ray.cs" />
<Compile Include="math\Rectangle.cs" />
<Compile Include="math\RectangleF.cs" />
<Compile Include="math\Size2.cs" />
<Compile Include="math\Size2F.cs" />
<Compile Include="math\Size3.cs" />
<Compile Include="math\SphericalHarmonics.cs" />
<Compile Include="math\UInt4.cs" />
<Compile Include="math\Vector2.cs" />
<Compile Include="math\Vector3.cs" />
<Compile Include="math\Vector4.cs" />
<Compile Include="math\VectorExtensions.cs" />
<Compile Include="mod\Modules.cs" /> <Compile Include="mod\Modules.cs" />
<Compile Include="NetMsg.cs" /> <Compile Include="NetMsg.cs" />
<Compile Include="Pos.cs" /> <Compile Include="Pos.cs" />

779
math/AngleSingle.cs Normal file
View File

@ -0,0 +1,779 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a unit independant angle using a single-precision floating-point
/// internal representation.
/// </summary>
[DataStyle(DataStyle.Compact)]
[DataContract]
public struct AngleSingle : IComparable, IComparable<AngleSingle>, IEquatable<AngleSingle>, IFormattable
{
/// <summary>
/// A value that specifies the size of a single degree.
/// </summary>
public const float Degree = 0.002777777777777778f;
/// <summary>
/// A value that specifies the size of a single minute.
/// </summary>
public const float Minute = 0.000046296296296296f;
/// <summary>
/// A value that specifies the size of a single second.
/// </summary>
public const float Second = 0.000000771604938272f;
/// <summary>
/// A value that specifies the size of a single radian.
/// </summary>
public const float Radian = 0.159154943091895336f;
/// <summary>
/// A value that specifies the size of a single milliradian.
/// </summary>
public const float Milliradian = 0.0001591549431f;
/// <summary>
/// A value that specifies the size of a single gradian.
/// </summary>
public const float Gradian = 0.0025f;
/// <summary>
/// The internal representation of the angle.
/// </summary>
private float radians;
/// <summary>
/// Initializes a new instance of the <see cref="AngleSingle"/> struct with the
/// given unit dependant angle and unit type.
/// </summary>
/// <param name="angle">A unit dependant measure of the angle.</param>
/// <param name="type">The type of unit the angle argument is.</param>
public AngleSingle(float angle, AngleType type)
{
switch (type)
{
case AngleType.Revolution:
radians = MathUtil.RevolutionsToRadians(angle);
break;
case AngleType.Degree:
radians = MathUtil.DegreesToRadians(angle);
break;
case AngleType.Radian:
radians = angle;
break;
case AngleType.Gradian:
radians = MathUtil.GradiansToRadians(angle);
break;
default:
radians = 0.0f;
break;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="AngleSingle"/> struct using the
/// arc length formula (θ = s/r).
/// </summary>
/// <param name="arcLength">The measure of the arc.</param>
/// <param name="radius">The radius of the circle.</param>
public AngleSingle(float arcLength, float radius)
{
radians = arcLength / radius;
}
/// <summary>
/// Wraps this math.AngleSingle to be in the range [π, -π].
/// </summary>
public void Wrap()
{
float newangle = (float)Math.IEEERemainder(radians, MathUtil.TwoPi);
if (newangle <= -MathUtil.Pi)
newangle += MathUtil.TwoPi;
else if (newangle > MathUtil.Pi)
newangle -= MathUtil.TwoPi;
radians = newangle;
}
/// <summary>
/// Wraps this math.AngleSingle to be in the range [0, 2π).
/// </summary>
public void WrapPositive()
{
float newangle = radians % MathUtil.TwoPi;
if (newangle < 0.0)
newangle += MathUtil.TwoPi;
radians = newangle;
}
/// <summary>
/// Gets or sets the total number of revolutions this math.AngleSingle represents.
/// </summary>
[DataMemberIgnore]
public float Revolutions
{
get { return MathUtil.RadiansToRevolutions(radians); }
set { radians = MathUtil.RevolutionsToRadians(value); }
}
/// <summary>
/// Gets or sets the total number of degrees this math.AngleSingle represents.
/// </summary>
[DataMemberIgnore]
public float Degrees
{
get { return MathUtil.RadiansToDegrees(radians); }
set { radians = MathUtil.DegreesToRadians(value); }
}
/// <summary>
/// Gets or sets the minutes component of the degrees this math.AngleSingle represents.
/// When setting the minutes, if the value is in the range (-60, 60) the whole degrees are
/// not changed; otherwise, the whole degrees may be changed. Fractional values may set
/// the seconds component.
/// </summary>
[DataMemberIgnore]
public float Minutes
{
get
{
float degrees = MathUtil.RadiansToDegrees(radians);
if (degrees < 0)
{
float degreesfloor = (float)Math.Ceiling(degrees);
return (degrees - degreesfloor) * 60.0f;
}
else
{
float degreesfloor = (float)Math.Floor(degrees);
return (degrees - degreesfloor) * 60.0f;
}
}
set
{
float degrees = MathUtil.RadiansToDegrees(radians);
float degreesfloor = (float)Math.Floor(degrees);
degreesfloor += value / 60.0f;
radians = MathUtil.DegreesToRadians(degreesfloor);
}
}
/// <summary>
/// Gets or sets the seconds of the degrees this math.AngleSingle represents.
/// When setting te seconds, if the value is in the range (-60, 60) the whole minutes
/// or whole degrees are not changed; otherwise, the whole minutes or whole degrees
/// may be changed.
/// </summary>
[DataMemberIgnore]
public float Seconds
{
get
{
float degrees = MathUtil.RadiansToDegrees(radians);
if (degrees < 0)
{
float degreesfloor = (float)Math.Ceiling(degrees);
float minutes = (degrees - degreesfloor) * 60.0f;
float minutesfloor = (float)Math.Ceiling(minutes);
return (minutes - minutesfloor) * 60.0f;
}
else
{
float degreesfloor = (float)Math.Floor(degrees);
float minutes = (degrees - degreesfloor) * 60.0f;
float minutesfloor = (float)Math.Floor(minutes);
return (minutes - minutesfloor) * 60.0f;
}
}
set
{
float degrees = MathUtil.RadiansToDegrees(radians);
float degreesfloor = (float)Math.Floor(degrees);
float minutes = (degrees - degreesfloor) * 60.0f;
float minutesfloor = (float)Math.Floor(minutes);
minutesfloor += value / 60.0f;
degreesfloor += minutesfloor / 60.0f;
radians = MathUtil.DegreesToRadians(degreesfloor);
}
}
/// <summary>
/// Gets or sets the total number of radians this math.AngleSingle represents.
/// </summary>
public float Radians
{
get { return radians; }
set { radians = value; }
}
/// <summary>
/// Gets or sets the total number of milliradians this math.AngleSingle represents.
/// One milliradian is equal to 1/(2000π).
/// </summary>
[DataMemberIgnore]
public float Milliradians
{
get { return radians / (Milliradian * MathUtil.TwoPi); }
set { radians = value * (Milliradian * MathUtil.TwoPi); }
}
/// <summary>
/// Gets or sets the total number of gradians this math.AngleSingle represents.
/// </summary>
[DataMemberIgnore]
public float Gradians
{
get { return MathUtil.RadiansToGradians(radians); }
set { radians = MathUtil.GradiansToRadians(value); }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is a right angle (i.e. 90° or π/2).
/// </summary>
[DataMemberIgnore]
public bool IsRight
{
get { return radians == MathUtil.PiOverTwo; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is a straight angle (i.e. 180° or π).
/// </summary>
[DataMemberIgnore]
public bool IsStraight
{
get { return radians == MathUtil.Pi; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is a full rotation angle (i.e. 360° or 2π).
/// </summary>
[DataMemberIgnore]
public bool IsFullRotation
{
get { return radians == MathUtil.TwoPi; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is an oblique angle (i.e. is not 90° or a multiple of 90°).
/// </summary>
[DataMemberIgnore]
public bool IsOblique
{
get { return WrapPositive(this).radians != MathUtil.PiOverTwo; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is an acute angle (i.e. less than 90° but greater than 0°).
/// </summary>
[DataMemberIgnore]
public bool IsAcute
{
get { return radians > 0.0 && radians < MathUtil.PiOverTwo; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is an obtuse angle (i.e. greater than 90° but less than 180°).
/// </summary>
[DataMemberIgnore]
public bool IsObtuse
{
get { return radians > MathUtil.PiOverTwo && radians < MathUtil.Pi; }
}
/// <summary>
/// Gets a System.Boolean that determines whether this math.Angle
/// is a reflex angle (i.e. greater than 180° but less than 360°).
/// </summary>
[DataMemberIgnore]
public bool IsReflex
{
get { return radians > MathUtil.Pi && radians < MathUtil.TwoPi; }
}
/// <summary>
/// Gets a math.AngleSingle instance that complements this angle (i.e. the two angles add to 90°).
/// </summary>
[DataMemberIgnore]
public AngleSingle Complement
{
get { return new AngleSingle(MathUtil.PiOverTwo - radians, AngleType.Radian); }
}
/// <summary>
/// Gets a math.AngleSingle instance that supplements this angle (i.e. the two angles add to 180°).
/// </summary>
[DataMemberIgnore]
public AngleSingle Supplement
{
get { return new AngleSingle(MathUtil.Pi - radians, AngleType.Radian); }
}
/// <summary>
/// Wraps the math.AngleSingle given in the value argument to be in the range [π, -π].
/// </summary>
/// <param name="value">A math.AngleSingle to wrap.</param>
/// <returns>The math.AngleSingle that is wrapped.</returns>
public static AngleSingle Wrap(AngleSingle value)
{
value.Wrap();
return value;
}
/// <summary>
/// Wraps the math.AngleSingle given in the value argument to be in the range [0, 2π).
/// </summary>
/// <param name="value">A math.AngleSingle to wrap.</param>
/// <returns>The math.AngleSingle that is wrapped.</returns>
public static AngleSingle WrapPositive(AngleSingle value)
{
value.WrapPositive();
return value;
}
/// <summary>
/// Compares two math.AngleSingle instances and returns the smaller angle.
/// </summary>
/// <param name="left">The first math.AngleSingle instance to compare.</param>
/// <param name="right">The second math.AngleSingle instance to compare.</param>
/// <returns>The smaller of the two given math.AngleSingle instances.</returns>
public static AngleSingle Min(AngleSingle left, AngleSingle right)
{
if (left.radians < right.radians)
return left;
return right;
}
/// <summary>
/// Compares two math.AngleSingle instances and returns the greater angle.
/// </summary>
/// <param name="left">The first math.AngleSingle instance to compare.</param>
/// <param name="right">The second math.AngleSingle instance to compare.</param>
/// <returns>The greater of the two given math.AngleSingle instances.</returns>
public static AngleSingle Max(AngleSingle left, AngleSingle right)
{
if (left.radians > right.radians)
return left;
return right;
}
/// <summary>
/// Adds two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to add.</param>
/// <param name="right">The second object to add.</param>
/// <returns>The value of the two objects added together.</returns>
public static AngleSingle Add(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians + right.radians, AngleType.Radian);
}
/// <summary>
/// Subtracts two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to subtract.</param>
/// <param name="right">The second object to subtract.</param>
/// <returns>The value of the two objects subtracted.</returns>
public static AngleSingle Subtract(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians - right.radians, AngleType.Radian);
}
/// <summary>
/// Multiplies two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to multiply.</param>
/// <param name="right">The second object to multiply.</param>
/// <returns>The value of the two objects multiplied together.</returns>
public static AngleSingle Multiply(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians * right.radians, AngleType.Radian);
}
/// <summary>
/// Divides two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The numerator object.</param>
/// <param name="right">The denominator object.</param>
/// <returns>The value of the two objects divided.</returns>
public static AngleSingle Divide(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians / right.radians, AngleType.Radian);
}
/// <summary>
/// Gets a new math.AngleSingle instance that represents the zero angle (i.e. 0°).
/// </summary>
public static AngleSingle ZeroAngle
{
get { return new AngleSingle(0.0f, AngleType.Radian); }
}
/// <summary>
/// Gets a new math.AngleSingle instance that represents the right angle (i.e. 90° or π/2).
/// </summary>
public static AngleSingle RightAngle
{
get { return new AngleSingle(MathUtil.PiOverTwo, AngleType.Radian); }
}
/// <summary>
/// Gets a new math.AngleSingle instance that represents the straight angle (i.e. 180° or π).
/// </summary>
public static AngleSingle StraightAngle
{
get { return new AngleSingle(MathUtil.Pi, AngleType.Radian); }
}
/// <summary>
/// Gets a new math.AngleSingle instance that represents the full rotation angle (i.e. 360° or 2π).
/// </summary>
public static AngleSingle FullRotationAngle
{
get { return new AngleSingle(MathUtil.TwoPi, AngleType.Radian); }
}
/// <summary>
/// Returns a System.Boolean that indicates whether the values of two math.Angle
/// objects are equal.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if the left and right parameters have the same value; otherwise, false.</returns>
public static bool operator ==(AngleSingle left, AngleSingle right)
{
return left.radians == right.radians;
}
/// <summary>
/// Returns a System.Boolean that indicates whether the values of two math.Angle
/// objects are not equal.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if the left and right parameters do not have the same value; otherwise, false.</returns>
public static bool operator !=(AngleSingle left, AngleSingle right)
{
return left.radians != right.radians;
}
/// <summary>
/// Returns a System.Boolean that indicates whether a math.Angle
/// object is less than another math.AngleSingle object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if left is less than right; otherwise, false.</returns>
public static bool operator <(AngleSingle left, AngleSingle right)
{
return left.radians < right.radians;
}
/// <summary>
/// Returns a System.Boolean that indicates whether a math.Angle
/// object is greater than another math.AngleSingle object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if left is greater than right; otherwise, false.</returns>
public static bool operator >(AngleSingle left, AngleSingle right)
{
return left.radians > right.radians;
}
/// <summary>
/// Returns a System.Boolean that indicates whether a math.Angle
/// object is less than or equal to another math.AngleSingle object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if left is less than or equal to right; otherwise, false.</returns>
public static bool operator <=(AngleSingle left, AngleSingle right)
{
return left.radians <= right.radians;
}
/// <summary>
/// Returns a System.Boolean that indicates whether a math.Angle
/// object is greater than or equal to another math.AngleSingle object.
/// </summary>
/// <param name="left">The first object to compare.</param>
/// <param name="right">The second object to compare.</param>
/// <returns>True if left is greater than or equal to right; otherwise, false.</returns>
public static bool operator >=(AngleSingle left, AngleSingle right)
{
return left.radians >= right.radians;
}
/// <summary>
/// Returns the value of the math.AngleSingle operand. (The sign of
/// the operand is unchanged.)
/// </summary>
/// <param name="value">A math.AngleSingle object.</param>
/// <returns>The value of the value parameter.</returns>
public static AngleSingle operator +(AngleSingle value)
{
return value;
}
/// <summary>
/// Returns the the negated value of the math.AngleSingle operand.
/// </summary>
/// <param name="value">A math.AngleSingle object.</param>
/// <returns>The negated value of the value parameter.</returns>
public static AngleSingle operator -(AngleSingle value)
{
return new AngleSingle(-value.radians, AngleType.Radian);
}
/// <summary>
/// Adds two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to add.</param>
/// <param name="right">The second object to add.</param>
/// <returns>The value of the two objects added together.</returns>
public static AngleSingle operator +(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians + right.radians, AngleType.Radian);
}
/// <summary>
/// Subtracts two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to subtract</param>
/// <param name="right">The second object to subtract.</param>
/// <returns>The value of the two objects subtracted.</returns>
public static AngleSingle operator -(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians - right.radians, AngleType.Radian);
}
/// <summary>
/// Multiplies two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The first object to multiply.</param>
/// <param name="right">The second object to multiply.</param>
/// <returns>The value of the two objects multiplied together.</returns>
public static AngleSingle operator *(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians * right.radians, AngleType.Radian);
}
/// <summary>
/// Divides two math.AngleSingle objects and returns the result.
/// </summary>
/// <param name="left">The numerator object.</param>
/// <param name="right">The denominator object.</param>
/// <returns>The value of the two objects divided.</returns>
public static AngleSingle operator /(AngleSingle left, AngleSingle right)
{
return new AngleSingle(left.radians / right.radians, AngleType.Radian);
}
/// <summary>
/// Compares this instance to a specified object and returns an integer that
/// indicates whether the value of this instance is less than, equal to, or greater
/// than the value of the specified object.
/// </summary>
/// <param name="other">The object to compare.</param>
/// <returns>
/// A signed integer that indicates the relationship of the current instance
/// to the obj parameter. If the value is less than zero, the current instance
/// is less than the other. If the value is zero, the current instance is equal
/// to the other. If the value is greater than zero, the current instance is
/// greater than the other.
/// </returns>
public int CompareTo(object other)
{
if (other == null)
return 1;
if (!(other is AngleSingle))
throw new ArgumentException("Argument must be of type Angle.", "other");
float radians = ((AngleSingle)other).radians;
if (this.radians > radians)
return 1;
if (this.radians < radians)
return -1;
return 0;
}
/// <summary>
/// Compares this instance to a second math.AngleSingle and returns
/// an integer that indicates whether the value of this instance is less than,
/// equal to, or greater than the value of the specified object.
/// </summary>
/// <param name="other">The object to compare.</param>
/// <returns>
/// A signed integer that indicates the relationship of the current instance
/// to the obj parameter. If the value is less than zero, the current instance
/// is less than the other. If the value is zero, the current instance is equal
/// to the other. If the value is greater than zero, the current instance is
/// greater than the other.
/// </returns>
public int CompareTo(AngleSingle other)
{
if (this.radians > other.radians)
return 1;
if (this.radians < other.radians)
return -1;
return 0;
}
/// <summary>
/// Returns a value that indicates whether the current instance and a specified
/// math.AngleSingle object have the same value.
/// </summary>
/// <param name="other">The object to compare.</param>
/// <returns>
/// Returns true if this math.AngleSingle object and another have the same value;
/// otherwise, false.
/// </returns>
public bool Equals(AngleSingle other)
{
return this == other;
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, MathUtil.RadiansToDegrees(radians).ToString("0.##°"));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, MathUtil.RadiansToDegrees(radians).ToString("0.##°"));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a hash code for this math.AngleSingle instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return (int)(BitConverter.DoubleToInt64Bits(radians) % int.MaxValue);
}
/// <summary>
/// Returns a value that indicates whether the current instance and a specified
/// object have the same value.
/// </summary>
/// <param name="obj">The object to compare.</param>
/// <returns>
/// Returns true if the obj parameter is a math.AngleSingle object or a type
/// capable of implicit conversion to a math.AngleSingle value, and
/// its value is equal to the value of the current math.Angle
/// object; otherwise, false.
/// </returns>
public override bool Equals(object obj)
{
return (obj is AngleSingle) && (this == (AngleSingle)obj);
}
}
}

56
math/AngleType.cs Normal file
View File

@ -0,0 +1,56 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace math
{
/// <summary>
/// Describes the type of angle.
/// </summary>
public enum AngleType
{
/// <summary>
/// Specifies an angle measurement in revolutions.
/// </summary>
Revolution,
/// <summary>
/// Specifies an angle measurement in degrees.
/// </summary>
Degree,
/// <summary>
/// Specifies an angle measurement in radians.
/// </summary>
Radian,
/// <summary>
/// Specifies an angle measurement in gradians.
/// </summary>
Gradian,
}
}

466
math/BoundingBox.cs Normal file
View File

@ -0,0 +1,466 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents an axis-aligned bounding box in three dimensional space.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct BoundingBox : IEquatable<BoundingBox>, IFormattable
{
/// <summary>
/// A <see cref="BoundingBox"/> which represents an empty space.
/// </summary>
public static readonly BoundingBox Empty = new BoundingBox(new Vector3(float.MaxValue), new Vector3(float.MinValue));
/// <summary>
/// The minimum point of the box.
/// </summary>
public Vector3 Minimum;
/// <summary>
/// The maximum point of the box.
/// </summary>
public Vector3 Maximum;
/// <summary>
/// Initializes a new instance of the <see cref="math.BoundingBox"/> struct.
/// </summary>
/// <param name="minimum">The minimum vertex of the bounding box.</param>
/// <param name="maximum">The maximum vertex of the bounding box.</param>
public BoundingBox(Vector3 minimum, Vector3 maximum)
{
this.Minimum = minimum;
this.Maximum = maximum;
}
/// <summary>
/// Gets the center of this bouding box.
/// </summary>
public Vector3 Center
{
get { return (Minimum + Maximum) / 2; }
}
/// <summary>
/// Gets the extent of this bouding box.
/// </summary>
public Vector3 Extent
{
get { return (Maximum - Minimum) / 2; }
}
/// <summary>
/// Retrieves the eight corners of the bounding box.
/// </summary>
/// <returns>An array of points representing the eight corners of the bounding box.</returns>
public Vector3[] GetCorners()
{
Vector3[] results = new Vector3[8];
results[0] = new Vector3(Minimum.X, Maximum.Y, Maximum.Z);
results[1] = new Vector3(Maximum.X, Maximum.Y, Maximum.Z);
results[2] = new Vector3(Maximum.X, Minimum.Y, Maximum.Z);
results[3] = new Vector3(Minimum.X, Minimum.Y, Maximum.Z);
results[4] = new Vector3(Minimum.X, Maximum.Y, Minimum.Z);
results[5] = new Vector3(Maximum.X, Maximum.Y, Minimum.Z);
results[6] = new Vector3(Maximum.X, Minimum.Y, Minimum.Z);
results[7] = new Vector3(Minimum.X, Minimum.Y, Minimum.Z);
return results;
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray)
{
float distance;
return CollisionHelper.RayIntersectsBox(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out float distance)
{
return CollisionHelper.RayIntersectsBox(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out Vector3 point)
{
return CollisionHelper.RayIntersectsBox(ref ray, ref this, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref Plane plane)
{
return CollisionHelper.PlaneIntersectsBox(ref plane, ref this);
}
/* This implentation is wrong
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triagnle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
return Collision.BoxIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
}
*/
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingBox box)
{
return CollisionHelper.BoxIntersectsBox(ref this, ref box);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingSphere sphere)
{
return CollisionHelper.BoxIntersectsSphere(ref this, ref sphere);
}
/// <summary>
/// Determines whether the current objects contains a point.
/// </summary>
/// <param name="point">The point to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref Vector3 point)
{
return CollisionHelper.BoxContainsPoint(ref this, ref point);
}
/* This implentation is wrong
/// <summary>
/// Determines whether the current objects contains a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triagnle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
return Collision.BoxContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
}
*/
/// <summary>
/// Determines whether the current objects contains a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref BoundingBox box)
{
return CollisionHelper.BoxContainsBox(ref this, ref box);
}
/// <summary>
/// Determines whether the current objects contains a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref BoundingSphere sphere)
{
return CollisionHelper.BoxContainsSphere(ref this, ref sphere);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> that fully contains the given points.
/// </summary>
/// <param name="points">The points that will be contained by the box.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding box.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="points"/> is <c>null</c>.</exception>
public static void FromPoints(Vector3[] points, out BoundingBox result)
{
if (points == null)
throw new ArgumentNullException("points");
Vector3 min = new Vector3(float.MaxValue);
Vector3 max = new Vector3(float.MinValue);
for (int i = 0; i < points.Length; ++i)
{
Vector3.Min(ref min, ref points[i], out min);
Vector3.Max(ref max, ref points[i], out max);
}
result = new BoundingBox(min, max);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> that fully contains the given points.
/// </summary>
/// <param name="points">The points that will be contained by the box.</param>
/// <returns>The newly constructed bounding box.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="points"/> is <c>null</c>.</exception>
public static BoundingBox FromPoints(Vector3[] points)
{
if (points == null)
throw new ArgumentNullException("points");
Vector3 min = new Vector3(float.MaxValue);
Vector3 max = new Vector3(float.MinValue);
for (int i = 0; i < points.Length; ++i)
{
Vector3.Min(ref min, ref points[i], out min);
Vector3.Max(ref max, ref points[i], out max);
}
return new BoundingBox(min, max);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> from a given sphere.
/// </summary>
/// <param name="sphere">The sphere that will designate the extents of the box.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding box.</param>
public static void FromSphere(ref BoundingSphere sphere, out BoundingBox result)
{
result.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius);
result.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> from a given sphere.
/// </summary>
/// <param name="sphere">The sphere that will designate the extents of the box.</param>
/// <returns>The newly constructed bounding box.</returns>
public static BoundingBox FromSphere(BoundingSphere sphere)
{
BoundingBox box;
box.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius);
box.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius);
return box;
}
/// <summary>
/// Transform a bounding box.
/// </summary>
/// <param name="value">The original bounding box.</param>
/// <param name="transform">The transform to apply to the bounding box.</param>
/// <param name="result">The transformed bounding box.</param>
public static void Transform(ref BoundingBox value, ref Matrix transform, out BoundingBox result)
{
var boundingBox = new BoundingBoxExt(value);
boundingBox.Transform(transform);
result = (BoundingBox)boundingBox;
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> that is as large enough to contains the bounding box and the given point.
/// </summary>
/// <param name="value1">The box to merge.</param>
/// <param name="value2">The point to merge.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding box.</param>
public static void Merge(ref BoundingBox value1, ref Vector3 value2, out BoundingBox result)
{
Vector3.Min(ref value1.Minimum, ref value2, out result.Minimum);
Vector3.Max(ref value1.Maximum, ref value2, out result.Maximum);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> that is as large as the total combined area of the two specified boxes.
/// </summary>
/// <param name="value1">The first box to merge.</param>
/// <param name="value2">The second box to merge.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding box.</param>
public static void Merge(ref BoundingBox value1, ref BoundingBox value2, out BoundingBox result)
{
Vector3.Min(ref value1.Minimum, ref value2.Minimum, out result.Minimum);
Vector3.Max(ref value1.Maximum, ref value2.Maximum, out result.Maximum);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBox"/> that is as large as the total combined area of the two specified boxes.
/// </summary>
/// <param name="value1">The first box to merge.</param>
/// <param name="value2">The second box to merge.</param>
/// <returns>The newly constructed bounding box.</returns>
public static BoundingBox Merge(BoundingBox value1, BoundingBox value2)
{
BoundingBox box;
Vector3.Min(ref value1.Minimum, ref value2.Minimum, out box.Minimum);
Vector3.Max(ref value1.Maximum, ref value2.Maximum, out box.Maximum);
return box;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(BoundingBox left, BoundingBox right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(BoundingBox left, BoundingBox right)
{
return !left.Equals(right);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, CultureInfo.CurrentCulture),
Maximum.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, formatProvider),
Maximum.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return Minimum.GetHashCode() + Maximum.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="math.Vector4"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="math.Vector4"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="math.Vector4"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(BoundingBox value)
{
return Minimum == value.Minimum && Maximum == value.Maximum;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((BoundingBox)value);
}
}
}

186
math/BoundingBoxExt.cs Normal file
View File

@ -0,0 +1,186 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents an axis-aligned bounding box in three dimensional space that store only the Center and Extent.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct BoundingBoxExt : IEquatable<BoundingBoxExt>
{
/// <summary>
/// A <see cref="BoundingBoxExt"/> which represents an empty space.
/// </summary>
public static readonly BoundingBoxExt Empty = new BoundingBoxExt(BoundingBox.Empty);
/// <summary>
/// The center of this bounding box.
/// </summary>
public Vector3 Center;
/// <summary>
/// The extent of this bounding box.
/// </summary>
public Vector3 Extent;
/// <summary>
/// Initializes a new instance of the <see cref="math.BoundingBoxExt" /> struct.
/// </summary>
/// <param name="box">The box.</param>
public BoundingBoxExt(BoundingBox box)
{
this.Center = box.Center;
this.Extent = box.Extent;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.BoundingBoxExt"/> struct.
/// </summary>
/// <param name="minimum">The minimum vertex of the bounding box.</param>
/// <param name="maximum">The maximum vertex of the bounding box.</param>
public BoundingBoxExt(Vector3 minimum, Vector3 maximum)
{
this.Center = (minimum + maximum) / 2;
this.Extent = (maximum - minimum) / 2;
}
/// <summary>
/// Gets the minimum.
/// </summary>
/// <value>The minimum.</value>
public Vector3 Minimum
{
get
{
return Center - Extent;
}
}
/// <summary>
/// Gets the maximum.
/// </summary>
/// <value>The maximum.</value>
public Vector3 Maximum
{
get
{
return Center + Extent;
}
}
/// <summary>
/// Transform this Bounding box
/// </summary>
/// <param name="world">The transform to apply to the bounding box.</param>
public void Transform(Matrix world)
{
// http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
// Compute transformed AABB (by world)
var center = Center;
var extent = Extent;
Vector3.TransformCoordinate(ref center, ref world, out Center);
// Update world matrix into absolute form
unsafe
{
// Perform an abs on the matrix
var matrixData = (float*)&world;
for (int j = 0; j < 16; ++j)
{
//*matrixData &= 0x7FFFFFFF;
*matrixData = Math.Abs(*matrixData);
++matrixData;
}
}
Vector3.TransformNormal(ref extent, ref world, out Extent);
}
/// <summary>
/// Constructs a <see cref="math.BoundingBoxExt"/> that is as large as the total combined area of the two specified boxes.
/// </summary>
/// <param name="value1">The first box to merge.</param>
/// <param name="value2">The second box to merge.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding box.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Merge(ref BoundingBoxExt value1, ref BoundingBoxExt value2, out BoundingBoxExt result)
{
var maximum = Vector3.Max(value1.Maximum, value2.Maximum);
var minimum = Vector3.Min(value1.Minimum, value2.Minimum);
result.Center = (minimum + maximum) / 2;
result.Extent = (maximum - minimum) / 2;
}
/// <inheritdoc/>
public bool Equals(BoundingBoxExt other)
{
return Center.Equals(other.Center) && Extent.Equals(other.Extent);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is BoundingBoxExt && Equals((BoundingBoxExt)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (Center.GetHashCode() * 397) ^ Extent.GetHashCode();
}
}
/// <summary>
/// Implements the ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(BoundingBoxExt left, BoundingBoxExt right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(BoundingBoxExt left, BoundingBoxExt right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref="BoundingBoxExt"/> to <see cref="BoundingBox"/>.
/// </summary>
/// <param name="bbExt">The bb ext.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator BoundingBox(BoundingBoxExt bbExt)
{
return new BoundingBox(bbExt.Minimum, bbExt.Maximum);
}
/// <summary>
/// Performs an explicit conversion from <see cref="BoundingBox"/> to <see cref="BoundingBoxExt"/>.
/// </summary>
/// <param name="boundingBox">The bounding box.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator BoundingBoxExt(BoundingBox boundingBox)
{
return new BoundingBoxExt(boundingBox);
}
}
}

103
math/BoundingFrustum.cs Normal file
View File

@ -0,0 +1,103 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Runtime.CompilerServices;
namespace math
{
/// <summary>
/// A bounding frustum.
/// </summary>
public struct BoundingFrustum
{
/// <summary>
/// The left plane of this frustum.
/// </summary>
public Plane LeftPlane;
/// <summary>
/// The right plane of this frustum.
/// </summary>
public Plane RightPlane;
/// <summary>
/// The top plane of this frustum.
/// </summary>
public Plane TopPlane;
/// <summary>
/// The bottom plane of this frustum.
/// </summary>
public Plane BottomPlane;
/// <summary>
/// The near plane of this frustum.
/// </summary>
public Plane NearPlane;
/// <summary>
/// The far plane of this frustum.
/// </summary>
public Plane FarPlane;
/// <summary>
/// Initializes a new instance of the <see cref="BoundingFrustum"/> struct from a matrix view-projection.
/// </summary>
/// <param name="matrix">The matrix view projection.</param>
public BoundingFrustum(ref Matrix matrix)
{
// Left
LeftPlane = Plane.Normalize(new Plane(
matrix.M14 + matrix.M11,
matrix.M24 + matrix.M21,
matrix.M34 + matrix.M31,
matrix.M44 + matrix.M41));
// Right
RightPlane = Plane.Normalize(new Plane(
matrix.M14 - matrix.M11,
matrix.M24 - matrix.M21,
matrix.M34 - matrix.M31,
matrix.M44 - matrix.M41));
// Top
TopPlane = Plane.Normalize(new Plane(
matrix.M14 - matrix.M12,
matrix.M24 - matrix.M22,
matrix.M34 - matrix.M32,
matrix.M44 - matrix.M42));
// Bottom
BottomPlane = Plane.Normalize(new Plane(
matrix.M14 + matrix.M12,
matrix.M24 + matrix.M22,
matrix.M34 + matrix.M32,
matrix.M44 + matrix.M42));
// Near
NearPlane = Plane.Normalize(new Plane(
matrix.M13,
matrix.M23,
matrix.M33,
matrix.M43));
// Far
FarPlane = Plane.Normalize(new Plane(
matrix.M14 - matrix.M13,
matrix.M24 - matrix.M23,
matrix.M34 - matrix.M33,
matrix.M44 - matrix.M43));
}
/// <summary>
/// Check whether this frustum contains the specified <see cref="BoundingBoxExt"/>.
/// </summary>
/// <param name="boundingBoxExt">The bounding box.</param>
/// <returns><c>true</c> if this frustum contains the specified bounding box.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(ref BoundingBoxExt boundingBoxExt)
{
return CollisionHelper.FrustumContainsBox(ref this, ref boundingBoxExt);
}
}
}

539
math/BoundingSphere.cs Normal file
View File

@ -0,0 +1,539 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a bounding sphere in three dimensional space.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct BoundingSphere : IEquatable<BoundingSphere>, IFormattable
{
/// <summary>
/// An empty bounding sphere (Center = 0 and Radius = 0).
/// </summary>
public static readonly BoundingSphere Empty = new BoundingSphere();
/// <summary>
/// The center of the sphere in three dimensional space.
/// </summary>
public Vector3 Center;
/// <summary>
/// The radious of the sphere.
/// </summary>
public float Radius;
/// <summary>
/// Initializes a new instance of the <see cref="BoundingSphere"/> struct.
/// </summary>
/// <param name="center">The center of the sphere in three dimensional space.</param>
/// <param name="radius">The radius of the sphere.</param>
public BoundingSphere(Vector3 center, float radius)
{
this.Center = center;
this.Radius = radius;
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray)
{
float distance;
return CollisionHelper.RayIntersectsSphere(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out float distance)
{
return CollisionHelper.RayIntersectsSphere(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out Vector3 point)
{
return CollisionHelper.RayIntersectsSphere(ref ray, ref this, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref Plane plane)
{
return CollisionHelper.PlaneIntersectsSphere(ref plane, ref this);
}
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triagnle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
return CollisionHelper.SphereIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingBox box)
{
return CollisionHelper.BoxIntersectsSphere(ref box, ref this);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingSphere sphere)
{
return CollisionHelper.SphereIntersectsSphere(ref this, ref sphere);
}
/// <summary>
/// Determines whether the current objects contains a point.
/// </summary>
/// <param name="point">The point to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref Vector3 point)
{
return CollisionHelper.SphereContainsPoint(ref this, ref point);
}
/// <summary>
/// Determines whether the current objects contains a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triagnle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
return CollisionHelper.SphereContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
}
/// <summary>
/// Determines whether the current objects contains a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref BoundingBox box)
{
return CollisionHelper.SphereContainsBox(ref this, ref box);
}
/// <summary>
/// Determines whether the current objects contains a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>The type of containment the two objects have.</returns>
public ContainmentType Contains(ref BoundingSphere sphere)
{
return CollisionHelper.SphereContainsSphere(ref this, ref sphere);
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> that fully contains the given points.
/// </summary>
/// <param name="points">The points that will be contained by the sphere.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
public static unsafe void FromPoints(Vector3[] points, out BoundingSphere result)
{
if (points == null) throw new ArgumentNullException("points");
fixed (void* pointsPtr = points)
{
FromPoints((IntPtr)pointsPtr, 0, points.Length, Utilities.SizeOf<Vector3>(), out result);
}
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere" /> that fully contains the given unmanaged points.
/// </summary>
/// <param name="vertexBufferPtr">A pointer to of vertices containing points.</param>
/// <param name="vertexPositionOffsetInBytes">The point offset in bytes starting from the vertex structure.</param>
/// <param name="vertexCount">The verterx vertexCount.</param>
/// <param name="vertexStride">The vertex stride (size of vertex).</param>
/// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
public static unsafe void FromPoints(IntPtr vertexBufferPtr, int vertexPositionOffsetInBytes, int vertexCount, int vertexStride, out BoundingSphere result)
{
if (vertexBufferPtr == IntPtr.Zero)
{
throw new ArgumentNullException("vertexBufferPtr");
}
var startPoint = (byte*)vertexBufferPtr + vertexPositionOffsetInBytes;
//Find the center of all points.
Vector3 center = Vector3.Zero;
var nextPoint = startPoint;
for (int i = 0; i < vertexCount; ++i)
{
Vector3.Add(ref *(Vector3*)nextPoint, ref center, out center);
nextPoint += vertexStride;
}
//This is the center of our sphere.
center /= (float)vertexCount;
//Find the radius of the sphere
float radius = 0f;
nextPoint = startPoint;
for (int i = 0; i < vertexCount; ++i)
{
//We are doing a relative distance comparasin to find the maximum distance
//from the center of our sphere.
float distance;
Vector3.DistanceSquared(ref center, ref *(Vector3*)nextPoint, out distance);
if (distance > radius)
radius = distance;
nextPoint += vertexStride;
}
//Find the real distance from the DistanceSquared.
radius = (float)Math.Sqrt(radius);
//Construct the sphere.
result.Center = center;
result.Radius = radius;
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> that fully contains the given points.
/// </summary>
/// <param name="points">The points that will be contained by the sphere.</param>
/// <returns>The newly constructed bounding sphere.</returns>
public static BoundingSphere FromPoints(Vector3[] points)
{
BoundingSphere result;
FromPoints(points, out result);
return result;
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> from a given box.
/// </summary>
/// <param name="box">The box that will designate the extents of the sphere.</param>
/// <param name="result">When the method completes, the newly constructed bounding sphere.</param>
public static void FromBox(ref BoundingBox box, out BoundingSphere result)
{
Vector3.Lerp(ref box.Minimum, ref box.Maximum, 0.5f, out result.Center);
float x = box.Minimum.X - box.Maximum.X;
float y = box.Minimum.Y - box.Maximum.Y;
float z = box.Minimum.Z - box.Maximum.Z;
float distance = (float)(Math.Sqrt((x * x) + (y * y) + (z * z)));
result.Radius = distance * 0.5f;
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> from a given box.
/// </summary>
/// <param name="box">The box that will designate the extents of the sphere.</param>
/// <returns>The newly constructed bounding sphere.</returns>
public static BoundingSphere FromBox(BoundingBox box)
{
BoundingSphere result;
FromBox(ref box, out result);
return result;
}
/// <summary>
/// Transforms a bounding bounding sphere, yielding the bounding sphere of all points contained by the original one, transformed by the specified transform.
/// </summary>
/// <param name="value">The original bounding sphere.</param>
/// <param name="transform">The transform to apply to the bounding sphere.</param>
/// <param name="result">The transformed bounding sphere.</param>
public static void Transform(ref BoundingSphere value, ref Matrix transform, out BoundingSphere result)
{
Vector3.TransformCoordinate(ref value.Center, ref transform, out result.Center);
var majorAxisLengthSquared = Math.Max(
(transform.M11 * transform.M11) + (transform.M12 * transform.M12) + (transform.M13 * transform.M13), Math.Max(
(transform.M21 * transform.M21) + (transform.M22 * transform.M22) + (transform.M23 * transform.M23),
(transform.M31 * transform.M31) + (transform.M32 * transform.M32) + (transform.M33 * transform.M33)));
result.Radius = value.Radius * (float)Math.Sqrt(majorAxisLengthSquared);
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> that is the as large as the total combined area of the two specified spheres.
/// </summary>
/// <param name="value1">The first sphere to merge.</param>
/// <param name="value2">The second sphere to merge.</param>
/// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
public static void Merge(ref BoundingSphere value1, ref BoundingSphere value2, out BoundingSphere result)
{
// Pre-exit if one of the bounding sphere by assuming that a merge with an empty sphere is equivalent at taking the non-empty sphere
if (value1 == Empty)
{
result = value2;
return;
}
if (value2 == Empty)
{
result = value1;
return;
}
Vector3 difference = value2.Center - value1.Center;
float length = difference.Length();
float radius = value1.Radius;
float radius2 = value2.Radius;
if (radius + radius2 >= length)
{
if (radius - radius2 >= length)
{
result = value1;
return;
}
if (radius2 - radius >= length)
{
result = value2;
return;
}
}
Vector3 vector = difference * (1.0f / length);
float min = Math.Min(-radius, length - radius2);
float max = (Math.Max(radius, length + radius2) - min) * 0.5f;
result.Center = value1.Center + vector * (max + min);
result.Radius = max;
}
/// <summary>
/// Constructs a <see cref="math.BoundingSphere"/> that is the as large as the total combined area of the two specified spheres.
/// </summary>
/// <param name="value1">The first sphere to merge.</param>
/// <param name="value2">The second sphere to merge.</param>
/// <returns>The newly constructed bounding sphere.</returns>
public static BoundingSphere Merge(BoundingSphere value1, BoundingSphere value2)
{
BoundingSphere result;
Merge(ref value1, ref value2, out result);
return result;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(BoundingSphere left, BoundingSphere right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(BoundingSphere left, BoundingSphere right)
{
return !left.Equals(right);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(format, CultureInfo.CurrentCulture),
Radius.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(format, formatProvider),
Radius.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return Center.GetHashCode() + Radius.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="math.Vector4"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="math.Vector4"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="math.Vector4"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(BoundingSphere value)
{
return Center == value.Center && Radius == value.Radius;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((BoundingSphere)value);
}
#if SlimDX1xInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.BoundingSphere"/> to <see cref="SlimDX.BoundingSphere"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SlimDX.BoundingSphere(BoundingSphere value)
{
return new SlimDX.BoundingSphere(value.Center, value.Radius);
}
/// <summary>
/// Performs an implicit conversion from <see cref="SlimDX.BoundingSphere"/> to <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator BoundingSphere(SlimDX.BoundingSphere value)
{
return new BoundingSphere(value.Center, value.Radius);
}
#endif
#if SlimDX1xInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.BoundingSphere"/> to <see cref="Microsoft.Xna.Framework.BoundingSphere"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Microsoft.Xna.Framework.BoundingSphere(BoundingSphere value)
{
return new Microsoft.Xna.Framework.BoundingSphere(value.Center, value.Radius);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.BoundingSphere"/> to <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator BoundingSphere(Microsoft.Xna.Framework.BoundingSphere value)
{
return new BoundingSphere(value.Center, value.Radius);
}
#endif
}
}

1551
math/CollisionHelper.cs Normal file

File diff suppressed because it is too large Load Diff

725
math/Color.Palette.cs Normal file
View File

@ -0,0 +1,725 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
namespace math
{
/// <summary>
/// List of predefined <see cref="Color" />.
/// </summary>
public partial struct Color
{
/// <summary>
/// Zero color.
/// </summary>
public static readonly Color Zero = Color.FromBgra(0x00000000);
/// <summary>
/// Transparent color.
/// </summary>
public static readonly Color Transparent = Color.FromBgra(0x00000000);
/// <summary>
/// AliceBlue color.
/// </summary>
public static readonly Color AliceBlue = Color.FromBgra(0xFFF0F8FF);
/// <summary>
/// AntiqueWhite color.
/// </summary>
public static readonly Color AntiqueWhite = Color.FromBgra(0xFFFAEBD7);
/// <summary>
/// Aqua color.
/// </summary>
public static readonly Color Aqua = Color.FromBgra(0xFF00FFFF);
/// <summary>
/// Aquamarine color.
/// </summary>
public static readonly Color Aquamarine = Color.FromBgra(0xFF7FFFD4);
/// <summary>
/// Azure color.
/// </summary>
public static readonly Color Azure = Color.FromBgra(0xFFF0FFFF);
/// <summary>
/// Beige color.
/// </summary>
public static readonly Color Beige = Color.FromBgra(0xFFF5F5DC);
/// <summary>
/// Bisque color.
/// </summary>
public static readonly Color Bisque = Color.FromBgra(0xFFFFE4C4);
/// <summary>
/// Black color.
/// </summary>
public static readonly Color Black = Color.FromBgra(0xFF000000);
/// <summary>
/// BlanchedAlmond color.
/// </summary>
public static readonly Color BlanchedAlmond = Color.FromBgra(0xFFFFEBCD);
/// <summary>
/// Blue color.
/// </summary>
public static readonly Color Blue = Color.FromBgra(0xFF0000FF);
/// <summary>
/// BlueViolet color.
/// </summary>
public static readonly Color BlueViolet = Color.FromBgra(0xFF8A2BE2);
/// <summary>
/// Brown color.
/// </summary>
public static readonly Color Brown = Color.FromBgra(0xFFA52A2A);
/// <summary>
/// BurlyWood color.
/// </summary>
public static readonly Color BurlyWood = Color.FromBgra(0xFFDEB887);
/// <summary>
/// CadetBlue color.
/// </summary>
public static readonly Color CadetBlue = Color.FromBgra(0xFF5F9EA0);
/// <summary>
/// Chartreuse color.
/// </summary>
public static readonly Color Chartreuse = Color.FromBgra(0xFF7FFF00);
/// <summary>
/// Chocolate color.
/// </summary>
public static readonly Color Chocolate = Color.FromBgra(0xFFD2691E);
/// <summary>
/// Coral color.
/// </summary>
public static readonly Color Coral = Color.FromBgra(0xFFFF7F50);
/// <summary>
/// CornflowerBlue color.
/// </summary>
public static readonly Color CornflowerBlue = Color.FromBgra(0xFF6495ED);
/// <summary>
/// Cornsilk color.
/// </summary>
public static readonly Color Cornsilk = Color.FromBgra(0xFFFFF8DC);
/// <summary>
/// Crimson color.
/// </summary>
public static readonly Color Crimson = Color.FromBgra(0xFFDC143C);
/// <summary>
/// Cyan color.
/// </summary>
public static readonly Color Cyan = Color.FromBgra(0xFF00FFFF);
/// <summary>
/// DarkBlue color.
/// </summary>
public static readonly Color DarkBlue = Color.FromBgra(0xFF00008B);
/// <summary>
/// DarkCyan color.
/// </summary>
public static readonly Color DarkCyan = Color.FromBgra(0xFF008B8B);
/// <summary>
/// DarkGoldenrod color.
/// </summary>
public static readonly Color DarkGoldenrod = Color.FromBgra(0xFFB8860B);
/// <summary>
/// DarkGray color.
/// </summary>
public static readonly Color DarkGray = Color.FromBgra(0xFFA9A9A9);
/// <summary>
/// DarkGreen color.
/// </summary>
public static readonly Color DarkGreen = Color.FromBgra(0xFF006400);
/// <summary>
/// DarkKhaki color.
/// </summary>
public static readonly Color DarkKhaki = Color.FromBgra(0xFFBDB76B);
/// <summary>
/// DarkMagenta color.
/// </summary>
public static readonly Color DarkMagenta = Color.FromBgra(0xFF8B008B);
/// <summary>
/// DarkOliveGreen color.
/// </summary>
public static readonly Color DarkOliveGreen = Color.FromBgra(0xFF556B2F);
/// <summary>
/// DarkOrange color.
/// </summary>
public static readonly Color DarkOrange = Color.FromBgra(0xFFFF8C00);
/// <summary>
/// DarkOrchid color.
/// </summary>
public static readonly Color DarkOrchid = Color.FromBgra(0xFF9932CC);
/// <summary>
/// DarkRed color.
/// </summary>
public static readonly Color DarkRed = Color.FromBgra(0xFF8B0000);
/// <summary>
/// DarkSalmon color.
/// </summary>
public static readonly Color DarkSalmon = Color.FromBgra(0xFFE9967A);
/// <summary>
/// DarkSeaGreen color.
/// </summary>
public static readonly Color DarkSeaGreen = Color.FromBgra(0xFF8FBC8B);
/// <summary>
/// DarkSlateBlue color.
/// </summary>
public static readonly Color DarkSlateBlue = Color.FromBgra(0xFF483D8B);
/// <summary>
/// DarkSlateGray color.
/// </summary>
public static readonly Color DarkSlateGray = Color.FromBgra(0xFF2F4F4F);
/// <summary>
/// DarkTurquoise color.
/// </summary>
public static readonly Color DarkTurquoise = Color.FromBgra(0xFF00CED1);
/// <summary>
/// DarkViolet color.
/// </summary>
public static readonly Color DarkViolet = Color.FromBgra(0xFF9400D3);
/// <summary>
/// DeepPink color.
/// </summary>
public static readonly Color DeepPink = Color.FromBgra(0xFFFF1493);
/// <summary>
/// DeepSkyBlue color.
/// </summary>
public static readonly Color DeepSkyBlue = Color.FromBgra(0xFF00BFFF);
/// <summary>
/// DimGray color.
/// </summary>
public static readonly Color DimGray = Color.FromBgra(0xFF696969);
/// <summary>
/// VeryDimGray color.
/// </summary>
public static readonly Color VeryDimGray = Color.FromBgra(0xFF404040);
/// <summary>
/// DodgerBlue color.
/// </summary>
public static readonly Color DodgerBlue = Color.FromBgra(0xFF1E90FF);
/// <summary>
/// Firebrick color.
/// </summary>
public static readonly Color Firebrick = Color.FromBgra(0xFFB22222);
/// <summary>
/// FloralWhite color.
/// </summary>
public static readonly Color FloralWhite = Color.FromBgra(0xFFFFFAF0);
/// <summary>
/// ForestGreen color.
/// </summary>
public static readonly Color ForestGreen = Color.FromBgra(0xFF228B22);
/// <summary>
/// Fuchsia color.
/// </summary>
public static readonly Color Fuchsia = Color.FromBgra(0xFFFF00FF);
/// <summary>
/// Gainsboro color.
/// </summary>
public static readonly Color Gainsboro = Color.FromBgra(0xFFDCDCDC);
/// <summary>
/// GhostWhite color.
/// </summary>
public static readonly Color GhostWhite = Color.FromBgra(0xFFF8F8FF);
/// <summary>
/// Gold color.
/// </summary>
public static readonly Color Gold = Color.FromBgra(0xFFFFD700);
/// <summary>
/// Goldenrod color.
/// </summary>
public static readonly Color Goldenrod = Color.FromBgra(0xFFDAA520);
/// <summary>
/// Gray color.
/// </summary>
public static readonly Color Gray = Color.FromBgra(0xFF808080);
/// <summary>
/// Green color.
/// </summary>
public static readonly Color Green = Color.FromBgra(0xFF008000);
/// <summary>
/// GreenYellow color.
/// </summary>
public static readonly Color GreenYellow = Color.FromBgra(0xFFADFF2F);
/// <summary>
/// Honeydew color.
/// </summary>
public static readonly Color Honeydew = Color.FromBgra(0xFFF0FFF0);
/// <summary>
/// HotPink color.
/// </summary>
public static readonly Color HotPink = Color.FromBgra(0xFFFF69B4);
/// <summary>
/// IndianRed color.
/// </summary>
public static readonly Color IndianRed = Color.FromBgra(0xFFCD5C5C);
/// <summary>
/// Indigo color.
/// </summary>
public static readonly Color Indigo = Color.FromBgra(0xFF4B0082);
/// <summary>
/// Ivory color.
/// </summary>
public static readonly Color Ivory = Color.FromBgra(0xFFFFFFF0);
/// <summary>
/// Khaki color.
/// </summary>
public static readonly Color Khaki = Color.FromBgra(0xFFF0E68C);
/// <summary>
/// Lavender color.
/// </summary>
public static readonly Color Lavender = Color.FromBgra(0xFFE6E6FA);
/// <summary>
/// LavenderBlush color.
/// </summary>
public static readonly Color LavenderBlush = Color.FromBgra(0xFFFFF0F5);
/// <summary>
/// LawnGreen color.
/// </summary>
public static readonly Color LawnGreen = Color.FromBgra(0xFF7CFC00);
/// <summary>
/// LemonChiffon color.
/// </summary>
public static readonly Color LemonChiffon = Color.FromBgra(0xFFFFFACD);
/// <summary>
/// LightBlue color.
/// </summary>
public static readonly Color LightBlue = Color.FromBgra(0xFFADD8E6);
/// <summary>
/// LightCoral color.
/// </summary>
public static readonly Color LightCoral = Color.FromBgra(0xFFF08080);
/// <summary>
/// LightCyan color.
/// </summary>
public static readonly Color LightCyan = Color.FromBgra(0xFFE0FFFF);
/// <summary>
/// LightGoldenrodYellow color.
/// </summary>
public static readonly Color LightGoldenrodYellow = Color.FromBgra(0xFFFAFAD2);
/// <summary>
/// LightGray color.
/// </summary>
public static readonly Color LightGray = Color.FromBgra(0xFFD3D3D3);
/// <summary>
/// LightGreen color.
/// </summary>
public static readonly Color LightGreen = Color.FromBgra(0xFF90EE90);
/// <summary>
/// LightPink color.
/// </summary>
public static readonly Color LightPink = Color.FromBgra(0xFFFFB6C1);
/// <summary>
/// LightSalmon color.
/// </summary>
public static readonly Color LightSalmon = Color.FromBgra(0xFFFFA07A);
/// <summary>
/// LightSeaGreen color.
/// </summary>
public static readonly Color LightSeaGreen = Color.FromBgra(0xFF20B2AA);
/// <summary>
/// LightSkyBlue color.
/// </summary>
public static readonly Color LightSkyBlue = Color.FromBgra(0xFF87CEFA);
/// <summary>
/// LightSlateGray color.
/// </summary>
public static readonly Color LightSlateGray = Color.FromBgra(0xFF778899);
/// <summary>
/// LightSteelBlue color.
/// </summary>
public static readonly Color LightSteelBlue = Color.FromBgra(0xFFB0C4DE);
/// <summary>
/// LightYellow color.
/// </summary>
public static readonly Color LightYellow = Color.FromBgra(0xFFFFFFE0);
/// <summary>
/// Lime color.
/// </summary>
public static readonly Color Lime = Color.FromBgra(0xFF00FF00);
/// <summary>
/// LimeGreen color.
/// </summary>
public static readonly Color LimeGreen = Color.FromBgra(0xFF32CD32);
/// <summary>
/// Linen color.
/// </summary>
public static readonly Color Linen = Color.FromBgra(0xFFFAF0E6);
/// <summary>
/// Magenta color.
/// </summary>
public static readonly Color Magenta = Color.FromBgra(0xFFFF00FF);
/// <summary>
/// Maroon color.
/// </summary>
public static readonly Color Maroon = Color.FromBgra(0xFF800000);
/// <summary>
/// MediumAquamarine color.
/// </summary>
public static readonly Color MediumAquamarine = Color.FromBgra(0xFF66CDAA);
/// <summary>
/// MediumBlue color.
/// </summary>
public static readonly Color MediumBlue = Color.FromBgra(0xFF0000CD);
/// <summary>
/// MediumOrchid color.
/// </summary>
public static readonly Color MediumOrchid = Color.FromBgra(0xFFBA55D3);
/// <summary>
/// MediumPurple color.
/// </summary>
public static readonly Color MediumPurple = Color.FromBgra(0xFF9370DB);
/// <summary>
/// MediumSeaGreen color.
/// </summary>
public static readonly Color MediumSeaGreen = Color.FromBgra(0xFF3CB371);
/// <summary>
/// MediumSlateBlue color.
/// </summary>
public static readonly Color MediumSlateBlue = Color.FromBgra(0xFF7B68EE);
/// <summary>
/// MediumSpringGreen color.
/// </summary>
public static readonly Color MediumSpringGreen = Color.FromBgra(0xFF00FA9A);
/// <summary>
/// MediumTurquoise color.
/// </summary>
public static readonly Color MediumTurquoise = Color.FromBgra(0xFF48D1CC);
/// <summary>
/// MediumVioletRed color.
/// </summary>
public static readonly Color MediumVioletRed = Color.FromBgra(0xFFC71585);
/// <summary>
/// MidnightBlue color.
/// </summary>
public static readonly Color MidnightBlue = Color.FromBgra(0xFF191970);
/// <summary>
/// MintCream color.
/// </summary>
public static readonly Color MintCream = Color.FromBgra(0xFFF5FFFA);
/// <summary>
/// MistyRose color.
/// </summary>
public static readonly Color MistyRose = Color.FromBgra(0xFFFFE4E1);
/// <summary>
/// Moccasin color.
/// </summary>
public static readonly Color Moccasin = Color.FromBgra(0xFFFFE4B5);
/// <summary>
/// NavajoWhite color.
/// </summary>
public static readonly Color NavajoWhite = Color.FromBgra(0xFFFFDEAD);
/// <summary>
/// Navy color.
/// </summary>
public static readonly Color Navy = Color.FromBgra(0xFF000080);
/// <summary>
/// OldLace color.
/// </summary>
public static readonly Color OldLace = Color.FromBgra(0xFFFDF5E6);
/// <summary>
/// Olive color.
/// </summary>
public static readonly Color Olive = Color.FromBgra(0xFF808000);
/// <summary>
/// OliveDrab color.
/// </summary>
public static readonly Color OliveDrab = Color.FromBgra(0xFF6B8E23);
/// <summary>
/// Orange color.
/// </summary>
public static readonly Color Orange = Color.FromBgra(0xFFFFA500);
/// <summary>
/// OrangeRed color.
/// </summary>
public static readonly Color OrangeRed = Color.FromBgra(0xFFFF4500);
/// <summary>
/// Orchid color.
/// </summary>
public static readonly Color Orchid = Color.FromBgra(0xFFDA70D6);
/// <summary>
/// PaleGoldenrod color.
/// </summary>
public static readonly Color PaleGoldenrod = Color.FromBgra(0xFFEEE8AA);
/// <summary>
/// PaleGreen color.
/// </summary>
public static readonly Color PaleGreen = Color.FromBgra(0xFF98FB98);
/// <summary>
/// PaleTurquoise color.
/// </summary>
public static readonly Color PaleTurquoise = Color.FromBgra(0xFFAFEEEE);
/// <summary>
/// PaleVioletRed color.
/// </summary>
public static readonly Color PaleVioletRed = Color.FromBgra(0xFFDB7093);
/// <summary>
/// PapayaWhip color.
/// </summary>
public static readonly Color PapayaWhip = Color.FromBgra(0xFFFFEFD5);
/// <summary>
/// PeachPuff color.
/// </summary>
public static readonly Color PeachPuff = Color.FromBgra(0xFFFFDAB9);
/// <summary>
/// Peru color.
/// </summary>
public static readonly Color Peru = Color.FromBgra(0xFFCD853F);
/// <summary>
/// Pink color.
/// </summary>
public static readonly Color Pink = Color.FromBgra(0xFFFFC0CB);
/// <summary>
/// Plum color.
/// </summary>
public static readonly Color Plum = Color.FromBgra(0xFFDDA0DD);
/// <summary>
/// PowderBlue color.
/// </summary>
public static readonly Color PowderBlue = Color.FromBgra(0xFFB0E0E6);
/// <summary>
/// Purple color.
/// </summary>
public static readonly Color Purple = Color.FromBgra(0xFF800080);
/// <summary>
/// Red color.
/// </summary>
public static readonly Color Red = Color.FromBgra(0xFFFF0000);
/// <summary>
/// RosyBrown color.
/// </summary>
public static readonly Color RosyBrown = Color.FromBgra(0xFFBC8F8F);
/// <summary>
/// RoyalBlue color.
/// </summary>
public static readonly Color RoyalBlue = Color.FromBgra(0xFF4169E1);
/// <summary>
/// SaddleBrown color.
/// </summary>
public static readonly Color SaddleBrown = Color.FromBgra(0xFF8B4513);
/// <summary>
/// Salmon color.
/// </summary>
public static readonly Color Salmon = Color.FromBgra(0xFFFA8072);
/// <summary>
/// SandyBrown color.
/// </summary>
public static readonly Color SandyBrown = Color.FromBgra(0xFFF4A460);
/// <summary>
/// SeaGreen color.
/// </summary>
public static readonly Color SeaGreen = Color.FromBgra(0xFF2E8B57);
/// <summary>
/// SeaShell color.
/// </summary>
public static readonly Color SeaShell = Color.FromBgra(0xFFFFF5EE);
/// <summary>
/// Sienna color.
/// </summary>
public static readonly Color Sienna = Color.FromBgra(0xFFA0522D);
/// <summary>
/// Silver color.
/// </summary>
public static readonly Color Silver = Color.FromBgra(0xFFC0C0C0);
/// <summary>
/// SkyBlue color.
/// </summary>
public static readonly Color SkyBlue = Color.FromBgra(0xFF87CEEB);
/// <summary>
/// SlateBlue color.
/// </summary>
public static readonly Color SlateBlue = Color.FromBgra(0xFF6A5ACD);
/// <summary>
/// SlateGray color.
/// </summary>
public static readonly Color SlateGray = Color.FromBgra(0xFF708090);
/// <summary>
/// Snow color.
/// </summary>
public static readonly Color Snow = Color.FromBgra(0xFFFFFAFA);
/// <summary>
/// SpringGreen color.
/// </summary>
public static readonly Color SpringGreen = Color.FromBgra(0xFF00FF7F);
/// <summary>
/// SteelBlue color.
/// </summary>
public static readonly Color SteelBlue = Color.FromBgra(0xFF4682B4);
/// <summary>
/// Tan color.
/// </summary>
public static readonly Color Tan = Color.FromBgra(0xFFD2B48C);
/// <summary>
/// Teal color.
/// </summary>
public static readonly Color Teal = Color.FromBgra(0xFF008080);
/// <summary>
/// Thistle color.
/// </summary>
public static readonly Color Thistle = Color.FromBgra(0xFFD8BFD8);
/// <summary>
/// Tomato color.
/// </summary>
public static readonly Color Tomato = Color.FromBgra(0xFFFF6347);
/// <summary>
/// Turquoise color.
/// </summary>
public static readonly Color Turquoise = Color.FromBgra(0xFF40E0D0);
/// <summary>
/// Violet color.
/// </summary>
public static readonly Color Violet = Color.FromBgra(0xFFEE82EE);
/// <summary>
/// Wheat color.
/// </summary>
public static readonly Color Wheat = Color.FromBgra(0xFFF5DEB3);
/// <summary>
/// White color.
/// </summary>
public static readonly Color White = Color.FromBgra(0xFFFFFFFF);
/// <summary>
/// WhiteSmoke color.
/// </summary>
public static readonly Color WhiteSmoke = Color.FromBgra(0xFFF5F5F5);
/// <summary>
/// Yellow color.
/// </summary>
public static readonly Color Yellow = Color.FromBgra(0xFFFFFF00);
/// <summary>
/// YellowGreen color.
/// </summary>
public static readonly Color YellowGreen = Color.FromBgra(0xFF9ACD32);
}
}

1128
math/Color.cs Normal file

File diff suppressed because it is too large Load Diff

905
math/Color3.cs Normal file
View File

@ -0,0 +1,905 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a color in the form of rgb.
/// </summary>
[DataContract( Name = "Color3")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Color3 : IEquatable<Color3>, IFormattable
{
private const string ToStringFormat = "R:{0} G:{1} B:{2}";
/// <summary>
/// The red component of the color.
/// </summary>
[DataMember( Order = 0 )]
public float R;
/// <summary>
/// The green component of the color.
/// </summary>
[DataMember( Order = 1 )]
public float G;
/// <summary>
/// The blue component of the color.
/// </summary>
[DataMember( Order = 2 )]
public float B;
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="value">The value that will be assigned to all components.</param>
public Color3(float value)
{
R = G = B = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="red">The red component of the color.</param>
/// <param name="green">The green component of the color.</param>
/// <param name="blue">The blue component of the color.</param>
public Color3(float red, float green, float blue)
{
R = red;
G = green;
B = blue;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="value">The red, green, and blue components of the color.</param>
public Color3(Vector3 value)
{
R = value.X;
G = value.Y;
B = value.Z;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="rgb">A packed integer containing all three color components.
/// The alpha component is ignored.</param>
public Color3(int rgb)
{
B = ((rgb >> 16) & 255) / 255.0f;
G = ((rgb >> 8) & 255) / 255.0f;
R = (rgb & 255) / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="rgb">A packed unsigned integer containing all three color components.
/// The alpha component is ignored.</param>
public Color3(uint rgb)
{
B = ((rgb >> 16) & 255) / 255.0f;
G = ((rgb >> 8) & 255) / 255.0f;
R = (rgb & 255) / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color3"/> struct.
/// </summary>
/// <param name="values">The values to assign to the red, green, and blue components of the color. This must be an array with three elements.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than four elements.</exception>
public Color3(float[] values)
{
if (values == null)
throw new ArgumentNullException(nameof(values));
if (values.Length != 3)
throw new ArgumentOutOfRangeException(nameof(values), "There must be three and only three input values for Color3.");
R = values[0];
G = values[1];
B = values[2];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the red, green, or blue component, depending on the index.</value>
/// <param name="index">The index of the component to access. Use 0 for the red component, 1 for the green component, and 2 for the blue component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 2].</exception>
public float this[int index]
{
get
{
switch (index)
{
case 0: return R;
case 1: return G;
case 2: return B;
}
throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color3 run from 0 to 2, inclusive.");
}
set
{
switch (index)
{
case 0: R = value; break;
case 1: G = value; break;
case 2: B = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color3 run from 0 to 2, inclusive.");
}
}
}
/// <summary>
/// Converts the color into a packed integer.
/// </summary>
/// <returns>A packed integer containing all three color components.
/// The alpha channel is set to 255.</returns>
public int ToRgb()
{
uint a = 255;
uint r = (uint)(R * 255.0f);
uint g = (uint)(G * 255.0f);
uint b = (uint)(B * 255.0f);
uint value = r;
value += g << 8;
value += b << 16;
value += a << 24;
return (int)value;
}
/// <summary>
/// Raises the exponent for each components.
/// </summary>
/// <param name="exponent">The exponent.</param>
public void Pow(float exponent)
{
R = (float)Math.Pow(R, exponent);
G = (float)Math.Pow(G, exponent);
B = (float)Math.Pow(B, exponent);
}
/// <summary>
/// Converts the color into a three component vector.
/// </summary>
/// <returns>A three component vector containing the red, green, and blue components of the color.</returns>
public Vector3 ToVector3()
{
return new Vector3(R, G, B);
}
/// <summary>
/// Creates an array containing the elements of the color.
/// </summary>
/// <returns>A three-element array containing the components of the color.</returns>
public float[] ToArray()
{
return new[] { R, G, B };
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <param name="result">When the method completes, completes the sum of the two colors.</param>
public static void Add(ref Color3 left, ref Color3 right, out Color3 result)
{
result.R = left.R + right.R;
result.G = left.G + right.G;
result.B = left.B + right.B;
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <returns>The sum of the two colors.</returns>
public static Color3 Add(Color3 left, Color3 right)
{
return new Color3(left.R + right.R, left.G + right.G, left.B + right.B);
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract.</param>
/// <param name="result">WHen the method completes, contains the difference of the two colors.</param>
public static void Subtract(ref Color3 left, ref Color3 right, out Color3 result)
{
result.R = left.R - right.R;
result.G = left.G - right.G;
result.B = left.B - right.B;
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract</param>
/// <returns>The difference of the two colors.</returns>
public static Color3 Subtract(Color3 left, Color3 right)
{
return new Color3(left.R - right.R, left.G - right.G, left.B - right.B);
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <param name="result">When the method completes, contains the modulated color.</param>
public static void Modulate(ref Color3 left, ref Color3 right, out Color3 result)
{
result.R = left.R * right.R;
result.G = left.G * right.G;
result.B = left.B * right.B;
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <returns>The modulated color.</returns>
public static Color3 Modulate(Color3 left, Color3 right)
{
return new Color3(left.R * right.R, left.G * right.G, left.B * right.B);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The color to scale.</param>
/// <param name="scale">The amount by which to scale.</param>
/// <param name="result">When the method completes, contains the scaled color.</param>
public static void Scale(ref Color3 value, float scale, out Color3 result)
{
result.R = value.R * scale;
result.G = value.G * scale;
result.B = value.B * scale;
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The color to scale.</param>
/// <param name="scale">The amount by which to scale.</param>
/// <returns>The scaled color.</returns>
public static Color3 Scale(Color3 value, float scale)
{
return new Color3(value.R * scale, value.G * scale, value.B * scale);
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <param name="result">When the method completes, contains the negated color.</param>
public static void Negate(ref Color3 value, out Color3 result)
{
result.R = 1.0f - value.R;
result.G = 1.0f - value.G;
result.B = 1.0f - value.B;
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <returns>The negated color.</returns>
public static Color3 Negate(Color3 value)
{
return new Color3(1.0f - value.R, 1.0f - value.G, 1.0f - value.B);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <param name="result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref Color3 value, ref Color3 min, ref Color3 max, out Color3 result)
{
float red = value.R;
red = (red > max.R) ? max.R : red;
red = (red < min.R) ? min.R : red;
float green = value.G;
green = (green > max.G) ? max.G : green;
green = (green < min.G) ? min.G : green;
float blue = value.B;
blue = (blue > max.B) ? max.B : blue;
blue = (blue < min.B) ? min.B : blue;
result = new Color3(red, green, blue);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static Color3 Clamp(Color3 value, Color3 min, Color3 max)
{
Color3 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Performs a linear interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the linear interpolation of the two colors.</param>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static void Lerp(ref Color3 start, ref Color3 end, float amount, out Color3 result)
{
result.R = start.R + amount * (end.R - start.R);
result.G = start.G + amount * (end.G - start.G);
result.B = start.B + amount * (end.B - start.B);
}
/// <summary>
/// Performs a linear interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The linear interpolation of the two colors.</returns>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static Color3 Lerp(Color3 start, Color3 end, float amount)
{
return new Color3(
start.R + amount * (end.R - start.R),
start.G + amount * (end.G - start.G),
start.B + amount * (end.B - start.B));
}
/// <summary>
/// Performs a cubic interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the cubic interpolation of the two colors.</param>
public static void SmoothStep(ref Color3 start, ref Color3 end, float amount, out Color3 result)
{
amount = (amount > 1.0f) ? 1.0f : ((amount < 0.0f) ? 0.0f : amount);
amount = (amount * amount) * (3.0f - (2.0f * amount));
result.R = start.R + ((end.R - start.R) * amount);
result.G = start.G + ((end.G - start.G) * amount);
result.B = start.B + ((end.B - start.B) * amount);
}
/// <summary>
/// Performs a cubic interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The cubic interpolation of the two colors.</returns>
public static Color3 SmoothStep(Color3 start, Color3 end, float amount)
{
amount = (amount > 1.0f) ? 1.0f : ((amount < 0.0f) ? 0.0f : amount);
amount = (amount * amount) * (3.0f - (2.0f * amount));
return new Color3(
start.R + ((end.R - start.R) * amount),
start.G + ((end.G - start.G) * amount),
start.B + ((end.B - start.B) * amount));
}
/// <summary>
/// Returns a color containing the smallest components of the specified colorss.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <param name="result">When the method completes, contains an new color composed of the largest components of the source colorss.</param>
public static void Max(ref Color3 left, ref Color3 right, out Color3 result)
{
result.R = (left.R > right.R) ? left.R : right.R;
result.G = (left.G > right.G) ? left.G : right.G;
result.B = (left.B > right.B) ? left.B : right.B;
}
/// <summary>
/// Returns a color containing the largest components of the specified colorss.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>A color containing the largest components of the source colors.</returns>
public static Color3 Max(Color3 left, Color3 right)
{
Color3 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a color containing the smallest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <param name="result">When the method completes, contains an new color composed of the smallest components of the source colors.</param>
public static void Min(ref Color3 left, ref Color3 right, out Color3 result)
{
result.R = (left.R < right.R) ? left.R : right.R;
result.G = (left.G < right.G) ? left.G : right.G;
result.B = (left.B < right.B) ? left.B : right.B;
}
/// <summary>
/// Returns a color containing the smallest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>A color containing the smallest components of the source colors.</returns>
public static Color3 Min(Color3 left, Color3 right)
{
Color3 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adjusts the contrast of a color.
/// </summary>
/// <param name="value">The color whose contrast is to be adjusted.</param>
/// <param name="contrast">The amount by which to adjust the contrast.</param>
/// <param name="result">When the method completes, contains the adjusted color.</param>
public static void AdjustContrast(ref Color3 value, float contrast, out Color3 result)
{
result.R = 0.5f + contrast * (value.R - 0.5f);
result.G = 0.5f + contrast * (value.G - 0.5f);
result.B = 0.5f + contrast * (value.B - 0.5f);
}
/// <summary>
/// Adjusts the contrast of a color.
/// </summary>
/// <param name="value">The color whose contrast is to be adjusted.</param>
/// <param name="contrast">The amount by which to adjust the contrast.</param>
/// <returns>The adjusted color.</returns>
public static Color3 AdjustContrast(Color3 value, float contrast)
{
return new Color3(
0.5f + contrast * (value.R - 0.5f),
0.5f + contrast * (value.G - 0.5f),
0.5f + contrast * (value.B - 0.5f));
}
/// <summary>
/// Adjusts the saturation of a color.
/// </summary>
/// <param name="value">The color whose saturation is to be adjusted.</param>
/// <param name="saturation">The amount by which to adjust the saturation.</param>
/// <param name="result">When the method completes, contains the adjusted color.</param>
public static void AdjustSaturation(ref Color3 value, float saturation, out Color3 result)
{
float grey = value.R * 0.2125f + value.G * 0.7154f + value.B * 0.0721f;
result.R = grey + saturation * (value.R - grey);
result.G = grey + saturation * (value.G - grey);
result.B = grey + saturation * (value.B - grey);
}
/// <summary>
/// Adjusts the saturation of a color.
/// </summary>
/// <param name="value">The color whose saturation is to be adjusted.</param>
/// <param name="saturation">The amount by which to adjust the saturation.</param>
/// <returns>The adjusted color.</returns>
public static Color3 AdjustSaturation(Color3 value, float saturation)
{
float grey = value.R * 0.2125f + value.G * 0.7154f + value.B * 0.0721f;
return new Color3(
grey + saturation * (value.R - grey),
grey + saturation * (value.G - grey),
grey + saturation * (value.B - grey));
}
/// <summary>
/// Converts this color from linear space to sRGB space.
/// </summary>
/// <returns>A color3 in sRGB space.</returns>
public Color3 ToSRgb()
{
return new Color3(MathUtil.LinearToSRgb(R), MathUtil.LinearToSRgb(G), MathUtil.LinearToSRgb(B));
}
/// <summary>
/// Converts this color from sRGB space to linear space.
/// </summary>
/// <returns>Color3.</returns>
public Color3 ToLinear()
{
return new Color3(MathUtil.SRgbToLinear(R), MathUtil.SRgbToLinear(G), MathUtil.SRgbToLinear(B));
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <returns>The sum of the two colors.</returns>
public static Color3 operator +(Color3 left, Color3 right)
{
return new Color3(left.R + right.R, left.G + right.G, left.B + right.B);
}
/// <summary>
/// Assert a color (return it unchanged).
/// </summary>
/// <param name="value">The color to assert (unchange).</param>
/// <returns>The asserted (unchanged) color.</returns>
public static Color3 operator +(Color3 value)
{
return value;
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract.</param>
/// <returns>The difference of the two colors.</returns>
public static Color3 operator -(Color3 left, Color3 right)
{
return new Color3(left.R - right.R, left.G - right.G, left.B - right.B);
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <returns>A negated color.</returns>
public static Color3 operator -(Color3 value)
{
return new Color3(-value.R, -value.G, -value.B);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="scale">The factor by which to scale the color.</param>
/// <param name="value">The color to scale.</param>
/// <returns>The scaled color.</returns>
public static Color3 operator *(float scale, Color3 value)
{
return new Color3(value.R * scale, value.G * scale, value.B * scale);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The factor by which to scale the color.</param>
/// <param name="scale">The color to scale.</param>
/// <returns>The scaled color.</returns>
public static Color3 operator *(Color3 value, float scale)
{
return new Color3(value.R * scale, value.G * scale, value.B * scale);
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <returns>The modulated color.</returns>
public static Color3 operator *(Color3 left, Color3 right)
{
return new Color3(left.R * right.R, left.G * right.G, left.B * right.B);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Color3 left, Color3 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Color3 left, Color3 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Color3"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color4(Color3 value)
{
return new Color4(value.R, value.G, value.B, 1.0f);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Color3"/> to <see cref="math.Vector3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(Color3 value)
{
return new Vector3(value.R, value.G, value.B);
}
/// <summary>
/// Performs an explicit conversion from <see cref="math.Vector3"/> to <see cref="Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color3(Vector3 value)
{
return new Color3(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref="int"/> to <see cref="Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color3(int value)
{
return new Color3(value);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return ToString(CultureInfo.CurrentCulture);
}
/// <summary>
/// Convert this color to an equivalent <see cref="Color4"/> with an opaque alpha.
/// </summary>
/// <returns>An equivalent <see cref="Color4"/> with an opaque alpha.</returns>
public Color4 ToColor4()
{
return new Color4(R, G, B, 1.0f);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, ToStringFormat, R, G, B);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, ToStringFormat,
R.ToString(format, formatProvider),
G.ToString(format, formatProvider),
B.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return R.GetHashCode() + G.GetHashCode() + B.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="Color3"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="Color3"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="Color3"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Color3 other)
{
return R == other.R && G == other.G && B == other.B;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Color3)value);
}
#if SlimDX1xInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Color3"/> to <see cref="SlimDX.Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SlimDX.Color3(Color3 value)
{
return new SlimDX.Color3(value.Red, value.Green, value.Blue);
}
/// <summary>
/// Performs an implicit conversion from <see cref="SlimDX.Color3"/> to <see cref="math.Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Color3(SlimDX.Color3 value)
{
return new Color3(value.Red, value.Green, value.Blue);
}
#endif
#if WPFInterop
/// <summary>
/// Performs an explicit conversion from <see cref="math.Color3"/> to <see cref="System.Windows.Media.Color"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator System.Windows.Media.Color(Color3 value)
{
return new System.Windows.Media.Color()
{
A = 255,
R = (byte)(255f * value.Red),
G = (byte)(255f * value.Green),
B = (byte)(255f * value.Blue)
};
}
/// <summary>
/// Performs an explicit conversion from <see cref="System.Windows.Media.Color"/> to <see cref="math.Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color3(System.Windows.Media.Color value)
{
return new Color3()
{
Red = (float)value.R / 255f,
Green = (float)value.G / 255f,
Blue = (float)value.B / 255f
};
}
#endif
#if WinFormsInterop
/// <summary>
/// Performs an explicit conversion from <see cref="math.Color3"/> to <see cref="System.Drawing.Color"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator System.Drawing.Color(Color3 value)
{
return System.Drawing.Color.FromArgb(
(byte)(255f * value.Red),
(byte)(255f * value.Green),
(byte)(255f * value.Blue));
}
/// <summary>
/// Performs an explicit conversion from <see cref="System.Drawing.Color"/> to <see cref="math.Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Color3(System.Drawing.Color value)
{
return new Color3()
{
Red = (float)value.R / 255f,
Green = (float)value.G / 255f,
Blue = (float)value.B / 255f
};
}
#endif
}
}

999
math/Color4.cs Normal file
View File

@ -0,0 +1,999 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a color in the form of rgba.
/// </summary>
[DataContract( Name = "Color4")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Color4 : IEquatable<Color4>, IFormattable
{
private const string ToStringFormat = "A:{0} R:{1} G:{2} B:{3}";
/// <summary>
/// The Black color (0, 0, 0, 1).
/// </summary>
public static readonly Color4 Black = new Color4(0.0f, 0.0f, 0.0f, 1.0f);
/// <summary>
/// The White color (1, 1, 1, 1).
/// </summary>
public static readonly Color4 White = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
/// <summary>
/// The red component of the color.
/// </summary>
[DataMember( Order = 0 )]
public float R;
/// <summary>
/// The green component of the color.
/// </summary>
[DataMember( Order = 1 )]
public float G;
/// <summary>
/// The blue component of the color.
/// </summary>
[DataMember( Order = 2 )]
public float B;
/// <summary>
/// The alpha component of the color.
/// </summary>
[DataMember( Order = 3 )]
public float A;
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="value">The value that will be assigned to all components.</param>
public Color4(float value)
{
A = R = G = B = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="red">The red component of the color.</param>
/// <param name="green">The green component of the color.</param>
/// <param name="blue">The blue component of the color.</param>
/// <param name="alpha">The alpha component of the color.</param>
public Color4(float red, float green, float blue, float alpha)
{
R = red;
G = green;
B = blue;
A = alpha;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="value">The red, green, blue, and alpha components of the color.</param>
public Color4(Vector4 value)
{
R = value.X;
G = value.Y;
B = value.Z;
A = value.W;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="value">The red, green, and blue components of the color.</param>
/// <param name="alpha">The alpha component of the color.</param>
public Color4(Vector3 value, float alpha)
{
R = value.X;
G = value.Y;
B = value.Z;
A = alpha;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="rgba">A packed integer containing all four color components in RGBA order.</param>
public Color4(uint rgba)
{
A = ((rgba >> 24) & 255) / 255.0f;
B = ((rgba >> 16) & 255) / 255.0f;
G = ((rgba >> 8) & 255) / 255.0f;
R = (rgba & 255) / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="rgba">A packed integer containing all four color components in RGBA order.</param>
public Color4(int rgba)
{
A = ((rgba >> 24) & 255) / 255.0f;
B = ((rgba >> 16) & 255) / 255.0f;
G = ((rgba >> 8) & 255) / 255.0f;
R = (rgba & 255) / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="values">The values to assign to the red, green, blue, and alpha components of the color. This must be an array with four elements.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than four elements.</exception>
public Color4(float[] values)
{
if (values == null)
throw new ArgumentNullException(nameof(values));
if (values.Length != 4)
throw new ArgumentOutOfRangeException(nameof(values), "There must be four and only four input values for Color4.");
R = values[0];
G = values[1];
B = values[2];
A = values[3];
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="color"><see cref="Color3"/> used to initialize the color.</param>
public Color4(Color3 color)
{
R = color.R;
G = color.G;
B = color.B;
A = 1.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="color"><see cref="Color"/> used to initialize the color.</param>
public Color4(Color color)
{
R = color.R / 255.0f;
G = color.G / 255.0f;
B = color.B / 255.0f;
A = color.A / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="color"><see cref="Color"/> used to initialize the color.</param>
public Color4(ColorBGRA color)
{
R = color.R / 255.0f;
G = color.G / 255.0f;
B = color.B / 255.0f;
A = color.A / 255.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="Color4"/> struct.
/// </summary>
/// <param name="color"><see cref="Color3"/> used to initialize the color.</param>
/// <param name="alpha">The alpha component of the color.</param>
public Color4(Color3 color, float alpha)
{
R = color.R;
G = color.G;
B = color.B;
A = alpha;
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the red, green, blue, and alpha components, depending on the index.</value>
/// <param name="index">The index of the component to access. Use 0 for the alpha component, 1 for the red component, 2 for the green component, and 3 for the blue component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 3].</exception>
public float this[int index]
{
get
{
switch (index)
{
case 0: return R;
case 1: return G;
case 2: return B;
case 3: return A;
}
throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color4 run from 0 to 3, inclusive.");
}
set
{
switch (index)
{
case 0: R = value; break;
case 1: G = value; break;
case 2: B = value; break;
case 3: A = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color4 run from 0 to 3, inclusive.");
}
}
}
/// <summary>
/// Converts the color into a packed integer.
/// </summary>
/// <returns>A packed integer containing all four color components.</returns>
public int ToBgra()
{
uint a = (uint)(A * 255.0f) & 255;
uint r = (uint)(R * 255.0f) & 255;
uint g = (uint)(G * 255.0f) & 255;
uint b = (uint)(B * 255.0f) & 255;
uint value = b;
value |= g << 8;
value |= r << 16;
value |= a << 24;
return (int)value;
}
/// <summary>
/// Converts the color into a packed integer.
/// </summary>
public void ToBgra(out byte r, out byte g, out byte b, out byte a)
{
a = (byte)(A * 255.0f);
r = (byte)(R * 255.0f);
g = (byte)(G * 255.0f);
b = (byte)(B * 255.0f);
}
/// <summary>
/// Converts the color into a packed integer.
/// </summary>
/// <returns>A packed integer containing all four color components.</returns>
public int ToRgba()
{
uint a = (uint)(A * 255.0f) & 255;
uint r = (uint)(R * 255.0f) & 255;
uint g = (uint)(G * 255.0f) & 255;
uint b = (uint)(B * 255.0f) & 255;
uint value = r;
value |= g << 8;
value |= b << 16;
value |= a << 24;
return (int)value;
}
/// <summary>
/// Converts the color into a three component vector.
/// </summary>
/// <returns>A three component vector containing the red, green, and blue components of the color.</returns>
public Vector3 ToVector3()
{
return new Vector3(R, G, B);
}
/// <summary>
/// Converts the color into a four component vector.
/// </summary>
/// <returns>A four component vector containing all four color components.</returns>
public Vector4 ToVector4()
{
return new Vector4(R, G, B, A);
}
/// <summary>
/// Creates an array containing the elements of the color.
/// </summary>
/// <returns>A four-element array containing the components of the color.</returns>
public float[] ToArray()
{
return new[] { R, G, B, A };
}
/// <summary>
/// Converts this color from linear space to sRGB space.
/// </summary>
/// <returns>A color3 in sRGB space.</returns>
public Color4 ToSRgb()
{
return new Color4(MathUtil.LinearToSRgb(R), MathUtil.LinearToSRgb(G), MathUtil.LinearToSRgb(B), A);
}
/// <summary>
/// Converts this color from sRGB space to linear space.
/// </summary>
/// <returns>A color4 in linear space.</returns>
public Color4 ToLinear()
{
return new Color4(MathUtil.SRgbToLinear(R), MathUtil.SRgbToLinear(G), MathUtil.SRgbToLinear(B), A);
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <param name="result">When the method completes, completes the sum of the two colors.</param>
public static void Add(ref Color4 left, ref Color4 right, out Color4 result)
{
result.A = left.A + right.A;
result.R = left.R + right.R;
result.G = left.G + right.G;
result.B = left.B + right.B;
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <returns>The sum of the two colors.</returns>
public static Color4 Add(Color4 left, Color4 right)
{
return new Color4(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A);
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract.</param>
/// <param name="result">WHen the method completes, contains the difference of the two colors.</param>
public static void Subtract(ref Color4 left, ref Color4 right, out Color4 result)
{
result.A = left.A - right.A;
result.R = left.R - right.R;
result.G = left.G - right.G;
result.B = left.B - right.B;
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract</param>
/// <returns>The difference of the two colors.</returns>
public static Color4 Subtract(Color4 left, Color4 right)
{
return new Color4(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A);
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <param name="result">When the method completes, contains the modulated color.</param>
public static void Modulate(ref Color4 left, ref Color4 right, out Color4 result)
{
result.A = left.A * right.A;
result.R = left.R * right.R;
result.G = left.G * right.G;
result.B = left.B * right.B;
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <returns>The modulated color.</returns>
public static Color4 Modulate(Color4 left, Color4 right)
{
return new Color4(left.R * right.R, left.G * right.G, left.B * right.B, left.A * right.A);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The color to scale.</param>
/// <param name="scale">The amount by which to scale.</param>
/// <param name="result">When the method completes, contains the scaled color.</param>
public static void Scale(ref Color4 value, float scale, out Color4 result)
{
result.A = value.A * scale;
result.R = value.R * scale;
result.G = value.G * scale;
result.B = value.B * scale;
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The color to scale.</param>
/// <param name="scale">The amount by which to scale.</param>
/// <returns>The scaled color.</returns>
public static Color4 Scale(Color4 value, float scale)
{
return new Color4(value.R * scale, value.G * scale, value.B * scale, value.A * scale);
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <param name="result">When the method completes, contains the negated color.</param>
public static void Negate(ref Color4 value, out Color4 result)
{
result.A = 1.0f - value.A;
result.R = 1.0f - value.R;
result.G = 1.0f - value.G;
result.B = 1.0f - value.B;
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <returns>The negated color.</returns>
public static Color4 Negate(Color4 value)
{
return new Color4(1.0f - value.R, 1.0f - value.G, 1.0f - value.B, 1.0f - value.A);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <param name="result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref Color4 value, ref Color4 min, ref Color4 max, out Color4 result)
{
float alpha = value.A;
alpha = (alpha > max.A) ? max.A : alpha;
alpha = (alpha < min.A) ? min.A : alpha;
float red = value.R;
red = (red > max.R) ? max.R : red;
red = (red < min.R) ? min.R : red;
float green = value.G;
green = (green > max.G) ? max.G : green;
green = (green < min.G) ? min.G : green;
float blue = value.B;
blue = (blue > max.B) ? max.B : blue;
blue = (blue < min.B) ? min.B : blue;
result = new Color4(red, green, blue, alpha);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static Color4 Clamp(Color4 value, Color4 min, Color4 max)
{
Color4 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Performs a linear interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the linear interpolation of the two colors.</param>
/// <remarks>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static void Lerp(ref Color4 start, ref Color4 end, float amount, out Color4 result)
{
result.R = MathUtil.Lerp(start.R, end.R, amount);
result.G = MathUtil.Lerp(start.G, end.G, amount);
result.B = MathUtil.Lerp(start.B, end.B, amount);
result.A = MathUtil.Lerp(start.A, end.A, amount);
}
/// <summary>
/// Performs a linear interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The linear interpolation of the two colors.</returns>
/// <remarks>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static Color4 Lerp(Color4 start, Color4 end, float amount)
{
Color4 result;
Lerp(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Performs a cubic interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the cubic interpolation of the two colors.</param>
public static void SmoothStep(ref Color4 start, ref Color4 end, float amount, out Color4 result)
{
amount = MathUtil.SmoothStep(amount);
Lerp(ref start, ref end, amount, out result);
}
/// <summary>
/// Performs a cubic interpolation between two colors.
/// </summary>
/// <param name="start">Start color.</param>
/// <param name="end">End color.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The cubic interpolation of the two colors.</returns>
public static Color4 SmoothStep(Color4 start, Color4 end, float amount)
{
Color4 result;
SmoothStep(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Returns a color containing the smallest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <param name="result">When the method completes, contains an new color composed of the largest components of the source colors.</param>
public static void Max(ref Color4 left, ref Color4 right, out Color4 result)
{
result.A = (left.A > right.A) ? left.A : right.A;
result.R = (left.R > right.R) ? left.R : right.R;
result.G = (left.G > right.G) ? left.G : right.G;
result.B = (left.B > right.B) ? left.B : right.B;
}
/// <summary>
/// Returns a color containing the largest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>A color containing the largest components of the source colors.</returns>
public static Color4 Max(Color4 left, Color4 right)
{
Color4 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a color containing the smallest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <param name="result">When the method completes, contains an new color composed of the smallest components of the source colors.</param>
public static void Min(ref Color4 left, ref Color4 right, out Color4 result)
{
result.A = (left.A < right.A) ? left.A : right.A;
result.R = (left.R < right.R) ? left.R : right.R;
result.G = (left.G < right.G) ? left.G : right.G;
result.B = (left.B < right.B) ? left.B : right.B;
}
/// <summary>
/// Returns a color containing the smallest components of the specified colors.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>A color containing the smallest components of the source colors.</returns>
public static Color4 Min(Color4 left, Color4 right)
{
Color4 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adjusts the contrast of a color.
/// </summary>
/// <param name="value">The color whose contrast is to be adjusted.</param>
/// <param name="contrast">The amount by which to adjust the contrast.</param>
/// <param name="result">When the method completes, contains the adjusted color.</param>
public static void AdjustContrast(ref Color4 value, float contrast, out Color4 result)
{
result.A = value.A;
result.R = 0.5f + contrast * (value.R - 0.5f);
result.G = 0.5f + contrast * (value.G - 0.5f);
result.B = 0.5f + contrast * (value.B - 0.5f);
}
/// <summary>
/// Adjusts the contrast of a color.
/// </summary>
/// <param name="value">The color whose contrast is to be adjusted.</param>
/// <param name="contrast">The amount by which to adjust the contrast.</param>
/// <returns>The adjusted color.</returns>
public static Color4 AdjustContrast(Color4 value, float contrast)
{
return new Color4(
0.5f + contrast * (value.R - 0.5f),
0.5f + contrast * (value.G - 0.5f),
0.5f + contrast * (value.B - 0.5f),
value.A);
}
/// <summary>
/// Adjusts the saturation of a color.
/// </summary>
/// <param name="value">The color whose saturation is to be adjusted.</param>
/// <param name="saturation">The amount by which to adjust the saturation.</param>
/// <param name="result">When the method completes, contains the adjusted color.</param>
public static void AdjustSaturation(ref Color4 value, float saturation, out Color4 result)
{
float grey = value.R * 0.2125f + value.G * 0.7154f + value.B * 0.0721f;
result.A = value.A;
result.R = grey + saturation * (value.R - grey);
result.G = grey + saturation * (value.G - grey);
result.B = grey + saturation * (value.B - grey);
}
/// <summary>
/// Adjusts the saturation of a color.
/// </summary>
/// <param name="value">The color whose saturation is to be adjusted.</param>
/// <param name="saturation">The amount by which to adjust the saturation.</param>
/// <returns>The adjusted color.</returns>
public static Color4 AdjustSaturation(Color4 value, float saturation)
{
float grey = value.R * 0.2125f + value.G * 0.7154f + value.B * 0.0721f;
return new Color4(
grey + saturation * (value.R - grey),
grey + saturation * (value.G - grey),
grey + saturation * (value.B - grey),
value.A);
}
/// <summary>
/// Premultiplies the color components by the alpha value.
/// </summary>
/// <param name="value">The color to premultiply.</param>
/// <returns>A color with premultiplied alpha.</returns>
public static Color4 PremultiplyAlpha(Color4 value)
{
return new Color4(value.R * value.A, value.G * value.A, value.B * value.A, value.A);
}
/// <summary>
/// Adds two colors.
/// </summary>
/// <param name="left">The first color to add.</param>
/// <param name="right">The second color to add.</param>
/// <returns>The sum of the two colors.</returns>
public static Color4 operator +(Color4 left, Color4 right)
{
return new Color4(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A);
}
/// <summary>
/// Assert a color (return it unchanged).
/// </summary>
/// <param name="value">The color to assert (unchanged).</param>
/// <returns>The asserted (unchanged) color.</returns>
public static Color4 operator +(Color4 value)
{
return value;
}
/// <summary>
/// Subtracts two colors.
/// </summary>
/// <param name="left">The first color to subtract.</param>
/// <param name="right">The second color to subtract.</param>
/// <returns>The difference of the two colors.</returns>
public static Color4 operator -(Color4 left, Color4 right)
{
return new Color4(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A);
}
/// <summary>
/// Negates a color.
/// </summary>
/// <param name="value">The color to negate.</param>
/// <returns>A negated color.</returns>
public static Color4 operator -(Color4 value)
{
return new Color4(-value.R, -value.G, -value.B, -value.A);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="scale">The factor by which to scale the color.</param>
/// <param name="value">The color to scale.</param>
/// <returns>The scaled color.</returns>
public static Color4 operator *(float scale, Color4 value)
{
return new Color4(value.R * scale, value.G * scale, value.B * scale, value.A * scale);
}
/// <summary>
/// Scales a color.
/// </summary>
/// <param name="value">The factor by which to scale the color.</param>
/// <param name="scale">The color to scale.</param>
/// <returns>The scaled color.</returns>
public static Color4 operator *(Color4 value, float scale)
{
return new Color4(value.R * scale, value.G * scale, value.B * scale, value.A * scale);
}
/// <summary>
/// Modulates two colors.
/// </summary>
/// <param name="left">The first color to modulate.</param>
/// <param name="right">The second color to modulate.</param>
/// <returns>The modulated color.</returns>
public static Color4 operator *(Color4 left, Color4 right)
{
return new Color4(left.R * right.R, left.G * right.G, left.B * right.B, left.A * right.A);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Color4 left, Color4 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Color4 left, Color4 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Color4"/> to <see cref="Color3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color3(Color4 value)
{
return new Color3(value.R, value.G, value.B);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Color4"/> to <see cref="Vector3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(Color4 value)
{
return new Vector3(value.R, value.G, value.B);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Color4"/> to <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Vector4(Color4 value)
{
return new Vector4(value.R, value.G, value.B, value.A);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector3"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color4(Vector3 value)
{
return new Color4(value.X, value.Y, value.Z, 1.0f);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector4"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color4(Vector4 value)
{
return new Color4(value.X, value.Y, value.Z, value.W);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector3"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Color4(ColorBGRA value)
{
return new Color4(value);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector4"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator ColorBGRA(Color4 value)
{
return new ColorBGRA(value.R, value.G, value.B, value.A);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Color4"/> to <see cref="int"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// The result of the conversion.
/// </returns>
public static explicit operator int(Color4 value)
{
return value.ToRgba();
}
/// <summary>
/// Performs an explicit conversion from <see cref="int"/> to <see cref="Color4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// The result of the conversion.
/// </returns>
public static explicit operator Color4(int value)
{
return new Color4(value);
}
/// <summary>
/// Converts this color to an equivalent <see cref="Color3"/>, discarding the alpha channel.
/// </summary>
/// <returns>An equivalent <see cref="Color3"/>, discarding the alpha channel.</returns>
public Color3 ToColor3()
{
return new Color3(R, G, B);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return ToString(CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format to apply to each channel (float).</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, ToStringFormat, A, R, G, B);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format to apply to each channel (float).</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, ToStringFormat,
A.ToString(format, formatProvider),
R.ToString(format, formatProvider),
G.ToString(format, formatProvider),
B.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return A.GetHashCode() + R.GetHashCode() + G.GetHashCode() + B.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="Color4"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="Color4"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="Color4"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Color4 other)
{
return A == other.A && R == other.R && G == other.G && B == other.B;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (!ReferenceEquals(value.GetType(), typeof(Color4)))
return false;
return Equals((Color4)value);
}
}
}

1097
math/ColorBGRA.cs Normal file

File diff suppressed because it is too large Load Diff

94
math/ColorExtensions.cs Normal file
View File

@ -0,0 +1,94 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Globalization;
using Xenko.Core.Annotations;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A class containing extension methods for processing colors.
/// </summary>
public static class ColorExtensions
{
/// <summary>
/// Indicates if the given string can be converted to an <see cref="uint"/> RGBA value using <see cref="StringToRgba"/>.
/// </summary>
/// <param name="stringColor">The string to convert.</param>
/// <returns>True if the string can be converted, false otherwise.</returns>
public static bool CanConvertStringToRgba([CanBeNull] string stringColor)
{
return stringColor?.StartsWith("#") ?? false;
}
/// <summary>
/// Converts the given string to an <see cref="uint"/> RGBA value.
/// </summary>
/// <param name="stringColor">The string to convert.</param>
/// <returns>The converted RGBA value.</returns>
public static uint StringToRgba([CanBeNull] string stringColor)
{
var intValue = 0xFF000000;
if (stringColor != null)
{
if (stringColor.StartsWith("#"))
{
if (stringColor.Length == "#000".Length && uint.TryParse(stringColor.Substring(1, 3), NumberStyles.HexNumber, null, out intValue))
{
intValue = ((intValue & 0x00F) << 16)
| ((intValue & 0x00F) << 20)
| ((intValue & 0x0F0) << 4)
| ((intValue & 0x0F0) << 8)
| ((intValue & 0xF00) >> 4)
| ((intValue & 0xF00) >> 8)
| (0xFF000000);
}
if (stringColor.Length == "#000000".Length && uint.TryParse(stringColor.Substring(1, 6), NumberStyles.HexNumber, null, out intValue))
{
intValue = ((intValue & 0x000000FF) << 16)
| (intValue & 0x0000FF00)
| ((intValue & 0x00FF0000) >> 16)
| (0xFF000000);
}
if (stringColor.Length == "#00000000".Length && uint.TryParse(stringColor.Substring(1, 8), NumberStyles.HexNumber, null, out intValue))
{
intValue = ((intValue & 0x000000FF) << 16)
| (intValue & 0x0000FF00)
| ((intValue & 0x00FF0000) >> 16)
| (intValue & 0xFF000000);
}
}
}
return intValue;
}
/// <summary>
/// Converts the given RGB value to a string.
/// </summary>
/// <param name="value">The RGB value to convert.</param>
/// <returns>The converted string.</returns>
[NotNull]
public static string RgbToString(int value)
{
var r = (value & 0x000000FF);
var g = (value & 0x0000FF00) >> 8;
var b = (value & 0x00FF0000) >> 16;
return $"#{r:X2}{g:X2}{b:X2}";
}
/// <summary>
/// Converts the given RGBA value to a string.
/// </summary>
/// <param name="value">The RGBA value to convert.</param>
/// <returns>The converted string.</returns>
[NotNull]
public static string RgbaToString(int value)
{
var r = (value & 0x000000FF);
var g = (value & 0x0000FF00) >> 8;
var b = (value & 0x00FF0000) >> 16;
var a = (value & 0xFF000000) >> 24;
return $"#{a:X2}{r:X2}{g:X2}{b:X2}";
}
}
}

203
math/ColorHSV.cs Normal file
View File

@ -0,0 +1,203 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a color in the form of Hue, Saturation, Value, Alpha.
/// </summary>
[DataContract( Name = "ColorHSV")]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct ColorHSV : IEquatable<ColorHSV>, IFormattable
{
private const string ToStringFormat = "Hue:{0} Saturation:{1} Value:{2} Alpha:{3}";
/// <summary>
/// The Hue of the color.
/// </summary>
[DataMember( Order = 0 )]
public float H;
/// <summary>
/// The Saturation of the color.
/// </summary>
[DataMember( Order = 1 )]
public float S;
/// <summary>
/// The Value of the color.
/// </summary>
[DataMember( Order = 2 )]
public float V;
/// <summary>
/// The alpha component of the color.
/// </summary>
[DataMember( Order = 3 )]
public float A;
/// <summary>
/// Initializes a new instance of the <see cref="ColorHSV"/> struct.
/// </summary>
/// <param name="h">The h.</param>
/// <param name="s">The s.</param>
/// <param name="v">The v.</param>
/// <param name="a">A.</param>
public ColorHSV(float h, float s, float v, float a)
{
H = h;
S = s;
V = v;
A = a;
}
/// <summary>
/// Converts the color into a three component vector.
/// </summary>
/// <returns>A three component vector containing the red, green, and blue components of the color.</returns>
public Color4 ToColor()
{
float hdiv = H / 60;
int hi = (int)hdiv;
float f = hdiv - hi;
float p = V * (1 - S);
float q = V * (1 - (S * f));
float t = V * (1 - (S * (1 - f)));
switch (hi)
{
case 0:
return new Color4(V, t, p, A);
case 1:
return new Color4(q, V, p, A);
case 2:
return new Color4(p, V, t, A);
case 3:
return new Color4(p, q, V, A);
case 4:
return new Color4(t, p, V, A);
default:
return new Color4(V, p, q, A);
}
}
/// <summary>
/// Converts the color into a HSV color.
/// </summary>
/// <param name="color">The color.</param>
/// <returns>A HSV color</returns>
public static ColorHSV FromColor(Color4 color)
{
float max = Math.Max(color.R, Math.Max(color.G, color.B));
float min = Math.Min(color.R, Math.Min(color.G, color.B));
float delta = max - min;
float h = 0.0f;
if (delta > 0.0f)
{
if (color.R >= max)
h = (color.G - color.B) / delta;
else if (color.G >= max)
h = (color.B - color.R) / delta + 2.0f;
else
h = (color.R - color.G) / delta + 4.0f;
h *= 60.0f;
if (h < 0)
h += 360f;
}
float s = MathUtil.IsZero(max) ? 0.0f : delta / max;
return new ColorHSV(h, s, max, color.A);
}
/// <inheritdoc/>
public bool Equals(ColorHSV other)
{
return other.H.Equals(H) && other.S.Equals(S) && other.V.Equals(V) && other.A.Equals(A);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(ColorHSV)) return false;
return Equals((ColorHSV)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int result = H.GetHashCode();
result = (result * 397) ^ S.GetHashCode();
result = (result * 397) ^ V.GetHashCode();
result = (result * 397) ^ A.GetHashCode();
return result;
}
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return ToString(CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, ToStringFormat, H, S, V, A);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, ToStringFormat,
H.ToString(format, formatProvider),
S.ToString(format, formatProvider),
V.ToString(format, formatProvider),
A.ToString(format, formatProvider));
}
}
}

51
math/ContainmentType.cs Normal file
View File

@ -0,0 +1,51 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace math
{
/// <summary>
/// Describes how one bounding volume contains another.
/// </summary>
public enum ContainmentType
{
/// <summary>
/// The two bounding volumes don't intersect at all.
/// </summary>
Disjoint,
/// <summary>
/// One bounding volume completely contains another.
/// </summary>
Contains,
/// <summary>
/// The two bounding volumes overlap.
/// </summary>
Intersects,
}
}

View File

@ -0,0 +1,53 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
//TODO @@ Move this stuff
namespace math
{
public enum DataStyle
{
Invalid = 0,
Compact = 1,
}
public class DataStyleAttribute : Attribute
{
public DataStyle style { get; private set; }
public DataStyleAttribute( DataStyle n_style )
{
style = n_style;
}
}
}

1486
math/Double2.cs Normal file

File diff suppressed because it is too large Load Diff

1765
math/Double3.cs Normal file

File diff suppressed because it is too large Load Diff

1436
math/Double4.cs Normal file

File diff suppressed because it is too large Load Diff

183
math/GuillotinePacker.cs Normal file
View File

@ -0,0 +1,183 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Implementation of a "Guillotine" packer.
/// More information at http://clb.demon.fi/files/RectangleBinPack.pdf.
/// </summary>
public class GuillotinePacker
{
private readonly List<Rectangle> freeRectangles = new List<Rectangle>();
private readonly List<Rectangle> tempFreeRectangles = new List<Rectangle>();
/// <summary>
/// A delegate callback used by <see cref="TryInsert"/>
/// </summary>
/// <param name="cascadeIndex">The index of the rectangle</param>
/// <param name="rectangle">The rectangle found</param>
public delegate void InsertRectangleCallback(int cascadeIndex, ref Rectangle rectangle);
/// <summary>
/// Current width used by the packer.
/// </summary>
public int Width { get; private set; }
/// <summary>
/// Current height used by the packer.
/// </summary>
public int Height { get; private set; }
/// <summary>
/// Clears the specified region.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public void Clear(int width, int height)
{
freeRectangles.Clear();
freeRectangles.Add(new Rectangle { X = 0, Y = 0, Width = width, Height = height });
Width = width;
Height = height;
}
/// <summary>
/// Clears the whole region.
/// </summary>
public virtual void Clear()
{
Clear(Width, Height);
}
/// <summary>
/// Frees the specified old rectangle.
/// </summary>
/// <param name="oldRectangle">The old rectangle.</param>
public void Free(ref Rectangle oldRectangle)
{
freeRectangles.Add(oldRectangle);
}
/// <summary>
/// Tries to fit a single rectangle with the specified width and height.
/// </summary>
/// <param name="width">Width requested.</param>
/// <param name="height">Height requested</param>
/// <param name="bestRectangle">Fill with the rectangle if it was successfully inserted.</param>
/// <returns><c>true</c> if it was successfully inserted.</returns>
public bool Insert(int width, int height, ref Rectangle bestRectangle)
{
return Insert(width, height, freeRectangles, ref bestRectangle);
}
/// <summary>
/// Tries to fit multiple rectangle with (width, height).
/// </summary>
/// <param name="width">Width requested.</param>
/// <param name="height">Height requested</param>
/// <param name="count">The number of rectangle to fit.</param>
/// <param name="inserted">A callback called for each rectangle successfully fitted.</param>
/// <returns><c>true</c> if all rectangles were successfully fitted.</returns>
public bool TryInsert(int width, int height, int count, InsertRectangleCallback inserted)
{
var bestRectangle = new Rectangle();
tempFreeRectangles.Clear();
foreach (var freeRectangle in freeRectangles)
{
tempFreeRectangles.Add(freeRectangle);
}
for (var i = 0; i < count; ++i)
{
if (!Insert(width, height, tempFreeRectangles, ref bestRectangle))
{
tempFreeRectangles.Clear();
return false;
}
inserted(i, ref bestRectangle);
}
// if the insertion went well, use the new configuration
freeRectangles.Clear();
foreach (var tempFreeRectangle in tempFreeRectangles)
{
freeRectangles.Add(tempFreeRectangle);
}
tempFreeRectangles.Clear();
return true;
}
private static bool Insert(int width, int height, List<Rectangle> freeRectanglesList, ref Rectangle bestRectangle)
{
// Info on algorithm: http://clb.demon.fi/files/RectangleBinPack.pdf
int bestScore = int.MaxValue;
int freeRectangleIndex = -1;
// Find space for new rectangle
for (int i = 0; i < freeRectanglesList.Count; ++i)
{
var currentFreeRectangle = freeRectanglesList[i];
if (width == currentFreeRectangle.Width && height == currentFreeRectangle.Height)
{
// Perfect fit
bestRectangle.X = currentFreeRectangle.X;
bestRectangle.Y = currentFreeRectangle.Y;
bestRectangle.Width = width;
bestRectangle.Height = height;
freeRectangleIndex = i;
break;
}
if (width <= currentFreeRectangle.Width && height <= currentFreeRectangle.Height)
{
// Can fit inside
// Use "BAF" heuristic (best area fit)
var score = currentFreeRectangle.Width * currentFreeRectangle.Height - width * height;
if (score < bestScore)
{
bestRectangle.X = currentFreeRectangle.X;
bestRectangle.Y = currentFreeRectangle.Y;
bestRectangle.Width = width;
bestRectangle.Height = height;
bestScore = score;
freeRectangleIndex = i;
}
}
}
// No space could be found
if (freeRectangleIndex == -1)
return false;
var freeRectangle = freeRectanglesList[freeRectangleIndex];
// Choose an axis to split (trying to minimize the smaller area "MINAS")
int w = freeRectangle.Width - bestRectangle.Width;
int h = freeRectangle.Height - bestRectangle.Height;
var splitHorizontal = (bestRectangle.Width * h > w * bestRectangle.Height);
// Form the two new rectangles.
var bottom = new Rectangle { X = freeRectangle.X, Y = freeRectangle.Y + bestRectangle.Height, Width = splitHorizontal ? freeRectangle.Width : bestRectangle.Width, Height = h };
var right = new Rectangle { X = freeRectangle.X + bestRectangle.Width, Y = freeRectangle.Y, Width = w, Height = splitHorizontal ? bestRectangle.Height : freeRectangle.Height };
if (bottom.Width > 0 && bottom.Height > 0)
freeRectanglesList.Add(bottom);
if (right.Width > 0 && right.Height > 0)
freeRectanglesList.Add(right);
// Remove previously selected freeRectangle
if (freeRectangleIndex != freeRectanglesList.Count - 1)
freeRectanglesList[freeRectangleIndex] = freeRectanglesList[freeRectanglesList.Count - 1];
freeRectanglesList.RemoveAt(freeRectanglesList.Count - 1);
return true;
}
}
}

268
math/Half.cs Normal file
View File

@ -0,0 +1,268 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A half precision (16 bit) floating point value.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct Half
{
private ushort value;
/// <summary>
/// Number of decimal digits of precision.
/// </summary>
public const int PrecisionDigits = 3;
/// <summary>
/// Number of bits in the mantissa.
/// </summary>
public const int MantissaBits = 11;
/// <summary>
/// Maximum decimal exponent.
/// </summary>
public const int MaximumDecimalExponent = 4;
/// <summary>
/// Maximum binary exponent.
/// </summary>
public const int MaximumBinaryExponent = 15;
/// <summary>
/// Minimum decimal exponent.
/// </summary>
public const int MinimumDecimalExponent = -4;
/// <summary>
/// Minimum binary exponent.
/// </summary>
public const int MinimumBinaryExponent = -14;
/// <summary>
/// Exponent radix.
/// </summary>
public const int ExponentRadix = 2;
/// <summary>
/// Additional rounding.
/// </summary>
public const int AdditionRounding = 1;
/// <summary>
/// Smallest such that 1.0 + epsilon != 1.0
/// </summary>
public static readonly float Epsilon;
/// <summary>
/// Maximum value of the number.
/// </summary>
public static readonly float MaxValue;
/// <summary>
/// Minimum value of the number.
/// </summary>
public static readonly float MinValue;
/// <summary>
/// A <see cref="Half"/> whose value is 0.0f.
/// </summary>
public static readonly Half Zero;
/// <summary>
/// A <see cref="Half"/> whose value is 1.0f.
/// </summary>
public static readonly Half One;
/// <summary>
/// Initializes a new instance of the <see cref="Half"/> structure.
/// </summary>
/// <param name = "value">The floating point value that should be stored in 16 bit format.</param>
public Half(float value)
{
this.value = HalfUtils.Pack(value);
}
/// <summary>
/// Gets or sets the raw 16 bit value used to back this half-float.
/// </summary>
public ushort RawValue
{
get { return value; }
set { this.value = value; }
}
/// <summary>
/// Converts an array of half precision values into full precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static float[] ConvertToFloat(Half[] values)
{
float[] results = new float[values.Length];
for (int i = 0; i < results.Length; i++)
results[i] = HalfUtils.Unpack(values[i].RawValue);
return results;
}
/// <summary>
/// Converts an array of full precision values into half precision values.
/// </summary>
/// <param name = "values">The values to be converted.</param>
/// <returns>An array of converted values.</returns>
public static Half[] ConvertToHalf(float[] values)
{
Half[] results = new Half[values.Length];
for (int i = 0; i < results.Length; i++)
results[i] = new Half(values[i]);
return results;
}
/// <summary>
/// Performs an explicit conversion from <see cref = "T:System.Single" /> to <see cref = "T:math.Half" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static explicit operator Half(float value)
{
return new Half(value);
}
/// <summary>
/// Performs an implicit conversion from <see cref = "T:math.Half" /> to <see cref = "T:System.Single" />.
/// </summary>
/// <param name = "value">The value to be converted.</param>
/// <returns>The converted value.</returns>
public static implicit operator float(Half value)
{
return HalfUtils.Unpack(value.value);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has the same value as <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(Half left, Half right)
{
return left.value == right.value;
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name = "left" /> has a different value than <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=(Half left, Half right)
{
return left.value != right.value;
}
/// <summary>
/// Converts the value of the object to its equivalent string representation.
/// </summary>
/// <returns>The string representation of the value of this instance.</returns>
public override string ToString()
{
float num = this;
return num.ToString(CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
ushort num = value;
return ((num * 3) / 2) ^ num;
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name = "value1">The first value.</param>
/// <param name = "value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name = "value1" /> is the same instance as <paramref name = "value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals(ref Half value1, ref Half value2)
{
return value1.value == value2.value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name = "other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals(Half other)
{
return other.value == value;
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name = "obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj.GetType() != GetType())
{
return false;
}
Half half = (Half)obj;
return half.value == value;
}
static Half()
{
Epsilon = 0.0004887581f;
MaxValue = 65504f;
MinValue = 6.103516E-05f;
Zero = (Half)0.0f;
One = (Half)1.0f;
}
}
}

190
math/Half2.cs Normal file
View File

@ -0,0 +1,190 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a two dimensional mathematical vector with half-precision floats.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct Half2 : IEquatable<Half2>
{
/// <summary>
/// Gets or sets the X component of the vector.
/// </summary>
/// <value>The X component of the vector.</value>
public Half X;
/// <summary>
/// Gets or sets the Y component of the vector.
/// </summary>
/// <value>The Y component of the vector.</value>
public Half Y;
/// <summary>
/// Initializes a new instance of the <see cref="Half2"/> structure.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
public Half2(Half x, Half y)
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half2"/> structure.
/// </summary>
/// <param name="value">The value to set for both the X and Y components.</param>
public Half2(Half value)
{
this.X = value;
this.Y = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half2"/> structure.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
public Half2(float x, float y)
{
this.X = (Half)x;
this.Y = (Half)y;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half2"/> structure.
/// </summary>
/// <param name="value">The value to set for both the X and Y components.</param>
public Half2(float value)
{
this.X = (Half)value;
this.Y = (Half)value;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(Half2 left, Half2 right)
{
return Equals(ref left, ref right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise, <c>false</c>.</returns>
[return: MarshalAs(UnmanagedType.U1)]
public static bool operator !=(Half2 left, Half2 right)
{
return !Equals(ref left, ref right);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return (this.Y.GetHashCode() + this.X.GetHashCode());
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name="value1">The first value.</param>
/// <param name="value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name="value1" /> is the same instance as <paramref name="value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals(ref Half2 value1, ref Half2 value2)
{
return ((value1.X == value2.X) && (value1.Y == value2.Y));
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name="other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals(Half2 other)
{
return ((this.X == other.X) && (this.Y == other.Y));
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name="obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj.GetType() != GetType())
{
return false;
}
return this.Equals((Half2)obj);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vec2"/> to <see cref="Half2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Half2(Vec2 value)
{
return new Half2((Half)value.X, (Half)value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Half2"/> to <see cref="Vec2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vec2(Half2 value)
{
return new Vec2(value.X, value.Y);
}
}
}

203
math/Half3.cs Normal file
View File

@ -0,0 +1,203 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a three dimensional mathematical vector with half-precision floats.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct Half3 : IEquatable<Half3>
{
/// <summary>
/// Gets or sets the X component of the vector.
/// </summary>
/// <value>The X component of the vector.</value>
public Half X;
/// <summary>
/// Gets or sets the Y component of the vector.
/// </summary>
/// <value>The Y component of the vector.</value>
public Half Y;
/// <summary>
/// Gets or sets the Z component of the vector.
/// </summary>
/// <value>The Z component of the vector.</value>
public Half Z;
/// <summary>
/// Initializes a new instance of the <see cref="Half3"/> structure.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
/// <param name="z">The Z component.</param>
public Half3(Half x, Half y, Half z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half3"/> structure.
/// </summary>
/// <param name="value">The value to set for the X, Y, and Z components.</param>
public Half3(Half value)
{
this.X = value;
this.Y = value;
this.Z = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half3"/> structure.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
/// <param name="z">The Z component.</param>
public Half3(float x, float y, float z)
{
this.X = (Half)x;
this.Y = (Half)y;
this.Z = (Half)z;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half3"/> structure.
/// </summary>
/// <param name="value">The value to set for the X, Y, and Z components.</param>
public Half3(float value)
{
this.X = (Half)value;
this.Y = (Half)value;
this.Z = (Half)value;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(Half3 left, Half3 right)
{
return Equals(ref left, ref right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise, <c>false</c>.</returns>
[return: MarshalAs(UnmanagedType.U1)]
public static bool operator !=(Half3 left, Half3 right)
{
return !Equals(ref left, ref right);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
int num = this.Z.GetHashCode() + this.Y.GetHashCode();
return (this.X.GetHashCode() + num);
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name="value1">The first value.</param>
/// <param name="value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name="value1" /> is the same instance as <paramref name="value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals(ref Half3 value1, ref Half3 value2)
{
return (((value1.X == value2.X) && (value1.Y == value2.Y)) && (value1.Z == value2.Z));
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name="other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals(Half3 other)
{
return (((this.X == other.X) && (this.Y == other.Y)) && (this.Z == other.Z));
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector3"/> to <see cref="Half3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Half3(Vector3 value)
{
return new Half3((Half)value.X, (Half)value.Y, (Half)value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Half3"/> to <see cref="Vector3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(Half3 value)
{
return new Vector3(value.X, value.Y, value.Z);
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name="obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj.GetType() != GetType())
{
return false;
}
return this.Equals((Half3)obj);
}
}
}

188
math/Half4.cs Normal file
View File

@ -0,0 +1,188 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a four dimensional mathematical vector with half-precision floats.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct Half4 : IEquatable<Half4>
{
/// <summary>
/// Gets or sets the X component of the vector.
/// </summary>
/// <value>The X component of the vector.</value>
public Half X;
/// <summary>
/// Gets or sets the Y component of the vector.
/// </summary>
/// <value>The Y component of the vector.</value>
public Half Y;
/// <summary>
/// Gets or sets the Z component of the vector.
/// </summary>
/// <value>The Z component of the vector.</value>
public Half Z;
/// <summary>
/// Gets or sets the W component of the vector.
/// </summary>
/// <value>The W component of the vector.</value>
public Half W;
/// <summary>
/// Initializes a new instance of the <see cref="Half4"/> structure.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
/// <param name="z">The Z component.</param>
/// <param name="w">The W component.</param>
public Half4(Half x, Half y, Half z, Half w)
{
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
/// <summary>
/// Initializes a new instance of the <see cref="Half4"/> structure.
/// </summary>
/// <param name="value">The value to set for the X, Y, Z, and W components.</param>
public Half4(Half value)
{
this.X = value;
this.Y = value;
this.Z = value;
this.W = value;
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(Half4 left, Half4 right)
{
return Equals(ref left, ref right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=(Half4 left, Half4 right)
{
return !Equals(ref left, ref right);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
int num2 = this.W.GetHashCode() + this.Z.GetHashCode();
int num = this.Y.GetHashCode() + num2;
return (this.X.GetHashCode() + num);
}
/// <summary>
/// Determines whether the specified object instances are considered equal.
/// </summary>
/// <param name="value1">The first value.</param>
/// <param name="value2">The second value.</param>
/// <returns>
/// <c>true</c> if <paramref name="value1" /> is the same instance as <paramref name="value2" /> or
/// if both are <c>null</c> references or if <c>value1.Equals(value2)</c> returns <c>true</c>; otherwise, <c>false</c>.</returns>
public static bool Equals(ref Half4 value1, ref Half4 value2)
{
return (((value1.X == value2.X) && (value1.Y == value2.Y)) && ((value1.Z == value2.Z) && (value1.W == value2.W)));
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to the specified object.
/// </summary>
/// <param name="other">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public bool Equals(Half4 other)
{
return (((this.X == other.X) && (this.Y == other.Y)) && ((this.Z == other.Z) && (this.W == other.W)));
}
/// <summary>
/// Performs an explicit conversion from <see cref="Vector4"/> to <see cref="Half4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Half4(Vector4 value)
{
return new Half4((Half)value.X, (Half)value.Y, (Half)value.Z, (Half)value.W);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Half4"/> to <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector4(Half4 value)
{
return new Vector4(value.X, value.Y, value.Z, value.W);
}
/// <summary>
/// Returns a value that indicates whether the current instance is equal to a specified object.
/// </summary>
/// <param name="obj">Object to make the comparison with.</param>
/// <returns>
/// <c>true</c> if the current instance is equal to the specified object; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj.GetType() != GetType())
{
return false;
}
return this.Equals((Half4)obj);
}
}
}

173
math/HalfUtils.cs Normal file
View File

@ -0,0 +1,173 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Helper class to perform Half/Float conversion.
/// Code extract from paper : www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf by Jeroen van der Zijp
/// </summary>
internal class HalfUtils
{
[StructLayout(LayoutKind.Explicit, Pack = 4)]
private struct FloatToUint
{
[FieldOffset(0)]
public uint UIntValue;
[FieldOffset(0)]
public float FloatValue;
}
/// <summary>
/// Unpacks the specified h.
/// </summary>
/// <param name="h">The packed value.</param>
/// <returns>The float representation of the packed value.</returns>
public static float Unpack(ushort h)
{
var conv = new FloatToUint();
conv.UIntValue = HalfToFloatMantissaTable[HalfToFloatOffsetTable[h >> 10] + (((uint)h) & 0x3ff)] + HalfToFloatExponentTable[h >> 10];
return conv.FloatValue;
}
/// <summary>
/// Packs the specified f.
/// </summary>
/// <param name="f">The float value.</param>
/// <returns>The packed representation of the float value.</returns>
public static ushort Pack(float f)
{
FloatToUint conv = new FloatToUint();
conv.FloatValue = f;
return (ushort)(FloatToHalfBaseTable[(conv.UIntValue >> 23) & 0x1ff] + ((conv.UIntValue & 0x007fffff) >> FloatToHalfShiftTable[(conv.UIntValue >> 23) & 0x1ff]));
}
private static readonly uint[] HalfToFloatMantissaTable = new uint[2048];
private static readonly uint[] HalfToFloatExponentTable = new uint[64];
private static readonly uint[] HalfToFloatOffsetTable = new uint[64];
private static readonly ushort[] FloatToHalfBaseTable = new ushort[512];
private static readonly byte[] FloatToHalfShiftTable = new byte[512];
static HalfUtils()
{
int i;
// -------------------------------------------------------------------
// Half to Float tables
// -------------------------------------------------------------------
// Mantissa table
// 0 => 0
HalfToFloatMantissaTable[0] = 0;
// Transform subnormal to normalized
for (i = 1; i < 1024; i++)
{
uint m = ((uint)i) << 13;
uint e = 0;
while ((m & 0x00800000) == 0)
{
e -= 0x00800000;
m <<= 1;
}
m &= ~0x00800000U;
e += 0x38800000;
HalfToFloatMantissaTable[i] = m | e;
}
// Normal case
for (i = 1024; i < 2048; i++)
HalfToFloatMantissaTable[i] = 0x38000000 + (((uint)(i - 1024)) << 13);
// Exponent table
// 0 => 0
HalfToFloatExponentTable[0] = 0;
for (i = 1; i < 63; i++)
{
if (i < 31) // Positive Numbers
HalfToFloatExponentTable[i] = ((uint)i) << 23;
else // Negative Numbers
HalfToFloatExponentTable[i] = 0x80000000 + (((uint)(i - 32)) << 23);
}
HalfToFloatExponentTable[31] = 0x47800000;
HalfToFloatExponentTable[32] = 0x80000000;
HalfToFloatExponentTable[63] = 0xC7800000;
// Offset table
HalfToFloatOffsetTable[0] = 0;
for (i = 1; i < 64; i++)
HalfToFloatOffsetTable[i] = 1024;
HalfToFloatOffsetTable[32] = 0;
// -------------------------------------------------------------------
// Float to Half tables
// -------------------------------------------------------------------
for (i = 0; i < 256; i++)
{
int e = i - 127;
if (e < -24)
{ // Very small numbers map to zero
FloatToHalfBaseTable[i | 0x000] = 0x0000;
FloatToHalfBaseTable[i | 0x100] = 0x8000;
FloatToHalfShiftTable[i | 0x000] = 24;
FloatToHalfShiftTable[i | 0x100] = 24;
}
else if (e < -14)
{ // Small numbers map to denorms
FloatToHalfBaseTable[i | 0x000] = (ushort)((0x0400 >> (-e - 14)));
FloatToHalfBaseTable[i | 0x100] = (ushort)((0x0400 >> (-e - 14)) | 0x8000);
FloatToHalfShiftTable[i | 0x000] = (byte)(-e - 1);
FloatToHalfShiftTable[i | 0x100] = (byte)(-e - 1);
}
else if (e <= 15)
{ // Normal numbers just lose precision
FloatToHalfBaseTable[i | 0x000] = (ushort)(((e + 15) << 10));
FloatToHalfBaseTable[i | 0x100] = (ushort)(((e + 15) << 10) | 0x8000);
FloatToHalfShiftTable[i | 0x000] = 13;
FloatToHalfShiftTable[i | 0x100] = 13;
}
else if (e < 128)
{ // Large numbers map to Infinity
FloatToHalfBaseTable[i | 0x000] = 0x7C00;
FloatToHalfBaseTable[i | 0x100] = 0xFC00;
FloatToHalfShiftTable[i | 0x000] = 24;
FloatToHalfShiftTable[i | 0x100] = 24;
}
else
{ // Infinity and NaN's stay Infinity and NaN's
FloatToHalfBaseTable[i | 0x000] = 0x7C00;
FloatToHalfBaseTable[i | 0x100] = 0xFC00;
FloatToHalfShiftTable[i | 0x000] = 13;
FloatToHalfShiftTable[i | 0x100] = 13;
}
}
}
}
}

764
math/Int2.cs Normal file
View File

@ -0,0 +1,764 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a three dimensional mathematical vector.
/// </summary>
[DataContract( Name = "Int2")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Int2 : IEquatable<Int2>, IFormattable
{
/// <summary>
/// The size of the <see cref="math.Int2"/> type, in bytes.
/// </summary>
public static readonly int SizeInBytes = Utilities.SizeOf<Int2>();
/// <summary>
/// A <see cref="math.Int2"/> with all of its components set to zero.
/// </summary>
public static readonly Int2 Zero = new Int2();
/// <summary>
/// The X unit <see cref="math.Int2"/> (1, 0, 0).
/// </summary>
public static readonly Int2 UnitX = new Int2(1, 0);
/// <summary>
/// The Y unit <see cref="math.Int2"/> (0, 1, 0).
/// </summary>
public static readonly Int2 UnitY = new Int2(0, 1);
/// <summary>
/// A <see cref="math.Int2"/> with all of its components set to one.
/// </summary>
public static readonly Int2 One = new Int2(1, 1);
/// <summary>
/// The X component of the vector.
/// </summary>
[DataMember( Order = 0 )]
public int X;
/// <summary>
/// The Y component of the vector.
/// </summary>
[DataMember( Order = 1 )]
public int Y;
/// <summary>
/// Initializes a new instance of the <see cref="math.Int2"/> struct.
/// </summary>
/// <param name="value">The value that will be assigned to all components.</param>
public Int2(int value)
{
X = value;
Y = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Int2"/> struct.
/// </summary>
/// <param name="x">Initial value for the X component of the vector.</param>
/// <param name="y">Initial value for the Y component of the vector.</param>
public Int2(int x, int y)
{
X = x;
Y = y;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Int2"/> struct.
/// </summary>
/// <param name="value">A vector containing the values with which to initialize the X and Y components.</param>
public Int2(Vec2 value)
{
X = (int)value.X;
Y = (int)value.Y;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Int2"/> struct.
/// </summary>
/// <param name="values">The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than three elements.</exception>
public Int2(int[] values)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length != 2)
throw new ArgumentOutOfRangeException("values", "There must be two and only two input values for Int2.");
X = values[0];
Y = values[1];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the X or Y component, depending on the index.</value>
/// <param name="index">The index of the component to access. Use 0 for the X component and 1 for the Y component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 1].</exception>
public int this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
}
throw new ArgumentOutOfRangeException("index", "Indices for Int2 run from 0 to 1, inclusive.");
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Int2 run from 0 to 1, inclusive.");
}
}
}
/// <summary>
/// Calculates the length of the vector.
/// </summary>
/// <returns>The length of the vector.</returns>
/// <remarks>
/// <see cref="math.Int2.LengthSquared"/> may be preferred when only the relative length is needed
/// and speed is of the essence.
/// </remarks>
public int Length()
{
return (int)Math.Sqrt((X * X) + (Y * Y));
}
/// <summary>
/// Calculates the squared length of the vector.
/// </summary>
/// <returns>The squared length of the vector.</returns>
/// <remarks>
/// This method may be preferred to <see cref="math.Int2.Length"/> when only a relative length is needed
/// and speed is of the essence.
/// </remarks>
public int LengthSquared()
{
return (X * X) + (Y * Y);
}
/// <summary>
/// Raises the exponent for each components.
/// </summary>
/// <param name="exponent">The exponent.</param>
public void Pow(int exponent)
{
X = (int)Math.Pow(X, exponent);
Y = (int)Math.Pow(Y, exponent);
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>
/// <returns>A two-element array containing the components of the vector.</returns>
public int[] ToArray()
{
return new int[] { X, Y };
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <param name="result">When the method completes, contains the sum of the two vectors.</param>
public static void Add(ref Int2 left, ref Int2 right, out Int2 result)
{
result = new Int2(left.X + right.X, left.Y + right.Y);
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int2 Add(Int2 left, Int2 right)
{
return new Int2(left.X + right.X, left.Y + right.Y);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <param name="result">When the method completes, contains the difference of the two vectors.</param>
public static void Subtract(ref Int2 left, ref Int2 right, out Int2 result)
{
result = new Int2(left.X - right.X, left.Y - right.Y);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int2 Subtract(Int2 left, Int2 right)
{
return new Int2(left.X - right.X, left.Y - right.Y);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <param name="result">When the method completes, contains the scaled vector.</param>
public static void Multiply(ref Int2 value, int scale, out Int2 result)
{
result = new Int2(value.X * scale, value.Y * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int2 Multiply(Int2 value, int scale)
{
return new Int2(value.X * scale, value.Y * scale);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name="left">The first vector to modulate.</param>
/// <param name="right">The second vector to modulate.</param>
/// <param name="result">When the method completes, contains the modulated vector.</param>
public static void Modulate(ref Int2 left, ref Int2 right, out Int2 result)
{
result = new Int2(left.X * right.X, left.Y * right.Y);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name="left">The first vector to modulate.</param>
/// <param name="right">The second vector to modulate.</param>
/// <returns>The modulated vector.</returns>
public static Int2 Modulate(Int2 left, Int2 right)
{
return new Int2(left.X * right.X, left.Y * right.Y);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <param name="result">When the method completes, contains the scaled vector.</param>
public static void Divide(ref Int2 value, int scale, out Int2 result)
{
result = new Int2(value.X / scale, value.Y / scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int2 Divide(Int2 value, int scale)
{
return new Int2(value.X / scale, value.Y / scale);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <param name="result">When the method completes, contains a vector facing in the opposite direction.</param>
public static void Negate(ref Int2 value, out Int2 result)
{
result = new Int2(-value.X, -value.Y);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int2 Negate(Int2 value)
{
return new Int2(-value.X, -value.Y);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <param name="result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref Int2 value, ref Int2 min, ref Int2 max, out Int2 result)
{
int x = value.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
int y = value.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
result = new Int2(x, y);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static Int2 Clamp(Int2 value, Int2 min, Int2 max)
{
Int2 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">First source vector.</param>
/// <param name="right">Second source vector.</param>
/// <param name="result">When the method completes, contains the dot product of the two vectors.</param>
public static void Dot(ref Int2 left, ref Int2 right, out int result)
{
result = (left.X * right.X) + (left.Y * right.Y);
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">First source vector.</param>
/// <param name="right">Second source vector.</param>
/// <returns>The dot product of the two vectors.</returns>
public static int Dot(Int2 left, Int2 right)
{
return (left.X * right.X) + (left.Y * right.Y);
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the linear interpolation of the two vectors.</param>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static void Lerp(ref Int2 start, ref Int2 end, float amount, out Int2 result)
{
result.X = (int)(start.X + ((end.X - start.X) * amount));
result.Y = (int)(start.Y + ((end.Y - start.Y) * amount));
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The linear interpolation of the two vectors.</returns>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static Int2 Lerp(Int2 start, Int2 end, float amount)
{
Int2 result;
Lerp(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Performs a cubic interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the cubic interpolation of the two vectors.</param>
public static void SmoothStep(ref Int2 start, ref Int2 end, float amount, out Int2 result)
{
amount = (amount > 1) ? 1 : ((amount < 0) ? 0 : amount);
amount = (amount * amount) * (3 - (2 * amount));
result.X = (int)(start.X + ((end.X - start.X) * amount));
result.Y = (int)(start.Y + ((end.Y - start.Y) * amount));
}
/// <summary>
/// Performs a cubic interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The cubic interpolation of the two vectors.</returns>
public static Int2 SmoothStep(Int2 start, Int2 end, float amount)
{
Int2 result;
SmoothStep(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <param name="result">When the method completes, contains an new vector composed of the largest components of the source vectors.</param>
public static void Max(ref Int2 left, ref Int2 right, out Int2 result)
{
result.X = (left.X > right.X) ? left.X : right.X;
result.Y = (left.Y > right.Y) ? left.Y : right.Y;
}
/// <summary>
/// Returns a vector containing the largest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>A vector containing the largest components of the source vectors.</returns>
public static Int2 Max(Int2 left, Int2 right)
{
Int2 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <param name="result">When the method completes, contains an new vector composed of the smallest components of the source vectors.</param>
public static void Min(ref Int2 left, ref Int2 right, out Int2 result)
{
result.X = (left.X < right.X) ? left.X : right.X;
result.Y = (left.Y < right.Y) ? left.Y : right.Y;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>A vector containing the smallest components of the source vectors.</returns>
public static Int2 Min(Int2 left, Int2 right)
{
Int2 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int2 operator +(Int2 left, Int2 right)
{
return new Int2(left.X + right.X, left.Y + right.Y);
}
/// <summary>
/// Assert a vector (return it unchanged).
/// </summary>
/// <param name="value">The vector to assert (unchange).</param>
/// <returns>The asserted (unchanged) vector.</returns>
public static Int2 operator +(Int2 value)
{
return value;
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int2 operator -(Int2 left, Int2 right)
{
return new Int2(left.X - right.X, left.Y - right.Y);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int2 operator -(Int2 value)
{
return new Int2(-value.X, -value.Y);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int2 operator *(float scale, Int2 value)
{
return new Int2((int)(value.X * scale), (int)(value.Y * scale));
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int2 operator *(Int2 value, float scale)
{
return new Int2((int)(value.X * scale), (int)(value.Y * scale));
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int2 operator /(Int2 value, float scale)
{
return new Int2((int)(value.X / scale), (int)(value.Y / scale));
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Int2 left, Int2 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Int2 left, Int2 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref="math.Int2"/> to <see cref="Vec2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vec2(Int2 value)
{
return new Vec2(value.X, value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref="math.Int2"/> to <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector4(Int2 value)
{
return new Vector4(value.X, value.Y, 0, 0);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X, Y);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X.ToString(format, CultureInfo.CurrentCulture), Y.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "X:{0} Y:{1}", X, Y);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, "X:{0} Y:{1}", X.ToString(format, formatProvider), Y.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="math.Int2"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="math.Int2"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="math.Int2"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Int2 other)
{
return ((float)Math.Abs(other.X - X) < MathUtil.ZeroTolerance &&
(float)Math.Abs(other.Y - Y) < MathUtil.ZeroTolerance);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Int2)value);
}
#if WPFInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Int2"/> to <see cref="System.Windows.Media.Media3D.Int3D"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator System.Windows.Media.Media3D.Int3D(Int2 value)
{
return new System.Windows.Media.Media3D.Int3D(value.X, value.Y, 0.0f);
}
/// <summary>
/// Performs an explicit conversion from <see cref="System.Windows.Media.Media3D.Int3D"/> to <see cref="math.Int2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Int2(System.Windows.Media.Media3D.Int3D value)
{
return new Int2((float)value.X, (float)value.Y);
}
#endif
#if XnaInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Int2"/> to <see cref="Microsoft.Xna.Framework.Int2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Microsoft.Xna.Framework.Int2(Int2 value)
{
return new Microsoft.Xna.Framework.Int2(value.X, value.Y);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Int2"/> to <see cref="math.Int2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Int2(Microsoft.Xna.Framework.Int2 value)
{
return new Int2(value.X, value.Y);
}
#endif
}
}

805
math/Int3.cs Normal file
View File

@ -0,0 +1,805 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a three dimensional mathematical vector.
/// </summary>
[DataContract( Name = "Int3")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Int3 : IEquatable<Int3>, IFormattable
{
/// <summary>
/// The size of the <see cref="Int3"/> type, in bytes.
/// </summary>
public static readonly int SizeInBytes = Utilities.SizeOf<Int3>();
/// <summary>
/// A <see cref="Int3"/> with all of its components set to zero.
/// </summary>
public static readonly Int3 Zero = new Int3();
/// <summary>
/// The X unit <see cref="Int3"/> (1, 0, 0).
/// </summary>
public static readonly Int3 UnitX = new Int3(1, 0, 0);
/// <summary>
/// The Y unit <see cref="Int3"/> (0, 1, 0).
/// </summary>
public static readonly Int3 UnitY = new Int3(0, 1, 0);
/// <summary>
/// The Z unit <see cref="Int3"/> (0, 0, 1).
/// </summary>
public static readonly Int3 UnitZ = new Int3(0, 0, 1);
/// <summary>
/// A <see cref="Int3"/> with all of its components set to one.
/// </summary>
public static readonly Int3 One = new Int3(1, 1, 1);
/// <summary>
/// The X component of the vector.
/// </summary>
[DataMember( Order = 0 )]
public int X;
/// <summary>
/// The Y component of the vector.
/// </summary>
[DataMember( Order = 1 )]
public int Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
[DataMember( Order = 2 )]
public int Z;
/// <summary>
/// Initializes a new instance of the <see cref="Int3"/> struct.
/// </summary>
/// <param name="value">The value that will be assigned to all components.</param>
public Int3(int value)
{
X = value;
Y = value;
Z = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Int3"/> struct.
/// </summary>
/// <param name="x">Initial value for the X component of the vector.</param>
/// <param name="y">Initial value for the Y component of the vector.</param>
/// <param name="z">Initial value for the Z component of the vector.</param>
public Int3(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
/// <summary>
/// Initializes a new instance of the <see cref="Int3"/> struct.
/// </summary>
/// <param name="value">A vector containing the values with which to initialize the X and Y components.</param>
/// <param name="z">Initial value for the Z component of the vector.</param>
public Int3(Vec2 value, int z)
{
X = (int)value.X;
Y = (int)value.Y;
Z = z;
}
/// <summary>
/// Initializes a new instance of the <see cref="Int3"/> struct.
/// </summary>
/// <param name="values">The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than three elements.</exception>
public Int3(int[] values)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length != 3)
throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Int3.");
X = values[0];
Y = values[1];
Z = values[2];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the X, Y, or Z component, depending on the index.</value>
/// <param name="index">The index of the component to access. Use 0 for the X component, 1 for the Y component, and 2 for the Z component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 2].</exception>
public int this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
}
throw new ArgumentOutOfRangeException("index", "Indices for Int3 run from 0 to 2, inclusive.");
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
case 2: Z = value; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Int3 run from 0 to 2, inclusive.");
}
}
}
/// <summary>
/// Calculates the length of the vector.
/// </summary>
/// <returns>The length of the vector.</returns>
/// <remarks>
/// <see cref="Int3.LengthSquared"/> may be preferred when only the relative length is needed
/// and speed is of the essence.
/// </remarks>
public int Length()
{
return (int)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
}
/// <summary>
/// Calculates the squared length of the vector.
/// </summary>
/// <returns>The squared length of the vector.</returns>
/// <remarks>
/// This method may be preferred to <see cref="Int3.Length"/> when only a relative length is needed
/// and speed is of the essence.
/// </remarks>
public int LengthSquared()
{
return (X * X) + (Y * Y) + (Z * Z);
}
/// <summary>
/// Raises the exponent for each components.
/// </summary>
/// <param name="exponent">The exponent.</param>
public void Pow(int exponent)
{
X = (int)Math.Pow(X, exponent);
Y = (int)Math.Pow(Y, exponent);
Z = (int)Math.Pow(Z, exponent);
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>
/// <returns>A three-element array containing the components of the vector.</returns>
public int[] ToArray()
{
return new int[] { X, Y, Z };
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <param name="result">When the method completes, contains the sum of the two vectors.</param>
public static void Add(ref Int3 left, ref Int3 right, out Int3 result)
{
result = new Int3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int3 Add(Int3 left, Int3 right)
{
return new Int3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <param name="result">When the method completes, contains the difference of the two vectors.</param>
public static void Subtract(ref Int3 left, ref Int3 right, out Int3 result)
{
result = new Int3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int3 Subtract(Int3 left, Int3 right)
{
return new Int3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <param name="result">When the method completes, contains the scaled vector.</param>
public static void Multiply(ref Int3 value, int scale, out Int3 result)
{
result = new Int3(value.X * scale, value.Y * scale, value.Z * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int3 Multiply(Int3 value, int scale)
{
return new Int3(value.X * scale, value.Y * scale, value.Z * scale);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name="left">The first vector to modulate.</param>
/// <param name="right">The second vector to modulate.</param>
/// <param name="result">When the method completes, contains the modulated vector.</param>
public static void Modulate(ref Int3 left, ref Int3 right, out Int3 result)
{
result = new Int3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name="left">The first vector to modulate.</param>
/// <param name="right">The second vector to modulate.</param>
/// <returns>The modulated vector.</returns>
public static Int3 Modulate(Int3 left, Int3 right)
{
return new Int3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <param name="result">When the method completes, contains the scaled vector.</param>
public static void Divide(ref Int3 value, int scale, out Int3 result)
{
result = new Int3(value.X / scale, value.Y / scale, value.Z / scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int3 Divide(Int3 value, int scale)
{
return new Int3(value.X / scale, value.Y / scale, value.Z / scale);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <param name="result">When the method completes, contains a vector facing in the opposite direction.</param>
public static void Negate(ref Int3 value, out Int3 result)
{
result = new Int3(-value.X, -value.Y, -value.Z);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int3 Negate(Int3 value)
{
return new Int3(-value.X, -value.Y, -value.Z);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <param name="result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref Int3 value, ref Int3 min, ref Int3 max, out Int3 result)
{
int x = value.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
int y = value.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
int z = value.Z;
z = (z > max.Z) ? max.Z : z;
z = (z < min.Z) ? min.Z : z;
result = new Int3(x, y, z);
}
/// <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.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static Int3 Clamp(Int3 value, Int3 min, Int3 max)
{
Int3 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">First source vector.</param>
/// <param name="right">Second source vector.</param>
/// <param name="result">When the method completes, contains the dot product of the two vectors.</param>
public static void Dot(ref Int3 left, ref Int3 right, out int result)
{
result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z);
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="left">First source vector.</param>
/// <param name="right">Second source vector.</param>
/// <returns>The dot product of the two vectors.</returns>
public static int Dot(Int3 left, Int3 right)
{
return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z);
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the linear interpolation of the two vectors.</param>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static void Lerp(ref Int3 start, ref Int3 end, float amount, out Int3 result)
{
result.X = (int)(start.X + ((end.X - start.X) * amount));
result.Y = (int)(start.Y + ((end.Y - start.Y) * amount));
result.Z = (int)(start.Z + ((end.Z - start.Z) * amount));
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The linear interpolation of the two vectors.</returns>
/// <remarks>
/// This method performs the linear interpolation based on the following formula.
/// <code>start + (end - start) * amount</code>
/// Passing <paramref name="amount"/> a value of 0 will cause <paramref name="start"/> to be returned; a value of 1 will cause <paramref name="end"/> to be returned.
/// </remarks>
public static Int3 Lerp(Int3 start, Int3 end, float amount)
{
Int3 result;
Lerp(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Performs a cubic interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <param name="result">When the method completes, contains the cubic interpolation of the two vectors.</param>
public static void SmoothStep(ref Int3 start, ref Int3 end, float amount, out Int3 result)
{
amount = (amount > 1) ? 1 : ((amount < 0) ? 0 : amount);
amount = (amount * amount) * (3 - (2 * amount));
result.X = (int)(start.X + ((end.X - start.X) * amount));
result.Y = (int)(start.Y + ((end.Y - start.Y) * amount));
result.Z = (int)(start.Z + ((end.Z - start.Z) * amount));
}
/// <summary>
/// Performs a cubic interpolation between two vectors.
/// </summary>
/// <param name="start">Start vector.</param>
/// <param name="end">End vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of <paramref name="end"/>.</param>
/// <returns>The cubic interpolation of the two vectors.</returns>
public static Int3 SmoothStep(Int3 start, Int3 end, float amount)
{
Int3 result;
SmoothStep(ref start, ref end, amount, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <param name="result">When the method completes, contains an new vector composed of the largest components of the source vectors.</param>
public static void Max(ref Int3 left, ref Int3 right, out Int3 result)
{
result.X = (left.X > right.X) ? left.X : right.X;
result.Y = (left.Y > right.Y) ? left.Y : right.Y;
result.Z = (left.Z > right.Z) ? left.Z : right.Z;
}
/// <summary>
/// Returns a vector containing the largest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>A vector containing the largest components of the source vectors.</returns>
public static Int3 Max(Int3 left, Int3 right)
{
Int3 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <param name="result">When the method completes, contains an new vector composed of the smallest components of the source vectors.</param>
public static void Min(ref Int3 left, ref Int3 right, out Int3 result)
{
result.X = (left.X < right.X) ? left.X : right.X;
result.Y = (left.Y < right.Y) ? left.Y : right.Y;
result.Z = (left.Z < right.Z) ? left.Z : right.Z;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>A vector containing the smallest components of the source vectors.</returns>
public static Int3 Min(Int3 left, Int3 right)
{
Int3 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="left">The first vector to add.</param>
/// <param name="right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int3 operator +(Int3 left, Int3 right)
{
return new Int3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
}
/// <summary>
/// Assert a vector (return it unchanged).
/// </summary>
/// <param name="value">The vector to assert (unchange).</param>
/// <returns>The asserted (unchanged) vector.</returns>
public static Int3 operator +(Int3 value)
{
return value;
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name="left">The first vector to subtract.</param>
/// <param name="right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int3 operator -(Int3 left, Int3 right)
{
return new Int3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name="value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int3 operator -(Int3 value)
{
return new Int3(-value.X, -value.Y, -value.Z);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int3 operator *(float scale, Int3 value)
{
return new Int3((int)(value.X * scale), (int)(value.Y * scale), (int)(value.Z * scale));
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int3 operator *(Int3 value, float scale)
{
return new Int3((int)(value.X * scale), (int)(value.Y * scale), (int)(value.Z * scale));
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name="value">The vector to scale.</param>
/// <param name="scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int3 operator /(Int3 value, float scale)
{
return new Int3((int)(value.X / scale), (int)(value.Y / scale), (int)(value.Z / scale));
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Int3 left, Int3 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Int3 left, Int3 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Int3"/> to <see cref="Vec2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vec2(Int3 value)
{
return new Vec2(value.X, value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Int3"/> to <see cref="Vector3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(Int3 value)
{
return new Vector3(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Int3"/> to <see cref="Vector4"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector4(Int3 value)
{
return new Vector4(value.X, value.Y, value.Z, 0);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X, Y, Z);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X.ToString(format, CultureInfo.CurrentCulture),
Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X, Y, Z);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString(formatProvider);
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X.ToString(format, formatProvider),
Y.ToString(format, formatProvider), Z.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="Int3"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="Int3"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="Int3"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Int3 other)
{
return ((float)Math.Abs(other.X - X) < MathUtil.ZeroTolerance &&
(float)Math.Abs(other.Y - Y) < MathUtil.ZeroTolerance &&
(float)Math.Abs(other.Z - Z) < MathUtil.ZeroTolerance);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Int3)value);
}
#if WPFInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Int3"/> to <see cref="System.Windows.Media.Media3D.Int3D"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator System.Windows.Media.Media3D.Int3D(Int3 value)
{
return new System.Windows.Media.Media3D.Int3D(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref="System.Windows.Media.Media3D.Int3D"/> to <see cref="math.Int3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Int3(System.Windows.Media.Media3D.Int3D value)
{
return new Int3((float)value.X, (float)value.Y, (float)value.Z);
}
#endif
#if XnaInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Int3"/> to <see cref="Microsoft.Xna.Framework.Int3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Microsoft.Xna.Framework.Int3(Int3 value)
{
return new Microsoft.Xna.Framework.Int3(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Int3"/> to <see cref="math.Int3"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Int3(Microsoft.Xna.Framework.Int3 value)
{
return new Int3(value.X, value.Y, value.Z);
}
#endif
}
}

700
math/Int4.cs Normal file
View File

@ -0,0 +1,700 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a four dimensional mathematical vector.
/// </summary>
[DataContract( Name = "Int4")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Int4 : IEquatable<Int4>, IFormattable
{
/// <summary>
/// The size of the <see cref = "Int4" /> type, in bytes.
/// </summary>
public static readonly int SizeInBytes = Utilities.SizeOf<Int4>();
/// <summary>
/// A <see cref = "Int4" /> with all of its components set to zero.
/// </summary>
public static readonly Int4 Zero = new Int4();
/// <summary>
/// The X unit <see cref = "Int4" /> (1, 0, 0, 0).
/// </summary>
public static readonly Int4 UnitX = new Int4(1, 0, 0, 0);
/// <summary>
/// The Y unit <see cref = "Int4" /> (0, 1, 0, 0).
/// </summary>
public static readonly Int4 UnitY = new Int4(0, 1, 0, 0);
/// <summary>
/// The Z unit <see cref = "Int4" /> (0, 0, 1, 0).
/// </summary>
public static readonly Int4 UnitZ = new Int4(0, 0, 1, 0);
/// <summary>
/// The W unit <see cref = "Int4" /> (0, 0, 0, 1).
/// </summary>
public static readonly Int4 UnitW = new Int4(0, 0, 0, 1);
/// <summary>
/// A <see cref = "Int4" /> with all of its components set to one.
/// </summary>
public static readonly Int4 One = new Int4(1, 1, 1, 1);
/// <summary>
/// The X component of the vector.
/// </summary>
[DataMember( Order = 0 )]
public int X;
/// <summary>
/// The Y component of the vector.
/// </summary>
[DataMember( Order = 1 )]
public int Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
[DataMember( Order = 2 )]
public int Z;
/// <summary>
/// The W component of the vector.
/// </summary>
[DataMember( Order = 3 )]
public int W;
/// <summary>
/// Initializes a new instance of the <see cref = "Int4" /> struct.
/// </summary>
/// <param name = "value">The value that will be assigned to all components.</param>
public Int4(int value)
{
X = value;
Y = value;
Z = value;
W = value;
}
/// <summary>
/// Initializes a new instance of the <see cref = "Int4" /> struct.
/// </summary>
/// <param name = "x">Initial value for the X component of the vector.</param>
/// <param name = "y">Initial value for the Y component of the vector.</param>
/// <param name = "z">Initial value for the Z component of the vector.</param>
/// <param name = "w">Initial value for the W component of the vector.</param>
public Int4(int x, int y, int z, int w)
{
X = x;
Y = y;
Z = z;
W = w;
}
/// <summary>
/// Initializes a new instance of the <see cref = "Int4" /> struct.
/// </summary>
/// <param name = "values">The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements.</param>
/// <exception cref = "ArgumentNullException">Thrown when <paramref name = "values" /> is <c>null</c>.</exception>
/// <exception cref = "ArgumentOutOfRangeException">Thrown when <paramref name = "values" /> contains more or less than four elements.</exception>
public Int4(int[] values)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length != 4)
throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Int4.");
X = values[0];
Y = values[1];
Z = values[2];
W = values[3];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the X, Y, Z, or W component, depending on the index.</value>
/// <param name = "index">The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref = "System.ArgumentOutOfRangeException">Thrown when the <paramref name = "index" /> is out of the range [0, 3].</exception>
public int this[int index]
{
get
{
switch (index)
{
case 0:
return X;
case 1:
return Y;
case 2:
return Z;
case 3:
return W;
}
throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive.");
}
set
{
switch (index)
{
case 0:
X = value;
break;
case 1:
Y = value;
break;
case 2:
Z = value;
break;
case 3:
W = value;
break;
default:
throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive.");
}
}
}
/// <summary>
/// Calculates the length of the vector.
/// </summary>
/// <returns>The length of the vector.</returns>
/// <remarks>
/// <see cref="Int4.LengthSquared"/> may be preferred when only the relative length is needed
/// and speed is of the essence.
/// </remarks>
public int Length()
{
return (int)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W));
}
/// <summary>
/// Calculates the squared length of the vector.
/// </summary>
/// <returns>The squared length of the vector.</returns>
/// <remarks>
/// This method may be preferred to <see cref="Int4.Length"/> when only a relative length is needed
/// and speed is of the essence.
/// </remarks>
public int LengthSquared()
{
return (X * X) + (Y * Y) + (Z * Z) + (W * W);
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>
/// <returns>A four-element array containing the components of the vector.</returns>
public int[] ToArray()
{
return new int[] { X, Y, Z, W };
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <param name = "result">When the method completes, contains the sum of the two vectors.</param>
public static void Add(ref Int4 left, ref Int4 right, out Int4 result)
{
result = new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int4 Add(Int4 left, Int4 right)
{
return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <param name = "result">When the method completes, contains the difference of the two vectors.</param>
public static void Subtract(ref Int4 left, ref Int4 right, out Int4 result)
{
result = new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int4 Subtract(Int4 left, Int4 right)
{
return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <param name = "result">When the method completes, contains the scaled vector.</param>
public static void Multiply(ref Int4 value, int scale, out Int4 result)
{
result = new Int4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int4 Multiply(Int4 value, int scale)
{
return new Int4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name = "left">The first vector to modulate.</param>
/// <param name = "right">The second vector to modulate.</param>
/// <param name = "result">When the method completes, contains the modulated vector.</param>
public static void Modulate(ref Int4 left, ref Int4 right, out Int4 result)
{
result = new Int4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name = "left">The first vector to modulate.</param>
/// <param name = "right">The second vector to modulate.</param>
/// <returns>The modulated vector.</returns>
public static Int4 Modulate(Int4 left, Int4 right)
{
return new Int4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <param name = "result">When the method completes, contains the scaled vector.</param>
public static void Divide(ref Int4 value, int scale, out Int4 result)
{
result = new Int4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int4 Divide(Int4 value, int scale)
{
return new Int4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name = "value">The vector to negate.</param>
/// <param name = "result">When the method completes, contains a vector facing in the opposite direction.</param>
public static void Negate(ref Int4 value, out Int4 result)
{
result = new Int4(-value.X, -value.Y, -value.Z, -value.W);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name = "value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int4 Negate(Int4 value)
{
return new Int4(-value.X, -value.Y, -value.Z, -value.W);
}
/// <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.</param>
/// <param name = "max">The maximum value.</param>
/// <param name = "result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref Int4 value, ref Int4 min, ref Int4 max, out Int4 result)
{
int x = value.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
int y = value.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
int z = value.Z;
z = (z > max.Z) ? max.Z : z;
z = (z < min.Z) ? min.Z : z;
int w = value.W;
w = (w > max.W) ? max.W : w;
w = (w < min.W) ? min.W : w;
result = new Int4(x, y, z, w);
}
/// <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.</param>
/// <param name = "max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static Int4 Clamp(Int4 value, Int4 min, Int4 max)
{
Int4 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <param name = "result">When the method completes, contains an new vector composed of the largest components of the source vectors.</param>
public static void Max(ref Int4 left, ref Int4 right, out Int4 result)
{
result.X = (left.X > right.X) ? left.X : right.X;
result.Y = (left.Y > right.Y) ? left.Y : right.Y;
result.Z = (left.Z > right.Z) ? left.Z : right.Z;
result.W = (left.W > right.W) ? left.W : right.W;
}
/// <summary>
/// Returns a vector containing the largest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <returns>A vector containing the largest components of the source vectors.</returns>
public static Int4 Max(Int4 left, Int4 right)
{
Int4 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <param name = "result">When the method completes, contains an new vector composed of the smallest components of the source vectors.</param>
public static void Min(ref Int4 left, ref Int4 right, out Int4 result)
{
result.X = (left.X < right.X) ? left.X : right.X;
result.Y = (left.Y < right.Y) ? left.Y : right.Y;
result.Z = (left.Z < right.Z) ? left.Z : right.Z;
result.W = (left.W < right.W) ? left.W : right.W;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <returns>A vector containing the smallest components of the source vectors.</returns>
public static Int4 Min(Int4 left, Int4 right)
{
Int4 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static Int4 operator +(Int4 left, Int4 right)
{
return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Assert a vector (return it unchanged).
/// </summary>
/// <param name = "value">The vector to assert (unchange).</param>
/// <returns>The asserted (unchanged) vector.</returns>
public static Int4 operator +(Int4 value)
{
return value;
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static Int4 operator -(Int4 left, Int4 right)
{
return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Reverses the direction of a given vector.
/// </summary>
/// <param name = "value">The vector to negate.</param>
/// <returns>A vector facing in the opposite direction.</returns>
public static Int4 operator -(Int4 value)
{
return new Int4(-value.X, -value.Y, -value.Z, -value.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int4 operator *(int scale, Int4 value)
{
return new Int4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int4 operator *(Int4 value, int scale)
{
return new Int4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static Int4 operator /(Int4 value, int scale)
{
return new Int4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name = "left" /> has the same value as <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(Int4 left, Int4 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name = "left" /> has a different value than <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=(Int4 left, Int4 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "Int4" /> to <see cref = "Vec2" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vec2(Int4 value)
{
return new Vec2(value.X, value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "Int4" /> to <see cref = "Vector3" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(Int4 value)
{
return new Vector3(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "Int4" /> to <see cref = "Vector4" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector4(Int4 value)
{
return new Vector4(value.X, value.Y, value.Z, value.W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "format">The format.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}",
X.ToString(format, CultureInfo.CurrentCulture),
Y.ToString(format, CultureInfo.CurrentCulture),
Z.ToString(format, CultureInfo.CurrentCulture),
W.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "formatProvider">The format provider.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "format">The format.</param>
/// <param name = "formatProvider">The format provider.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
ToString(formatProvider);
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider),
Y.ToString(format, formatProvider), Z.ToString(format, formatProvider),
W.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref = "Int4" /> is equal to this instance.
/// </summary>
/// <param name = "other">The <see cref = "Int4" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref = "Int4" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Int4 other)
{
return other.X == X && other.Y == Y && other.Z == Z && other.W == W;
}
/// <summary>
/// Determines whether the specified <see cref = "object" /> is equal to this instance.
/// </summary>
/// <param name = "value">The <see cref = "object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref = "object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Int4)value);
}
/// <summary>
/// Performs an implicit conversion from <see cref="int"/> array to <see cref="math.Int4"/>.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Int4(int[] input)
{
return new Int4(input);
}
/// <summary>
/// Performs an implicit conversion from <see cref="math.Int4"/> to <see cref="int"/> array.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator int[](Int4 input)
{
return input.ToArray();
}
}
}

656
math/MathUtil.cs Normal file
View File

@ -0,0 +1,656 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Common utility methods for math operations.
/// </summary>
public static class MathUtil
{
/// <summary>
/// The value for which all absolute numbers smaller than are considered equal to zero.
/// </summary>
public const float ZeroTolerance = 1e-6f; // Value a 8x higher than 1.19209290E-07F
/// <summary>
/// The value for which all absolute numbers smaller than are considered equal to zero.
/// </summary>
public const double ZeroToleranceDouble = double.Epsilon * 8;
/// <summary>
/// A value specifying the approximation of π which is 180 degrees.
/// </summary>
public const float Pi = (float)Math.PI;
/// <summary>
/// A value specifying the approximation of 2π which is 360 degrees.
/// </summary>
public const float TwoPi = (float)(2 * Math.PI);
/// <summary>
/// A value specifying the approximation of π/2 which is 90 degrees.
/// </summary>
public const float PiOverTwo = (float)(Math.PI / 2);
/// <summary>
/// A value specifying the approximation of π/4 which is 45 degrees.
/// </summary>
public const float PiOverFour = (float)(Math.PI / 4);
/// <summary>
/// Checks if a and b are almost equals, taking into account the magnitude of floating point numbers (unlike <see cref="WithinEpsilon"/> method). See Remarks.
/// See remarks.
/// </summary>
/// <param name="a">The left value to compare.</param>
/// <param name="b">The right value to compare.</param>
/// <returns><c>true</c> if a almost equal to b, <c>false</c> otherwise</returns>
/// <remarks>
/// The code is using the technique described by Bruce Dawson in
/// <a href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">Comparing Floating point numbers 2012 edition</a>.
/// </remarks>
public static unsafe bool NearEqual(float a, float b)
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
if (IsZero(a - b))
return true;
// Original from Bruce Dawson: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
int aInt = *(int*)&a;
int bInt = *(int*)&b;
// Different signs means they do not match.
if ((aInt < 0) != (bInt < 0))
return false;
// Find the difference in ULPs.
int ulp = Math.Abs(aInt - bInt);
// Choose of maxUlp = 4
// according to http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h
const int maxUlp = 4;
return (ulp <= maxUlp);
}
/// <summary>
/// Determines whether the specified value is close to zero (0.0f).
/// </summary>
/// <param name="a">The floating value.</param>
/// <returns><c>true</c> if the specified value is close to zero (0.0f); otherwise, <c>false</c>.</returns>
public static bool IsZero(float a)
{
return Math.Abs(a) < ZeroTolerance;
}
/// <summary>
/// Determines whether the specified value is close to zero (0.0f).
/// </summary>
/// <param name="a">The floating value.</param>
/// <returns><c>true</c> if the specified value is close to zero (0.0f); otherwise, <c>false</c>.</returns>
public static bool IsZero(double a)
{
return Math.Abs(a) < ZeroToleranceDouble;
}
/// <summary>
/// Determines whether the specified value is close to one (1.0f).
/// </summary>
/// <param name="a">The floating value.</param>
/// <returns><c>true</c> if the specified value is close to one (1.0f); otherwise, <c>false</c>.</returns>
public static bool IsOne(float a)
{
return IsZero(a - 1.0f);
}
/// <summary>
/// Checks if a - b are almost equals within a float epsilon.
/// </summary>
/// <param name="a">The left value to compare.</param>
/// <param name="b">The right value to compare.</param>
/// <param name="epsilon">Epsilon value</param>
/// <returns><c>true</c> if a almost equal to b within a float epsilon, <c>false</c> otherwise</returns>
public static bool WithinEpsilon(float a, float b, float epsilon)
{
float num = a - b;
return ((-epsilon <= num) && (num <= epsilon));
}
/// <summary>
/// Creates a one-dimensional array of the specified <typeparamref name="T"/> and <paramref name="length"/> filled with the specified <paramref name="value"/>.
/// </summary>
/// <typeparam name="T">The Type of the array to create.</typeparam>
/// <param name="value">The value to fill the array with.</param>
/// <param name="length">The size of the array to create.</param>
/// <returns>A new one-dimensional array of the specified type with the specified length and filled with the specified value.</returns>
public static T[] Array<T>(T value, int length)
{
var result = new T[length];
for (var i = 0; i < length; i++)
result[i] = value;
return result;
}
/// <summary>
/// Converts revolutions to degrees.
/// </summary>
/// <param name="revolution">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RevolutionsToDegrees(float revolution)
{
return revolution * 360.0f;
}
/// <summary>
/// Converts revolutions to radians.
/// </summary>
/// <param name="revolution">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RevolutionsToRadians(float revolution)
{
return revolution * TwoPi;
}
/// <summary>
/// Converts revolutions to gradians.
/// </summary>
/// <param name="revolution">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RevolutionsToGradians(float revolution)
{
return revolution * 400.0f;
}
/// <summary>
/// Converts degrees to revolutions.
/// </summary>
/// <param name="degree">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float DegreesToRevolutions(float degree)
{
return degree / 360.0f;
}
/// <summary>
/// Converts degrees to radians.
/// </summary>
/// <param name="degree">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float DegreesToRadians(float degree)
{
return degree * (Pi / 180.0f);
}
/// <summary>
/// Converts radians to revolutions.
/// </summary>
/// <param name="radian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RadiansToRevolutions(float radian)
{
return radian / TwoPi;
}
/// <summary>
/// Converts radians to gradians.
/// </summary>
/// <param name="radian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RadiansToGradians(float radian)
{
return radian * (200.0f / Pi);
}
/// <summary>
/// Converts gradians to revolutions.
/// </summary>
/// <param name="gradian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float GradiansToRevolutions(float gradian)
{
return gradian / 400.0f;
}
/// <summary>
/// Converts gradians to degrees.
/// </summary>
/// <param name="gradian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float GradiansToDegrees(float gradian)
{
return gradian * (9.0f / 10.0f);
}
/// <summary>
/// Converts gradians to radians.
/// </summary>
/// <param name="gradian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float GradiansToRadians(float gradian)
{
return gradian * (Pi / 200.0f);
}
/// <summary>
/// Converts radians to degrees.
/// </summary>
/// <param name="radian">The value to convert.</param>
/// <returns>The converted value.</returns>
public static float RadiansToDegrees(float radian)
{
return radian * (180.0f / Pi);
}
/// <summary>
/// Clamps the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="min">The min.</param>
/// <param name="max">The max.</param>
/// <returns>The result of clamping a value between min and max</returns>
public static float Clamp(float value, float min, float max)
{
return value < min ? min : value > max ? max : value;
}
/// <summary>
/// Clamps the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="min">The min.</param>
/// <param name="max">The max.</param>
/// <returns>The result of clamping a value between min and max</returns>
public static double Clamp(double value, double min, double max)
{
return value < min ? min : value > max ? max : value;
}
/// <summary>
/// Clamps the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="min">The min.</param>
/// <param name="max">The max.</param>
/// <returns>The result of clamping a value between min and max</returns>
public static int Clamp(int value, int min, int max)
{
return value < min ? min : value > max ? max : value;
}
/// <summary>
/// Inverse-interpolates a value linearly.
/// </summary>
/// <param name="min">Minimum value that takes place in inverse-interpolation.</param>
/// <param name="max">Maximum value that takes place in inverse-interpolation.</param>
/// <param name="value">Value to get inverse interpolation.</param>
/// <returns>Returns an inverse-linearly interpolated coeficient.</returns>
public static float InverseLerp(float min, float max, float value)
{
if (IsZero(Math.Abs(max - min)))
return float.NaN;
return (value - min) / (max - min);
}
/// <summary>
/// Inverse-interpolates a value linearly.
/// </summary>
/// <param name="min">Minimum value that takes place in inverse-interpolation.</param>
/// <param name="max">Maximum value that takes place in inverse-interpolation.</param>
/// <param name="value">Value to get inverse interpolation.</param>
/// <returns>Returns an inverse-linearly interpolated coeficient.</returns>
public static double InverseLerp(double min, double max, double value)
{
if (IsZero(Math.Abs(max - min)))
return double.NaN;
return (value - min) / (max - min);
}
/// <summary>
/// Interpolates between two values using a linear function by a given amount.
/// </summary>
/// <remarks>
/// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and
/// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
/// </remarks>
/// <param name="from">Value to interpolate from.</param>
/// <param name="to">Value to interpolate to.</param>
/// <param name="amount">Interpolation amount.</param>
/// <returns>The result of linear interpolation of values based on the amount.</returns>
public static double Lerp(double from, double to, double amount)
{
return (1 - amount) * from + amount * to;
}
/// <summary>
/// Interpolates between two values using a linear function by a given amount.
/// </summary>
/// <remarks>
/// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and
/// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
/// </remarks>
/// <param name="from">Value to interpolate from.</param>
/// <param name="to">Value to interpolate to.</param>
/// <param name="amount">Interpolation amount.</param>
/// <returns>The result of linear interpolation of values based on the amount.</returns>
public static float Lerp(float from, float to, float amount)
{
return (1 - amount) * from + amount * to;
}
/// <summary>
/// Interpolates between two values using a linear function by a given amount.
/// </summary>
/// <remarks>
/// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and
/// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
/// </remarks>
/// <param name="from">Value to interpolate from.</param>
/// <param name="to">Value to interpolate to.</param>
/// <param name="amount">Interpolation amount.</param>
/// <returns>The result of linear interpolation of values based on the amount.</returns>
public static byte Lerp(byte from, byte to, float amount)
{
return (byte)Lerp((float)from, (float)to, amount);
}
/// <summary>
/// Performs smooth (cubic Hermite) interpolation between 0 and 1.
/// </summary>
/// <remarks>
/// See https://en.wikipedia.org/wiki/Smoothstep
/// </remarks>
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
public static float SmoothStep(float amount)
{
return (amount <= 0) ? 0
: (amount >= 1) ? 1
: amount * amount * (3 - (2 * amount));
}
/// <summary>
/// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints.
/// </summary>
/// <remarks>
/// See https://en.wikipedia.org/wiki/Smoothstep
/// </remarks>
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
public static float SmootherStep(float amount)
{
return (amount <= 0) ? 0
: (amount >= 1) ? 1
: amount * amount * amount * (amount * ((amount * 6) - 15) + 10);
}
/// <summary>
/// Determines whether the value is inside the given range (inclusively).
/// </summary>
/// <param name="value">The value.</param>
/// <param name="min">The minimum value of the range.</param>
/// <param name="max">The maximum value of the range.</param>
/// <returns><c>true</c> if value is inside the specified range; otherwise, <c>false</c>.</returns>
public static bool IsInRange(float value, float min, float max)
{
return min <= value && value <= max;
}
/// <summary>
/// Determines whether the value is inside the given range (inclusively).
/// </summary>
/// <param name="value">The value.</param>
/// <param name="min">The minimum value of the range.</param>
/// <param name="max">The maximum value of the range.</param>
/// <returns><c>true</c> if value is inside the specified range; otherwise, <c>false</c>.</returns>
public static bool IsInRange(int value, int min, int max)
{
return min <= value && value <= max;
}
/// <summary>
/// Determines whether the specified x is pow2.
/// </summary>
/// <param name="x">The x.</param>
/// <returns><c>true</c> if the specified x is pow2; otherwise, <c>false</c>.</returns>
public static bool IsPow2(int x)
{
return ((x != 0) && (x & (x - 1)) == 0);
}
/// <summary>
/// Converts a float value from sRGB to linear.
/// </summary>
/// <param name="sRgbValue">The sRGB value.</param>
/// <returns>A linear value.</returns>
public static float SRgbToLinear(float sRgbValue)
{
if (sRgbValue < 0.04045f) return sRgbValue / 12.92f;
return (float)Math.Pow((sRgbValue + 0.055) / 1.055, 2.4);
}
/// <summary>
/// Converts a float value from linear to sRGB.
/// </summary>
/// <param name="linearValue">The linear value.</param>
/// <returns>The encoded sRGB value.</returns>
public static float LinearToSRgb(float linearValue)
{
if (linearValue < 0.0031308f) return linearValue * 12.92f;
return (float)(1.055 * Math.Pow(linearValue, 1 / 2.4) - 0.055);
}
/// <summary>
/// Calculate the logarithm 2 of a floating point.
/// </summary>
/// <param name="x">The input float</param>
/// <returns><value>Log2(x)</value></returns>
public static float Log2(float x)
{
return (float)Math.Log(x) / 0.6931471805599453f;
}
/// <summary>
/// Calculate the logarithm 2 of an integer.
/// </summary>
/// <param name="i">The input integer</param>
/// <returns><value>the log2(i) rounded to lower integer</value></returns>
public static int Log2(int i)
{
var r = 0;
while ((i >>= 1) != 0)
++r;
return r;
}
/// <summary>
/// Get the next power of two of an integer.
/// </summary>
/// <param name="x">The size.</param>
/// <returns>System.Int32.</returns>
/// <remarks>https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2</remarks>
public static int NextPowerOfTwo(int x)
{
if (x < 0)
return 0;
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
/// <summary>
/// Get the next power of two for a size.
/// </summary>
/// <param name="size">The size.</param>
/// <returns>System.Int32.</returns>
public static float NextPowerOfTwo(float size)
{
return (float)Math.Pow(2, Math.Ceiling(Math.Log(size, 2)));
}
/// <summary>
/// Get the previous power of two of the provided integer.
/// </summary>
/// <param name="size">The value</param>
public static int PreviousPowerOfTwo(int size)
{
return 1 << (int)Math.Floor(Math.Log(size, 2));
}
/// <summary>
/// Get the previous power of two of the provided float.
/// </summary>
/// <param name="size">The value</param>
public static float PreviousPowerOfTwo(float size)
{
return (float)Math.Pow(2, Math.Floor(Math.Log(size, 2)));
}
/// <summary>
/// Alignes value up to match desire alignment.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="alignment">The alignment.</param>
/// <returns>Aligned value (multiple of alignment).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int AlignUp(int value, int alignment)
{
int mask = alignment - 1;
return (value + mask) & ~mask;
}
/// <summary>
/// Alignes value down to match desire alignment.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="alignment">The alignment.</param>
/// <returns>Aligned value (multiple of alignment).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int AlignDown(int value, int alignment)
{
int mask = alignment - 1;
return value & ~mask;
}
/// <summary>
/// Determines whether the specified value is aligned.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="alignment">The alignment.</param>
/// <returns><c>true</c> if the specified value is aligned; otherwise, <c>false</c>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAligned(int value, int alignment)
{
return (value & (alignment - 1)) == 0;
}
/// <summary>
/// Snaps a value to the nearest interval.
/// </summary>
/// <param name="value">The value to snap.</param>
/// <param name="gap">The interval gap.</param>
/// <returns>The nearest interval to the provided value.</returns>
public static float Snap(float value, float gap)
{
if (gap == 0)
return value;
return (float)Math.Round((value / gap), MidpointRounding.AwayFromZero) * gap;
}
/// <summary>
/// Snaps a value to the nearest interval.
/// </summary>
/// <param name="value">The value to snap.</param>
/// <param name="gap">The interval gap.</param>
/// <returns>The nearest interval to the provided value.</returns>
public static double Snap(double value, double gap)
{
if (gap == 0)
return value;
return Math.Round((value / gap), MidpointRounding.AwayFromZero) * gap;
}
/// <summary>
/// Snaps all vector components to the nearest interval.
/// </summary>
/// <param name="value">The vector to snap.</param>
/// <param name="gap">The interval gap.</param>
/// <returns>A vector which components are snapped to the nearest interval.</returns>
public static Vec2 Snap(Vec2 value, float gap)
{
if (gap == 0)
return value;
return new Vec2(
(float)Math.Round((value.X / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.Y / gap), MidpointRounding.AwayFromZero) * gap);
}
/// <summary>
/// Snaps all vector components to the nearest interval.
/// </summary>
/// <param name="value">The vector to snap.</param>
/// <param name="gap">The interval gap.</param>
/// <returns>A vector which components are snapped to the nearest interval.</returns>
public static Vector3 Snap(Vector3 value, float gap)
{
if (gap == 0)
return value;
return new Vector3(
(float)Math.Round((value.X / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.Y / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.Z / gap), MidpointRounding.AwayFromZero) * gap);
}
/// <summary>
/// Snaps all vector components to the nearest interval.
/// </summary>
/// <param name="value">The vector to snap.</param>
/// <param name="gap">The interval gap.</param>
/// <returns>A vector which components are snapped to the nearest interval.</returns>
public static Vector4 Snap(Vector4 value, float gap)
{
if (gap == 0)
return value;
return new Vector4(
(float)Math.Round((value.X / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.Y / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.Z / gap), MidpointRounding.AwayFromZero) * gap,
(float)Math.Round((value.W / gap), MidpointRounding.AwayFromZero) * gap);
}
}
}

3482
math/Matrix.cs Normal file

File diff suppressed because it is too large Load Diff

22
math/Module.cs Normal file
View File

@ -0,0 +1,22 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Reflection;
using Xenko.Core.Reflection;
namespace math
{
/// <summary>
/// Module initializer.
/// </summary>
internal class Module
{
/// <summary>
/// Module initializer.
/// </summary>
[ModuleInitializer]
public static void Initialize()
{
AssemblyRegistry.Register(typeof(Module).GetTypeInfo().Assembly, AssemblyCommonCategories.Assets);
}
}
}

12
math/NamespaceDoc.cs Normal file
View File

@ -0,0 +1,12 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
namespace math
{
/// <summary>
/// The <see cref="math"/> namespace contains types that allows to manipulate mathematical objects, such as vectors, points, quaternions, planes, etc.
/// </summary>
[System.Runtime.CompilerServices.CompilerGenerated]
internal class NamespaceDoc
{
}
}

838
math/Plane.cs Normal file
View File

@ -0,0 +1,838 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a plane in three dimensional space.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Plane : IEquatable<Plane>, IFormattable
{
/// <summary>
/// The normal vector of the plane.
/// </summary>
public Vector3 Normal;
/// <summary>
/// The distance of the plane along its normal from the origin.
/// </summary>
public float D;
/// <summary>
/// Initializes a new instance of the <see cref="math.Plane"/> struct.
/// </summary>
/// <param name="value">The value that will be assigned to all components.</param>
public Plane(float value)
{
Normal.X = Normal.Y = Normal.Z = D = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Plane"/> struct.
/// </summary>
/// <param name="a">The X component of the normal.</param>
/// <param name="b">The Y component of the normal.</param>
/// <param name="c">The Z component of the normal.</param>
/// <param name="d">The distance of the plane along its normal from the origin.</param>
public Plane(float a, float b, float c, float d)
{
Normal.X = a;
Normal.Y = b;
Normal.Z = c;
D = d;
}
/// <summary>
/// Initializes a new instance of the <see cref="Plane"/> struct.
/// </summary>
/// <param name="point">Any point that lies along the plane.</param>
/// <param name="normal">The normal vector to the plane.</param>
public Plane(Vector3 point, Vector3 normal)
{
this.Normal = normal;
this.D = Vector3.Dot(normal, point);
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Plane"/> struct.
/// </summary>
/// <param name="value">The normal of the plane.</param>
/// <param name="d">The distance of the plane along its normal from the origin</param>
public Plane(Vector3 value, float d)
{
Normal = value;
D = d;
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Plane"/> struct.
/// </summary>
/// <param name="point1">First point of a triangle defining the plane.</param>
/// <param name="point2">Second point of a triangle defining the plane.</param>
/// <param name="point3">Third point of a triangle defining the plane.</param>
public Plane(Vector3 point1, Vector3 point2, Vector3 point3)
{
float x1 = point2.X - point1.X;
float y1 = point2.Y - point1.Y;
float z1 = point2.Z - point1.Z;
float x2 = point3.X - point1.X;
float y2 = point3.Y - point1.Y;
float z2 = point3.Z - point1.Z;
float yz = (y1 * z2) - (z1 * y2);
float xz = (z1 * x2) - (x1 * z2);
float xy = (x1 * y2) - (y1 * x2);
float invPyth = 1.0f / (float)(Math.Sqrt((yz * yz) + (xz * xz) + (xy * xy)));
Normal.X = yz * invPyth;
Normal.Y = xz * invPyth;
Normal.Z = xy * invPyth;
D = -((Normal.X * point1.X) + (Normal.Y * point1.Y) + (Normal.Z * point1.Z));
}
/// <summary>
/// Initializes a new instance of the <see cref="math.Plane"/> struct.
/// </summary>
/// <param name="values">The values to assign to the A, B, C, and D components of the plane. This must be an array with four elements.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values"/> contains more or less than four elements.</exception>
public Plane(float[] values)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length != 4)
throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Plane.");
Normal.X = values[0];
Normal.Y = values[1];
Normal.Z = values[2];
D = values[3];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the A, B, C, or D component, depending on the index.</value>
/// <param name="index">The index of the component to access. Use 0 for the A component, 1 for the B component, 2 for the C component, and 3 for the D component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is out of the range [0, 3].</exception>
public float this[int index]
{
get
{
switch (index)
{
case 0: return Normal.X;
case 1: return Normal.Y;
case 2: return Normal.Z;
case 3: return D;
}
throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive.");
}
set
{
switch (index)
{
case 0: Normal.X = value; break;
case 1: Normal.Y = value; break;
case 2: Normal.Z = value; break;
case 3: D = value; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive.");
}
}
}
/// <summary>
/// Negates a plane by negating all its coefficients, which result in a plane in opposite direction.
/// </summary>
public void Negate()
{
Normal.X = -Normal.X;
Normal.Y = -Normal.Y;
Normal.Z = -Normal.Z;
D = -D;
}
/// <summary>
/// Changes the coefficients of the normal vector of the plane to make it of unit length.
/// </summary>
public void Normalize()
{
float magnitude = 1.0f / (float)(Math.Sqrt((Normal.X * Normal.X) + (Normal.Y * Normal.Y) + (Normal.Z * Normal.Z)));
Normal.X *= magnitude;
Normal.Y *= magnitude;
Normal.Z *= magnitude;
D *= magnitude;
}
/// <summary>
/// Creates an array containing the elements of the plane.
/// </summary>
/// <returns>A four-element array containing the components of the plane.</returns>
public float[] ToArray()
{
return new float[] { Normal.X, Normal.Y, Normal.Z, D };
}
/// <summary>
/// Determines if there is an intersection between the current object and a point.
/// </summary>
/// <param name="point">The point to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref Vector3 point)
{
return CollisionHelper.PlaneIntersectsPoint(ref this, ref point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray)
{
float distance;
return CollisionHelper.RayIntersectsPlane(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out float distance)
{
return CollisionHelper.RayIntersectsPlane(ref ray, ref this, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out Vector3 point)
{
return CollisionHelper.RayIntersectsPlane(ref ray, ref this, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Plane plane)
{
return CollisionHelper.PlaneIntersectsPlane(ref this, ref plane);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <param name="line">When the method completes, contains the line of intersection
/// as a <see cref="math.Ray"/>, or a zero ray if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Plane plane, out Ray line)
{
return CollisionHelper.PlaneIntersectsPlane(ref this, ref plane, out line);
}
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triagnle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
return CollisionHelper.PlaneIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref BoundingBox box)
{
return CollisionHelper.PlaneIntersectsBox(ref this, ref box);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public PlaneIntersectionType Intersects(ref BoundingSphere sphere)
{
return CollisionHelper.PlaneIntersectsSphere(ref this, ref sphere);
}
/// <summary>
/// Scales the plane by the given scaling factor.
/// </summary>
/// <param name="value">The plane to scale.</param>
/// <param name="scale">The amount by which to scale the plane.</param>
/// <param name="result">When the method completes, contains the scaled plane.</param>
public static void Multiply(ref Plane value, float scale, out Plane result)
{
result.Normal.X = value.Normal.X * scale;
result.Normal.Y = value.Normal.Y * scale;
result.Normal.Z = value.Normal.Z * scale;
result.D = value.D * scale;
}
/// <summary>
/// Scales the plane by the given scaling factor.
/// </summary>
/// <param name="value">The plane to scale.</param>
/// <param name="scale">The amount by which to scale the plane.</param>
/// <returns>The scaled plane.</returns>
public static Plane Multiply(Plane value, float scale)
{
return new Plane(value.Normal.X * scale, value.Normal.Y * scale, value.Normal.Z * scale, value.D * scale);
}
/// <summary>
/// Calculates the dot product of the specified vector and plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <param name="result">When the method completes, contains the dot product of the specified plane and vector.</param>
public static void Dot(ref Plane left, ref Vector4 right, out float result)
{
result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W);
}
/// <summary>
/// Calculates the dot product of the specified vector and plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <returns>The dot product of the specified plane and vector.</returns>
public static float Dot(Plane left, Vector4 right)
{
return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W);
}
/// <summary>
/// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <param name="result">When the method completes, contains the dot product of a specified vector and the normal of the Plane plus the distance value of the plane.</param>
public static void DotCoordinate(ref Plane left, ref Vector3 right, out float result)
{
result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D;
}
/// <summary>
/// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <returns>The dot product of a specified vector and the normal of the Plane plus the distance value of the plane.</returns>
public static float DotCoordinate(Plane left, Vector3 right)
{
return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D;
}
/// <summary>
/// Calculates the dot product of the specified vector and the normal of the plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <param name="result">When the method completes, contains the dot product of the specified vector and the normal of the plane.</param>
public static void DotNormal(ref Plane left, ref Vector3 right, out float result)
{
result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z);
}
/// <summary>
/// Calculates the dot product of the specified vector and the normal of the plane.
/// </summary>
/// <param name="left">The source plane.</param>
/// <param name="right">The source vector.</param>
/// <returns>The dot product of the specified vector and the normal of the plane.</returns>
public static float DotNormal(Plane left, Vector3 right)
{
return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z);
}
/// <summary>
/// Projects a point onto a plane.
/// </summary>
/// <param name="plane">The plane to project the point to.</param>
/// <param name="point">The point to project.</param>
/// <param name="result">The projected point.</param>
public static void Project(ref Plane plane, ref Vector3 point, out Vector3 result)
{
float distance;
DotCoordinate(ref plane, ref point, out distance);
// compute: point - distance * plane.Normal
Vector3.Multiply(ref plane.Normal, distance, out result);
Vector3.Subtract(ref point, ref result, out result);
}
/// <summary>
/// Projects a point onto a plane.
/// </summary>
/// <param name="plane">The plane to project the point to.</param>
/// <param name="point">The point to project.</param>
/// <returns>The projected point.</returns>
public static Vector3 Project(Plane plane, Vector3 point)
{
Vector3 result;
Project(ref plane, ref point, out result);
return result;
}
/// <summary>
/// Changes the coefficients of the normal vector of the plane to make it of unit length.
/// </summary>
/// <param name="plane">The source plane.</param>
/// <param name="result">When the method completes, contains the normalized plane.</param>
public static void Normalize(ref Plane plane, out Plane result)
{
float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z)));
result.Normal.X = plane.Normal.X * magnitude;
result.Normal.Y = plane.Normal.Y * magnitude;
result.Normal.Z = plane.Normal.Z * magnitude;
result.D = plane.D * magnitude;
}
/// <summary>
/// Changes the coefficients of the normal vector of the plane to make it of unit length.
/// </summary>
/// <param name="plane">The source plane.</param>
/// <returns>The normalized plane.</returns>
public static Plane Normalize(Plane plane)
{
float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z)));
return new Plane(plane.Normal.X * magnitude, plane.Normal.Y * magnitude, plane.Normal.Z * magnitude, plane.D * magnitude);
}
/// <summary>
/// Negates a plane by negating all its coefficients, which result in a plane in opposite direction.
/// </summary>
/// <param name="plane">The source plane.</param>
/// <param name="result">When the method completes, contains the flipped plane.</param>
public static void Negate(ref Plane plane, out Plane result)
{
result.Normal.X = -plane.Normal.X;
result.Normal.Y = -plane.Normal.Y;
result.Normal.Z = -plane.Normal.Z;
result.D = -plane.D;
}
/// <summary>
/// Negates a plane by negating all its coefficients, which result in a plane in opposite direction.
/// </summary>
/// <param name="plane">The source plane.</param>
/// <returns>The flipped plane.</returns>
public static Plane Negate(Plane plane)
{
float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z)));
return new Plane(plane.Normal.X * magnitude, plane.Normal.Y * magnitude, plane.Normal.Z * magnitude, plane.D * magnitude);
}
/// <summary>
/// Transforms a normalized plane by a quaternion rotation.
/// </summary>
/// <param name="plane">The normalized source plane.</param>
/// <param name="rotation">The quaternion rotation.</param>
/// <param name="result">When the method completes, contains the transformed plane.</param>
public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result)
{
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx = rotation.W * x2;
float wy = rotation.W * y2;
float wz = rotation.W * z2;
float xx = rotation.X * x2;
float xy = rotation.X * y2;
float xz = rotation.X * z2;
float yy = rotation.Y * y2;
float yz = rotation.Y * z2;
float zz = rotation.Z * z2;
float x = plane.Normal.X;
float y = plane.Normal.Y;
float z = plane.Normal.Z;
result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy));
result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx));
result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy));
result.D = plane.D;
}
/// <summary>
/// Transforms a normalized plane by a quaternion rotation.
/// </summary>
/// <param name="plane">The normalized source plane.</param>
/// <param name="rotation">The quaternion rotation.</param>
/// <returns>The transformed plane.</returns>
public static Plane Transform(Plane plane, Quaternion rotation)
{
Plane result;
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx = rotation.W * x2;
float wy = rotation.W * y2;
float wz = rotation.W * z2;
float xx = rotation.X * x2;
float xy = rotation.X * y2;
float xz = rotation.X * z2;
float yy = rotation.Y * y2;
float yz = rotation.Y * z2;
float zz = rotation.Z * z2;
float x = plane.Normal.X;
float y = plane.Normal.Y;
float z = plane.Normal.Z;
result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy));
result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx));
result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy));
result.D = plane.D;
return result;
}
/// <summary>
/// Transforms an array of normalized planes by a quaternion rotation.
/// </summary>
/// <param name="planes">The array of normalized planes to transform.</param>
/// <param name="rotation">The quaternion rotation.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="planes"/> is <c>null</c>.</exception>
public static void Transform(Plane[] planes, ref Quaternion rotation)
{
if (planes == null)
throw new ArgumentNullException("planes");
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx = rotation.W * x2;
float wy = rotation.W * y2;
float wz = rotation.W * z2;
float xx = rotation.X * x2;
float xy = rotation.X * y2;
float xz = rotation.X * z2;
float yy = rotation.Y * y2;
float yz = rotation.Y * z2;
float zz = rotation.Z * z2;
for (int i = 0; i < planes.Length; ++i)
{
float x = planes[i].Normal.X;
float y = planes[i].Normal.Y;
float z = planes[i].Normal.Z;
/*
* Note:
* Factor common arithmetic out of loop.
*/
planes[i].Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy));
planes[i].Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx));
planes[i].Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy));
}
}
/// <summary>
/// Transforms a normalized plane by a matrix.
/// </summary>
/// <param name="plane">The normalized source plane.</param>
/// <param name="transformation">The transformation matrix.</param>
/// <param name="result">When the method completes, contains the transformed plane.</param>
public static void Transform(ref Plane plane, ref Matrix transformation, out Plane result)
{
float x = plane.Normal.X;
float y = plane.Normal.Y;
float z = plane.Normal.Z;
float d = plane.D;
Matrix inverse;
Matrix.Invert(ref transformation, out inverse);
result.Normal.X = (((x * inverse.M11) + (y * inverse.M12)) + (z * inverse.M13)) + (d * inverse.M14);
result.Normal.Y = (((x * inverse.M21) + (y * inverse.M22)) + (z * inverse.M23)) + (d * inverse.M24);
result.Normal.Z = (((x * inverse.M31) + (y * inverse.M32)) + (z * inverse.M33)) + (d * inverse.M34);
result.D = (((x * inverse.M41) + (y * inverse.M42)) + (z * inverse.M43)) + (d * inverse.M44);
}
/// <summary>
/// Transforms a normalized plane by a matrix.
/// </summary>
/// <param name="plane">The normalized source plane.</param>
/// <param name="transformation">The transformation matrix.</param>
/// <returns>When the method completes, contains the transformed plane.</returns>
public static Plane Transform(Plane plane, Matrix transformation)
{
Plane result;
float x = plane.Normal.X;
float y = plane.Normal.Y;
float z = plane.Normal.Z;
float d = plane.D;
transformation.Invert();
result.Normal.X = (((x * transformation.M11) + (y * transformation.M12)) + (z * transformation.M13)) + (d * transformation.M14);
result.Normal.Y = (((x * transformation.M21) + (y * transformation.M22)) + (z * transformation.M23)) + (d * transformation.M24);
result.Normal.Z = (((x * transformation.M31) + (y * transformation.M32)) + (z * transformation.M33)) + (d * transformation.M34);
result.D = (((x * transformation.M41) + (y * transformation.M42)) + (z * transformation.M43)) + (d * transformation.M44);
return result;
}
/// <summary>
/// Transforms an array of normalized planes by a matrix.
/// </summary>
/// <param name="planes">The array of normalized planes to transform.</param>
/// <param name="transformation">The transformation matrix.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="planes"/> is <c>null</c>.</exception>
public static void Transform(Plane[] planes, ref Matrix transformation)
{
if (planes == null)
throw new ArgumentNullException("planes");
Matrix inverse;
Matrix.Invert(ref transformation, out inverse);
for (int i = 0; i < planes.Length; ++i)
{
Transform(ref planes[i], ref transformation, out planes[i]);
}
}
/// <summary>
/// Scales a plane by the given value.
/// </summary>
/// <param name="scale">The amount by which to scale the plane.</param>
/// <param name="plane">The plane to scale.</param>
/// <returns>The scaled plane.</returns>
public static Plane operator *(float scale, Plane plane)
{
return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale);
}
/// <summary>
/// Scales a plane by the given value.
/// </summary>
/// <param name="plane">The plane to scale.</param>
/// <param name="scale">The amount by which to scale the plane.</param>
/// <returns>The scaled plane.</returns>
public static Plane operator *(Plane plane, float scale)
{
return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale);
}
/// <summary>
/// Negates a plane by negating all its coefficients, which result in a plane in opposite direction.
/// </summary>
/// <returns>The negated plane.</returns>
public static Plane operator -(Plane plane)
{
return new Plane(-plane.Normal.X, -plane.Normal.Y, -plane.Normal.Z, -plane.D);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Plane left, Plane right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Plane left, Plane right)
{
return !left.Equals(right);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, CultureInfo.CurrentCulture),
Normal.Y.ToString(format, CultureInfo.CurrentCulture), Normal.Z.ToString(format, CultureInfo.CurrentCulture), D.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, formatProvider),
Normal.Y.ToString(format, formatProvider), Normal.Z.ToString(format, formatProvider), D.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return Normal.GetHashCode() + D.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="math.Vector4"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="math.Vector4"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="math.Vector4"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Plane value)
{
return Normal == value.Normal && D == value.D;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Plane)value);
}
#if SlimDX1xInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Plane"/> to <see cref="SlimDX.Plane"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SlimDX.Plane(Plane value)
{
return new SlimDX.Plane(value.Normal, value.D);
}
/// <summary>
/// Performs an implicit conversion from <see cref="SlimDX.Plane"/> to <see cref="math.Plane"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Plane(SlimDX.Plane value)
{
return new Plane(value.Normal, value.D);
}
#endif
#if XnaInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Plane"/> to <see cref="Microsoft.Xna.Framework.Plane"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Microsoft.Xna.Framework.Plane(Plane value)
{
return new Microsoft.Xna.Framework.Plane(value.Normal, value.D);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Plane"/> to <see cref="math.Plane"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Plane(Microsoft.Xna.Framework.Plane value)
{
return new Plane(value.Normal, value.D);
}
#endif
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace math
{
/*
* The enumerations defined in this file are in alphabetical order. When
* adding new enumerations or renaming existing ones, please make sure
* the ordering is maintained.
*/
/// <summary>
/// Describes the result of an intersection with a plane in three dimensions.
/// </summary>
public enum PlaneIntersectionType
{
/// <summary>
/// The object is behind the plane.
/// </summary>
Back,
/// <summary>
/// The object is in front of the plane.
/// </summary>
Front,
/// <summary>
/// The object is intersecting the plane.
/// </summary>
Intersecting,
}
}

147
math/Point.cs Normal file
View File

@ -0,0 +1,147 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A 2D point.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Point : IEquatable<Point>
{
/// <summary>
/// A point with (0,0) coordinates.
/// </summary>
public static readonly Point Zero = new Point(0, 0);
/// <summary>
/// Initializes a new instance of the <see cref="Point"/> struct.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
public Point(int x, int y)
{
X = x;
Y = y;
}
/// <summary>
/// Left coordinate.
/// </summary>
[DataMember( Order = 0 )]
public int X;
/// <summary>
/// Top coordinate.
/// </summary>
[DataMember( Order = 1 )]
public int Y;
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Point other)
{
return other.X == X && other.Y == Y;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Point)) return false;
return Equals((Point)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Y;
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(Point left, Point right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(Point left, Point right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format("({0},{1})", X, Y);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Vec2"/> to <see cref="Point"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Point(Vec2 value)
{
return new Point((int)value.X, (int)value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref="Point"/> to <see cref="Vec2"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Vec2(Point value)
{
return new Vec2(value.X, value.Y);
}
}
}

View File

@ -0,0 +1,8 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Reflection;
using System.Runtime.CompilerServices;
#pragma warning disable 436 // Xenko.PublicKeys is defined in multiple assemblies
[assembly: InternalsVisibleTo("math.Serializers" + Xenko.PublicKeys.Default)]

1424
math/Quaternion.cs Normal file

File diff suppressed because it is too large Load Diff

61
math/RandomSeed.cs Normal file
View File

@ -0,0 +1,61 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
// Random numbers which also allow creation of random values in the shaders and are deterministic
// Based on this article:
// http://martindevans.me/game-development/2015/02/22/Random-Gibberish/
using System;
namespace math
{
/// <summary>
/// The <see cref="RandomSeed"/> is a structure for deterministically acquiring random values.
/// One <see cref="RandomSeed"/> should be able to reproduce the same pseudo-random value for a fixed offset, but
/// provide enough random distribution for different offsets or different random seeds
/// Although other methods exist, the current implementation can easily be replicated in the shaders if required
/// </summary>
public struct RandomSeed
{
private const double GelfondConst = 23.1406926327792690; // e to the power of Pi = (-1) to the power of -i
private const double GelfondSchneiderConst = 2.6651441426902251; // 2 to the power of sqrt(2)
private const double Numerator = 123456789;
// When casting uint to double it works fine, but when casting it to float it might cause underflow errors (loss of precision)
// We want to limit the maximum settable value to prevent such errors.
private const uint UnderflowGuard = 0xFFFF;
private readonly uint seed;
/// <summary>
/// Initializes a new instance of the <see cref="RandomSeed"/> struct from a target uint.
/// </summary>
/// <param name="seed">The seed value to initialize the deterministic random generator.</param>
public RandomSeed(uint seed)
{
this.seed = (seed & UnderflowGuard);
}
/// <summary>
/// Get a deterministic double value between 0 and 1 based on the seed
/// </summary>
/// <returns>Deterministic pseudo-random value between 0 and 1</returns>
public double GetDouble(uint offset)
{
var dRand = (double)(unchecked(seed + offset)); // We want it to overflow
var dotProduct = Math.Cos(dRand) * GelfondConst + Math.Sin(dRand) * GelfondSchneiderConst;
var denominator = 1e-7 + 256 * dotProduct;
var remainder = Numerator % denominator;
return (remainder - Math.Floor(remainder));
}
/// <summary>
/// Get a deterministic float value between 0 and 1 based on the seed
/// The calculations are still made as doubles to prevent underflow errors.
/// </summary>
/// <returns>Deterministic pseudo-random value between 0 and 1</returns>
public float GetFloat(uint offset) => (float)GetDouble(offset);
}
}

400
math/Ray.cs Normal file
View File

@ -0,0 +1,400 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// -----------------------------------------------------------------------------
// Original code from SlimMath project. http://code.google.com/p/slimmath/
// Greetings to SlimDX Group. Original code published with the following license:
// -----------------------------------------------------------------------------
/*
* Copyright (c) 2007-2011 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a three dimensional line based on a point in space and a direction.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Ray : IEquatable<Ray>, IFormattable
{
/// <summary>
/// The position in three dimensional space where the ray starts.
/// </summary>
public Vector3 Position;
/// <summary>
/// The normalized direction in which the ray points.
/// </summary>
public Vector3 Direction;
/// <summary>
/// Initializes a new instance of the <see cref="math.Ray"/> struct.
/// </summary>
/// <param name="position">The position in three dimensional space of the origin of the ray.</param>
/// <param name="direction">The normalized direction of the ray.</param>
public Ray(Vector3 position, Vector3 direction)
{
this.Position = position;
this.Direction = direction;
}
/// <summary>
/// Determines if there is an intersection between the current object and a point.
/// </summary>
/// <param name="point">The point to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 point)
{
return CollisionHelper.RayIntersectsPoint(ref this, ref point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray)
{
Vector3 point;
return CollisionHelper.RayIntersectsRay(ref this, ref ray, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Ray"/>.
/// </summary>
/// <param name="ray">The ray to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Ray ray, out Vector3 point)
{
return CollisionHelper.RayIntersectsRay(ref this, ref ray, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Plane plane)
{
float distance;
return CollisionHelper.RayIntersectsPlane(ref this, ref plane, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Plane plane, out float distance)
{
return CollisionHelper.RayIntersectsPlane(ref this, ref plane, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.Plane"/>.
/// </summary>
/// <param name="plane">The plane to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Plane plane, out Vector3 point)
{
return CollisionHelper.RayIntersectsPlane(ref this, ref plane, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triangle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
{
float distance;
return CollisionHelper.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triangle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out float distance)
{
return CollisionHelper.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a triangle.
/// </summary>
/// <param name="vertex1">The first vertex of the triangle to test.</param>
/// <param name="vertex2">The second vertex of the triangle to test.</param>
/// <param name="vertex3">The third vertex of the triangle to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 point)
{
return CollisionHelper.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingBox box)
{
float distance;
return CollisionHelper.RayIntersectsBox(ref this, ref box, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingBox box, out float distance)
{
return CollisionHelper.RayIntersectsBox(ref this, ref box, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingBox"/>.
/// </summary>
/// <param name="box">The box to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingBox box, out Vector3 point)
{
return CollisionHelper.RayIntersectsBox(ref this, ref box, out point);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingSphere sphere)
{
float distance;
return CollisionHelper.RayIntersectsSphere(ref this, ref sphere, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <param name="distance">When the method completes, contains the distance of the intersection,
/// or 0 if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingSphere sphere, out float distance)
{
return CollisionHelper.RayIntersectsSphere(ref this, ref sphere, out distance);
}
/// <summary>
/// Determines if there is an intersection between the current object and a <see cref="math.BoundingSphere"/>.
/// </summary>
/// <param name="sphere">The sphere to test.</param>
/// <param name="point">When the method completes, contains the point of intersection,
/// or <see cref="math.Vector3.Zero"/> if there was no intersection.</param>
/// <returns>Whether the two objects intersected.</returns>
public bool Intersects(ref BoundingSphere sphere, out Vector3 point)
{
return CollisionHelper.RayIntersectsSphere(ref this, ref sphere, out point);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator ==(Ray left, Ray right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name="left">The first value to compare.</param>
/// <param name="right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
public static bool operator !=(Ray left, Ray right)
{
return !left.Equals(right);
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format)
{
return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(format, CultureInfo.CurrentCulture),
Direction.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString());
}
/// <summary>
/// Returns a <see cref="string"/> that represents this instance.
/// </summary>
/// <param name="format">The format.</param>
/// <param name="formatProvider">The format provider.</param>
/// <returns>
/// A <see cref="string"/> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(format, formatProvider),
Direction.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return Position.GetHashCode() + Direction.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref="math.Vector4"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="math.Vector4"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="math.Vector4"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Ray value)
{
return Position == value.Position && Direction == value.Direction;
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="value">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((Ray)value);
}
#if SlimDX1xInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Ray"/> to <see cref="SlimDX.Ray"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SlimDX.Ray(Ray value)
{
return new SlimDX.Ray(value.Position, value.Direction);
}
/// <summary>
/// Performs an implicit conversion from <see cref="SlimDX.Ray"/> to <see cref="math.Ray"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Ray(SlimDX.Ray value)
{
return new Ray(value.Position, value.Direction);
}
#endif
#if XnaInterop
/// <summary>
/// Performs an implicit conversion from <see cref="math.Ray"/> to <see cref="Microsoft.Xna.Framework.Ray"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Microsoft.Xna.Framework.Ray(Ray value)
{
return new Microsoft.Xna.Framework.Ray(value.Position, value.Direction);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.Ray"/> to <see cref="math.Ray"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator Ray(Microsoft.Xna.Framework.Ray value)
{
return new Ray(value.Position, value.Direction);
}
#endif
}
}

502
math/Rectangle.cs Normal file
View File

@ -0,0 +1,502 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A rectangle structure defining X,Y,Width,Height.
/// </summary>
[DataContract( Name = "Rectangle")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Rectangle : IEquatable<Rectangle>
{
/// <summary>
/// An empty rectangle.
/// </summary>
public static readonly Rectangle Empty;
static Rectangle()
{
Empty = new Rectangle();
}
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
/// </summary>
/// <param name="x">The left.</param>
/// <param name="y">The top.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public Rectangle(int x, int y, int width, int height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
/// <summary>
/// Gets or sets the left.
/// </summary>
/// <value>The left.</value>
[DataMemberIgnore]
public int Left
{
get { return X; }
set { X = value; }
}
/// <summary>
/// Gets or sets the top.
/// </summary>
/// <value>The top.</value>
[DataMemberIgnore]
public int Top
{
get { return Y; }
set { Y = value; }
}
/// <summary>
/// Gets or sets the right.
/// </summary>
/// <value>The right.</value>
[DataMemberIgnore]
public int Right
{
get { return X + Width; }
}
/// <summary>
/// Gets or sets the bottom.
/// </summary>
/// <value>The bottom.</value>
[DataMemberIgnore]
public int Bottom
{
get { return Y + Height; }
}
/// <summary>
/// Gets or sets the X position.
/// </summary>
/// <value>The X position.</value>
[DataMember( Order = 0 )]
public int X;
/// <summary>
/// Gets or sets the Y position.
/// </summary>
/// <value>The Y position.</value>
[DataMember( Order = 1 )]
public int Y;
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>The width.</value>
[DataMember( Order = 2 )]
public int Width;
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
[DataMember( Order = 3 )]
public int Height;
/// <summary>
/// Gets or sets the location.
/// </summary>
/// <value>
/// The location.
/// </value>
[DataMemberIgnore]
public Point Location
{
get
{
return new Point(X, Y);
}
set
{
X = value.X;
Y = value.Y;
}
}
/// <summary>
/// Gets the Point that specifies the center of the rectangle.
/// </summary>
/// <value>
/// The center.
/// </value>
[DataMemberIgnore]
public Point Center
{
get
{
return new Point(X + (Width / 2), Y + (Height / 2));
}
}
/// <summary>
/// Gets a value that indicates whether the rectangle is empty.
/// </summary>
/// <value>
/// <c>true</c> if [is empty]; otherwise, <c>false</c>.
/// </value>
public bool IsEmpty
{
get
{
return (Width == 0) && (Height == 0) && (X == 0) && (Y == 0);
}
}
/// <summary>
/// Gets or sets the size of the rectangle.
/// </summary>
/// <value>The size of the rectangle.</value>
[DataMemberIgnore]
public Size2 Size
{
get
{
return new Size2(Width, Height);
}
set
{
Width = value.Width;
Height = value.Height;
}
}
/// <summary>
/// Gets the position of the top-left corner of the rectangle.
/// </summary>
/// <value>The top-left corner of the rectangle.</value>
public Point TopLeft { get { return new Point(Left, Top); } }
/// <summary>
/// Gets the position of the top-right corner of the rectangle.
/// </summary>
/// <value>The top-right corner of the rectangle.</value>
public Point TopRight { get { return new Point(Right, Top); } }
/// <summary>
/// Gets the position of the bottom-left corner of the rectangle.
/// </summary>
/// <value>The bottom-left corner of the rectangle.</value>
public Point BottomLeft { get { return new Point(Left, Bottom); } }
/// <summary>
/// Gets the position of the bottom-right corner of the rectangle.
/// </summary>
/// <value>The bottom-right corner of the rectangle.</value>
public Point BottomRight { get { return new Point(Right, Bottom); } }
/// <summary>Changes the position of the rectangle.</summary>
/// <param name="amount">The values to adjust the position of the rectangle by.</param>
public void Offset(Point amount)
{
Offset(amount.X, amount.Y);
}
/// <summary>Changes the position of the rectangle.</summary>
/// <param name="offsetX">Change in the x-position.</param>
/// <param name="offsetY">Change in the y-position.</param>
public void Offset(int offsetX, int offsetY)
{
X += offsetX;
Y += offsetY;
}
/// <summary>Pushes the edges of the rectangle out by the horizontal and vertical values specified.</summary>
/// <param name="horizontalAmount">Value to push the sides out by.</param>
/// <param name="verticalAmount">Value to push the top and bottom out by.</param>
public void Inflate(int horizontalAmount, int verticalAmount)
{
X -= horizontalAmount;
Y -= verticalAmount;
Width += horizontalAmount * 2;
Height += verticalAmount * 2;
}
/// <summary>Determines whether this rectangle contains a specified point represented by its x- and y-coordinates.</summary>
/// <param name="x">The x-coordinate of the specified point.</param>
/// <param name="y">The y-coordinate of the specified point.</param>
public bool Contains(int x, int y)
{
return (X <= x) && (x < Right) && (Y <= y) && (y < Bottom);
}
/// <summary>Determines whether this rectangle contains a specified Point.</summary>
/// <param name="value">The Point to evaluate.</param>
public bool Contains(Point value)
{
bool result;
Contains(ref value, out result);
return result;
}
/// <summary>Determines whether this rectangle contains a specified Point.</summary>
/// <param name="value">The Point to evaluate.</param>
/// <param name="result">[OutAttribute] true if the specified Point is contained within this rectangle; false otherwise.</param>
public void Contains(ref Point value, out bool result)
{
result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom);
}
/// <summary>Determines whether this rectangle entirely contains a specified rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
public bool Contains(Rectangle value)
{
bool result;
Contains(ref value, out result);
return result;
}
/// <summary>Determines whether this rectangle entirely contains a specified rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
/// <param name="result">[OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not.</param>
public void Contains(ref Rectangle value, out bool result)
{
result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom);
}
/// <summary>
/// Checks, if specified point is inside <see cref="Rectangle"/>.
/// </summary>
/// <param name="x">X point coordinate.</param>
/// <param name="y">Y point coordinate.</param>
/// <returns><c>true</c> if point is inside <see cref="Rectangle"/>, otherwise <c>false</c>.</returns>
public bool Contains(float x, float y)
{
return (x >= this.X && x <= Right && y >= this.Y && y <= Bottom);
}
/// <summary>
/// Checks, if specified <see cref="Vec2"/> is inside <see cref="Rectangle"/>.
/// </summary>
/// <param name="vector2D">Coordinate <see cref="Vec2"/>.</param>
/// <returns><c>true</c> if <see cref="Vec2"/> is inside <see cref="Rectangle"/>, otherwise <c>false</c>.</returns>
public bool Contains(Vec2 vector2D)
{
return Contains(vector2D.X, vector2D.Y);
}
/// <summary>
/// Checks, if specified <see cref="Int2"/> is inside <see cref="Rectangle"/>.
/// </summary>
/// <param name="int2">Coordinate <see cref="Int2"/>.</param>
/// <returns><c>true</c> if <see cref="Int2"/> is inside <see cref="Rectangle"/>, otherwise <c>false</c>.</returns>
public bool Contains(Int2 int2)
{
return Contains(int2.X, int2.Y);
}
/// <summary>Determines whether a specified rectangle intersects with this rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
public bool Intersects(Rectangle value)
{
bool result;
Intersects(ref value, out result);
return result;
}
/// <summary>
/// Determines whether a specified rectangle intersects with this rectangle.
/// </summary>
/// <param name="value">The rectangle to evaluate</param>
/// <param name="result">[OutAttribute] true if the specified rectangle intersects with this one; false otherwise.</param>
public void Intersects(ref Rectangle value, out bool result)
{
result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom);
}
/// <summary>
/// Creates a rectangle defining the area where one rectangle overlaps with another rectangle.
/// </summary>
/// <param name="value1">The first rectangle to compare.</param>
/// <param name="value2">The second rectangle to compare.</param>
/// <returns>The intersection rectangle.</returns>
public static Rectangle Intersect(Rectangle value1, Rectangle value2)
{
Rectangle result;
Intersect(ref value1, ref value2, out result);
return result;
}
/// <summary>Creates a rectangle defining the area where one rectangle overlaps with another rectangle.</summary>
/// <param name="value1">The first rectangle to compare.</param>
/// <param name="value2">The second rectangle to compare.</param>
/// <param name="result">[OutAttribute] The area where the two first parameters overlap.</param>
public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
{
int newLeft = (value1.X > value2.X) ? value1.X : value2.X;
int newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y;
int newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right;
int newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom;
if ((newRight > newLeft) && (newBottom > newTop))
{
result = new Rectangle(newLeft, newTop, newRight - newLeft, newBottom - newTop);
}
else
{
result = Empty;
}
}
/// <summary>
/// Creates a new rectangle that incorporate the provided point to the given rectangle.
/// </summary>
/// <param name="rectangle">The original rectangle.</param>
/// <param name="point">The point to incorporate.</param>
/// <returns>The union rectangle.</returns>
public static Rectangle Union(Rectangle rectangle, Int2 point)
{
Rectangle result;
var rect = new Rectangle(point.X, point.Y, 1, 1);
Union(ref rectangle, ref rect, out result);
return result;
}
/// <summary>
/// Creates a new rectangle that exactly contains two other rectangles.
/// </summary>
/// <param name="value1">The first rectangle to contain.</param>
/// <param name="value2">The second rectangle to contain.</param>
/// <returns>The union rectangle.</returns>
public static Rectangle Union(Rectangle value1, Rectangle value2)
{
Rectangle result;
Union(ref value1, ref value2, out result);
return result;
}
/// <summary>
/// Creates a new rectangle that exactly contains two other rectangles.
/// </summary>
/// <param name="value1">The first rectangle to contain.</param>
/// <param name="value2">The second rectangle to contain.</param>
/// <param name="result">[OutAttribute] The rectangle that must be the union of the first two rectangles.</param>
public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result)
{
var left = Math.Min(value1.Left, value2.Left);
var right = Math.Max(value1.Right, value2.Right);
var top = Math.Min(value1.Top, value2.Top);
var bottom = Math.Max(value1.Bottom, value2.Bottom);
result = new Rectangle(left, top, right - left, bottom - top);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Rectangle)) return false;
return Equals((Rectangle)obj);
}
/// <summary>
/// Determines whether the specified <see cref="Rectangle"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="Rectangle"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="Rectangle"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Rectangle other)
{
return other.X == this.X && other.Y == this.Y && other.Width == Width && other.Height == Height;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
unchecked
{
int result = X;
result = (result * 397) ^ Y;
result = (result * 397) ^ Width;
result = (result * 397) ^ Height;
return result;
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(Rectangle left, Rectangle right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(Rectangle left, Rectangle right)
{
return !(left == right);
}
/// <summary>
/// Performs an implicit conversion to the <see cref="RectangleF"/> structure.
/// </summary>
/// <remarks>Performs direct converstion from int to float.</remarks>
/// <param name="value">The source <see cref="Rectangle"/> value.</param>
/// <returns>The converted structure.</returns>
public static implicit operator RectangleF(Rectangle value)
{
return new RectangleF(value.X, value.Y, value.Width, value.Height);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height);
}
}
}

492
math/RectangleF.cs Normal file
View File

@ -0,0 +1,492 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Define a RectangleF.
/// </summary>
[DataContract( Name = "RectangleF")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct RectangleF : IEquatable<RectangleF>
{
/// <summary>
/// An empty rectangle
/// </summary>
public static readonly RectangleF Empty;
static RectangleF()
{
Empty = new RectangleF();
}
/// <summary>
/// Initializes a new instance of the <see cref="RectangleF"/> struct.
/// </summary>
/// <param name="x">The left.</param>
/// <param name="y">The top.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public RectangleF(float x, float y, float width, float height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
/// <summary>
/// Gets or sets the X position of the left edge.
/// </summary>
/// <value>The left.</value>
[DataMemberIgnore]
public float Left
{
get { return X; }
set { X = value; }
}
/// <summary>
/// Gets or sets the top.
/// </summary>
/// <value>The top.</value>
[DataMemberIgnore]
public float Top
{
get { return Y; }
set { Y = value; }
}
/// <summary>
/// Gets the right.
/// </summary>
/// <value>The right.</value>
[DataMemberIgnore]
public float Right
{
get
{
return X + Width;
}
}
/// <summary>
/// Gets the bottom.
/// </summary>
/// <value>The bottom.</value>
public float Bottom
{
get
{
return Y + Height;
}
}
/// <summary>
/// Gets or sets the X position.
/// </summary>
/// <value>The X position.</value>
/// <userdoc>The beginning of the rectangle along the Ox axis.</userdoc>
[DataMember( Order = 0 )]
public float X;
/// <summary>
/// Gets or sets the Y position.
/// </summary>
/// <value>The Y position.</value>
/// <userdoc>The beginning of the rectangle along the Oy axis.</userdoc>
[DataMember( Order = 1 )]
public float Y;
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>The width.</value>
/// <userdoc>The width of the rectangle.</userdoc>
[DataMember( Order = 2 )]
public float Width;
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
/// <userdoc>The height of the rectangle.</userdoc>
[DataMember( Order = 3 )]
public float Height;
/// <summary>
/// Gets or sets the location.
/// </summary>
/// <value>
/// The location.
/// </value>
[DataMemberIgnore]
public Vec2 Location
{
get
{
return new Vec2(X, Y);
}
set
{
X = value.X;
Y = value.Y;
}
}
/// <summary>
/// Gets the Point that specifies the center of the rectangle.
/// </summary>
/// <value>
/// The center.
/// </value>
[DataMemberIgnore]
public Vec2 Center
{
get
{
return new Vec2(X + (Width / 2), Y + (Height / 2));
}
}
/// <summary>
/// Gets a value that indicates whether the rectangle is empty.
/// </summary>
/// <value>
/// <c>true</c> if [is empty]; otherwise, <c>false</c>.
/// </value>
public bool IsEmpty
{
get
{
return (Width == 0.0f) && (Height == 0.0f) && (X == 0.0f) && (Y == 0.0f);
}
}
/// <summary>
/// Gets or sets the size of the rectangle.
/// </summary>
/// <value>The size of the rectangle.</value>
[DataMemberIgnore]
public Size2F Size
{
get
{
return new Size2F(Width, Height);
}
set
{
Width = value.Width;
Height = value.Height;
}
}
/// <summary>
/// Gets the position of the top-left corner of the rectangle.
/// </summary>
/// <value>The top-left corner of the rectangle.</value>
public Vec2 TopLeft { get { return new Vec2(X, Y); } }
/// <summary>
/// Gets the position of the top-right corner of the rectangle.
/// </summary>
/// <value>The top-right corner of the rectangle.</value>
public Vec2 TopRight { get { return new Vec2(Right, Y); } }
/// <summary>
/// Gets the position of the bottom-left corner of the rectangle.
/// </summary>
/// <value>The bottom-left corner of the rectangle.</value>
public Vec2 BottomLeft { get { return new Vec2(X, Bottom); } }
/// <summary>
/// Gets the position of the bottom-right corner of the rectangle.
/// </summary>
/// <value>The bottom-right corner of the rectangle.</value>
public Vec2 BottomRight { get { return new Vec2(Right, Bottom); } }
/// <summary>Changes the position of the rectangle.</summary>
/// <param name="amount">The values to adjust the position of the rectangle by.</param>
public void Offset(Point amount)
{
Offset(amount.X, amount.Y);
}
/// <summary>Changes the position of the rectangle.</summary>
/// <param name="amount">The values to adjust the position of the rectangle by.</param>
public void Offset(Vec2 amount)
{
Offset(amount.X, amount.Y);
}
/// <summary>Changes the position of the rectangle.</summary>
/// <param name="offsetX">Change in the x-position.</param>
/// <param name="offsetY">Change in the y-position.</param>
public void Offset(float offsetX, float offsetY)
{
X += offsetX;
Y += offsetY;
}
/// <summary>Pushes the edges of the rectangle out by the horizontal and vertical values specified.</summary>
/// <param name="horizontalAmount">Value to push the sides out by.</param>
/// <param name="verticalAmount">Value to push the top and bottom out by.</param>
public void Inflate(float horizontalAmount, float verticalAmount)
{
X -= horizontalAmount;
Y -= verticalAmount;
Width += horizontalAmount * 2;
Height += verticalAmount * 2;
}
/// <summary>Determines whether this rectangle contains a specified Point.</summary>
/// <param name="value">The Point to evaluate.</param>
/// <param name="result">[OutAttribute] true if the specified Point is contained within this rectangle; false otherwise.</param>
public void Contains(ref Vec2 value, out bool result)
{
result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom);
}
/// <summary>Determines whether this rectangle entirely contains a specified rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
public bool Contains(Rectangle value)
{
return (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom);
}
/// <summary>Determines whether this rectangle entirely contains a specified rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
/// <param name="result">[OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not.</param>
public void Contains(ref RectangleF value, out bool result)
{
result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom);
}
/// <summary>
/// Checks, if specified point is inside <see cref="RectangleF"/>.
/// </summary>
/// <param name="x">X point coordinate.</param>
/// <param name="y">Y point coordinate.</param>
/// <returns><c>true</c> if point is inside <see cref="RectangleF"/>, otherwise <c>false</c>.</returns>
public bool Contains(float x, float y)
{
return (x >= this.X && x <= Right && y >= this.Y && y <= Bottom);
}
/// <summary>
/// Checks, if specified <see cref="Vec2"/> is inside <see cref="RectangleF"/>.
/// </summary>
/// <param name="vector2D">Coordinate <see cref="Vec2"/>.</param>
/// <returns><c>true</c> if <see cref="Vec2"/> is inside <see cref="RectangleF"/>, otherwise <c>false</c>.</returns>
public bool Contains(Vec2 vector2D)
{
return Contains(vector2D.X, vector2D.Y);
}
/// <summary>
/// Checks, if specified <see cref="Int2"/> is inside <see cref="Rectangle"/>.
/// </summary>
/// <param name="int2">Coordinate <see cref="Int2"/>.</param>
/// <returns><c>true</c> if <see cref="Int2"/> is inside <see cref="Rectangle"/>, otherwise <c>false</c>.</returns>
public bool Contains(Int2 int2)
{
return Contains(int2.X, int2.Y);
}
/// <summary>
/// Checks, if specified <see cref="Point"/> is inside <see cref="RectangleF"/>.
/// </summary>
/// <param name="point">Coordinate <see cref="Point"/>.</param>
/// <returns><c>true</c> if <see cref="Point"/> is inside <see cref="RectangleF"/>, otherwise <c>false</c>.</returns>
public bool Contains(Point point)
{
return Contains(point.X, point.Y);
}
/// <summary>Determines whether a specified rectangle intersects with this rectangle.</summary>
/// <param name="value">The rectangle to evaluate.</param>
public bool Intersects(RectangleF value)
{
bool result;
Intersects(ref value, out result);
return result;
}
/// <summary>
/// Determines whether a specified rectangle intersects with this rectangle.
/// </summary>
/// <param name="value">The rectangle to evaluate</param>
/// <param name="result">[OutAttribute] true if the specified rectangle intersects with this one; false otherwise.</param>
public void Intersects(ref RectangleF value, out bool result)
{
result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom);
}
/// <summary>
/// Creates a rectangle defining the area where one rectangle overlaps with another rectangle.
/// </summary>
/// <param name="value1">The first Rectangle to compare.</param>
/// <param name="value2">The second Rectangle to compare.</param>
/// <returns>The intersection rectangle.</returns>
public static RectangleF Intersect(RectangleF value1, RectangleF value2)
{
RectangleF result;
Intersect(ref value1, ref value2, out result);
return result;
}
/// <summary>Creates a rectangle defining the area where one rectangle overlaps with another rectangle.</summary>
/// <param name="value1">The first rectangle to compare.</param>
/// <param name="value2">The second rectangle to compare.</param>
/// <param name="result">[OutAttribute] The area where the two first parameters overlap.</param>
public static void Intersect(ref RectangleF value1, ref RectangleF value2, out RectangleF result)
{
float newLeft = (value1.X > value2.X) ? value1.X : value2.X;
float newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y;
float newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right;
float newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom;
if ((newRight > newLeft) && (newBottom > newTop))
{
result = new RectangleF(newLeft, newTop, newRight - newLeft, newBottom - newTop);
}
else
{
result = Empty;
}
}
/// <summary>
/// Creates a new rectangle that exactly contains two other rectangles.
/// </summary>
/// <param name="value1">The first rectangle to contain.</param>
/// <param name="value2">The second rectangle to contain.</param>
/// <returns>The union rectangle.</returns>
public static RectangleF Union(RectangleF value1, RectangleF value2)
{
RectangleF result;
Union(ref value1, ref value2, out result);
return result;
}
/// <summary>
/// Creates a new rectangle that exactly contains two other rectangles.
/// </summary>
/// <param name="value1">The first rectangle to contain.</param>
/// <param name="value2">The second rectangle to contain.</param>
/// <param name="result">[OutAttribute] The rectangle that must be the union of the first two rectangles.</param>
public static void Union(ref RectangleF value1, ref RectangleF value2, out RectangleF result)
{
var left = Math.Min(value1.Left, value2.Left);
var right = Math.Max(value1.Right, value2.Right);
var top = Math.Min(value1.Top, value2.Top);
var bottom = Math.Max(value1.Bottom, value2.Bottom);
result = new RectangleF(left, top, right - left, bottom - top);
}
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(RectangleF)) return false;
return Equals((RectangleF)obj);
}
/// <inheritdoc/>
public bool Equals(RectangleF other)
{
return MathUtil.NearEqual(other.Left, Left) &&
MathUtil.NearEqual(other.Right, Right) &&
MathUtil.NearEqual(other.Top, Top) &&
MathUtil.NearEqual(other.Bottom, Bottom);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
unchecked
{
int result = X.GetHashCode();
result = (result * 397) ^ Y.GetHashCode();
result = (result * 397) ^ Width.GetHashCode();
result = (result * 397) ^ Height.GetHashCode();
return result;
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(RectangleF left, RectangleF right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(RectangleF left, RectangleF right)
{
return !(left == right);
}
/// <summary>
/// Performs an explicit conversion to <see cref="Rectangle"/> structure.
/// </summary>
/// <remarks>Performs direct float to int conversion, any fractional data is truncated.</remarks>
/// <param name="value">The source <see cref="RectangleF"/> value.</param>
/// <returns>A converted <see cref="Rectangle"/> structure.</returns>
public static explicit operator Rectangle(RectangleF value)
{
return new Rectangle((int)value.X, (int)value.Y, (int)value.Width, (int)value.Height);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height);
}
}
}

132
math/Size2.cs Normal file
View File

@ -0,0 +1,132 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Defines a 2D rectangular size (width,height).
/// </summary>
[DataContract( Name = "!Size2")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Size2 : IEquatable<Size2>
{
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2 Zero = new Size2(0, 0);
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2 Empty = Zero;
/// <summary>
/// Initializes a new instance of the <see cref="Size2"/> struct.
/// </summary>
/// <param name="width">The x.</param>
/// <param name="height">The y.</param>
public Size2(int width, int height)
{
Width = width;
Height = height;
}
/// <summary>
/// Width.
/// </summary>
[DataMember( Order = 0 )]
public int Width;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 1 )]
public int Height;
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Size2 other)
{
return other.Width == Width && other.Height == Height;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Size2)) return false;
return Equals((Size2)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (Width * 397) ^ Height;
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(Size2 left, Size2 right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(Size2 left, Size2 right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format("({0},{1})", Width, Height);
}
}
}

132
math/Size2F.cs Normal file
View File

@ -0,0 +1,132 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Defines a 2D rectangular size (width,height).
/// </summary>
[DataContract( Name = "Size2F")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Size2F : IEquatable<Size2F>
{
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Zero = new Size2F(0, 0);
/// <summary>
/// A zero size with (width, height) = (0,0)
/// </summary>
public static readonly Size2F Empty = Zero;
/// <summary>
/// Initializes a new instance of the <see cref="Size2F"/> struct.
/// </summary>
/// <param name="width">The x.</param>
/// <param name="height">The y.</param>
public Size2F(float width, float height)
{
Width = width;
Height = height;
}
/// <summary>
/// Width.
/// </summary>
[DataMember( Order = 0 )]
public float Width;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 1 )]
public float Height;
/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(Size2F other)
{
return other.Width == Width && other.Height == Height;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Size2F)) return false;
return Equals((Size2F)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (Width.GetHashCode() * 397) ^ Height.GetHashCode();
}
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(Size2F left, Size2F right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(Size2F left, Size2F right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format("({0},{1})", Width, Height);
}
}
}

237
math/Size3.cs Normal file
View File

@ -0,0 +1,237 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Structure providing Width, Height and Depth.
/// </summary>
[DataContract( Name = "!Size3")]
[DataStyle(DataStyle.Compact)]
[StructLayout(LayoutKind.Sequential)]
public struct Size3 : IEquatable<Size3>, IComparable<Size3>
{
/// <summary>
/// A zero size with (width, height, depth) = (0,0,0)
/// </summary>
public static readonly Size3 Zero = new Size3(0, 0, 0);
/// <summary>
/// A one size with (width, height, depth) = (1,1,1)
/// </summary>
public static readonly Size3 One = new Size3(1, 1, 1);
/// <summary>
/// A zero size with (width, height, depth) = (0,0,0)
/// </summary>
public static readonly Size3 Empty = Zero;
/// <summary>
/// Initializes a new instance of the <see cref="Size3" /> struct.
/// </summary>
/// <param name="width">The x.</param>
/// <param name="height">The y.</param>
/// <param name="depth">The depth.</param>
public Size3(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
}
/// <summary>
/// Width.
/// </summary>
[DataMember( Order = 0 )]
public int Width;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 1 )]
public int Height;
/// <summary>
/// Height.
/// </summary>
[DataMember( Order = 2 )]
public int Depth;
/// <summary>
/// Gets a volume size.
/// </summary>
private long VolumeSize
{
get
{
return (long)Width * Height * Depth;
}
}
/// <inheritdoc/>
public bool Equals(Size3 other)
{
return Width == other.Width && Height == other.Height && Depth == other.Depth;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Size3 && Equals((Size3)obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int hashCode = Width;
hashCode = (hashCode * 397) ^ Height;
hashCode = (hashCode * 397) ^ Depth;
return hashCode;
}
}
/// <inheritdoc/>
public int CompareTo(Size3 other)
{
return Math.Sign(this.VolumeSize - other.VolumeSize);
}
/// <inheritdoc/>
public override string ToString()
{
return string.Format("({0},{1},{2})", Width, Height, Depth);
}
/// <summary>
/// Implements the &lt;.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator <(Size3 left, Size3 right)
{
return left.CompareTo(right) < 0;
}
/// <summary>
/// Implements the &lt;.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator <=(Size3 left, Size3 right)
{
return left.CompareTo(right) <= 0;
}
/// <summary>
/// Implements the &lt; or ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator >(Size3 left, Size3 right)
{
return left.CompareTo(right) > 0;
}
/// <summary>
/// Implements the &gt; or ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator >=(Size3 left, Size3 right)
{
return left.CompareTo(right) >= 0;
}
/// <summary>
/// Implements the ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(Size3 left, Size3 right)
{
return left.Equals(right);
}
/// <summary>
/// Implements the !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(Size3 left, Size3 right)
{
return !left.Equals(right);
}
/// <summary>
/// Calculates the next up mip-level (*2) of this size.
/// </summary>
/// <returns>A next up mip-level Size3.</returns>
public Size3 Up2(int count = 1)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", "Must be >= 0");
}
return new Size3(Math.Max(1, Width << count), Math.Max(1, Height << count), Math.Max(1, Depth << count));
}
/// <summary>
/// Calculates the next down mip-level (/2) of this size.
/// </summary>
/// <param name="count">The count.</param>
/// <returns>A next down mip-level Size3.</returns>
public Size3 Down2(int count = 1)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", "Must be >= 0");
}
return new Size3(Math.Max(1, Width >> count), Math.Max(1, Height >> count), Math.Max(1, Depth >> count));
}
/// <summary>
/// Calculates the mip size based on a direction.
/// </summary>
/// <param name="direction">The direction &lt; 0 then <see cref="Down2"/>, &gt; 0 then <see cref="Up2"/>, else this unchanged.</param>
/// <returns>Size3.</returns>
public Size3 Mip(int direction)
{
return direction == 0 ? this : direction < 0 ? Down2() : Up2();
}
}
}

250
math/SphericalHarmonics.cs Normal file
View File

@ -0,0 +1,250 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
#pragma warning disable SA1003 // Symbols must be spaced correctly
#pragma warning disable SA1008 // Opening parenthesis must be spaced correctly
#pragma warning disable SA1009 // Closing parenthesis must be spaced correctly
#pragma warning disable SA1010 // Opening square brackets must be spaced correctly
#pragma warning disable SA1025 // Code must not contain multiple whitespace in a row
#pragma warning disable SA1119 // Statement must not use unnecessary parenthesis
#pragma warning disable SA1402 // File may only contain a single class
using System;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// A representation of a sphere of values via Spherical Harmonics (SH).
/// </summary>
/// <typeparam name="TDataType">The type of data contained by the sphere</typeparam>
[DataContract( Name = "SphericalHarmonicsGeneric")]
public abstract class SphericalHarmonics<TDataType>
{
/// <summary>
/// The maximum order supported.
/// </summary>
public const int MaximumOrder = 5;
private int order;
/// <summary>
/// The order of calculation of the spherical harmonic.
/// </summary>
[DataMember( Order = 0 )]
public int Order
{
get { return order; }
internal set
{
if (order>5)
throw new NotSupportedException("Only orders inferior or equal to 5 are supported");
order = Math.Max(1, value);
}
}
/// <summary>
/// Get the coefficients defining the spherical harmonics (the spherical coordinates x{l,m} multiplying the spherical base Y{l,m}).
/// </summary>
[DataMember( Order = 1 )]
public TDataType[] Coefficients { get; internal set; }
/// <summary>
/// Initializes a new instance of the <see cref="SphericalHarmonics{TDataType}"/> class (null, for serialization).
/// </summary>
internal SphericalHarmonics()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SphericalHarmonics{TDataType}"/> class.
/// </summary>
/// <param name="order">The order of the harmonics</param>
protected SphericalHarmonics(int order)
{
this.order = order;
Coefficients = new TDataType[order * order];
}
/// <summary>
/// Evaluate the value of the spherical harmonics in the provided direction.
/// </summary>
/// <param name="direction">The direction</param>
/// <returns>The value of the spherical harmonics in the direction</returns>
public abstract TDataType Evaluate(Vector3 direction);
/// <summary>
/// Returns the coefficient x{l,m} of the spherical harmonics (the {l,m} spherical coordinate corresponding to the spherical base Y{l,m}).
/// </summary>
/// <param name="l">the l index of the coefficient</param>
/// <param name="m">the m index of the coefficient</param>
/// <returns>the value of the coefficient</returns>
public TDataType this[int l, int m]
{
get
{
CheckIndicesValidity(l, m, order);
return Coefficients[LmToCoefficientIndex(l, m)];
}
set
{
CheckIndicesValidity(l, m, order);
Coefficients[LmToCoefficientIndex(l, m)] = value;
}
}
// ReSharper disable UnusedParameter.Local
private static void CheckIndicesValidity(int l, int m, int maxOrder)
// ReSharper restore UnusedParameter.Local
{
if (l > maxOrder - 1)
throw new IndexOutOfRangeException("'l' parameter should be between '0' and '{0}' (order-1).".ToFormat(maxOrder-1));
if (Math.Abs(m) > l)
throw new IndexOutOfRangeException("'m' parameter should be between '-l' and '+l'.");
}
private static int LmToCoefficientIndex(int l, int m)
{
return l * l + l + m;
}
}
/// <summary>
/// A spherical harmonics representation of a cubemap.
/// </summary>
[DataContract( Name = "SphericalHarmonics")]
public class SphericalHarmonics : SphericalHarmonics<Color3>
{
private readonly float[] baseValues;
private const float Pi4 = 4 * MathUtil.Pi;
private const float Pi16 = 16 * MathUtil.Pi;
private const float Pi64 = 64 * MathUtil.Pi;
private static readonly float SqrtPi = (float)Math.Sqrt(MathUtil.Pi);
/// <summary>
/// Base coefficients for SH.
/// </summary>
public static readonly float[] BaseCoefficients =
{
(float)(1.0/(2.0*SqrtPi)),
(float)(-Math.Sqrt(3.0/Pi4)),
(float)(Math.Sqrt(3.0/Pi4)),
(float)(-Math.Sqrt(3.0/Pi4)),
(float)(Math.Sqrt(15.0/Pi4)),
(float)(-Math.Sqrt(15.0/Pi4)),
(float)(Math.Sqrt(5.0/Pi16)),
(float)(-Math.Sqrt(15.0/Pi4)),
(float)(Math.Sqrt(15.0/Pi16)),
-(float)Math.Sqrt(70/Pi64),
(float)Math.Sqrt(105/Pi4),
-(float)Math.Sqrt(42/Pi64),
(float)Math.Sqrt(7/Pi16),
-(float)Math.Sqrt(42/Pi64),
(float)Math.Sqrt(105/Pi16),
-(float)Math.Sqrt(70/Pi64),
3*(float)Math.Sqrt(35/Pi16),
-3*(float)Math.Sqrt(70/Pi64),
3*(float)Math.Sqrt(5/Pi16),
-3*(float)Math.Sqrt(10/Pi64),
(float)(1.0/(16.0*SqrtPi)),
-3*(float)Math.Sqrt(10/Pi64),
3*(float)Math.Sqrt(5/Pi64),
-3*(float)Math.Sqrt(70/Pi64),
3*(float)Math.Sqrt(35/(4*Pi64)),
};
/// <summary>
/// Initializes a new instance of the <see cref="SphericalHarmonics"/> class (null, for serialization).
/// </summary>
internal SphericalHarmonics()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SphericalHarmonics"/> class.
/// </summary>
/// <param name="order">The order of the harmonics</param>
public SphericalHarmonics(int order)
: base(order)
{
baseValues = new float[order * order];
}
/// <summary>
/// Evaluates the color for the specified direction.
/// </summary>
/// <param name="direction">The direction to evaluate.</param>
/// <returns>The color computed for this direction.</returns>
public override Color3 Evaluate(Vector3 direction)
{
var x = direction.X;
var y = direction.Y;
var z = direction.Z;
var x2 = x*x;
var y2 = y*y;
var z2 = z*z;
var z3 = (float)Math.Pow(z, 3.0);
var x4 = (float)Math.Pow(x, 4.0);
var y4 = (float)Math.Pow(y, 4.0);
var z4 = (float)Math.Pow(z, 4.0);
//Equations based on data from: http://ppsloan.org/publications/StupidSH36.pdf
baseValues[ 0] = 1/(2*SqrtPi);
if (Order > 1)
{
baseValues[ 1] = -(float)Math.Sqrt(3/Pi4)*y;
baseValues[ 2] = (float)Math.Sqrt(3/Pi4)*z;
baseValues[ 3] = -(float)Math.Sqrt(3/Pi4)*x;
if (Order > 2)
{
baseValues[ 4] = (float)Math.Sqrt(15/Pi4)*y*x;
baseValues[ 5] = -(float)Math.Sqrt(15/Pi4)*y*z;
baseValues[ 6] = (float)Math.Sqrt(5/Pi16)*(3*z2-1);
baseValues[ 7] = -(float)Math.Sqrt(15/Pi4)*x*z;
baseValues[ 8] = (float)Math.Sqrt(15/Pi16)*(x2-y2);
if (Order > 3)
{
baseValues[ 9] = -(float)Math.Sqrt( 70/Pi64)*y*(3*x2-y2);
baseValues[10] = (float)Math.Sqrt(105/ Pi4)*y*x*z;
baseValues[11] = -(float)Math.Sqrt( 42/Pi64)*y*(-1+5*z2);
baseValues[12] = (float)Math.Sqrt( 7/Pi16)*(5*z3-3*z);
baseValues[13] = -(float)Math.Sqrt( 42/Pi64)*x*(-1+5*z2);
baseValues[14] = (float)Math.Sqrt(105/Pi16)*(x2-y2)*z;
baseValues[15] = -(float)Math.Sqrt( 70/Pi64)*x*(x2-3*y2);
if (Order > 4)
{
baseValues[16] = 3*(float)Math.Sqrt(35/Pi16)*x*y*(x2-y2);
baseValues[17] = -3*(float)Math.Sqrt(70/Pi64)*y*z*(3*x2-y2);
baseValues[18] = 3*(float)Math.Sqrt( 5/Pi16)*y*x*(-1+7*z2);
baseValues[19] = -3*(float)Math.Sqrt(10/Pi64)*y*z*(-3+7*z2);
baseValues[20] = (105*z4-90*z2+9)/(16*SqrtPi);
baseValues[21] = -3*(float)Math.Sqrt(10/Pi64)*x*z*(-3+7*z2);
baseValues[22] = 3*(float)Math.Sqrt( 5/Pi64)*(x2-y2)*(-1+7*z2);
baseValues[23] = -3*(float)Math.Sqrt(70/Pi64)*x*z*(x2-3*y2);
baseValues[24] = 3*(float)Math.Sqrt(35/(4*Pi64))*(x4-6*y2*x2+y4);
}
}
}
}
var data = new Color3();
for (int i = 0; i < baseValues.Length; i++)
data += Coefficients[i] * baseValues[i];
return data;
}
}
}

640
math/UInt4.cs Normal file
View File

@ -0,0 +1,640 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
//
// Copyright (c) 2010-2011 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using Xenko.Core.Serialization;
using System.Runtime.Serialization;
namespace math
{
/// <summary>
/// Represents a four dimensional mathematical vector.
/// </summary>
[DataContract]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct UInt4 : IEquatable<UInt4>, IFormattable
{
/// <summary>
/// The size of the <see cref = "UInt4" /> type, in bytes.
/// </summary>
public static readonly int SizeInBytes = Utilities.SizeOf<UInt4>();
/// <summary>
/// A <see cref = "UInt4" /> with all of its components set to zero.
/// </summary>
public static readonly UInt4 Zero = new UInt4();
/// <summary>
/// The X unit <see cref = "UInt4" /> (1, 0, 0, 0).
/// </summary>
public static readonly UInt4 UnitX = new UInt4(1, 0, 0, 0);
/// <summary>
/// The Y unit <see cref = "UInt4" /> (0, 1, 0, 0).
/// </summary>
public static readonly UInt4 UnitY = new UInt4(0, 1, 0, 0);
/// <summary>
/// The Z unit <see cref = "UInt4" /> (0, 0, 1, 0).
/// </summary>
public static readonly UInt4 UnitZ = new UInt4(0, 0, 1, 0);
/// <summary>
/// The W unit <see cref = "UInt4" /> (0, 0, 0, 1).
/// </summary>
public static readonly UInt4 UnitW = new UInt4(0, 0, 0, 1);
/// <summary>
/// A <see cref = "UInt4" /> with all of its components set to one.
/// </summary>
public static readonly UInt4 One = new UInt4(1, 1, 1, 1);
/// <summary>
/// The X component of the vector.
/// </summary>
public uint X;
/// <summary>
/// The Y component of the vector.
/// </summary>
public uint Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
public uint Z;
/// <summary>
/// The W component of the vector.
/// </summary>
public uint W;
/// <summary>
/// Initializes a new instance of the <see cref = "UInt4" /> struct.
/// </summary>
/// <param name = "value">The value that will be assigned to all components.</param>
public UInt4(uint value)
{
X = value;
Y = value;
Z = value;
W = value;
}
/// <summary>
/// Initializes a new instance of the <see cref = "UInt4" /> struct.
/// </summary>
/// <param name = "x">Initial value for the X component of the vector.</param>
/// <param name = "y">Initial value for the Y component of the vector.</param>
/// <param name = "z">Initial value for the Z component of the vector.</param>
/// <param name = "w">Initial value for the W component of the vector.</param>
public UInt4(uint x, uint y, uint z, uint w)
{
X = x;
Y = y;
Z = z;
W = w;
}
/// <summary>
/// Initializes a new instance of the <see cref = "UInt4" /> struct.
/// </summary>
/// <param name = "values">The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements.</param>
/// <exception cref = "ArgumentNullException">Thrown when <paramref name = "values" /> is <c>null</c>.</exception>
/// <exception cref = "ArgumentOutOfRangeException">Thrown when <paramref name = "values" /> contains more or less than four elements.</exception>
public UInt4(uint[] values)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length != 4)
throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for UInt4.");
X = values[0];
Y = values[1];
Z = values[2];
W = values[3];
}
/// <summary>
/// Gets or sets the component at the specified index.
/// </summary>
/// <value>The value of the X, Y, Z, or W component, depending on the index.</value>
/// <param name = "index">The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component.</param>
/// <returns>The value of the component at the specified index.</returns>
/// <exception cref = "System.ArgumentOutOfRangeException">Thrown when the <paramref name = "index" /> is out of the range [0, 3].</exception>
public uint this[uint index]
{
get
{
switch (index)
{
case 0:
return X;
case 1:
return Y;
case 2:
return Z;
case 3:
return W;
}
throw new ArgumentOutOfRangeException("index", "Indices for UInt4 run from 0 to 3, inclusive.");
}
set
{
switch (index)
{
case 0:
X = value;
break;
case 1:
Y = value;
break;
case 2:
Z = value;
break;
case 3:
W = value;
break;
default:
throw new ArgumentOutOfRangeException("index", "Indices for UInt4 run from 0 to 3, inclusive.");
}
}
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>
/// <returns>A four-element array containing the components of the vector.</returns>
public uint[] ToArray()
{
return new uint[] { X, Y, Z, W };
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <param name = "result">When the method completes, contains the sum of the two vectors.</param>
public static void Add(ref UInt4 left, ref UInt4 right, out UInt4 result)
{
result = new UInt4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static UInt4 Add(UInt4 left, UInt4 right)
{
return new UInt4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <param name = "result">When the method completes, contains the difference of the two vectors.</param>
public static void Subtract(ref UInt4 left, ref UInt4 right, out UInt4 result)
{
result = new UInt4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static UInt4 Subtract(UInt4 left, UInt4 right)
{
return new UInt4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <param name = "result">When the method completes, contains the scaled vector.</param>
public static void Multiply(ref UInt4 value, uint scale, out UInt4 result)
{
result = new UInt4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static UInt4 Multiply(UInt4 value, uint scale)
{
return new UInt4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name = "left">The first vector to modulate.</param>
/// <param name = "right">The second vector to modulate.</param>
/// <param name = "result">When the method completes, contains the modulated vector.</param>
public static void Modulate(ref UInt4 left, ref UInt4 right, out UInt4 result)
{
result = new UInt4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
}
/// <summary>
/// Modulates a vector with another by performing component-wise multiplication.
/// </summary>
/// <param name = "left">The first vector to modulate.</param>
/// <param name = "right">The second vector to modulate.</param>
/// <returns>The modulated vector.</returns>
public static UInt4 Modulate(UInt4 left, UInt4 right)
{
return new UInt4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <param name = "result">When the method completes, contains the scaled vector.</param>
public static void Divide(ref UInt4 value, uint scale, out UInt4 result)
{
result = new UInt4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static UInt4 Divide(UInt4 value, uint scale)
{
return new UInt4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <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.</param>
/// <param name = "max">The maximum value.</param>
/// <param name = "result">When the method completes, contains the clamped value.</param>
public static void Clamp(ref UInt4 value, ref UInt4 min, ref UInt4 max, out UInt4 result)
{
uint x = value.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
uint y = value.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
uint z = value.Z;
z = (z > max.Z) ? max.Z : z;
z = (z < min.Z) ? min.Z : z;
uint w = value.W;
w = (w > max.W) ? max.W : w;
w = (w < min.W) ? min.W : w;
result = new UInt4(x, y, z, w);
}
/// <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.</param>
/// <param name = "max">The maximum value.</param>
/// <returns>The clamped value.</returns>
public static UInt4 Clamp(UInt4 value, UInt4 min, UInt4 max)
{
UInt4 result;
Clamp(ref value, ref min, ref max, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <param name = "result">When the method completes, contains an new vector composed of the largest components of the source vectors.</param>
public static void Max(ref UInt4 left, ref UInt4 right, out UInt4 result)
{
result.X = (left.X > right.X) ? left.X : right.X;
result.Y = (left.Y > right.Y) ? left.Y : right.Y;
result.Z = (left.Z > right.Z) ? left.Z : right.Z;
result.W = (left.W > right.W) ? left.W : right.W;
}
/// <summary>
/// Returns a vector containing the largest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <returns>A vector containing the largest components of the source vectors.</returns>
public static UInt4 Max(UInt4 left, UInt4 right)
{
UInt4 result;
Max(ref left, ref right, out result);
return result;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <param name = "result">When the method completes, contains an new vector composed of the smallest components of the source vectors.</param>
public static void Min(ref UInt4 left, ref UInt4 right, out UInt4 result)
{
result.X = (left.X < right.X) ? left.X : right.X;
result.Y = (left.Y < right.Y) ? left.Y : right.Y;
result.Z = (left.Z < right.Z) ? left.Z : right.Z;
result.W = (left.W < right.W) ? left.W : right.W;
}
/// <summary>
/// Returns a vector containing the smallest components of the specified vectors.
/// </summary>
/// <param name = "left">The first source vector.</param>
/// <param name = "right">The second source vector.</param>
/// <returns>A vector containing the smallest components of the source vectors.</returns>
public static UInt4 Min(UInt4 left, UInt4 right)
{
UInt4 result;
Min(ref left, ref right, out result);
return result;
}
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name = "left">The first vector to add.</param>
/// <param name = "right">The second vector to add.</param>
/// <returns>The sum of the two vectors.</returns>
public static UInt4 operator +(UInt4 left, UInt4 right)
{
return new UInt4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Assert a vector (return it unchanged).
/// </summary>
/// <param name = "value">The vector to assert (unchange).</param>
/// <returns>The asserted (unchanged) vector.</returns>
public static UInt4 operator +(UInt4 value)
{
return value;
}
/// <summary>
/// Subtracts two vectors.
/// </summary>
/// <param name = "left">The first vector to subtract.</param>
/// <param name = "right">The second vector to subtract.</param>
/// <returns>The difference of the two vectors.</returns>
public static UInt4 operator -(UInt4 left, UInt4 right)
{
return new UInt4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static UInt4 operator *(uint scale, UInt4 value)
{
return new UInt4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static UInt4 operator *(UInt4 value, uint scale)
{
return new UInt4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale);
}
/// <summary>
/// Scales a vector by the given value.
/// </summary>
/// <param name = "value">The vector to scale.</param>
/// <param name = "scale">The amount by which to scale the vector.</param>
/// <returns>The scaled vector.</returns>
public static UInt4 operator /(UInt4 value, uint scale)
{
return new UInt4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale);
}
/// <summary>
/// Tests for equality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name = "left" /> has the same value as <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator ==(UInt4 left, UInt4 right)
{
return left.Equals(right);
}
/// <summary>
/// Tests for inequality between two objects.
/// </summary>
/// <param name = "left">The first value to compare.</param>
/// <param name = "right">The second value to compare.</param>
/// <returns><c>true</c> if <paramref name = "left" /> has a different value than <paramref name = "right" />; otherwise, <c>false</c>.</returns>
public static bool operator !=(UInt4 left, UInt4 right)
{
return !left.Equals(right);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "UInt4" /> to <see cref = "Vec2" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vec2(UInt4 value)
{
return new Vec2(value.X, value.Y);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "UInt4" /> to <see cref = "Vector3" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector3(UInt4 value)
{
return new Vector3(value.X, value.Y, value.Z);
}
/// <summary>
/// Performs an explicit conversion from <see cref = "UInt4" /> to <see cref = "Vector4" />.
/// </summary>
/// <param name = "value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator Vector4(UInt4 value)
{
return new Vector4(value.X, value.Y, value.Z, value.W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "format">The format.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(string format)
{
if (format == null)
return ToString();
return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}",
X.ToString(format, CultureInfo.CurrentCulture),
Y.ToString(format, CultureInfo.CurrentCulture),
Z.ToString(format, CultureInfo.CurrentCulture),
W.ToString(format, CultureInfo.CurrentCulture));
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "formatProvider">The format provider.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
}
/// <summary>
/// Returns a <see cref = "string" /> that represents this instance.
/// </summary>
/// <param name = "format">The format.</param>
/// <param name = "formatProvider">The format provider.</param>
/// <returns>
/// A <see cref = "string" /> that represents this instance.
/// </returns>
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
ToString(formatProvider);
return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider),
Y.ToString(format, formatProvider), Z.ToString(format, formatProvider),
W.ToString(format, formatProvider));
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode();
}
/// <summary>
/// Determines whether the specified <see cref = "UInt4" /> is equal to this instance.
/// </summary>
/// <param name = "other">The <see cref = "UInt4" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref = "UInt4" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(UInt4 other)
{
return other.X == X && other.Y == Y && other.Z == Z && other.W == W;
}
/// <summary>
/// Determines whether the specified <see cref = "object" /> is equal to this instance.
/// </summary>
/// <param name = "value">The <see cref = "object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref = "object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object value)
{
if (value == null)
return false;
if (value.GetType() != GetType())
return false;
return Equals((UInt4)value);
}
/// <summary>
/// Performs an implicit conversion from <see cref="uint"/> array to <see cref="math.UInt4"/>.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator UInt4(uint[] input)
{
return new UInt4(input);
}
/// <summary>
/// Performs an implicit conversion from <see cref="math.UInt4"/> to <see cref="int"/> array.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator uint[](UInt4 input)
{
return input.ToArray();
}
}
}

1462
math/Vector2.cs Normal file

File diff suppressed because it is too large Load Diff

1737
math/Vector3.cs Normal file

File diff suppressed because it is too large Load Diff

1410
math/Vector4.cs Normal file

File diff suppressed because it is too large Load Diff

64
math/VectorExtensions.cs Normal file
View File

@ -0,0 +1,64 @@
// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
namespace math
{
/// <summary>
/// Extensions methods of the vector classes.
/// </summary>
public static class VectorExtensions
{
/// <summary>
/// Return the Y/X components of the vector in the inverse order.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YX(this Vec2 vector)
{
return new Vec2(vector.Y, vector.X);
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY(this Vector3 vector)
{
return new Vec2(vector.X, vector.Y);
}
/// <summary>
/// Return the X/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XZ(this Vector3 vector)
{
return new Vec2(vector.X, vector.Z);
}
/// <summary>
/// Return the Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 YZ(this Vector3 vector)
{
return new Vec2(vector.Y, vector.Z);
}
/// <summary>
/// Return the X/Y components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vec2 XY(this Vector4 vector)
{
return new Vec2(vector.X, vector.Y);
}
/// <summary>
/// Return the X/Y/Z components of the vector.
/// </summary>
/// <param name="vector">the input vector</param>
public static Vector3 XYZ(this Vector4 vector)
{
return new Vector3(vector.X, vector.Y, vector.Z);
}
}
}