More cleanups of custom classes in favor of .NET runtime types.
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
@@ -233,14 +233,14 @@ namespace Framework.GameMath
|
||||
|
||||
public void merge(AxisAlignedBox a)
|
||||
{
|
||||
Lo = Lo.Min(a.Lo);
|
||||
Hi = Hi.Max(a.Hi);
|
||||
Lo = Vector3.Min(_lo, a.Lo);
|
||||
Hi = Vector3.Max(Hi, a.Hi);
|
||||
}
|
||||
|
||||
public void merge(Vector3 a)
|
||||
{
|
||||
_lo = _lo.Min(a);
|
||||
_hi = _hi.Max(a);
|
||||
_lo = Vector3.Min(_lo, a);
|
||||
_hi = Vector3.Max(_hi, a);
|
||||
}
|
||||
|
||||
public static AxisAlignedBox Zero()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
@@ -26,7 +27,7 @@ namespace Framework.GameMath
|
||||
Vector3 normal = Vector3.Zero;
|
||||
if (collisionLocationForMovingPointFixedAABox(origin, dir, box, ref location, out Inside, ref normal))
|
||||
{
|
||||
return (location - origin).magnitude();
|
||||
return Vector3.Distance(location, origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -43,26 +44,26 @@ namespace Framework.GameMath
|
||||
// Find candidate planes.
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (origin[i] < MinB[i])
|
||||
if (origin.GetAt(i) < MinB.GetAt(i))
|
||||
{
|
||||
location[i] = MinB[i];
|
||||
location.SetAt(MinB.GetAt(i), i);
|
||||
Inside = false;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if ((uint)dir[i] != 0)
|
||||
if ((uint)dir.GetAt(i) != 0)
|
||||
{
|
||||
MaxT[i] = (MinB[i] - origin[i]) / dir[i];
|
||||
MaxT.SetAt((MinB.GetAt(i) - origin.GetAt(i)) / dir.GetAt(i), i);
|
||||
}
|
||||
}
|
||||
else if (origin[i] > MaxB[i])
|
||||
else if (origin.GetAt(i) > MaxB.GetAt(i))
|
||||
{
|
||||
location[i] = MaxB[i];
|
||||
location.SetAt(MaxB.GetAt(i), i);
|
||||
Inside = false;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if ((uint)dir[i] != 0)
|
||||
if ((uint)dir.GetAt(i) != 0)
|
||||
{
|
||||
MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
|
||||
MaxT.SetAt((MaxB.GetAt(i) - origin.GetAt(i)) / dir.GetAt(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,18 +77,18 @@ namespace Framework.GameMath
|
||||
|
||||
// Get largest of the maxT's for final choice of intersection
|
||||
int WhichPlane = 0;
|
||||
if (MaxT[1] > MaxT[WhichPlane])
|
||||
if (MaxT.Y > MaxT.GetAt(WhichPlane))
|
||||
{
|
||||
WhichPlane = 1;
|
||||
}
|
||||
|
||||
if (MaxT[2] > MaxT[WhichPlane])
|
||||
if (MaxT.Z > MaxT.GetAt(WhichPlane))
|
||||
{
|
||||
WhichPlane = 2;
|
||||
}
|
||||
|
||||
// Check final candidate actually inside box
|
||||
if (Convert.ToBoolean((uint)MaxT[WhichPlane] & 0x80000000))
|
||||
if (Convert.ToBoolean((uint)MaxT.GetAt(WhichPlane) & 0x80000000))
|
||||
{
|
||||
// Miss the box
|
||||
return false;
|
||||
@@ -97,9 +98,9 @@ namespace Framework.GameMath
|
||||
{
|
||||
if (i != WhichPlane)
|
||||
{
|
||||
location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
|
||||
if ((location[i] < MinB[i]) ||
|
||||
(location[i] > MaxB[i]))
|
||||
location.SetAt(origin.GetAt(i) + MaxT.GetAt(WhichPlane) * dir.GetAt(i), i);
|
||||
if ((location.GetAt(i) < MinB.GetAt(i)) ||
|
||||
(location.GetAt(i) > MaxB.GetAt(i)))
|
||||
{
|
||||
// On this plane we're outside the box extents, so
|
||||
// we miss the box
|
||||
@@ -110,7 +111,7 @@ namespace Framework.GameMath
|
||||
|
||||
// Choose the normal to be the plane normal facing into the ray
|
||||
normal = Vector3.Zero;
|
||||
normal[WhichPlane] = (float)((dir[WhichPlane] > 0) ? -1.0 : 1.0);
|
||||
normal.SetAt((float)((dir.GetAt(WhichPlane) > 0) ? -1.0 : 1.0), WhichPlane);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,614 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 2-dimentional single-precision floating point matrix.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public struct Matrix2 : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private float _m11, _m12;
|
||||
private float _m21, _m22;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix2"/> structure with the specified values.
|
||||
/// </summary>
|
||||
public Matrix2(float m11, float m12, float m21, float m22)
|
||||
{
|
||||
_m11 = m11; _m12 = m12;
|
||||
_m21 = m21; _m22 = m22;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix2"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix2(float[] elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Length >= 4);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1];
|
||||
_m21 = elements[2]; _m22 = elements[3];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix2(List<float> elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Count >= 4);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1];
|
||||
_m21 = elements[2]; _m22 = elements[3];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix2"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="column1">A <see cref="Vector2"/> instance holding values for the first column.</param>
|
||||
/// <param name="column2">A <see cref="Vector2"/> instance holding values for the second column.</param>
|
||||
public Matrix2(Vector2 column1, Vector2 column2)
|
||||
{
|
||||
_m11 = column1.X; _m12 = column2.X;
|
||||
_m21 = column1.Y; _m22 = column2.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix2"/> class using a given matrix.
|
||||
/// </summary>
|
||||
public Matrix2(Matrix2 m)
|
||||
{
|
||||
_m11 = m.M11; _m12 = m.M12;
|
||||
_m21 = m.M21; _m22 = m.M22;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point zero matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix2 Zero = new(0, 0, 0, 0);
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point identity matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix2 Identity = new(1, 0, 0, 1);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M11
|
||||
{
|
||||
get { return _m11; }
|
||||
set { _m11 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M12
|
||||
{
|
||||
get { return _m12; }
|
||||
set { _m12 = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M21
|
||||
{
|
||||
get { return _m21; }
|
||||
set { _m21 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M22
|
||||
{
|
||||
get { return _m22; }
|
||||
set { _m22 = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the matrix's trace value.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float Trace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _m11 + _m22;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix2"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix2"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Matrix2(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix2"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix2"/> object this method creates.</returns>
|
||||
public Matrix2 Clone()
|
||||
{
|
||||
return new Matrix2(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Parse Methods
|
||||
private const string regularExp = @"2x2\s*\[(?<m11>.*),(?<m12>.*),(?<m21>.*),(?<m22>.*)\]";
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix2"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix2"/>.</param>
|
||||
/// <returns>A <see cref="Matrix2"/> that represents the vector specified by the <paramref name="value"/> parameter.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "2x2..matrix elements..>".<br/>
|
||||
/// Exmaple : "2x2[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static Matrix2 Parse(string value)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Matrix2(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix2"/> equivalent.
|
||||
/// A return value indicates whether the conversion succeeded or failed.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix2"/>.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, if the conversion succeeded,
|
||||
/// contains a <see cref="Matrix2"/> representing the vector specified by <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if value was converted successfully; otherwise, <see langword="false"/>.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "2x2..matrix elements..>".<br/>
|
||||
/// Exmaple : "2x2[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static bool TryParse(string value, out Matrix2 result)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
result = new Matrix2(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = Matrix2.Zero;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Matrix Arithmetics
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the sum.</returns>
|
||||
public static Matrix2 Add(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return new Matrix2(
|
||||
left.M11 + right.M11, left.M12 + right.M12,
|
||||
left.M21 + right.M21, left.M22 + right.M22
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the sum.</returns>
|
||||
public static Matrix2 Add(Matrix2 matrix, float scalar)
|
||||
{
|
||||
return new Matrix2(
|
||||
matrix.M11 + scalar, matrix.M12 + scalar,
|
||||
matrix.M21 + scalar, matrix.M22 + scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix2"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix2 left, Matrix2 right, ref Matrix2 result)
|
||||
{
|
||||
result.M11 = left.M11 + right.M11;
|
||||
result.M12 = left.M12 + right.M12;
|
||||
|
||||
result.M21 = left.M21 + right.M21;
|
||||
result.M22 = left.M22 + right.M22;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix2"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix2 matrix, float scalar, ref Matrix2 result)
|
||||
{
|
||||
result.M11 = matrix.M11 + scalar;
|
||||
result.M12 = matrix.M12 + scalar;
|
||||
|
||||
result.M21 = matrix.M21 + scalar;
|
||||
result.M22 = matrix.M22 + scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance to subtract.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the difference.</returns>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static Matrix2 Subtract(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return new Matrix2(
|
||||
left.M11 - right.M11, left.M12 - right.M12,
|
||||
left.M21 - right.M21, left.M22 - right.M22
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the difference.</returns>
|
||||
public static Matrix2 Subtract(Matrix2 matrix, float scalar)
|
||||
{
|
||||
return new Matrix2(
|
||||
matrix.M11 - scalar, matrix.M12 - scalar,
|
||||
matrix.M21 - scalar, matrix.M22 - scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance to subtract.</param>
|
||||
/// <param name="result">A <see cref="Matrix2"/> instance to hold the result.</param>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static void Subtract(Matrix2 left, Matrix2 right, ref Matrix2 result)
|
||||
{
|
||||
result.M11 = left.M11 - right.M11;
|
||||
result.M12 = left.M12 - right.M12;
|
||||
|
||||
result.M21 = left.M21 - right.M21;
|
||||
result.M22 = left.M22 - right.M22;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix2"/> instance to hold the result.</param>
|
||||
public static void Subtract(Matrix2 matrix, float scalar, ref Matrix2 result)
|
||||
{
|
||||
result.M11 = matrix.M11 - scalar;
|
||||
result.M12 = matrix.M12 - scalar;
|
||||
|
||||
result.M21 = matrix.M21 - scalar;
|
||||
result.M22 = matrix.M22 - scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the result.</returns>
|
||||
public static Matrix2 Multiply(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return new Matrix2(
|
||||
left.M11 * right.M11 + left.M12 * right.M21,
|
||||
left.M11 * right.M12 + left.M12 * right.M22,
|
||||
left.M21 * right.M11 + left.M22 * right.M21,
|
||||
left.M21 * right.M12 + left.M22 * right.M22
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix2"/> instance to hold the result.</param>
|
||||
public static void Multiply(Matrix2 left, Matrix2 right, ref Matrix2 result)
|
||||
{
|
||||
result.M11 = left.M11 * right.M11 + left.M12 * right.M21;
|
||||
result.M12 = left.M11 * right.M12 + left.M12 * right.M22;
|
||||
|
||||
result.M21 = left.M21 * right.M11 + left.M22 * right.M21;
|
||||
result.M22 = left.M21 * right.M12 + left.M22 * right.M22;
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the result.</returns>
|
||||
public static Vector2 Transform(Matrix2 matrix, Vector2 vector)
|
||||
{
|
||||
return new Vector2(
|
||||
(matrix.M11 * vector.X) + (matrix.M12 * vector.Y),
|
||||
(matrix.M21 * vector.X) + (matrix.M22 * vector.Y));
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix and put the result in a vector.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
public static void Transform(Matrix2 matrix, Vector2 vector, ref Vector2 result)
|
||||
{
|
||||
result.X = (matrix.M11 * vector.X) + (matrix.M12 * vector.Y);
|
||||
result.Y = (matrix.M21 * vector.X) + (matrix.M22 * vector.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes a matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the transposed matrix.</returns>
|
||||
public static Matrix2 Transpose(Matrix2 m)
|
||||
{
|
||||
Matrix2 t = new(m);
|
||||
t.Transpose();
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Object overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return
|
||||
_m11.GetHashCode() ^ _m12.GetHashCode() ^
|
||||
_m21.GetHashCode() ^ _m22.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="Matrix2"/> and has the same values as this instance; otherwise, <see langword="false"/>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Matrix2)
|
||||
{
|
||||
Matrix2 m = (Matrix2)obj;
|
||||
return
|
||||
(_m11 == m.M11) && (_m12 == m.M12) &&
|
||||
(_m21 == m.M21) && (_m22 == m.M22);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"2x2[{_m11}, {_m12}, {_m21}, {_m22}]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Calculates the determinant value of the matrix.
|
||||
/// </summary>
|
||||
/// <returns>The determinant value of the matrix.</returns>
|
||||
public float GetDeterminant()
|
||||
{
|
||||
return (_m11 * _m22) - (_m12 * _m21);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes this matrix.
|
||||
/// </summary>
|
||||
public void Transpose()
|
||||
{
|
||||
MathFunctions.Swap(ref _m12, ref _m21);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator ==(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return ValueType.Equals(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are not equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator !=(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return !ValueType.Equals(left, right);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Binary Operators
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the sum.</returns>
|
||||
public static Matrix2 operator +(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return Matrix2.Add(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the sum.</returns>
|
||||
public static Matrix2 operator +(Matrix2 matrix, float scalar)
|
||||
{
|
||||
return Matrix2.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the sum.</returns>
|
||||
public static Matrix2 operator +(float scalar, Matrix2 matrix)
|
||||
{
|
||||
return Matrix2.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the difference.</returns>
|
||||
public static Matrix2 operator -(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return Matrix2.Subtract(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the difference.</returns>
|
||||
public static Matrix2 operator -(Matrix2 matrix, float scalar)
|
||||
{
|
||||
return Matrix2.Subtract(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix2"/> instance containing the result.</returns>
|
||||
public static Matrix2 operator *(Matrix2 left, Matrix2 right)
|
||||
{
|
||||
return Matrix2.Multiply(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix2"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the result.</returns>
|
||||
public static Vector2 operator *(Matrix2 matrix, Vector2 vector)
|
||||
{
|
||||
return Matrix2.Transform(matrix, vector);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Indexing Operators
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by an index
|
||||
/// where index = 2*row + column.
|
||||
/// </summary>
|
||||
public unsafe float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= 4)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
return *(f + index);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= 4)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
*(f + index) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by row and column.
|
||||
/// </summary>
|
||||
public float this[int row, int column]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[(row - 1) * 2 + (column - 1)];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[(row - 1) * 2 + (column - 1)] = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,807 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 3-dimentional single-precision floating point matrix.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public struct Matrix3 : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private float _m11, _m12, _m13;
|
||||
private float _m21, _m22, _m23;
|
||||
private float _m31, _m32, _m33;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix3"/> structure with the specified values.
|
||||
/// </summary>
|
||||
public Matrix3(float m11, float m12, float m13, float m21, float m22, float m23, float m31, float m32, float m33)
|
||||
{
|
||||
_m11 = m11; _m12 = m12; _m13 = m13;
|
||||
_m21 = m21; _m22 = m22; _m23 = m23;
|
||||
_m31 = m31; _m32 = m32; _m33 = m33;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix3"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix3(float[] elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Length >= 9);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1]; _m13 = elements[2];
|
||||
_m21 = elements[3]; _m22 = elements[4]; _m23 = elements[5];
|
||||
_m31 = elements[6]; _m32 = elements[7]; _m33 = elements[8];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix3(List<float> elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Count >= 9);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1]; _m13 = elements[2];
|
||||
_m21 = elements[3]; _m22 = elements[4]; _m23 = elements[5];
|
||||
_m31 = elements[6]; _m32 = elements[7]; _m33 = elements[8];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix3"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="column1">A <see cref="Vector3"/> instance holding values for the first column.</param>
|
||||
/// <param name="column2">A <see cref="Vector3"/> instance holding values for the second column.</param>
|
||||
/// <param name="column3">A <see cref="Vector3"/> instance holding values for the third column.</param>
|
||||
public Matrix3(Vector3 column1, Vector3 column2, Vector3 column3)
|
||||
{
|
||||
_m11 = column1.X; _m12 = column2.X; _m13 = column3.X;
|
||||
_m21 = column1.Y; _m22 = column2.Y; _m23 = column3.Y;
|
||||
_m31 = column1.Z; _m32 = column2.Z; _m33 = column3.Z;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix3"/> class using a given matrix.
|
||||
/// </summary>
|
||||
public Matrix3(Matrix3 m)
|
||||
{
|
||||
_m11 = m.M11; _m12 = m.M12; _m13 = m.M13;
|
||||
_m21 = m.M21; _m22 = m.M22; _m23 = m.M23;
|
||||
_m31 = m.M31; _m32 = m.M32; _m33 = m.M33;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point zero matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix3 Zero = new(0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point identity matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix3 Identity = new(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M11
|
||||
{
|
||||
get { return _m11; }
|
||||
set { _m11 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M12
|
||||
{
|
||||
get { return _m12; }
|
||||
set { _m12 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M13
|
||||
{
|
||||
get { return _m13; }
|
||||
set { _m13 = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M21
|
||||
{
|
||||
get { return _m21; }
|
||||
set { _m21 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M22
|
||||
{
|
||||
get { return _m22; }
|
||||
set { _m22 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M23
|
||||
{
|
||||
get { return _m23; }
|
||||
set { _m23 = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M31
|
||||
{
|
||||
get { return _m31; }
|
||||
set { _m31 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M32
|
||||
{
|
||||
get { return _m32; }
|
||||
set { _m32 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M33
|
||||
{
|
||||
get { return _m33; }
|
||||
set { _m33 = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the matrix's trace value.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float Trace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _m11 + _m22 + _m33;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix3"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix3"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Matrix3(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix3"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix3"/> object this method creates.</returns>
|
||||
public Matrix3 Clone()
|
||||
{
|
||||
return new Matrix3(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Parse Methods
|
||||
private const string regularExp = @"3x3\s*\[(?<m11>.*),(?<m12>.*),(?<m13>.*),(?<m21>.*),(?<m22>.*),(?<m23>.*),(?<m31>.*),(?<m32>.*),(?<m33>.*)\]";
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix3"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix3"/>.</param>
|
||||
/// <returns>A <see cref="Matrix3"/> that represents the vector specified by the <paramref name="value"/> parameter.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "3x3..matrix elements..>".<br/>
|
||||
/// Exmaple : "3x3[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static Matrix3 Parse(string value)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Matrix3(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
float.Parse(m.Result("${m13}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}")),
|
||||
float.Parse(m.Result("${m23}")),
|
||||
|
||||
float.Parse(m.Result("${m31}")),
|
||||
float.Parse(m.Result("${m32}")),
|
||||
float.Parse(m.Result("${m33}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix3"/> equivalent.
|
||||
/// A return value indicates whether the conversion succeeded or failed.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix3"/>.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, if the conversion succeeded,
|
||||
/// contains a <see cref="Matrix3"/> representing the vector specified by <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if value was converted successfully; otherwise, <see langword="false"/>.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "3x3..matrix elements..>".<br/>
|
||||
/// Exmaple : "3x3[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static bool TryParse(string value, out Matrix3 result)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
result = new Matrix3(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
float.Parse(m.Result("${m13}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}")),
|
||||
float.Parse(m.Result("${m23}")),
|
||||
|
||||
float.Parse(m.Result("${m31}")),
|
||||
float.Parse(m.Result("${m32}")),
|
||||
float.Parse(m.Result("${m33}"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = Matrix3.Zero;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Matrix Arithmetics
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the sum.</returns>
|
||||
public static Matrix3 Add(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return new Matrix3(
|
||||
left.M11 + right.M11, left.M12 + right.M12, left.M13 + right.M13,
|
||||
left.M21 + right.M21, left.M22 + right.M22, left.M23 + right.M23,
|
||||
left.M31 + right.M31, left.M32 + right.M32, left.M33 + right.M33
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the sum.</returns>
|
||||
public static Matrix3 Add(Matrix3 matrix, float scalar)
|
||||
{
|
||||
return new Matrix3(
|
||||
matrix.M11 + scalar, matrix.M12 + scalar, matrix.M13 + scalar,
|
||||
matrix.M21 + scalar, matrix.M22 + scalar, matrix.M23 + scalar,
|
||||
matrix.M31 + scalar, matrix.M32 + scalar, matrix.M33 + scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix3"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix3 left, Matrix3 right, ref Matrix3 result)
|
||||
{
|
||||
result.M11 = left.M11 + right.M11;
|
||||
result.M12 = left.M12 + right.M12;
|
||||
result.M13 = left.M13 + right.M13;
|
||||
|
||||
result.M21 = left.M21 + right.M21;
|
||||
result.M22 = left.M22 + right.M22;
|
||||
result.M23 = left.M23 + right.M23;
|
||||
|
||||
result.M31 = left.M31 + right.M31;
|
||||
result.M32 = left.M32 + right.M32;
|
||||
result.M33 = left.M33 + right.M33;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix3"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix3 matrix, float scalar, ref Matrix3 result)
|
||||
{
|
||||
result.M11 = matrix.M11 + scalar;
|
||||
result.M12 = matrix.M12 + scalar;
|
||||
result.M13 = matrix.M13 + scalar;
|
||||
|
||||
result.M21 = matrix.M21 + scalar;
|
||||
result.M22 = matrix.M22 + scalar;
|
||||
result.M23 = matrix.M23 + scalar;
|
||||
|
||||
result.M31 = matrix.M31 + scalar;
|
||||
result.M32 = matrix.M32 + scalar;
|
||||
result.M33 = matrix.M33 + scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance to subtract.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the difference.</returns>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static Matrix3 Subtract(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return new Matrix3(
|
||||
left.M11 - right.M11, left.M12 - right.M12, left.M13 - right.M13,
|
||||
left.M21 - right.M21, left.M22 - right.M22, left.M23 - right.M23,
|
||||
left.M31 - right.M31, left.M32 - right.M32, left.M33 - right.M33
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the difference.</returns>
|
||||
public static Matrix3 Subtract(Matrix3 matrix, float scalar)
|
||||
{
|
||||
return new Matrix3(
|
||||
matrix.M11 - scalar, matrix.M12 - scalar, matrix.M13 - scalar,
|
||||
matrix.M21 - scalar, matrix.M22 - scalar, matrix.M23 - scalar,
|
||||
matrix.M31 - scalar, matrix.M32 - scalar, matrix.M33 - scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance to subtract.</param>
|
||||
/// <param name="result">A <see cref="Matrix3"/> instance to hold the result.</param>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static void Subtract(Matrix3 left, Matrix3 right, ref Matrix3 result)
|
||||
{
|
||||
result.M11 = left.M11 - right.M11;
|
||||
result.M12 = left.M12 - right.M12;
|
||||
result.M13 = left.M13 - right.M13;
|
||||
|
||||
result.M21 = left.M21 - right.M21;
|
||||
result.M22 = left.M22 - right.M22;
|
||||
result.M23 = left.M23 - right.M23;
|
||||
|
||||
result.M31 = left.M31 - right.M31;
|
||||
result.M32 = left.M32 - right.M32;
|
||||
result.M33 = left.M33 - right.M33;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix3"/> instance to hold the result.</param>
|
||||
public static void Subtract(Matrix3 matrix, float scalar, ref Matrix3 result)
|
||||
{
|
||||
result.M11 = matrix.M11 - scalar;
|
||||
result.M12 = matrix.M12 - scalar;
|
||||
result.M13 = matrix.M13 - scalar;
|
||||
|
||||
result.M21 = matrix.M21 - scalar;
|
||||
result.M22 = matrix.M22 - scalar;
|
||||
result.M23 = matrix.M23 - scalar;
|
||||
|
||||
result.M31 = matrix.M31 - scalar;
|
||||
result.M32 = matrix.M32 - scalar;
|
||||
result.M33 = matrix.M33 - scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the result.</returns>
|
||||
public static Matrix3 Multiply(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return new Matrix3(
|
||||
left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31,
|
||||
left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32,
|
||||
left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33,
|
||||
|
||||
left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31,
|
||||
left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32,
|
||||
left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33,
|
||||
|
||||
left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31,
|
||||
left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32,
|
||||
left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix3"/> instance to hold the result.</param>
|
||||
public static void Multiply(Matrix3 left, Matrix3 right, ref Matrix3 result)
|
||||
{
|
||||
result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31;
|
||||
result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32;
|
||||
result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33;
|
||||
|
||||
result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31;
|
||||
result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32;
|
||||
result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33;
|
||||
|
||||
result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31;
|
||||
result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32;
|
||||
result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33;
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector3"/> instance containing the result.</returns>
|
||||
public static Vector3 Transform(Matrix3 matrix, Vector3 vector)
|
||||
{
|
||||
return new Vector3(
|
||||
(matrix.M11 * vector.X) + (matrix.M12 * vector.Y) + (matrix.M13 * vector.Z),
|
||||
(matrix.M21 * vector.X) + (matrix.M22 * vector.Y) + (matrix.M23 * vector.Z),
|
||||
(matrix.M31 * vector.X) + (matrix.M32 * vector.Y) + (matrix.M33 * vector.Z));
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix and put the result in a vector.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector3"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Vector3"/> instance to hold the result.</param>
|
||||
public static void Transform(Matrix3 matrix, Vector3 vector, ref Vector3 result)
|
||||
{
|
||||
result.X = (matrix.M11 * vector.X) + (matrix.M12 * vector.Y) + (matrix.M13 * vector.Z);
|
||||
result.Y = (matrix.M21 * vector.X) + (matrix.M22 * vector.Y) + (matrix.M23 * vector.Z);
|
||||
result.Z = (matrix.M31 * vector.X) + (matrix.M32 * vector.Y) + (matrix.M33 * vector.Z);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes a matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the transposed matrix.</returns>
|
||||
public static Matrix3 Transpose(Matrix3 m)
|
||||
{
|
||||
Matrix3 t = new(m);
|
||||
t.Transpose();
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Matrix3 fromEulerAnglesZYX(float fYAngle, float fPAngle, float fRAngle)
|
||||
{
|
||||
float fCos, fSin;
|
||||
|
||||
fCos = (float)Math.Cos(fYAngle);
|
||||
fSin = (float)Math.Sin(fYAngle);
|
||||
Matrix3 kZMat = new(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
fCos = (float)Math.Cos(fPAngle);
|
||||
fSin = (float)Math.Sin(fPAngle);
|
||||
Matrix3 kYMat = new(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
|
||||
|
||||
fCos = (float)Math.Cos(fRAngle);
|
||||
fSin = (float)Math.Sin(fRAngle);
|
||||
Matrix3 kXMat = new(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos);
|
||||
|
||||
return (kZMat * (kYMat * kXMat));
|
||||
}
|
||||
|
||||
public Matrix3 inverse(float fTolerance = (float)1e-06)
|
||||
{
|
||||
Matrix3 kInverse = Matrix3.Zero;
|
||||
inverse(ref kInverse, fTolerance);
|
||||
return kInverse;
|
||||
}
|
||||
bool inverse(ref Matrix3 rkInverse, float fTolerance)
|
||||
{
|
||||
// Invert a 3x3 using cofactors. This is about 8 times faster than
|
||||
// the Numerical Recipes code which uses Gaussian elimination.
|
||||
rkInverse.M11 = M22 * M33 -
|
||||
M23 * M32;
|
||||
rkInverse.M12 = M13 * M32 -
|
||||
M12 * M33;
|
||||
rkInverse.M13 = M12 * M23 -
|
||||
M13 * M22;
|
||||
rkInverse.M21 = M23 * M31 -
|
||||
M21 * M33;
|
||||
rkInverse.M22 = M11 * M33 -
|
||||
M13 * M31;
|
||||
rkInverse.M23 = M13 * M21 -
|
||||
M11 * M23;
|
||||
rkInverse.M31 = M21 * M32 -
|
||||
M22 * M31;
|
||||
rkInverse.M32 = M12 * M31 -
|
||||
M11 * M32;
|
||||
rkInverse.M33 = M11 * M22 -
|
||||
M12 * M21;
|
||||
|
||||
|
||||
float fDet =
|
||||
M11 * rkInverse.M11 +
|
||||
M12 * rkInverse.M21 +
|
||||
M13 * rkInverse.M31;
|
||||
|
||||
if (Math.Abs(fDet) <= fTolerance)
|
||||
return false;
|
||||
|
||||
float fInvDet = (float)(1.0 / fDet);
|
||||
|
||||
rkInverse.M11 *= fInvDet;
|
||||
rkInverse.M12 *= fInvDet;
|
||||
rkInverse.M13 *= fInvDet;
|
||||
rkInverse.M21 *= fInvDet;
|
||||
rkInverse.M22 *= fInvDet;
|
||||
rkInverse.M23 *= fInvDet;
|
||||
rkInverse.M31 *= fInvDet;
|
||||
rkInverse.M32 *= fInvDet;
|
||||
rkInverse.M33 *= fInvDet;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Object overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return
|
||||
_m11.GetHashCode() ^ _m12.GetHashCode() ^ _m13.GetHashCode() ^
|
||||
_m21.GetHashCode() ^ _m22.GetHashCode() ^ _m23.GetHashCode() ^
|
||||
_m31.GetHashCode() ^ _m32.GetHashCode() ^ _m33.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="Matrix3"/> and has the same values as this instance; otherwise, <see langword="false"/>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Matrix3)
|
||||
{
|
||||
Matrix3 m = (Matrix3)obj;
|
||||
return
|
||||
(_m11 == m.M11) && (_m12 == m.M12) && (_m13 == m.M13) &&
|
||||
(_m21 == m.M21) && (_m22 == m.M22) && (_m23 == m.M23) &&
|
||||
(_m31 == m.M31) && (_m32 == m.M32) && (_m33 == m.M33);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"3x3[{_m11}, {_m12}, {_m13}, {_m21}, {_m22}, {_m23}, {_m31}, {_m32}, {_m33}]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Calculates the determinant value of the matrix.
|
||||
/// </summary>
|
||||
/// <returns>The determinant value of the matrix.</returns>
|
||||
public float GetDeterminant()
|
||||
{
|
||||
// rule of Sarrus
|
||||
return
|
||||
_m11 * _m22 * _m33 + _m12 * _m23 * _m31 + _m13 * _m21 * _m32 -
|
||||
_m13 * _m22 * _m31 - _m11 * _m23 * _m32 - _m12 * _m21 * _m33;
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes this matrix.
|
||||
/// </summary>
|
||||
public void Transpose()
|
||||
{
|
||||
MathFunctions.Swap<float>(ref _m12, ref _m21);
|
||||
MathFunctions.Swap<float>(ref _m13, ref _m31);
|
||||
MathFunctions.Swap<float>(ref _m23, ref _m32);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator ==(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return ValueType.Equals(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are not equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator !=(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return !ValueType.Equals(left, right);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Binary Operators
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the sum.</returns>
|
||||
public static Matrix3 operator +(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return Matrix3.Add(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the sum.</returns>
|
||||
public static Matrix3 operator +(Matrix3 matrix, float scalar)
|
||||
{
|
||||
return Matrix3.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the sum.</returns>
|
||||
public static Matrix3 operator +(float scalar, Matrix3 matrix)
|
||||
{
|
||||
return Matrix3.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the difference.</returns>
|
||||
public static Matrix3 operator -(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return Matrix3.Subtract(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the difference.</returns>
|
||||
public static Matrix3 operator -(Matrix3 matrix, float scalar)
|
||||
{
|
||||
return Matrix3.Subtract(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix3"/> instance containing the result.</returns>
|
||||
public static Matrix3 operator *(Matrix3 left, Matrix3 right)
|
||||
{
|
||||
return Matrix3.Multiply(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix3"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector3"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector3"/> instance containing the result.</returns>
|
||||
public static Vector3 operator *(Matrix3 matrix, Vector3 vector)
|
||||
{
|
||||
return Matrix3.Transform(matrix, vector);
|
||||
}
|
||||
public static Vector3 operator *(Vector3 rkPoint, Matrix3 rkMatrix)
|
||||
{
|
||||
return (Matrix3.Transpose(rkMatrix) * rkPoint);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Indexing Operators
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by an index
|
||||
/// where index = 2*row + column.
|
||||
/// </summary>
|
||||
public unsafe float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= 9)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
return *(f + index);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= 9)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
*(f + index) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by row and column.
|
||||
/// </summary>
|
||||
public float this[int row, int column]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[row * 3 + column];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[row * 3 + column] = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,900 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 4-dimentional single-precision floating point matrix.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public struct Matrix4 : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private float _m11, _m12, _m13, _m14;
|
||||
private float _m21, _m22, _m23, _m24;
|
||||
private float _m31, _m32, _m33, _m34;
|
||||
private float _m41, _m42, _m43, _m44;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
public Matrix4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
|
||||
{
|
||||
_m11 = m11; _m12 = m12; _m13 = m13; _m14 = m14;
|
||||
_m21 = m21; _m22 = m22; _m23 = m23; _m24 = m24;
|
||||
_m31 = m31; _m32 = m32; _m33 = m33; _m34 = m34;
|
||||
_m41 = m41; _m42 = m42; _m43 = m43; _m44 = m44;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix4(float[] elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Length >= 16);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1]; _m13 = elements[2]; _m14 = elements[3];
|
||||
_m21 = elements[4]; _m22 = elements[5]; _m23 = elements[6]; _m24 = elements[7];
|
||||
_m31 = elements[8]; _m32 = elements[9]; _m33 = elements[10]; _m34 = elements[11];
|
||||
_m41 = elements[12]; _m42 = elements[13]; _m43 = elements[14]; _m44 = elements[15];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="elements">An array containing the matrix values in row-major order.</param>
|
||||
public Matrix4(List<float> elements)
|
||||
{
|
||||
Debug.Assert(elements != null);
|
||||
Debug.Assert(elements.Count >= 16);
|
||||
|
||||
_m11 = elements[0]; _m12 = elements[1]; _m13 = elements[2]; _m14 = elements[3];
|
||||
_m21 = elements[4]; _m22 = elements[5]; _m23 = elements[6]; _m24 = elements[7];
|
||||
_m31 = elements[8]; _m32 = elements[9]; _m33 = elements[10]; _m34 = elements[11];
|
||||
_m41 = elements[12]; _m42 = elements[13]; _m43 = elements[14]; _m44 = elements[15];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> structure with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="column1">A <see cref="Vector4"/> instance holding values for the first column.</param>
|
||||
/// <param name="column2">A <see cref="Vector4"/> instance holding values for the second column.</param>
|
||||
/// <param name="column3">A <see cref="Vector4"/> instance holding values for the third column.</param>
|
||||
/// <param name="column4">A <see cref="Vector4"/> instance holding values for the fourth column.</param>
|
||||
public Matrix4(Vector4 column1, Vector4 column2, Vector4 column3, Vector4 column4)
|
||||
{
|
||||
_m11 = column1.X; _m12 = column2.X; _m13 = column3.X; _m14 = column4.X;
|
||||
_m21 = column1.Y; _m22 = column2.Y; _m23 = column3.Y; _m24 = column4.Y;
|
||||
_m31 = column1.Z; _m32 = column2.Z; _m33 = column3.Z; _m34 = column4.Z;
|
||||
_m41 = column1.W; _m42 = column2.W; _m43 = column3.W; _m44 = column4.W;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Matrix4"/> class using a given matrix.
|
||||
/// </summary>
|
||||
public Matrix4(Matrix4 m)
|
||||
{
|
||||
_m11 = m.M11; _m12 = m.M12; _m13 = m.M13; _m14 = m.M14;
|
||||
_m21 = m.M21; _m22 = m.M22; _m23 = m.M23; _m24 = m.M24;
|
||||
_m31 = m.M31; _m32 = m.M32; _m33 = m.M33; _m34 = m.M34;
|
||||
_m41 = m.M41; _m42 = m.M42; _m43 = m.M43; _m44 = m.M44;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point zero matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix4 Zero = new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
/// <summary>
|
||||
/// 4-dimentional single-precision floating point identity matrix.
|
||||
/// </summary>
|
||||
public static readonly Matrix4 Identity = new(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M11
|
||||
{
|
||||
get { return _m11; }
|
||||
set { _m11 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M12
|
||||
{
|
||||
get { return _m12; }
|
||||
set { _m12 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M13
|
||||
{
|
||||
get { return _m13; }
|
||||
set { _m13 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [1,4] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M14
|
||||
{
|
||||
get { return _m14; }
|
||||
set { _m14 = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M21
|
||||
{
|
||||
get { return _m21; }
|
||||
set { _m21 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M22
|
||||
{
|
||||
get { return _m22; }
|
||||
set { _m22 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M23
|
||||
{
|
||||
get { return _m23; }
|
||||
set { _m23 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [2,4] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M24
|
||||
{
|
||||
get { return _m24; }
|
||||
set { _m24 = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M31
|
||||
{
|
||||
get { return _m31; }
|
||||
set { _m31 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M32
|
||||
{
|
||||
get { return _m32; }
|
||||
set { _m32 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M33
|
||||
{
|
||||
get { return _m33; }
|
||||
set { _m33 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [3,4] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M34
|
||||
{
|
||||
get { return _m34; }
|
||||
set { _m34 = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [4,1] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M41
|
||||
{
|
||||
get { return _m41; }
|
||||
set { _m41 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [4,2] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M42
|
||||
{
|
||||
get { return _m42; }
|
||||
set { _m42 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [4,3] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M43
|
||||
{
|
||||
get { return _m43; }
|
||||
set { _m43 = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the [4,4] matrix element.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float M44
|
||||
{
|
||||
get { return _m44; }
|
||||
set { _m44 = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the matrix's trace value.
|
||||
/// </summary>
|
||||
/// <value>A single-precision floating-point number.</value>
|
||||
public float Trace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _m11 + _m22 + _m33 + _m44;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix4"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix4"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Matrix4(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Matrix4"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Matrix4"/> object this method creates.</returns>
|
||||
public Matrix4 Clone()
|
||||
{
|
||||
return new Matrix4(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Parse Methods
|
||||
private const string regularExp = @"4x4\s*\[(?<m11>.*),(?<m12>.*),(?<m13>.*),(?<m14>.*),(?<m21>.*),(?<m22>.*),(?<m23>.*),(?<m24>.*),(?<m31>.*),(?<m32>.*),(?<m33>.*),(?<m34>.*),(?<m41>.*),(?<m42>.*),(?<m43>.*),(?<m44>.*)\]";
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix4"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix4"/>.</param>
|
||||
/// <returns>A <see cref="Matrix4"/> that represents the vector specified by the <paramref name="value"/> parameter.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "4x4..matrix elements..>".<br/>
|
||||
/// Exmaple : "4x4[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static Matrix4 Parse(string value)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Matrix4(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
float.Parse(m.Result("${m13}")),
|
||||
float.Parse(m.Result("${m14}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}")),
|
||||
float.Parse(m.Result("${m23}")),
|
||||
float.Parse(m.Result("${m24}")),
|
||||
|
||||
float.Parse(m.Result("${m31}")),
|
||||
float.Parse(m.Result("${m32}")),
|
||||
float.Parse(m.Result("${m33}")),
|
||||
float.Parse(m.Result("${m34}")),
|
||||
|
||||
float.Parse(m.Result("${m41}")),
|
||||
float.Parse(m.Result("${m42}")),
|
||||
float.Parse(m.Result("${m43}")),
|
||||
float.Parse(m.Result("${m44}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Matrix4"/> equivalent.
|
||||
/// A return value indicates whether the conversion succeeded or failed.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Matrix4"/>.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, if the conversion succeeded,
|
||||
/// contains a <see cref="Matrix4"/> representing the vector specified by <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if value was converted successfully; otherwise, <see langword="false"/>.</returns>
|
||||
/// <remarks>
|
||||
/// The string should be in the following form: "4x4..matrix elements..>".<br/>
|
||||
/// Exmaple : "4x4[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
|
||||
/// </remarks>
|
||||
public static bool TryParse(string value, out Matrix4 result)
|
||||
{
|
||||
Regex r = new(regularExp, RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
result = new Matrix4(
|
||||
float.Parse(m.Result("${m11}")),
|
||||
float.Parse(m.Result("${m12}")),
|
||||
float.Parse(m.Result("${m13}")),
|
||||
float.Parse(m.Result("${m14}")),
|
||||
|
||||
float.Parse(m.Result("${m21}")),
|
||||
float.Parse(m.Result("${m22}")),
|
||||
float.Parse(m.Result("${m23}")),
|
||||
float.Parse(m.Result("${m24}")),
|
||||
|
||||
float.Parse(m.Result("${m31}")),
|
||||
float.Parse(m.Result("${m32}")),
|
||||
float.Parse(m.Result("${m33}")),
|
||||
float.Parse(m.Result("${m34}")),
|
||||
|
||||
float.Parse(m.Result("${m41}")),
|
||||
float.Parse(m.Result("${m42}")),
|
||||
float.Parse(m.Result("${m43}")),
|
||||
float.Parse(m.Result("${m44}"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = Matrix4.Zero;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Matrix Arithmetics
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the sum.</returns>
|
||||
public static Matrix4 Add(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return new Matrix4(
|
||||
left.M11 + right.M11, left.M12 + right.M12, left.M13 + right.M13, left.M14 + right.M14,
|
||||
left.M21 + right.M21, left.M22 + right.M22, left.M23 + right.M23, left.M24 + right.M24,
|
||||
left.M31 + right.M31, left.M32 + right.M32, left.M33 + right.M33, left.M34 + right.M34,
|
||||
left.M41 + right.M41, left.M42 + right.M42, left.M43 + right.M43, left.M44 + right.M44
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the sum.</returns>
|
||||
public static Matrix4 Add(Matrix4 matrix, float scalar)
|
||||
{
|
||||
return new Matrix4(
|
||||
matrix.M11 + scalar, matrix.M12 + scalar, matrix.M13 + scalar, matrix.M14 + scalar,
|
||||
matrix.M21 + scalar, matrix.M22 + scalar, matrix.M23 + scalar, matrix.M24 + scalar,
|
||||
matrix.M31 + scalar, matrix.M32 + scalar, matrix.M33 + scalar, matrix.M34 + scalar,
|
||||
matrix.M41 + scalar, matrix.M42 + scalar, matrix.M43 + scalar, matrix.M44 + scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix4"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix4 left, Matrix4 right, ref Matrix4 result)
|
||||
{
|
||||
result.M11 = left.M11 + right.M11;
|
||||
result.M12 = left.M12 + right.M12;
|
||||
result.M13 = left.M13 + right.M13;
|
||||
result.M14 = left.M14 + right.M14;
|
||||
|
||||
result.M21 = left.M21 + right.M21;
|
||||
result.M22 = left.M22 + right.M22;
|
||||
result.M23 = left.M23 + right.M23;
|
||||
result.M24 = left.M24 + right.M24;
|
||||
|
||||
result.M31 = left.M31 + right.M31;
|
||||
result.M32 = left.M32 + right.M32;
|
||||
result.M33 = left.M33 + right.M33;
|
||||
result.M34 = left.M34 + right.M34;
|
||||
|
||||
result.M41 = left.M41 + right.M41;
|
||||
result.M42 = left.M42 + right.M42;
|
||||
result.M43 = left.M43 + right.M43;
|
||||
result.M44 = left.M44 + right.M44;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix4"/> instance to hold the result.</param>
|
||||
public static void Add(Matrix4 matrix, float scalar, ref Matrix4 result)
|
||||
{
|
||||
result.M11 = matrix.M11 + scalar;
|
||||
result.M12 = matrix.M12 + scalar;
|
||||
result.M13 = matrix.M13 + scalar;
|
||||
result.M14 = matrix.M14 + scalar;
|
||||
|
||||
result.M21 = matrix.M21 + scalar;
|
||||
result.M22 = matrix.M22 + scalar;
|
||||
result.M23 = matrix.M23 + scalar;
|
||||
result.M24 = matrix.M24 + scalar;
|
||||
|
||||
result.M31 = matrix.M31 + scalar;
|
||||
result.M32 = matrix.M32 + scalar;
|
||||
result.M33 = matrix.M33 + scalar;
|
||||
result.M34 = matrix.M34 + scalar;
|
||||
|
||||
result.M41 = matrix.M41 + scalar;
|
||||
result.M42 = matrix.M42 + scalar;
|
||||
result.M43 = matrix.M43 + scalar;
|
||||
result.M44 = matrix.M44 + scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance to subtract.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the difference.</returns>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static Matrix4 Subtract(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return new Matrix4(
|
||||
left.M11 - right.M11, left.M12 - right.M12, left.M13 - right.M13, left.M14 - right.M14,
|
||||
left.M21 - right.M21, left.M22 - right.M22, left.M23 - right.M23, left.M24 - right.M24,
|
||||
left.M31 - right.M31, left.M32 - right.M32, left.M33 - right.M33, left.M34 - right.M34,
|
||||
left.M41 - right.M41, left.M42 - right.M42, left.M43 - right.M43, left.M44 - right.M44
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the difference.</returns>
|
||||
public static Matrix4 Subtract(Matrix4 matrix, float scalar)
|
||||
{
|
||||
return new Matrix4(
|
||||
matrix.M11 - scalar, matrix.M12 - scalar, matrix.M13 - scalar, matrix.M14 - scalar,
|
||||
matrix.M21 - scalar, matrix.M22 - scalar, matrix.M23 - scalar, matrix.M24 - scalar,
|
||||
matrix.M31 - scalar, matrix.M32 - scalar, matrix.M33 - scalar, matrix.M34 - scalar,
|
||||
matrix.M41 - scalar, matrix.M42 - scalar, matrix.M43 - scalar, matrix.M44 - scalar
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance to subtract from.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance to subtract.</param>
|
||||
/// <param name="result">A <see cref="Matrix4"/> instance to hold the result.</param>
|
||||
/// <remarks>result[x][y] = left[x][y] - right[x][y]</remarks>
|
||||
public static void Subtract(Matrix4 left, Matrix4 right, ref Matrix4 result)
|
||||
{
|
||||
result.M11 = left.M11 - right.M11;
|
||||
result.M12 = left.M12 - right.M12;
|
||||
result.M13 = left.M13 - right.M13;
|
||||
result.M14 = left.M14 - right.M14;
|
||||
|
||||
result.M21 = left.M21 - right.M21;
|
||||
result.M22 = left.M22 - right.M22;
|
||||
result.M23 = left.M23 - right.M23;
|
||||
result.M24 = left.M24 - right.M24;
|
||||
|
||||
result.M31 = left.M31 - right.M31;
|
||||
result.M32 = left.M32 - right.M32;
|
||||
result.M33 = left.M33 - right.M33;
|
||||
result.M34 = left.M34 - right.M34;
|
||||
|
||||
result.M41 = left.M41 - right.M41;
|
||||
result.M42 = left.M42 - right.M42;
|
||||
result.M43 = left.M43 - right.M43;
|
||||
result.M44 = left.M44 - right.M44;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Matrix4"/> instance to hold the result.</param>
|
||||
public static void Subtract(Matrix4 matrix, float scalar, ref Matrix4 result)
|
||||
{
|
||||
result.M11 = matrix.M11 - scalar;
|
||||
result.M12 = matrix.M12 - scalar;
|
||||
result.M13 = matrix.M13 - scalar;
|
||||
result.M14 = matrix.M14 - scalar;
|
||||
|
||||
result.M21 = matrix.M21 - scalar;
|
||||
result.M22 = matrix.M22 - scalar;
|
||||
result.M23 = matrix.M23 - scalar;
|
||||
result.M24 = matrix.M24 - scalar;
|
||||
|
||||
result.M31 = matrix.M31 - scalar;
|
||||
result.M32 = matrix.M32 - scalar;
|
||||
result.M33 = matrix.M33 - scalar;
|
||||
result.M34 = matrix.M34 - scalar;
|
||||
|
||||
result.M41 = matrix.M41 - scalar;
|
||||
result.M42 = matrix.M42 - scalar;
|
||||
result.M43 = matrix.M43 - scalar;
|
||||
result.M44 = matrix.M44 - scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the result.</returns>
|
||||
public static Matrix4 Multiply(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return new Matrix4(
|
||||
left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41,
|
||||
left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42,
|
||||
left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43,
|
||||
left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44,
|
||||
|
||||
left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41,
|
||||
left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42,
|
||||
left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43,
|
||||
left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44,
|
||||
|
||||
left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41,
|
||||
left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42,
|
||||
left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43,
|
||||
left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44,
|
||||
|
||||
left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41,
|
||||
left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42,
|
||||
left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43,
|
||||
left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44
|
||||
);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices and put the result in a third matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Matrix4"/> instance to hold the result.</param>
|
||||
public static void Multiply(Matrix4 left, Matrix4 right, ref Matrix4 result)
|
||||
{
|
||||
result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
|
||||
result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
|
||||
result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
|
||||
result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
|
||||
|
||||
result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
|
||||
result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
|
||||
result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
|
||||
result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
|
||||
|
||||
result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
|
||||
result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
|
||||
result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
|
||||
result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
|
||||
|
||||
result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
|
||||
result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
|
||||
result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
|
||||
result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector4"/> instance containing the result.</returns>
|
||||
public static Vector4 Transform(Matrix4 matrix, Vector4 vector)
|
||||
{
|
||||
return new Vector4(
|
||||
(matrix.M11 * vector.X) + (matrix.M12 * vector.Y) + (matrix.M13 * vector.Z) + (matrix.M14 * vector.W),
|
||||
(matrix.M21 * vector.X) + (matrix.M22 * vector.Y) + (matrix.M23 * vector.Z) + (matrix.M24 * vector.W),
|
||||
(matrix.M31 * vector.X) + (matrix.M32 * vector.Y) + (matrix.M33 * vector.Z) + (matrix.M34 * vector.W),
|
||||
(matrix.M41 * vector.X) + (matrix.M42 * vector.Y) + (matrix.M43 * vector.Z) + (matrix.M44 * vector.W));
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix and put the result in a vector.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector4"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Vector4"/> instance to hold the result.</param>
|
||||
public static void Transform(Matrix4 matrix, Vector4 vector, ref Vector4 result)
|
||||
{
|
||||
result.X = (matrix.M11 * vector.X) + (matrix.M12 * vector.Y) + (matrix.M13 * vector.Z) + (matrix.M14 * vector.W);
|
||||
result.Y = (matrix.M21 * vector.X) + (matrix.M22 * vector.Y) + (matrix.M23 * vector.Z) + (matrix.M24 * vector.W);
|
||||
result.Z = (matrix.M31 * vector.X) + (matrix.M32 * vector.Y) + (matrix.M33 * vector.Z) + (matrix.M34 * vector.W);
|
||||
result.W = (matrix.M41 * vector.X) + (matrix.M42 * vector.Y) + (matrix.M43 * vector.Z) + (matrix.M44 * vector.W);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes a matrix.
|
||||
/// </summary>
|
||||
/// <param name="m">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the transposed matrix.</returns>
|
||||
public static Matrix4 Transpose(Matrix4 m)
|
||||
{
|
||||
Matrix4 t = new(m);
|
||||
t.Transpose();
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Object overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return
|
||||
_m11.GetHashCode() ^ _m12.GetHashCode() ^ _m13.GetHashCode() ^ _m14.GetHashCode() ^
|
||||
_m21.GetHashCode() ^ _m22.GetHashCode() ^ _m23.GetHashCode() ^ _m24.GetHashCode() ^
|
||||
_m31.GetHashCode() ^ _m32.GetHashCode() ^ _m33.GetHashCode() ^ _m34.GetHashCode() ^
|
||||
_m41.GetHashCode() ^ _m42.GetHashCode() ^ _m43.GetHashCode() ^ _m44.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="Matrix4"/> and has the same values as this instance; otherwise, <see langword="false"/>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Matrix4)
|
||||
{
|
||||
Matrix4 m = (Matrix4)obj;
|
||||
return
|
||||
(_m11 == m.M11) && (_m12 == m.M12) && (_m13 == m.M13) && (_m14 == m.M14) &&
|
||||
(_m21 == m.M21) && (_m22 == m.M22) && (_m23 == m.M23) && (_m24 == m.M24) &&
|
||||
(_m31 == m.M31) && (_m32 == m.M32) && (_m33 == m.M33) && (_m34 == m.M34) &&
|
||||
(_m41 == m.M41) && (_m42 == m.M42) && (_m43 == m.M43) && (_m44 == m.M44);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"4x4[{_m11}, {_m12}, {_m13}, {_m14}, {_m21}, {_m22}, {_m23}, {_m24}, {_m31}, {_m32}, {_m33}, {_m34}, {_m41}, {_m42}, {_m43}, {_m44}]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Calculates the determinant value of the matrix.
|
||||
/// </summary>
|
||||
/// <returns>The determinant value of the matrix.</returns>
|
||||
public float GetDeterminant()
|
||||
{
|
||||
// float det = 0.0f;
|
||||
// for (int col = 0; col < 4; col++)
|
||||
// {
|
||||
// if ((col % 2) == 0)
|
||||
// det += this[0, col] * Minor(0, col).Determinant();
|
||||
// else
|
||||
// det -= this[0, col] * Minor(0, col).Determinant();
|
||||
// }
|
||||
// return det;
|
||||
return
|
||||
_m14 * _m23 * _m32 * _m41 - _m13 * _m24 * _m32 * _m41 - _m14 * _m22 * _m33 * _m41 + _m12 * _m24 * _m33 * _m41 +
|
||||
_m13 * _m22 * _m34 * _m41 - _m12 * _m23 * _m34 * _m41 - _m14 * _m23 * _m31 * _m42 + _m13 * _m24 * _m31 * _m42 +
|
||||
_m14 * _m21 * _m33 * _m42 - _m11 * _m24 * _m33 * _m42 - _m13 * _m21 * _m34 * _m42 + _m11 * _m23 * _m34 * _m42 +
|
||||
_m14 * _m22 * _m31 * _m43 - _m12 * _m24 * _m31 * _m43 - _m14 * _m21 * _m32 * _m43 + _m11 * _m24 * _m32 * _m43 +
|
||||
_m12 * _m21 * _m34 * _m43 - _m11 * _m22 * _m34 * _m43 - _m13 * _m22 * _m31 * _m44 + _m12 * _m23 * _m31 * _m44 +
|
||||
_m13 * _m21 * _m32 * _m44 - _m11 * _m23 * _m32 * _m44 - _m12 * _m21 * _m33 * _m44 + _m11 * _m22 * _m33 * _m44;
|
||||
}
|
||||
/// <summary>
|
||||
/// Transposes this matrix.
|
||||
/// </summary>
|
||||
public void Transpose()
|
||||
{
|
||||
MathFunctions.Swap<float>(ref _m12, ref _m21);
|
||||
MathFunctions.Swap<float>(ref _m13, ref _m31);
|
||||
MathFunctions.Swap<float>(ref _m14, ref _m41);
|
||||
MathFunctions.Swap<float>(ref _m23, ref _m32);
|
||||
MathFunctions.Swap<float>(ref _m24, ref _m42);
|
||||
MathFunctions.Swap<float>(ref _m34, ref _m43);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator ==(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return ValueType.Equals(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two specified matrices are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two matrices are not equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator !=(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return !ValueType.Equals(left, right);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Binary Operators
|
||||
/// <summary>
|
||||
/// Adds two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the sum.</returns>
|
||||
public static Matrix4 operator +(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return Matrix4.Add(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the sum.</returns>
|
||||
public static Matrix4 operator +(Matrix4 matrix, float scalar)
|
||||
{
|
||||
return Matrix4.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a matrix and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the sum.</returns>
|
||||
public static Matrix4 operator +(float scalar, Matrix4 matrix)
|
||||
{
|
||||
return Matrix4.Add(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a matrix from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the difference.</returns>
|
||||
public static Matrix4 operator -(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return Matrix4.Subtract(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the difference.</returns>
|
||||
public static Matrix4 operator -(Matrix4 matrix, float scalar)
|
||||
{
|
||||
return Matrix4.Subtract(matrix, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies two matrices.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Matrix4"/> instance containing the result.</returns>
|
||||
public static Matrix4 operator *(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return Matrix4.Multiply(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Transforms a given vector by a matrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">A <see cref="Matrix4"/> instance.</param>
|
||||
/// <param name="vector">A <see cref="Vector4"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector4"/> instance containing the result.</returns>
|
||||
public static Vector4 operator *(Matrix4 matrix, Vector4 vector)
|
||||
{
|
||||
Vector4 result = new();
|
||||
for (int r = 0; r < 4; ++r)
|
||||
{
|
||||
for (int c = 0; c < 4; ++c)
|
||||
{
|
||||
result[r] += matrix[r, c] * vector[c];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Indexing Operators
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by an index
|
||||
/// where index = 2*row + column.
|
||||
/// </summary>
|
||||
public unsafe float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= 16)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
return *(f + index);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= 16)
|
||||
throw new IndexOutOfRangeException("Invalid matrix index!");
|
||||
|
||||
fixed (float* f = &_m11)
|
||||
{
|
||||
*(f + index) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Indexer allowing to access the matrix elements by row and column.
|
||||
/// </summary>
|
||||
public float this[int row, int column]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[(row) * 4 + (column)];
|
||||
}
|
||||
set
|
||||
{
|
||||
this[(row) * 4 + (column)] = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// An enumeration representing the sides of the plane.
|
||||
/// </summary>
|
||||
public enum PlaneSide
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the plane itself.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Represents the positive halfspace of the plane (the side where the normal points to).
|
||||
/// </summary>
|
||||
Positive,
|
||||
/// <summary>
|
||||
/// Represents the negative halfspace of the plane
|
||||
/// </summary>
|
||||
Negative
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a plane in 3D space.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The plane is described by a normal and a constant (N,D) which
|
||||
/// denotes that the plane is consisting of points Q that
|
||||
/// satisfies (N dot Q)+D = 0.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
public struct Plane : ISerializable, ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private Vector3 _normal;
|
||||
private float _const;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Plane"/> class using given normal and constant values.
|
||||
/// </summary>
|
||||
/// <param name="normal">The plane's normal vector.</param>
|
||||
/// <param name="constant">The plane's constant value.</param>
|
||||
public Plane(Vector3 normal, float constant)
|
||||
{
|
||||
_normal = normal;
|
||||
_const = constant;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Plane"/> class using given normal and a point.
|
||||
/// </summary>
|
||||
/// <param name="normal">The plane's normal vector.</param>
|
||||
/// <param name="point">A point on the plane in 3D space.</param>
|
||||
public Plane(Vector3 normal, Vector3 point)
|
||||
{
|
||||
_normal = normal;
|
||||
_const = Vector3.DotProduct(normal, point);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Plane"/> class using 3 given points.
|
||||
/// </summary>
|
||||
/// <param name="p0">A point on the plane in 3D space.</param>
|
||||
/// <param name="p1">A point on the plane in 3D space.</param>
|
||||
/// <param name="p2">A point on the plane in 3D space.</param>
|
||||
public Plane(Vector3 p0, Vector3 p1, Vector3 p2)
|
||||
{
|
||||
_normal = Vector3.CrossProduct(p2 - p1, p0 - p1);
|
||||
_normal.Normalize();
|
||||
_const = Vector3.DotProduct(_normal, p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Plane"/> class using given a plane to assign values from.
|
||||
/// </summary>
|
||||
/// <param name="p">A 3D plane to assign values from.</param>
|
||||
public Plane(Plane p)
|
||||
{
|
||||
_normal = p.Normal;
|
||||
_const = p.Constant;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Plane"/> class with serialized data.
|
||||
/// </summary>
|
||||
/// <param name="info">The object that holds the serialized object data.</param>
|
||||
/// <param name="context">The contextual information about the source or destination.</param>
|
||||
private Plane(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
_normal = (Vector3)info.GetValue("Normal", typeof(Vector3));
|
||||
_const = info.GetSingle("Constant");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// Plane on the X axis.
|
||||
/// </summary>
|
||||
public static readonly Plane XPlane = new(Vector3.XAxis, Vector3.Zero);
|
||||
/// <summary>
|
||||
/// Plane on the Y axis.
|
||||
/// </summary>
|
||||
public static readonly Plane YPlane = new(Vector3.YAxis, Vector3.Zero);
|
||||
/// <summary>
|
||||
/// Plane on the Z axis.
|
||||
/// </summary>
|
||||
public static readonly Plane ZPlane = new(Vector3.ZAxis, Vector3.Zero);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Gets or sets the plane's normal vector.
|
||||
/// </summary>
|
||||
public Vector3 Normal
|
||||
{
|
||||
get { return _normal; }
|
||||
set { _normal = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the plane's constant value.
|
||||
/// </summary>
|
||||
public float Constant
|
||||
{
|
||||
get { return _const; }
|
||||
set { _const = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Plane"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Plane"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Plane(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Plane"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Plane"/> object this method creates.</returns>
|
||||
public Plane Clone()
|
||||
{
|
||||
return new Plane(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ISerializable Members
|
||||
/// <summary>
|
||||
/// Populates a <see cref="SerializationInfo"/> with the data needed to serialize the target object.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="SerializationInfo"/> to populate with data. </param>
|
||||
/// <param name="context">The destination (see <see cref="StreamingContext"/>) for this serialization.</param>
|
||||
//[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
info.AddValue("Normal", _normal, typeof(Vector3));
|
||||
info.AddValue("Constant", _const);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Flip the plane.
|
||||
/// </summary>
|
||||
public void Flip()
|
||||
{
|
||||
_normal = -_normal;
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new flipped plane (-normal, constant).
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="Plane"/> instance.</returns>
|
||||
public Plane GetFlipped()
|
||||
{
|
||||
return new Plane(-_normal, _const);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the shortest distance from a 3D vector to the plane.
|
||||
/// </summary>
|
||||
/// <param name="p">A <see cref="Vector3"/> instance.</param>
|
||||
/// <returns>A float representing the shortest distance from the given vector to the plane.</returns>
|
||||
public float GetDistanceToPlane(Vector3 p)
|
||||
{
|
||||
return Vector3.DotProduct(p, Normal) - Constant;
|
||||
}
|
||||
|
||||
public void getEquation(ref Vector3 n, out float d)
|
||||
{
|
||||
double _d;
|
||||
getEquation(ref n, out _d);
|
||||
d = (float)_d;
|
||||
}
|
||||
|
||||
void getEquation(ref Vector3 n, out double d)
|
||||
{
|
||||
n = _normal;
|
||||
d = -_const;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _normal.GetHashCode() ^ _const.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns>True if <paramref name="obj"/> is a <see cref="Plane"/> and has the same values as this instance; otherwise, False.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Plane)
|
||||
{
|
||||
Plane p = (Plane)obj;
|
||||
return (_normal == p.Normal) && (_const == p.Constant);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Plane[n={_normal}, c={_const}]";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,825 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a double-precision floating-point quaternion.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// A quaternion can be thought of as a 4-Dimentional vector of form:
|
||||
/// q = [w, x, y, z] = w + xi + yj +zk.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A Quaternion is often written as q = s + V where S represents
|
||||
/// the scalar part (w component) and V is a 3D vector representing
|
||||
/// the imaginery coefficients (x,y,z components).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Check out http://mathworld.wolfram.com/Quaternion.html for further details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Quaternion : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private float _w;
|
||||
private float _x;
|
||||
private float _y;
|
||||
private float _z;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Quaternion"/> class with the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The quaternions's X coordinate.</param>
|
||||
/// <param name="y">The quaternions's Y coordinate.</param>
|
||||
/// <param name="z">The quaternions's Z coordinate.</param>
|
||||
/// /// <param name="w">The quaternions's W coordinate.</param>
|
||||
public Quaternion(float x, float y, float z, float w)
|
||||
{
|
||||
_w = w;
|
||||
_x = x;
|
||||
_y = y;
|
||||
_z = z;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Quaternion"/> class using coordinates from a given <see cref="Quaternion"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance to copy the coordinates from.</param>
|
||||
public Quaternion(Quaternion quaternion)
|
||||
{
|
||||
_x = quaternion.X;
|
||||
_y = quaternion.Y;
|
||||
_z = quaternion.Z;
|
||||
_w = quaternion.W;
|
||||
}
|
||||
public Quaternion(Matrix3 rot) : this(Zero)
|
||||
{
|
||||
int[] plus1mod3 = { 1, 2, 0 };
|
||||
|
||||
// Find the index of the largest diagonal component
|
||||
// These ? operations hopefully compile to conditional
|
||||
// move instructions instead of branches.
|
||||
int i = (rot[1, 1] > rot[0, 0]) ? 2 : 1;
|
||||
i = (rot[2, 2] > rot[i, i]) ? 2 : i;
|
||||
|
||||
// Find the indices of the other elements
|
||||
int j = plus1mod3[i];
|
||||
int k = plus1mod3[j];
|
||||
|
||||
// If we attempted to pre-normalize and trusted the matrix to be
|
||||
// perfectly orthonormal, the result would be:
|
||||
//
|
||||
// double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0)
|
||||
// v[i] = -c * 0.5
|
||||
// v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c
|
||||
// v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c
|
||||
// w = (rot[j][k] - rot[k][j]) * 0.5 / c
|
||||
//
|
||||
// Since we're going to pay the sqrt anyway, we perform a post normalization, which also
|
||||
// fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
|
||||
|
||||
// nc2 = -c^2
|
||||
double nc2 = ((rot[j, j] + rot[k, k]) - rot[i, i]) - 1.0;
|
||||
this[i] = (float)nc2;
|
||||
W = (rot[j, k] - rot[k, j]);
|
||||
this[j] = -(rot[i, j] + rot[j, i]);
|
||||
this[k] = -(rot[i, k] + rot[k, i]);
|
||||
|
||||
// We now have the correct result with the wrong magnitude, so normalize it:
|
||||
float s = (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
|
||||
if (s > 0.00001f)
|
||||
{
|
||||
s = 1.0f / s;
|
||||
X *= s;
|
||||
Y *= s;
|
||||
Z *= s;
|
||||
W *= s;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The quaternion is nearly zero. Make it 0 0 0 1
|
||||
X = 0.0f;
|
||||
Y = 0.0f;
|
||||
Z = 0.0f;
|
||||
W = 1.0f;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// Double-precision floating point zero quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion Zero = new(0, 0, 0, 0);
|
||||
/// <summary>
|
||||
/// Double-precision floating point identity quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion Identity = new(0, 0, 0, 1);
|
||||
/// <summary>
|
||||
/// Double-precision floating point X-Axis quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion XAxis = new(1, 0, 0, 0);
|
||||
/// <summary>
|
||||
/// Double-precision floating point Y-Axis quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion YAxis = new(0, 1, 0, 0);
|
||||
/// <summary>
|
||||
/// Double-precision floating point Z-Axis quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion ZAxis = new(0, 0, 1, 0);
|
||||
/// <summary>
|
||||
/// Double-precision floating point W-Axis quaternion.
|
||||
/// </summary>
|
||||
public static readonly Quaternion WAxis = new(0, 0, 0, 1);
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summery>
|
||||
/// Gets or sets the x-coordinate of this quaternion.
|
||||
/// </summery>
|
||||
/// <value>The x-coordinate of this quaternion.</value>
|
||||
public float X
|
||||
{
|
||||
get { return _x; }
|
||||
set { _x = value; }
|
||||
}
|
||||
/// <summery>
|
||||
/// Gets or sets the y-coordinate of this quaternion.
|
||||
/// </summery>
|
||||
/// <value>The y-coordinate of this quaternion.</value>
|
||||
public float Y
|
||||
{
|
||||
get { return _y; }
|
||||
set { _y = value; }
|
||||
}
|
||||
/// <summery>
|
||||
/// Gets or sets the z-coordinate of this quaternion.
|
||||
/// </summery>
|
||||
/// <value>The z-coordinate of this quaternion.</value>
|
||||
public float Z
|
||||
{
|
||||
get { return _z; }
|
||||
set { _z = value; }
|
||||
}
|
||||
/// <summery>
|
||||
/// Gets or sets the w-coordinate of this quaternion.
|
||||
/// </summery>
|
||||
/// <value>The w-coordinate of this quaternion.</value>
|
||||
public float W
|
||||
{
|
||||
get { return _w; }
|
||||
set { _w = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the the modulus of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>A double-precision floating-point number.</value>
|
||||
public float Modulus
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)System.Math.Sqrt(_w * _w + _x * _x + _y * _y + _z * _z);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the the squared modulus of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>A double-precision floating-point number.</value>
|
||||
public float ModulusSquared
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_w * _w + _x * _x + _y * _y + _z * _z);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the conjugate of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>A <see cref="Quaternion"/> instance.</value>
|
||||
public Quaternion Conjugate
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Quaternion(-_x, -_y, -_z, _w);
|
||||
}
|
||||
set
|
||||
{
|
||||
this = value.Conjugate;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Quaternion"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Quaternion"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Quaternion(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Quaternion"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Quaternion"/> object this method creates.</returns>
|
||||
public Quaternion Clone()
|
||||
{
|
||||
return new Quaternion(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Parse Methods
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Quaternion"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Quaternion"/></param>
|
||||
/// <returns>A <see cref="Quaternion"/> that represents the vector specified by the <paramref name="value"/> parameter.</returns>
|
||||
public static Quaternion Parse(string value)
|
||||
{
|
||||
Regex r = new(@"\((?<w>.*),(?<x>.*),(?<y>.*),(?<z>.*)\)", RegexOptions.None);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Quaternion(
|
||||
float.Parse(m.Result("${x}")),
|
||||
float.Parse(m.Result("${y}")),
|
||||
float.Parse(m.Result("${z}")),
|
||||
float.Parse(m.Result("${w}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Quaternion"/> equivalent.
|
||||
/// A return value indicates whether the conversion succeeded or failed.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Quaternion"/>.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, if the conversion succeeded,
|
||||
/// contains a <see cref="Quaternion"/> representing the vector specified by <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if value was converted successfully; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool TryParse(string value, out Quaternion result)
|
||||
{
|
||||
Regex r = new(@"\((?<x>.*),(?<y>.*),(?<z>.*),(?<w>.*)\)", RegexOptions.None);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
result = new Quaternion(
|
||||
float.Parse(m.Result("${x}")),
|
||||
float.Parse(m.Result("${y}")),
|
||||
float.Parse(m.Result("${z}")),
|
||||
float.Parse(m.Result("${w}"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = Quaternion.Zero;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Quaternion Arithmetics
|
||||
/// <summary>
|
||||
/// Adds two quaternions.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> instance containing the sum.</returns>
|
||||
public static Quaternion Add(Quaternion left, Quaternion right)
|
||||
{
|
||||
return new Quaternion(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds two quaternions and put the result in the third quaternion.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Quaternion"/> instance to hold the result.</param>
|
||||
public static void Add(Quaternion left, Quaternion right, ref Quaternion result)
|
||||
{
|
||||
result.X = left.X + right.X;
|
||||
result.Y = left.Y + right.Y;
|
||||
result.Z = left.Z + right.Z;
|
||||
result.W = left.W + right.W;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts a quaternion from a quaternion.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> instance containing the difference.</returns>
|
||||
public static Quaternion Subtract(Quaternion left, Quaternion right)
|
||||
{
|
||||
return new Quaternion(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a quaternion from a quaternion and puts the result into a third quaternion.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Quaternion"/> instance to hold the result.</param>
|
||||
public static void Subtract(Quaternion left, Quaternion right, ref Quaternion result)
|
||||
{
|
||||
result.X = left.X - right.X;
|
||||
result.Y = left.Y - right.Y;
|
||||
result.Z = left.Z - right.Z;
|
||||
result.W = left.W - right.W;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies quaternion <paramref name="left"/> by quaternion <paramref name="right"/>.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> containing the result.</returns>
|
||||
public static Quaternion Multiply(Quaternion left, Quaternion right)
|
||||
{
|
||||
Quaternion result = new();
|
||||
result.X = left.W * right.X + left.X * right.W + left.Y * right.Z - left.Z * right.Y;
|
||||
result.Y = left.W * right.Y + left.Y * right.W + left.Z * right.X - left.X * right.Z;
|
||||
result.Z = left.W * right.Z + left.Z * right.W + left.X * right.Y - left.Y * right.X;
|
||||
result.W = left.W * right.W - left.X * right.X - left.Y * right.Y - left.Z * right.Z;
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies quaternion <paramref name="left"/> by quaternion <paramref name="right"/> and put the result in a third quaternion.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Quaternion"/> instance to hold the result.</param>
|
||||
public static void Multiply(Quaternion left, Quaternion right, ref Quaternion result)
|
||||
{
|
||||
result.X = left.W * right.X + left.X * right.W + left.Y * right.Z - left.Z * right.Y;
|
||||
result.Y = left.W * right.Y + left.Y * right.W + left.Z * right.X - left.X * right.Z;
|
||||
result.Z = left.W * right.Z + left.Z * right.W + left.X * right.Y - left.Y * right.X;
|
||||
result.W = left.W * right.W - left.X * right.X - left.Y * right.Y - left.Z * right.Z;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a quaternion by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion Multiply(Quaternion quaternion, float scalar)
|
||||
{
|
||||
Quaternion result = new(quaternion);
|
||||
result.X *= scalar;
|
||||
result.Y *= scalar;
|
||||
result.Z *= scalar;
|
||||
result.W *= scalar;
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a quaternion by a scalar and put the result in a third quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <param name="result">A <see cref="Quaternion"/> instance to hold the result.</param>
|
||||
public static void Multiply(Quaternion quaternion, float scalar, ref Quaternion result)
|
||||
{
|
||||
result.X = quaternion.X * scalar;
|
||||
result.Y = quaternion.Y * scalar;
|
||||
result.Z = quaternion.Z * scalar;
|
||||
result.W = quaternion.W * scalar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides a quaternion by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion Divide(Quaternion quaternion, float scalar)
|
||||
{
|
||||
if (scalar == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Dividing quaternion by zero");
|
||||
}
|
||||
|
||||
Quaternion result = new(quaternion);
|
||||
result.X /= scalar;
|
||||
result.Y /= scalar;
|
||||
result.Z /= scalar;
|
||||
result.W /= scalar;
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a quaternion by a scalar and put the result in a third quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <param name="result">A <see cref="Quaternion"/> instance to hold the result.</param>
|
||||
public static void Divide(Quaternion quaternion, float scalar, ref Quaternion result)
|
||||
{
|
||||
if (scalar == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Dividing quaternion by zero");
|
||||
}
|
||||
|
||||
result.X = quaternion.X / scalar;
|
||||
result.Y = quaternion.Y / scalar;
|
||||
result.Z = quaternion.Z / scalar;
|
||||
result.W = quaternion.W / scalar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the dot product of two quaternions.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>The dot product value.</returns>
|
||||
public static double DotProduct(Quaternion left, Quaternion right)
|
||||
{
|
||||
return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public bool isUnit(double tolerance = 1e-5)
|
||||
{
|
||||
return Math.Abs(dot(this) - 1.0f) < tolerance;
|
||||
}
|
||||
|
||||
public Quaternion ToUnit()
|
||||
{
|
||||
Quaternion copyOfThis = this;
|
||||
copyOfThis.unitize();
|
||||
return copyOfThis;
|
||||
}
|
||||
|
||||
public void unitize()
|
||||
{
|
||||
this *= rsq(dot(this));
|
||||
}
|
||||
|
||||
float dot(Quaternion other)
|
||||
{
|
||||
return (float)((X * other.X) + (Y * other.Y) + (Z * other.Z) + (W * other.W));
|
||||
}
|
||||
|
||||
float rsq(float x)
|
||||
{
|
||||
return 1.0f / (float)Math.Sqrt(x);
|
||||
}
|
||||
|
||||
public static Quaternion fromEulerAnglesZYX(float z, float y, float x)
|
||||
{
|
||||
return new Quaternion(Matrix3.fromEulerAnglesZYX(z, y, x));
|
||||
}
|
||||
|
||||
#region Public Static Complex Special Functions
|
||||
/// <summary>
|
||||
/// Calculates the logarithm of a given quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>The quaternion's logarithm.</returns>
|
||||
public static Quaternion Log(Quaternion quaternion)
|
||||
{
|
||||
Quaternion result = new(0, 0, 0, 0);
|
||||
|
||||
if (Math.Abs(quaternion.W) < 1.0)
|
||||
{
|
||||
float angle = (float)System.Math.Acos(quaternion.W);
|
||||
float sin = (float)System.Math.Sin(angle);
|
||||
|
||||
if (Math.Abs(sin) >= 0)
|
||||
{
|
||||
float coeff = angle / sin;
|
||||
result.X = coeff * quaternion.X;
|
||||
result.Y = coeff * quaternion.Y;
|
||||
result.Z = coeff * quaternion.Z;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.X = quaternion.X;
|
||||
result.Y = quaternion.Y;
|
||||
result.Z = quaternion.Z;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates the exponent of a quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>The quaternion's exponent.</returns>
|
||||
public Quaternion Exp(Quaternion quaternion)
|
||||
{
|
||||
Quaternion result = new(0, 0, 0, 0);
|
||||
|
||||
float angle = (float)System.Math.Sqrt(quaternion.X * quaternion.X + quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
|
||||
float sin = (float)System.Math.Sin(angle);
|
||||
|
||||
if (Math.Abs(sin) > 0)
|
||||
{
|
||||
float coeff = angle / sin;
|
||||
result.X = coeff * quaternion.X;
|
||||
result.Y = coeff * quaternion.Y;
|
||||
result.Z = coeff * quaternion.Z;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.X = quaternion.X;
|
||||
result.Y = quaternion.Y;
|
||||
result.Z = quaternion.Z;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Inverts the quaternion.
|
||||
/// </summary>
|
||||
public void Inverse()
|
||||
{
|
||||
float norm = ModulusSquared;
|
||||
if (norm > 0)
|
||||
{
|
||||
float invNorm = 1.0f / norm;
|
||||
_w *= invNorm;
|
||||
_x *= -invNorm;
|
||||
_y *= -invNorm;
|
||||
_z *= -invNorm;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Quaternion " + ToString() + " is not invertable");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Normelizes the quaternion.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float norm = Modulus;
|
||||
if (norm == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Trying to normalize a quaternion with modulus of zero.");
|
||||
}
|
||||
|
||||
_w /= norm;
|
||||
_x /= norm;
|
||||
_y /= norm;
|
||||
_z /= norm;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clamps quaternion values to zero using a given tolerance value.
|
||||
/// </summary>
|
||||
/// <param name="tolerance">The tolerance to use.</param>
|
||||
/// <remarks>
|
||||
/// The quaternion values that are close to zero within the given tolerance are set to zero.
|
||||
/// </remarks>
|
||||
public void ClampZero(float tolerance)
|
||||
{
|
||||
_x = MathFunctions.Clamp(_x, 0, tolerance);
|
||||
_y = MathFunctions.Clamp(_y, 0, tolerance);
|
||||
_z = MathFunctions.Clamp(_z, 0, tolerance);
|
||||
_w = MathFunctions.Clamp(_w, 0, tolerance);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clamps quaternion values to zero using the default tolerance value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The quaternion values that are close to zero within the given tolerance are set to zero.
|
||||
/// The tolerance value used is <see cref="MathFunctions.Epsilon"/>
|
||||
/// </remarks>
|
||||
public void ClampZero()
|
||||
{
|
||||
_x = MathFunctions.Clamp(_x, 0);
|
||||
_y = MathFunctions.Clamp(_y, 0);
|
||||
_z = MathFunctions.Clamp(_z, 0);
|
||||
_w = MathFunctions.Clamp(_w, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Object Overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _w.GetHashCode() ^ _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="Quaternion"/> and has the same values as this instance; otherwise, <see langword="false"/>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Quaternion)
|
||||
{
|
||||
Quaternion quaternion = (Quaternion)obj;
|
||||
return (_w == quaternion.W) && (_x == quaternion.X) && (_y == quaternion.Y) && (_z == quaternion.Z);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({_w}, {_x}, {_y}, {_z})";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Tests whether two specified quaternions are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">The left-hand quaternion.</param>
|
||||
/// <param name="right">The right-hand quaternion.</param>
|
||||
/// <returns><see langword="true"/> if the two quaternions are equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator ==(Quaternion left, Quaternion right)
|
||||
{
|
||||
return ValueType.Equals(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two specified quaternions are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">The left-hand quaternion.</param>
|
||||
/// <param name="right">The right-hand quaternion.</param>
|
||||
/// <returns><see langword="true"/> if the two quaternions are not equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator !=(Quaternion left, Quaternion right)
|
||||
{
|
||||
return !ValueType.Equals(left, right);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Binary Operators
|
||||
/// <summary>
|
||||
/// Adds two quaternions.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> instance containing the sum.</returns>
|
||||
public static Quaternion operator +(Quaternion left, Quaternion right)
|
||||
{
|
||||
return Quaternion.Add(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a quaternion from a quaternion.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> instance containing the difference.</returns>
|
||||
public static Quaternion operator -(Quaternion left, Quaternion right)
|
||||
{
|
||||
return Quaternion.Subtract(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies quaternion <paramref name="left"/> by quaternion <paramref name="right"/>.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>A new <see cref="Quaternion"/> containing the result.</returns>
|
||||
public static Quaternion operator *(Quaternion left, Quaternion right)
|
||||
{
|
||||
return Quaternion.Multiply(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a quaternion by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion operator *(Quaternion quaternion, float scalar)
|
||||
{
|
||||
return Quaternion.Multiply(quaternion, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a quaternion by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion operator *(float scalar, Quaternion quaternion)
|
||||
{
|
||||
return Quaternion.Multiply(quaternion, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a quaternion by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion operator /(Quaternion quaternion, float scalar)
|
||||
{
|
||||
return Quaternion.Divide(quaternion, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a scalar by a quaternion.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <param name="scalar">A scalar.</param>
|
||||
/// <returns>A <see cref="Quaternion"/> instance to hold the result.</returns>
|
||||
public static Quaternion operator /(float scalar, Quaternion quaternion)
|
||||
{
|
||||
return Quaternion.Multiply(quaternion, (1.0f / scalar));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Array Indexing Operator
|
||||
/// <summary>
|
||||
/// Indexer ( [w, x, y, z] ).
|
||||
/// </summary>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _x;
|
||||
case 1:
|
||||
return _y;
|
||||
case 2:
|
||||
return _z;
|
||||
case 3:
|
||||
return _w;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
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 IndexOutOfRangeException();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversion Operators
|
||||
/// <summary>
|
||||
/// Converts the quaternion to an array of double-precision floating point numbers.
|
||||
/// </summary>
|
||||
/// <param name="quaternion">A <see cref="Quaternion"/> instance.</param>
|
||||
/// <returns>An array of double-precision floating point numbers.</returns>
|
||||
/// <remarks>The array is [w, x, y, z].</remarks>
|
||||
public static explicit operator double[] (Quaternion quaternion)
|
||||
{
|
||||
double[] doubles = new double[4];
|
||||
doubles[1] = quaternion.X;
|
||||
doubles[2] = quaternion.Y;
|
||||
doubles[3] = quaternion.Z;
|
||||
doubles[0] = quaternion.W;
|
||||
return doubles;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Numerics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
@@ -33,6 +34,8 @@ namespace Framework.GameMath
|
||||
public struct Ray : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
private static Vector3 _inf = new(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
||||
|
||||
private Vector3 _origin;
|
||||
private Vector3 _direction;
|
||||
#endregion
|
||||
@@ -110,8 +113,8 @@ namespace Framework.GameMath
|
||||
if (m.Success)
|
||||
{
|
||||
return new Ray(
|
||||
Vector3.Parse(m.Result("${origin}")),
|
||||
Vector3.Parse(m.Result("${direction}"))
|
||||
m.Result("${origin}").ParseVector3(),
|
||||
m.Result("${direction}").ParseVector3()
|
||||
);
|
||||
}
|
||||
else
|
||||
@@ -194,18 +197,14 @@ namespace Framework.GameMath
|
||||
|
||||
public Vector3 intersection(Plane plane)
|
||||
{
|
||||
float d;
|
||||
Vector3 normal = plane.Normal;
|
||||
plane.getEquation(ref normal, out d);
|
||||
float rate = Direction.dot(normal);
|
||||
|
||||
float rate = Vector3.Dot(Direction, plane.Normal);
|
||||
if (rate >= 0.0f)
|
||||
{
|
||||
return Vector3.Inf;
|
||||
return _inf;
|
||||
}
|
||||
else
|
||||
{
|
||||
float t = -(d + Origin.dot(normal)) / rate;
|
||||
float t = -(-plane.D + Vector3.Dot(Origin, plane.Normal)) / rate;
|
||||
return Origin + Direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,947 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
* Copyright (C) 2003-2004 Eran Kampf eran@ekampf.com http://www.ekampf.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Framework.GameMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents 2-Dimentional vector of single-precision floating point numbers.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[TypeConverter(typeof(Vector2FConverter))]
|
||||
public struct Vector2 : ICloneable
|
||||
{
|
||||
#region Private fields
|
||||
private float _x;
|
||||
private float _y;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vector2"/> class with the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The vector's X coordinate.</param>
|
||||
/// <param name="y">The vector's Y coordinate.</param>
|
||||
public Vector2(float x, float y)
|
||||
{
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vector2"/> class with the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">An array containing the coordinate parameters.</param>
|
||||
public Vector2(float[] coordinates)
|
||||
{
|
||||
Debug.Assert(coordinates != null);
|
||||
Debug.Assert(coordinates.Length >= 2);
|
||||
|
||||
_x = coordinates[0];
|
||||
_y = coordinates[1];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vector2"/> class with the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">An array containing the coordinate parameters.</param>
|
||||
public Vector2(List<float> coordinates)
|
||||
{
|
||||
Debug.Assert(coordinates != null);
|
||||
Debug.Assert(coordinates.Count >= 2);
|
||||
|
||||
_x = coordinates[0];
|
||||
_y = coordinates[1];
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vector2"/> class using coordinates from a given <see cref="Vector2"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> to get the coordinates from.</param>
|
||||
public Vector2(Vector2 vector)
|
||||
{
|
||||
_x = vector.X;
|
||||
_y = vector.Y;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
/// <summary>
|
||||
/// 4-Dimentional single-precision floating point zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2 Zero = new(0.0f, 0.0f);
|
||||
/// <summary>
|
||||
/// 4-Dimentional single-precision floating point X-Axis vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2 XAxis = new(1.0f, 0.0f);
|
||||
/// <summary>
|
||||
/// 4-Dimentional single-precision floating point Y-Axis vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2 YAxis = new(0.0f, 1.0f);
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
/// <summary>
|
||||
/// Gets or sets the x-coordinate of this vector.
|
||||
/// </summary>
|
||||
/// <value>The x-coordinate of this vector.</value>
|
||||
public float X
|
||||
{
|
||||
get { return _x; }
|
||||
set { _x = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the y-coordinate of this vector.
|
||||
/// </summary>
|
||||
/// <value>The y-coordinate of this vector.</value>
|
||||
public float Y
|
||||
{
|
||||
get { return _y; }
|
||||
set { _y = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Vector2"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Vector2"/> object this method creates, cast as an object.</returns>
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Vector2(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates an exact copy of this <see cref="Vector2"/> object.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Vector2"/> object this method creates.</returns>
|
||||
public Vector2 Clone()
|
||||
{
|
||||
return new Vector2(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Parse Methods
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Vector2"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Vector2"/>.</param>
|
||||
/// <returns>A <see cref="Vector2"/> that represents the vector specified by the <paramref name="value"/> parameter.</returns>
|
||||
public static Vector2 Parse(string value)
|
||||
{
|
||||
Regex r = new(@"\((?<x>.*),(?<y>.*)\)", RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Vector2(
|
||||
float.Parse(m.Result("${x}")),
|
||||
float.Parse(m.Result("${y}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the specified string to its <see cref="Vector2"/> equivalent.
|
||||
/// A return value indicates whether the conversion succeeded or failed.
|
||||
/// </summary>
|
||||
/// <param name="value">A string representation of a <see cref="Vector2"/>.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, if the conversion succeeded,
|
||||
/// contains a <see cref="Vector2"/> representing the vector specified by <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> if value was converted successfully; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool TryParse(string value, out Vector2 result)
|
||||
{
|
||||
Regex r = new(@"\((?<x>.*),(?<y>.*)\)", RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
result = new Vector2(
|
||||
float.Parse(m.Result("${x}")),
|
||||
float.Parse(m.Result("${y}"))
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = Vector2.Zero;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Static Vector Arithmetics
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the sum.</returns>
|
||||
public static Vector2 Add(Vector2 left, Vector2 right)
|
||||
{
|
||||
return new Vector2(left.X + right.X, left.Y + right.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a vector and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the sum.</returns>
|
||||
public static Vector2 Add(Vector2 vector, float scalar)
|
||||
{
|
||||
return new Vector2(vector.X + scalar, vector.Y + scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds two vectors and put the result in the third vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
public static void Add(Vector2 left, Vector2 right, ref Vector2 result)
|
||||
{
|
||||
result.X = left.X + right.X;
|
||||
result.Y = left.Y + right.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a vector and a scalar and put the result into another vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
public static void Add(Vector2 vector, float scalar, ref Vector2 result)
|
||||
{
|
||||
result.X = vector.X + scalar;
|
||||
result.Y = vector.Y + scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = left[i] - right[i].
|
||||
/// </remarks>
|
||||
public static Vector2 Subtract(Vector2 left, Vector2 right)
|
||||
{
|
||||
return new Vector2(left.X - right.X, left.Y - right.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] - scalar
|
||||
/// </remarks>
|
||||
public static Vector2 Subtract(Vector2 vector, float scalar)
|
||||
{
|
||||
return new Vector2(vector.X - scalar, vector.Y - scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar - vector[i]
|
||||
/// </remarks>
|
||||
public static Vector2 Subtract(float scalar, Vector2 vector)
|
||||
{
|
||||
return new Vector2(scalar - vector.X, scalar - vector.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a second vector and puts the result into a third vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = left[i] - right[i].
|
||||
/// </remarks>
|
||||
public static void Subtract(Vector2 left, Vector2 right, ref Vector2 result)
|
||||
{
|
||||
result.X = left.X - right.X;
|
||||
result.Y = left.Y - right.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a scalar and put the result into another vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] - scalar
|
||||
/// </remarks>
|
||||
public static void Subtract(Vector2 vector, float scalar, ref Vector2 result)
|
||||
{
|
||||
result.X = vector.X - scalar;
|
||||
result.Y = vector.Y - scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a vector and put the result into another vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar - vector[i]
|
||||
/// </remarks>
|
||||
public static void Subtract(float scalar, Vector2 vector, ref Vector2 result)
|
||||
{
|
||||
result.X = scalar - vector.X;
|
||||
result.Y = scalar - vector.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a vector by another vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the quotient.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = left[i] / right[i].
|
||||
/// </remarks>
|
||||
public static Vector2 Divide(Vector2 left, Vector2 right)
|
||||
{
|
||||
return new Vector2(left.X / right.X, left.Y / right.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the quotient.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] / scalar;
|
||||
/// </remarks>
|
||||
public static Vector2 Divide(Vector2 vector, float scalar)
|
||||
{
|
||||
return new Vector2(vector.X / scalar, vector.Y / scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a scalar by a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the quotient.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar / vector[i]
|
||||
/// </remarks>
|
||||
public static Vector2 Divide(float scalar, Vector2 vector)
|
||||
{
|
||||
return new Vector2(scalar / vector.X, scalar / vector.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a vector by another vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = left[i] / right[i]
|
||||
/// </remarks>
|
||||
public static void Divide(Vector2 left, Vector2 right, ref Vector2 result)
|
||||
{
|
||||
result.X = left.X / right.X;
|
||||
result.Y = left.Y / right.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] / scalar
|
||||
/// </remarks>
|
||||
public static void Divide(Vector2 vector, float scalar, ref Vector2 result)
|
||||
{
|
||||
result.X = vector.X / scalar;
|
||||
result.Y = vector.Y / scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a scalar by a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar / vector[i]
|
||||
/// </remarks>
|
||||
public static void Divide(float scalar, Vector2 vector, ref Vector2 result)
|
||||
{
|
||||
result.X = scalar / vector.X;
|
||||
result.Y = scalar / vector.Y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the result.</returns>
|
||||
public static Vector2 Multiply(Vector2 vector, float scalar)
|
||||
{
|
||||
return new Vector2(vector.X * scalar, vector.Y * scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a vector by a scalar and put the result in another vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <param name="result">A <see cref="Vector2"/> instance to hold the result.</param>
|
||||
public static void Multiply(Vector2 vector, float scalar, ref Vector2 result)
|
||||
{
|
||||
result.X = vector.X * scalar;
|
||||
result.Y = vector.Y * scalar;
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates the dot product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>The dot product value.</returns>
|
||||
public static float DotProduct(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (left.X * right.X) + (left.Y * right.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates the Kross product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>The Kross product value.</returns>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// The Kross product is defined as:
|
||||
/// Kross(u,v) = u.X*v.Y - u.Y*v.X.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// The operation is related to the cross product in 3D given by (x0, y0, 0) X (x1, y1, 0) = (0, 0, Kross((x0, y0), (x1, y1))).
|
||||
/// The operation has the property that Kross(u, v) = -Kross(v, u).
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public static float KrossProduct(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (left.X * right.Y) - (left.Y * right.X);
|
||||
}
|
||||
/// <summary>
|
||||
/// Negates a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the negated values.</returns>
|
||||
public static Vector2 Negate(Vector2 vector)
|
||||
{
|
||||
return new Vector2(-vector.X, -vector.Y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two vectors are approximately equal using default tolerance value.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two vectors are approximately equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool ApproxEqual(Vector2 left, Vector2 right)
|
||||
{
|
||||
return ApproxEqual(left, right, MathFunctions.Epsilon);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two vectors are approximately equal given a tolerance value.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="tolerance">The tolerance value used to test approximate equality.</param>
|
||||
/// <returns><see langword="true"/> if the two vectors are approximately equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool ApproxEqual(Vector2 left, Vector2 right, float tolerance)
|
||||
{
|
||||
return
|
||||
(
|
||||
(System.Math.Abs(left.X - right.X) <= tolerance) &&
|
||||
(System.Math.Abs(left.Y - right.Y) <= tolerance)
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Scale the vector so that its length is 1.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float length = GetLength();
|
||||
if (length == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Trying to normalize a vector with length of zero.");
|
||||
}
|
||||
|
||||
_x /= length;
|
||||
_y /= length;
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates the length of the vector.
|
||||
/// </summary>
|
||||
/// <returns>Returns the length of the vector. (Sqrt(X*X + Y*Y))</returns>
|
||||
public float GetLength()
|
||||
{
|
||||
return (float)System.Math.Sqrt(_x * _x + _y * _y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates the squared length of the vector.
|
||||
/// </summary>
|
||||
/// <returns>Returns the squared length of the vector. (X*X + Y*Y)</returns>
|
||||
public float GetLengthSquared()
|
||||
{
|
||||
return (_x * _x + _y * _y);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clamps vector values to zero using a given tolerance value.
|
||||
/// </summary>
|
||||
/// <param name="tolerance">The tolerance to use.</param>
|
||||
/// <remarks>
|
||||
/// The vector values that are close to zero within the given tolerance are set to zero.
|
||||
/// </remarks>
|
||||
public void ClampZero(float tolerance)
|
||||
{
|
||||
_x = MathFunctions.Clamp(_x, 0, tolerance);
|
||||
_y = MathFunctions.Clamp(_y, 0, tolerance);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clamps vector values to zero using the default tolerance value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The vector values that are close to zero within the given tolerance are set to zero.
|
||||
/// The tolerance value used is <see cref="MathFunctions.Epsilon"/>
|
||||
/// </remarks>
|
||||
public void ClampZero()
|
||||
{
|
||||
_x = MathFunctions.Clamp(_x, 0);
|
||||
_y = MathFunctions.Clamp(_y, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Object Overrides
|
||||
/// <summary>
|
||||
/// Returns the hashcode for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _x.GetHashCode() ^ _y.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal to
|
||||
/// the specified object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare to this instance.</param>
|
||||
/// <returns><see langword="true"/> if <paramref name="obj"/> is a <see cref="Vector2"/> and has the same values as this instance; otherwise, <see langword="false"/>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Vector2)
|
||||
{
|
||||
Vector2 v = (Vector2)obj;
|
||||
return (_x == v.X) && (_y == v.Y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({_x}, {_y})";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparison Operators
|
||||
/// <summary>
|
||||
/// Tests whether two specified vectors are equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two vectors are equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator ==(Vector2 left, Vector2 right)
|
||||
{
|
||||
return ValueType.Equals(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests whether two specified vectors are not equal.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the two vectors are not equal; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator !=(Vector2 left, Vector2 right)
|
||||
{
|
||||
return !ValueType.Equals(left, right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests if a vector's components are greater than another vector's components.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the left-hand vector's components are greater than the right-hand vector's component; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator >(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (
|
||||
(left._x > right._x) &&
|
||||
(left._y > right._y));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests if a vector's components are smaller than another vector's components.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the left-hand vector's components are smaller than the right-hand vector's component; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator <(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (
|
||||
(left._x < right._x) &&
|
||||
(left._y < right._y));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests if a vector's components are greater or equal than another vector's components.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the left-hand vector's components are greater or equal than the right-hand vector's component; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator >=(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (
|
||||
(left._x >= right._x) &&
|
||||
(left._y >= right._y));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests if a vector's components are smaller or equal than another vector's components.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns><see langword="true"/> if the left-hand vector's components are smaller or equal than the right-hand vector's component; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool operator <=(Vector2 left, Vector2 right)
|
||||
{
|
||||
return (
|
||||
(left._x <= right._x) &&
|
||||
(left._y <= right._y));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Unary Operators
|
||||
/// <summary>
|
||||
/// Negates the values of the given vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the negated values.</returns>
|
||||
public static Vector2 operator -(Vector2 vector)
|
||||
{
|
||||
return Vector2.Negate(vector);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Binary Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the sum.</returns>
|
||||
public static Vector2 operator +(Vector2 left, Vector2 right)
|
||||
{
|
||||
return Vector2.Add(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a vector and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the sum.</returns>
|
||||
public static Vector2 operator +(Vector2 vector, float scalar)
|
||||
{
|
||||
return Vector2.Add(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a vector and a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the sum.</returns>
|
||||
public static Vector2 operator +(float scalar, Vector2 vector)
|
||||
{
|
||||
return Vector2.Add(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a vector.
|
||||
/// </summary>
|
||||
/// <param name="left">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="right">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = left[i] - right[i].
|
||||
/// </remarks>
|
||||
public static Vector2 operator -(Vector2 left, Vector2 right)
|
||||
{
|
||||
return Vector2.Subtract(left, right);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a scalar from a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] - scalar
|
||||
/// </remarks>
|
||||
public static Vector2 operator -(Vector2 vector, float scalar)
|
||||
{
|
||||
return Vector2.Subtract(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Subtracts a vector from a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> instance containing the difference.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar - vector[i]
|
||||
/// </remarks>
|
||||
public static Vector2 operator -(float scalar, Vector2 vector)
|
||||
{
|
||||
return Vector2.Subtract(scalar, vector);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the result.</returns>
|
||||
public static Vector2 operator *(Vector2 vector, float scalar)
|
||||
{
|
||||
return Vector2.Multiply(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Multiplies a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A single-precision floating-point number.</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the result.</returns>
|
||||
public static Vector2 operator *(float scalar, Vector2 vector)
|
||||
{
|
||||
return Vector2.Multiply(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a vector by a scalar.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the quotient.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = vector[i] / scalar;
|
||||
/// </remarks>
|
||||
public static Vector2 operator /(Vector2 vector, float scalar)
|
||||
{
|
||||
return Vector2.Divide(vector, scalar);
|
||||
}
|
||||
/// <summary>
|
||||
/// Divides a scalar by a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <param name="scalar">A scalar</param>
|
||||
/// <returns>A new <see cref="Vector2"/> containing the quotient.</returns>
|
||||
/// <remarks>
|
||||
/// result[i] = scalar / vector[i]
|
||||
/// </remarks>
|
||||
public static Vector2 operator /(float scalar, Vector2 vector)
|
||||
{
|
||||
return Vector2.Divide(scalar, vector);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Array Indexing Operator
|
||||
/// <summary>
|
||||
/// Indexer ( [x, y] ).
|
||||
/// </summary>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _x;
|
||||
case 1:
|
||||
return _y;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
_x = value;
|
||||
break;
|
||||
case 1:
|
||||
_y = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversion Operators
|
||||
/// <summary>
|
||||
/// Converts the vector to an array of single-precision floating point values.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>An array of single-precision floating point values.</returns>
|
||||
public static explicit operator float[] (Vector2 vector)
|
||||
{
|
||||
float[] array = new float[2];
|
||||
array[0] = vector.X;
|
||||
array[1] = vector.Y;
|
||||
return array;
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the vector to a <see cref="System.Collections.Generic.List{T}"/> of single-precision floating point values.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A <see cref="System.Collections.Generic.List{T}"/> of single-precision floating point values.</returns>
|
||||
public static explicit operator List<float>(Vector2 vector)
|
||||
{
|
||||
List<float> list = new();
|
||||
list.Add(vector.X);
|
||||
list.Add(vector.Y);
|
||||
|
||||
return list;
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the vector to a <see cref="System.Collections.Generic.LinkedList{T}"/> of single-precision floating point values.
|
||||
/// </summary>
|
||||
/// <param name="vector">A <see cref="Vector2"/> instance.</param>
|
||||
/// <returns>A <see cref="System.Collections.Generic.LinkedList{T}"/> of single-precision floating point values.</returns>
|
||||
public static explicit operator LinkedList<float>(Vector2 vector)
|
||||
{
|
||||
LinkedList<float> list = new();
|
||||
list.AddLast(vector.X);
|
||||
list.AddLast(vector.Y);
|
||||
|
||||
return list;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Vector2FConverter class
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Vector2"/> to and from string representation.
|
||||
/// </summary>
|
||||
public class Vector2FConverter : ExpandableObjectConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
|
||||
/// <param name="sourceType">A <see cref="Type"/> that represents the type you want to convert from.</param>
|
||||
/// <returns><b>true</b> if this converter can perform the conversion; otherwise, <b>false</b>.</returns>
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
return true;
|
||||
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns whether this converter can convert the object to the specified type, using the specified context.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
|
||||
/// <param name="destinationType">A <see cref="Type"/> that represents the type you want to convert to.</param>
|
||||
/// <returns><b>true</b> if this converter can perform the conversion; otherwise, <b>false</b>.</returns>
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
return true;
|
||||
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the given value object to the specified type, using the specified context and culture information.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
|
||||
/// <param name="culture">A <see cref="System.Globalization.CultureInfo"/> object. If a null reference (Nothing in Visual Basic) is passed, the current culture is assumed.</param>
|
||||
/// <param name="value">The <see cref="Object"/> to convert.</param>
|
||||
/// <param name="destinationType">The Type to convert the <paramref name="value"/> parameter to.</param>
|
||||
/// <returns>An <see cref="Object"/> that represents the converted value.</returns>
|
||||
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if ((destinationType == typeof(string)) && (value is Vector2))
|
||||
{
|
||||
Vector2 v = (Vector2)value;
|
||||
return v.ToString();
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts the given object to the type of this converter, using the specified context and culture information.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
|
||||
/// <param name="culture">The <see cref="System.Globalization.CultureInfo"/> to use as the current culture. </param>
|
||||
/// <param name="value">The <see cref="Object"/> to convert.</param>
|
||||
/// <returns>An <see cref="Object"/> that represents the converted value.</returns>
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
|
||||
{
|
||||
if (value.GetType() == typeof(string))
|
||||
{
|
||||
return Vector2.Parse((string)value);
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether this object supports a standard set of values that can be picked from a list.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
|
||||
/// <returns><b>true</b> if <see cref="GetStandardValues"/> should be called to find a common set of values the object supports; otherwise, <b>false</b>.</returns>
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of standard values for the data type this type converter is designed for when provided with a format context.
|
||||
/// </summary>
|
||||
/// <param name="context">An <see cref="ITypeDescriptorContext"/> that provides a format context that can be used to extract additional information about the environment from which this converter is invoked. This parameter or properties of this parameter can be a null reference.</param>
|
||||
/// <returns>A <see cref="TypeConverter.StandardValuesCollection"/> that holds a standard set of valid values, or a null reference (Nothing in Visual Basic) if the data type does not support a standard set of values.</returns>
|
||||
public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
||||
{
|
||||
StandardValuesCollection svc =
|
||||
new(new object[3] { Vector2.Zero, Vector2.XAxis, Vector2.YAxis });
|
||||
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
namespace Framework.IO
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Framework.IO
|
||||
{
|
||||
|
||||
@@ -182,6 +182,102 @@ namespace System
|
||||
return list;
|
||||
}
|
||||
|
||||
public static float GetAt(this Vector3 vector, long index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return vector.X;
|
||||
case 1:
|
||||
return vector.Y;
|
||||
case 2:
|
||||
return vector.Z;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetAt(this ref Vector3 vector, float value, long index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
vector.X = value;
|
||||
break;
|
||||
case 1:
|
||||
vector.Y = value;
|
||||
break;
|
||||
case 2:
|
||||
vector.Z = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static int primaryAxis(this Vector3 vector)
|
||||
{
|
||||
var a = 0;
|
||||
|
||||
double nx = Math.Abs(vector.X);
|
||||
double ny = Math.Abs(vector.Y);
|
||||
double nz = Math.Abs(vector.Z);
|
||||
|
||||
if (nx > ny)
|
||||
{
|
||||
if (nx > nz)
|
||||
a = 0;
|
||||
else
|
||||
a = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ny > nz)
|
||||
a = 1;
|
||||
else
|
||||
a = 2;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
public static Vector3 directionOrZero(this Vector3 vector)
|
||||
{
|
||||
float mag = vector.Length();
|
||||
if (mag < 0.0000001f)
|
||||
{
|
||||
return Vector3.Zero;
|
||||
}
|
||||
else if (mag < 1.00001f && mag > 0.99999f)
|
||||
{
|
||||
return vector;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vector * (1.0f / mag);
|
||||
}
|
||||
}
|
||||
|
||||
public static Matrix4x4 fromEulerAnglesZYX(float fYAngle, float fPAngle, float fRAngle)
|
||||
{
|
||||
float fCos = (float)Math.Cos(fYAngle);
|
||||
float fSin = (float)Math.Sin(fYAngle);
|
||||
|
||||
Matrix4x4 kZMat = new(fCos, -fSin, 0, 0, fSin, fCos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0);
|
||||
|
||||
fCos = (float)Math.Cos(fPAngle);
|
||||
fSin = (float)Math.Sin(fPAngle);
|
||||
|
||||
Matrix4x4 kYMat = new(fCos, 0, fSin, 0, 0, 1, 0, 0, -fSin, 0, fCos, 0, 0, 0, 0, 0);
|
||||
|
||||
fCos = (float)Math.Cos(fRAngle);
|
||||
fSin = (float)Math.Sin(fRAngle);
|
||||
|
||||
Matrix4x4 kXMat = new(1, 0, 0, 0, 0, fCos, -fSin, 0, 0, fSin, fCos, 0, 0, 0, 0, 0);
|
||||
|
||||
return (kZMat * (kYMat * kXMat));
|
||||
}
|
||||
|
||||
#region Strings
|
||||
public static bool IsEmpty(this string str)
|
||||
{
|
||||
@@ -255,6 +351,24 @@ namespace System
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Vector3 ParseVector3(this string value)
|
||||
{
|
||||
Regex r = new Regex(@"\((?<x>.*),(?<y>.*),(?<z>.*)\)", RegexOptions.Singleline);
|
||||
Match m = r.Match(value);
|
||||
if (m.Success)
|
||||
{
|
||||
return new Vector3(
|
||||
float.Parse(m.Result("${x}")),
|
||||
float.Parse(m.Result("${y}")),
|
||||
float.Parse(m.Result("${z}"))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsuccessful Match.");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BinaryReader
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Framework.Web.API
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using Framework.Constants;
|
||||
using Game.Entities;
|
||||
using Game.Spells;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game.AI
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Chat;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
@@ -27,6 +26,7 @@ using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.AI
|
||||
{
|
||||
@@ -1198,14 +1198,14 @@ namespace Game.AI
|
||||
foreach (var target in targets)
|
||||
{
|
||||
Position pos = target.GetPositionWithOffset(new Position(e.Target.x, e.Target.y, e.Target.z, e.Target.o));
|
||||
Quaternion rot = Quaternion.fromEulerAnglesZYX(pos.GetOrientation(), 0f, 0f);
|
||||
Quaternion rot = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(pos.GetOrientation(), 0f, 0f));
|
||||
summoner.SummonGameObject(e.Action.summonGO.entry, pos, rot, e.Action.summonGO.despawnTime, (GameObjectSummonType)e.Action.summonGO.summonType);
|
||||
}
|
||||
|
||||
if (e.GetTargetType() != SmartTargets.Position)
|
||||
break;
|
||||
|
||||
Quaternion _rot = Quaternion.fromEulerAnglesZYX(e.Target.o, 0f, 0f);
|
||||
Quaternion _rot = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(e.Target.o, 0f, 0f));
|
||||
summoner.SummonGameObject(e.Action.summonGO.entry, new Position(e.Target.x, e.Target.y, e.Target.z, e.Target.o), _rot, e.Action.summonGO.despawnTime, (GameObjectSummonType)e.Action.summonGO.summonType);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.Arenas;
|
||||
using Game.BattleFields;
|
||||
using Game.BattleGrounds;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
|
||||
@@ -24,9 +24,7 @@ using Game.Mails;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using Framework.Networking;
|
||||
using Framework.IO;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Groups;
|
||||
using Game.Maps;
|
||||
@@ -25,6 +23,7 @@ using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.BattleFields
|
||||
{
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.BattleFields
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Game.Chat;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
@@ -30,6 +29,7 @@ using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.BattleGrounds
|
||||
{
|
||||
@@ -1353,7 +1353,7 @@ namespace Game.BattleGrounds
|
||||
Log.outDebug(LogFilter.Battleground, $"Battleground.AddObject: gameoobject [entry: {entry}, object type: {type}] for BG (map: {GetMapId()}) has zeroed rotation fields, " +
|
||||
"orientation used temporally, but please fix the spawn");
|
||||
|
||||
rotation = Quaternion.fromEulerAnglesZYX(o, 0.0f, 0.0f);
|
||||
rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(o, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
// Must be created this way, adding to godatamap would add it to the base map of the instance
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
|
||||
@@ -20,7 +20,6 @@ using Framework.Constants;
|
||||
using System.Collections.Generic;
|
||||
using Game.Networking.Packets;
|
||||
using Game.DataStorage;
|
||||
using Game.BattleGrounds;
|
||||
|
||||
namespace Game.BattleGrounds.Zones
|
||||
{
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Networking.Packets;
|
||||
using System.Collections.Generic;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.BattleGrounds.Zones
|
||||
{
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Networking.Packets;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game.BattleGrounds.Zones
|
||||
{
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Constants;
|
||||
using Game.Cache;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
|
||||
namespace Game.Chat
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Chat.Commands
|
||||
{
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Framework.IO;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
namespace Game.Chat
|
||||
@@ -614,7 +614,7 @@ namespace Game.Chat
|
||||
Player player = handler.GetPlayer();
|
||||
Map map = player.GetMap();
|
||||
|
||||
GameObject obj = GameObject.CreateGameObject(objectInfo.entry, map, player, Quaternion.fromEulerAnglesZYX(player.GetOrientation(), 0.0f, 0.0f), 255, GameObjectState.Ready);
|
||||
GameObject obj = GameObject.CreateGameObject(objectInfo.entry, map, player, Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(player.GetOrientation(), 0.0f, 0.0f)), 255, GameObjectState.Ready);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
@@ -658,7 +658,7 @@ namespace Game.Chat
|
||||
if (spawntime != 0)
|
||||
spawntm = spawntime;
|
||||
|
||||
Quaternion rotation = Quaternion.fromEulerAnglesZYX(player.GetOrientation(), 0.0f, 0.0f);
|
||||
Quaternion rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(player.GetOrientation(), 0.0f, 0.0f));
|
||||
|
||||
if (Global.ObjectMgr.GetGameObjectTemplate(id) == null)
|
||||
{
|
||||
|
||||
@@ -19,12 +19,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Game.DataStorage;
|
||||
using Framework.Constants;
|
||||
using Game.Spells;
|
||||
using Framework.Dynamic;
|
||||
using Framework.Collections;
|
||||
|
||||
namespace Game.Chat
|
||||
|
||||
@@ -19,6 +19,7 @@ using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Game.Collision
|
||||
@@ -76,12 +77,12 @@ namespace Game.Collision
|
||||
Vector3 d = gridBox.hi - gridBox.lo;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i])
|
||||
if (nodeBox.hi.GetAt(i) < gridBox.lo.GetAt(i) || nodeBox.lo.GetAt(i) > gridBox.hi.GetAt(i))
|
||||
Log.outError(LogFilter.Server, "Reached tree area in error - discarding node with: {0} objects", right - left + 1);
|
||||
}
|
||||
// find longest axis
|
||||
axis = (int)d.primaryAxis();
|
||||
split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]);
|
||||
split = 0.5f * (gridBox.lo.GetAt(axis) + gridBox.hi.GetAt(axis));
|
||||
// partition L/R subsets
|
||||
clipL = float.NegativeInfinity;
|
||||
clipR = float.PositiveInfinity;
|
||||
@@ -91,8 +92,8 @@ namespace Game.Collision
|
||||
for (int i = left; i <= right; )
|
||||
{
|
||||
int obj = (int)dat.indices[i];
|
||||
float minb = dat.primBound[obj].Lo[axis];
|
||||
float maxb = dat.primBound[obj].Hi[axis];
|
||||
float minb = dat.primBound[obj].Lo.GetAt(axis);
|
||||
float maxb = dat.primBound[obj].Hi.GetAt(axis);
|
||||
float center = (minb + maxb) * 0.5f;
|
||||
if (center <= split)
|
||||
{
|
||||
@@ -115,9 +116,9 @@ namespace Game.Collision
|
||||
nodeR = Math.Max(nodeR, maxb);
|
||||
}
|
||||
// check for empty space
|
||||
if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis])
|
||||
if (nodeL > nodeBox.lo.GetAt(axis) && nodeR < nodeBox.hi.GetAt(axis))
|
||||
{
|
||||
float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis];
|
||||
float nodeBoxW = nodeBox.hi.GetAt(axis) - nodeBox.lo.GetAt(axis);
|
||||
float nodeNewW = nodeR - nodeL;
|
||||
// node box is too big compare to space occupied by primitives?
|
||||
if (1.3f * nodeNewW < nodeBoxW)
|
||||
@@ -134,8 +135,8 @@ namespace Game.Collision
|
||||
tempTree[nodeIndex + 1] = FloatToRawIntBits(nodeL);
|
||||
tempTree[nodeIndex + 2] = FloatToRawIntBits(nodeR);
|
||||
// update nodebox and recurse
|
||||
nodeBox.lo[axis] = nodeL;
|
||||
nodeBox.hi[axis] = nodeR;
|
||||
nodeBox.lo.SetAt(nodeL, axis);
|
||||
nodeBox.hi.SetAt(nodeR, axis);
|
||||
Subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex1, depth + 1, stats);
|
||||
return;
|
||||
}
|
||||
@@ -154,12 +155,12 @@ namespace Game.Collision
|
||||
if (clipL <= split)
|
||||
{
|
||||
// keep looping on left half
|
||||
gridBox.hi[axis] = split;
|
||||
gridBox.hi.SetAt(split, axis);
|
||||
prevClip = clipL;
|
||||
wasLeft = true;
|
||||
continue;
|
||||
}
|
||||
gridBox.hi[axis] = split;
|
||||
gridBox.hi.SetAt(split, axis);
|
||||
prevClip = float.NaN;
|
||||
}
|
||||
else if (left > right)
|
||||
@@ -177,12 +178,12 @@ namespace Game.Collision
|
||||
if (clipR >= split)
|
||||
{
|
||||
// keep looping on right half
|
||||
gridBox.lo[axis] = split;
|
||||
gridBox.lo.SetAt(split, axis);
|
||||
prevClip = clipR;
|
||||
wasLeft = false;
|
||||
continue;
|
||||
}
|
||||
gridBox.lo[axis] = split;
|
||||
gridBox.lo.SetAt(split, axis);
|
||||
prevClip = float.NaN;
|
||||
}
|
||||
else
|
||||
@@ -254,9 +255,12 @@ namespace Game.Collision
|
||||
AABound gridBoxR = gridBox;
|
||||
AABound nodeBoxL = nodeBox;
|
||||
AABound nodeBoxR = nodeBox;
|
||||
gridBoxL.hi[axis] = gridBoxR.lo[axis] = split;
|
||||
nodeBoxL.hi[axis] = clipL;
|
||||
nodeBoxR.lo[axis] = clipR;
|
||||
|
||||
gridBoxR.lo.SetAt(split, axis);
|
||||
gridBoxL.hi.SetAt(split, axis);
|
||||
nodeBoxL.hi.SetAt(clipL, axis);
|
||||
nodeBoxR.lo.SetAt(clipR, axis);
|
||||
|
||||
// recurse
|
||||
if (nl > 0)
|
||||
Subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
|
||||
@@ -325,11 +329,11 @@ namespace Game.Collision
|
||||
Vector3 invDir = new();
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
invDir[i] = 1.0f / dir[i];
|
||||
if (MathFunctions.fuzzyNe(dir[i], 0.0f))
|
||||
invDir.SetAt(1.0f / dir.GetAt(i), i);
|
||||
if (MathFunctions.fuzzyNe(dir.GetAt(i), 0.0f))
|
||||
{
|
||||
float t1 = (bounds.Lo[i] - org[i]) * invDir[i];
|
||||
float t2 = (bounds.Hi[i] - org[i]) * invDir[i];
|
||||
float t1 = (bounds.Lo.GetAt(i) - org.GetAt(i)) * invDir.GetAt(i);
|
||||
float t2 = (bounds.Hi.GetAt(i) - org.GetAt(i)) * invDir.GetAt(i);
|
||||
if (t1 > t2)
|
||||
MathFunctions.Swap<float>(ref t1, ref t2);
|
||||
if (t1 > intervalMin)
|
||||
@@ -356,7 +360,7 @@ namespace Game.Collision
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
offsetFront[i] = FloatToRawIntBits(dir[i]) >> 31;
|
||||
offsetFront[i] = FloatToRawIntBits(dir.GetAt(i)) >> 31;
|
||||
offsetBack[i] = offsetFront[i] ^ 1;
|
||||
offsetFront3[i] = offsetFront[i] * 3;
|
||||
offsetBack3[i] = offsetBack[i] * 3;
|
||||
@@ -383,8 +387,8 @@ namespace Game.Collision
|
||||
if (axis < 3)
|
||||
{
|
||||
// "normal" interior node
|
||||
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
|
||||
float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
|
||||
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
|
||||
float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
|
||||
// ray passes between clip zones
|
||||
if (tf < intervalMin && tb > intervalMax)
|
||||
break;
|
||||
@@ -432,8 +436,8 @@ namespace Game.Collision
|
||||
{
|
||||
if (axis > 2)
|
||||
return; // should not happen
|
||||
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org[axis]) * invDir[axis];
|
||||
float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org[axis]) * invDir[axis];
|
||||
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
|
||||
float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
|
||||
node = offset;
|
||||
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
|
||||
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
|
||||
@@ -484,18 +488,18 @@ namespace Game.Collision
|
||||
float tl = IntBitsToFloat(tree[node + 1]);
|
||||
float tr = IntBitsToFloat(tree[node + 2]);
|
||||
// point is between clip zones
|
||||
if (tl < p[(int)axis] && tr > p[axis])
|
||||
if (tl < p.GetAt(axis) && tr > p.GetAt(axis))
|
||||
break;
|
||||
int right = offset + 3;
|
||||
node = right;
|
||||
// point is in right node only
|
||||
if (tl < p[(int)axis])
|
||||
if (tl < p.GetAt(axis))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
node = offset; // left
|
||||
// point is in left node only
|
||||
if (tr > p[axis])
|
||||
if (tr > p.GetAt(axis))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -525,7 +529,7 @@ namespace Game.Collision
|
||||
float tl = IntBitsToFloat(tree[node + 1]);
|
||||
float tr = IntBitsToFloat(tree[node + 2]);
|
||||
node = offset;
|
||||
if (tl > p[axis] || tr < p[axis])
|
||||
if (tl > p.GetAt(axis) || tr < p.GetAt(axis))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
using Framework.GameMath;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -43,8 +44,8 @@ namespace Game.Collision
|
||||
Vector3 lo = vertices[(int)tri.idx0];
|
||||
Vector3 hi = lo;
|
||||
|
||||
lo = (lo.Min(vertices[(int)tri.idx1])).Min(vertices[(int)tri.idx2]);
|
||||
hi = (hi.Max(vertices[(int)tri.idx1])).Max(vertices[(int)tri.idx2]);
|
||||
lo = Vector3.Min(Vector3.Min(lo, vertices[(int)tri.idx1]), vertices[(int)tri.idx2]);
|
||||
hi = Vector3.Max(Vector3.Max(hi, vertices[(int)tri.idx1]), vertices[(int)tri.idx2]);
|
||||
|
||||
value = new AxisAlignedBox(lo, hi);
|
||||
}
|
||||
@@ -119,8 +120,8 @@ namespace Game.Collision
|
||||
|
||||
Vector3 e1 = points[(int)tri.idx1] - points[(int)tri.idx0];
|
||||
Vector3 e2 = points[(int)tri.idx2] - points[(int)tri.idx0];
|
||||
Vector3 p = new(ray.Direction.cross(e2));
|
||||
float a = e1.dot(p);
|
||||
Vector3 p = Vector3.Cross(ray.Direction, e2);
|
||||
float a = Vector3.Dot(e1, p);
|
||||
|
||||
if (Math.Abs(a) < EPS)
|
||||
{
|
||||
@@ -129,8 +130,8 @@ namespace Game.Collision
|
||||
}
|
||||
|
||||
float f = 1.0f / a;
|
||||
Vector3 s = new(ray.Origin - points[(int)tri.idx0]);
|
||||
float u = f * s.dot(p);
|
||||
Vector3 s = ray.Origin - points[(int)tri.idx0];
|
||||
float u = f * Vector3.Dot(s, p);
|
||||
|
||||
if ((u < 0.0f) || (u > 1.0f))
|
||||
{
|
||||
@@ -138,8 +139,8 @@ namespace Game.Collision
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 q = new(s.cross(e1));
|
||||
float v = f * ray.Direction.dot(q);
|
||||
Vector3 q = Vector3.Cross(s, e1);
|
||||
float v = f * Vector3.Dot(ray.Direction, q);
|
||||
|
||||
if ((v < 0.0f) || ((u + v) > 1.0f))
|
||||
{
|
||||
@@ -147,7 +148,7 @@ namespace Game.Collision
|
||||
return false;
|
||||
}
|
||||
|
||||
float t = f * e2.dot(q);
|
||||
float t = f * Vector3.Dot(e2, q);
|
||||
|
||||
if ((t > 0.0f) && (t < distance))
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -64,7 +65,7 @@ namespace Game.Collision
|
||||
public bool GetObjectHitPos(Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist, PhaseShift phaseShift)
|
||||
{
|
||||
bool result;
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
float maxDist = (endPos - startPos).Length();
|
||||
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
|
||||
Cypher.Assert(maxDist < float.MaxValue);
|
||||
// prevent NaN values which can cause BIH intersection to enter infinite loop
|
||||
@@ -81,7 +82,7 @@ namespace Game.Collision
|
||||
resultHitPos = startPos + dir * dist;
|
||||
if (modifyDist < 0)
|
||||
{
|
||||
if ((resultHitPos - startPos).magnitude() > -modifyDist)
|
||||
if ((resultHitPos - startPos).Length() > -modifyDist)
|
||||
resultHitPos += dir * modifyDist;
|
||||
else
|
||||
resultHitPos = startPos;
|
||||
@@ -101,7 +102,7 @@ namespace Game.Collision
|
||||
|
||||
public bool IsInLineOfSight(Vector3 startPos, Vector3 endPos, PhaseShift phaseShift)
|
||||
{
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
float maxDist = (endPos - startPos).Length();
|
||||
|
||||
if (!MathFunctions.fuzzyGt(maxDist, 0))
|
||||
return true;
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Framework.Dynamic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Framework.Dynamic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -346,7 +347,7 @@ namespace Game.Collision
|
||||
public bool GetObjectHitPos(Vector3 pPos1, Vector3 pPos2, out Vector3 pResultHitPos, float pModifyDist)
|
||||
{
|
||||
bool result;
|
||||
float maxDist = (pPos2 - pPos1).magnitude();
|
||||
float maxDist = (pPos2 - pPos1).Length();
|
||||
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
|
||||
Cypher.Assert(maxDist < float.MaxValue);
|
||||
// prevent NaN values which can cause BIH intersection to enter infinite loop
|
||||
@@ -363,7 +364,7 @@ namespace Game.Collision
|
||||
pResultHitPos = pPos1 + dir * dist;
|
||||
if (pModifyDist < 0)
|
||||
{
|
||||
if ((pResultHitPos - pPos1).magnitude() > -pModifyDist)
|
||||
if ((pResultHitPos - pPos1).Length() > -pModifyDist)
|
||||
{
|
||||
pResultHitPos += dir * pModifyDist;
|
||||
}
|
||||
@@ -388,7 +389,7 @@ namespace Game.Collision
|
||||
|
||||
public bool IsInLineOfSight(Vector3 pos1, Vector3 pos2, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
float maxDist = (pos2 - pos1).magnitude();
|
||||
float maxDist = (pos2 - pos1).Length();
|
||||
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
|
||||
if (maxDist == float.MaxValue ||
|
||||
maxDist == float.PositiveInfinity)
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Framework.Constants;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -64,13 +65,13 @@ namespace Game.Collision
|
||||
iScale = modelOwner.GetScale();
|
||||
iInvScale = 1.0f / iScale;
|
||||
|
||||
Matrix3 iRotation = Matrix3.fromEulerAnglesZYX(modelOwner.GetOrientation(), 0, 0);
|
||||
iInvRot = iRotation.inverse();
|
||||
Matrix4x4 iRotation = Extensions.fromEulerAnglesZYX(modelOwner.GetOrientation(), 0, 0);
|
||||
Matrix4x4.Invert(iRotation, out iInvRot);
|
||||
// transform bounding box:
|
||||
mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale);
|
||||
AxisAlignedBox rotated_bounds = new();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
rotated_bounds.merge(iRotation * mdl_box.corner(i));
|
||||
rotated_bounds.merge(Vector3.Transform(mdl_box.corner(i), iRotation));
|
||||
|
||||
iBound = rotated_bounds + iPos;
|
||||
owner = modelOwner;
|
||||
@@ -100,8 +101,8 @@ namespace Game.Collision
|
||||
return false;
|
||||
|
||||
// child bounds are defined in object space:
|
||||
Vector3 p = iInvRot * (ray.Origin - iPos) * iInvScale;
|
||||
Ray modRay = new(p, iInvRot * ray.Direction);
|
||||
Vector3 p = Vector3.Transform((ray.Origin - iPos) * iInvScale, iInvRot);
|
||||
Ray modRay = new Ray(p, Vector3.Transform(ray.Direction, iInvRot));
|
||||
float distance = maxDist * iInvScale;
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, stopAtFirstHit, ignoreFlags);
|
||||
if (hit)
|
||||
@@ -124,13 +125,13 @@ namespace Game.Collision
|
||||
return;
|
||||
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
|
||||
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 pModel = Vector3.Transform((point - iPos) * iInvScale, iInvRot);
|
||||
Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
|
||||
float zDist;
|
||||
if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info))
|
||||
{
|
||||
Vector3 modelGround = pModel + zDist * zDirModel;
|
||||
float world_Z = ((modelGround * iInvRot) * iScale + iPos).Z;
|
||||
float world_Z = (Vector3.Transform(modelGround, iInvRot) * iScale + iPos).Z;
|
||||
if (info.ground_Z < world_Z)
|
||||
{
|
||||
info.ground_Z = world_Z;
|
||||
@@ -151,13 +152,13 @@ namespace Game.Collision
|
||||
return false;
|
||||
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
|
||||
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 pModel = Vector3.Transform((point - iPos) * iInvScale, iInvRot);
|
||||
Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
|
||||
float zDist;
|
||||
if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info))
|
||||
{
|
||||
Vector3 modelGround = pModel + zDist * zDirModel;
|
||||
float world_Z = ((modelGround * iInvRot) * iScale + iPos).Z;
|
||||
float world_Z = (Vector3.Transform(modelGround, iInvRot) * iScale + iPos).Z;
|
||||
if (info.ground_Z < world_Z)
|
||||
{
|
||||
info.ground_Z = world_Z;
|
||||
@@ -171,7 +172,7 @@ namespace Game.Collision
|
||||
public bool GetLiquidLevel(Vector3 point, LocationInfo info, ref float liqHeight)
|
||||
{
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
|
||||
Vector3 pModel = Vector3.Transform((point - iPos) * iInvScale, iInvRot);
|
||||
//Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
|
||||
float zDist;
|
||||
if (info.hitModel.GetLiquidLevel(pModel, out zDist))
|
||||
@@ -203,13 +204,13 @@ namespace Game.Collision
|
||||
|
||||
iPos = owner.GetPosition();
|
||||
|
||||
Matrix3 iRotation = Matrix3.fromEulerAnglesZYX(owner.GetOrientation(), 0, 0);
|
||||
iInvRot = iRotation.inverse();
|
||||
Matrix4x4 iRotation = Extensions.fromEulerAnglesZYX(owner.GetOrientation(), 0, 0);
|
||||
Matrix4x4.Invert(iRotation, out iInvRot);
|
||||
// transform bounding box:
|
||||
mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale);
|
||||
AxisAlignedBox rotated_bounds = new();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
rotated_bounds.merge(iRotation * mdl_box.corner(i));
|
||||
rotated_bounds.merge(Vector3.Transform(mdl_box.corner(i), iRotation));
|
||||
|
||||
iBound = rotated_bounds + iPos;
|
||||
|
||||
@@ -269,7 +270,7 @@ namespace Game.Collision
|
||||
|
||||
bool _collisionEnabled;
|
||||
AxisAlignedBox iBound;
|
||||
Matrix3 iInvRot;
|
||||
Matrix4x4 iInvRot;
|
||||
Vector3 iPos;
|
||||
float iInvScale;
|
||||
float iScale;
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.GameMath;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -85,7 +86,7 @@ namespace Game.Collision
|
||||
|
||||
public class ModelInstance : ModelMinimalData
|
||||
{
|
||||
Matrix3 iInvRot;
|
||||
Matrix4x4 iInvRot;
|
||||
float iInvScale;
|
||||
WorldModel iModel;
|
||||
|
||||
@@ -107,7 +108,8 @@ namespace Game.Collision
|
||||
|
||||
iModel = model;
|
||||
|
||||
iInvRot = Matrix3.fromEulerAnglesZYX(MathFunctions.PI * spawn.iRot.Y / 180.0f, MathFunctions.PI * spawn.iRot.X / 180.0f, MathFunctions.PI * spawn.iRot.Z / 180.0f).inverse();
|
||||
Matrix4x4.Invert(Extensions.fromEulerAnglesZYX(MathFunctions.PI * spawn.iRot.Y / 180.0f, MathFunctions.PI * spawn.iRot.X / 180.0f, MathFunctions.PI * spawn.iRot.Z / 180.0f), out iInvRot);
|
||||
|
||||
iInvScale = 1.0f / iScale;
|
||||
}
|
||||
|
||||
@@ -121,8 +123,8 @@ namespace Game.Collision
|
||||
return false;
|
||||
|
||||
// child bounds are defined in object space:
|
||||
Vector3 p = iInvRot * (pRay.Origin - iPos) * iInvScale;
|
||||
Ray modRay = new(p, iInvRot * pRay.Direction);
|
||||
Vector3 p = Vector3.Transform((pRay.Origin - iPos) * iInvScale, iInvRot);
|
||||
Ray modRay = new Ray(p, Vector3.Transform(pRay.Direction, iInvRot));
|
||||
float distance = pMaxDist * iInvScale;
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, pStopAtFirstHit, ignoreFlags);
|
||||
if (hit)
|
||||
@@ -144,8 +146,8 @@ namespace Game.Collision
|
||||
if (!iBound.contains(p))
|
||||
return;
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
|
||||
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 pModel = Vector3.Transform((p - iPos) * iInvScale, iInvRot);
|
||||
Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
|
||||
float zDist;
|
||||
if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info))
|
||||
{
|
||||
@@ -153,7 +155,7 @@ namespace Game.Collision
|
||||
// Transform back to world space. Note that:
|
||||
// Mat * vec == vec * Mat.transpose()
|
||||
// and for rotation matrices: Mat.inverse() == Mat.transpose()
|
||||
float world_Z = ((modelGround * iInvRot) * iScale + iPos).Z;
|
||||
float world_Z = ((Vector3.Transform(modelGround, iInvRot)) * iScale + iPos).Z;
|
||||
if (info.ground_Z < world_Z)
|
||||
{
|
||||
info.ground_Z = world_Z;
|
||||
@@ -165,7 +167,7 @@ namespace Game.Collision
|
||||
public bool GetLiquidLevel(Vector3 p, LocationInfo info, ref float liqHeight)
|
||||
{
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
|
||||
Vector3 pModel = Vector3.Transform((p - iPos) * iInvScale, iInvRot);
|
||||
//Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
|
||||
float zDist;
|
||||
if (info.hitModel.GetLiquidLevel(pModel, out zDist))
|
||||
@@ -189,8 +191,8 @@ namespace Game.Collision
|
||||
if (!iBound.contains(p))
|
||||
return false;
|
||||
// child bounds are defined in object space:
|
||||
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
|
||||
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 pModel = Vector3.Transform((p - iPos) * iInvScale, iInvRot);
|
||||
Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
|
||||
float zDist;
|
||||
if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info))
|
||||
{
|
||||
@@ -198,7 +200,7 @@ namespace Game.Collision
|
||||
// Transform back to world space. Note that:
|
||||
// Mat * vec == vec * Mat.transpose()
|
||||
// and for rotation matrices: Mat.inverse() == Mat.transpose()
|
||||
float world_Z = ((modelGround * iInvRot) * iScale + iPos).Z;
|
||||
float world_Z = (Vector3.Transform(modelGround, iInvRot) * iScale + iPos).Z;
|
||||
if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
|
||||
{
|
||||
info.ground_Z = world_Z;
|
||||
|
||||
@@ -20,6 +20,7 @@ using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Framework.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -19,15 +19,15 @@ using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Game.Networking;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using Framework.Dynamic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
using Framework.GameMath;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using Framework.GameMath;
|
||||
|
||||
using Framework.Constants;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.Maps;
|
||||
using Game.Movement;
|
||||
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Game.Entities
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Combat;
|
||||
using Game.DataStorage;
|
||||
using Game.Groups;
|
||||
using Game.Loots;
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Framework.Dynamic;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Maps;
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Conditions;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Misc
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using Framework.Constants;
|
||||
using Game.Spells;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.BattleGrounds;
|
||||
using Game.Collision;
|
||||
@@ -25,12 +24,13 @@ using Game.DataStorage;
|
||||
using Game.Groups;
|
||||
using Game.Loots;
|
||||
using Game.Maps;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Game.Networking;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -246,7 +246,7 @@ namespace Game.Entities
|
||||
GameObjectAddon gameObjectAddon = Global.ObjectMgr.GetGameObjectAddon(GetSpawnId());
|
||||
|
||||
// For most of gameobjects is (0, 0, 0, 1) quaternion, there are only some transports with not standard rotation
|
||||
Quaternion parentRotation = Quaternion.WAxis;
|
||||
Quaternion parentRotation = Quaternion.Identity;
|
||||
if (gameObjectAddon != null)
|
||||
parentRotation = gameObjectAddon.ParentRotation;
|
||||
|
||||
@@ -2191,8 +2191,9 @@ namespace Game.Entities
|
||||
|
||||
public void SetWorldRotation(float qx, float qy, float qz, float qw)
|
||||
{
|
||||
Quaternion rotation = new(qx, qy, qz, qw);
|
||||
rotation.unitize();
|
||||
Quaternion rotation = new Quaternion(qx, qy, qz, qw);
|
||||
rotation = Quaternion.Multiply(rotation, 1.0f / MathF.Sqrt(Quaternion.Dot(rotation, rotation)));
|
||||
|
||||
m_worldRotation.X = rotation.X;
|
||||
m_worldRotation.Y = rotation.Y;
|
||||
m_worldRotation.Z = rotation.Z;
|
||||
@@ -2207,7 +2208,7 @@ namespace Game.Entities
|
||||
|
||||
public void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot)
|
||||
{
|
||||
Quaternion quat = Quaternion.fromEulerAnglesZYX(z_rot, y_rot, x_rot);
|
||||
Quaternion quat = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(z_rot, y_rot, x_rot));
|
||||
SetWorldRotation(quat.X, quat.Y, quat.Z, quat.W);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Maps;
|
||||
using Game.Networking.Packets;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -15,13 +15,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Game.Networking;
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.Networking.Packets;
|
||||
using Game.DataStorage;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Game.Networking;
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.GameMath;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.BattleFields;
|
||||
using Game.DataStorage;
|
||||
@@ -28,6 +27,7 @@ using Game.Scenarios;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.Arenas;
|
||||
using Game.BattleGrounds;
|
||||
using Game.DataStorage;
|
||||
using Game.Groups;
|
||||
@@ -32,7 +31,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Game.BattleFields;
|
||||
using Framework.Dynamic;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.BattlePets;
|
||||
using Game.DataStorage;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
using Framework.Algorithms;
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -132,7 +132,7 @@ namespace Game.Entities
|
||||
SetGoAnimProgress(animprogress);
|
||||
SetName(goinfo.name);
|
||||
SetWorldRotation(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
SetParentRotation(Quaternion.WAxis);
|
||||
SetParentRotation(Quaternion.Identity);
|
||||
|
||||
CreateModel();
|
||||
return true;
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Networking;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Combat;
|
||||
using Game.DataStorage;
|
||||
using Game.Maps;
|
||||
using Game.Movement;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.BattleGrounds;
|
||||
using Game.DataStorage;
|
||||
using Game.Maps;
|
||||
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.AI;
|
||||
using Game.Movement;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.BattleGrounds;
|
||||
using Game.Chat;
|
||||
@@ -32,6 +30,7 @@ using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Garrisons
|
||||
{
|
||||
@@ -735,7 +735,7 @@ namespace Game.Garrisons
|
||||
if (finalizeInfo != null)
|
||||
{
|
||||
Position pos2 = finalizeInfo.factionInfo[faction].Pos;
|
||||
GameObject finalizer = GameObject.CreateGameObject(finalizeInfo.factionInfo[faction].GameObjectId, map, pos2, Quaternion.fromEulerAnglesZYX(pos2.GetOrientation(), 0.0f, 0.0f), 255, GameObjectState.Ready);
|
||||
GameObject finalizer = GameObject.CreateGameObject(finalizeInfo.factionInfo[faction].GameObjectId, map, pos2, Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(pos2.GetOrientation(), 0.0f, 0.0f)), 255, GameObjectState.Ready);
|
||||
if (finalizer)
|
||||
{
|
||||
// set some spell id to make the object delete itself after use
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Framework.IO;
|
||||
using Game.Conditions;
|
||||
using Game.DataStorage;
|
||||
@@ -32,6 +31,7 @@ using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Game
|
||||
@@ -4257,10 +4257,10 @@ namespace Game
|
||||
gameObjectAddon.invisibilityValue = 1;
|
||||
}
|
||||
|
||||
if (!gameObjectAddon.ParentRotation.isUnit())
|
||||
if (!(Math.Abs(Quaternion.Dot(gameObjectAddon.ParentRotation, gameObjectAddon.ParentRotation) - 1) < 1e-5))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"GameObject (GUID: {guid}) has invalid parent rotation in `gameobject_addon`, set to default");
|
||||
gameObjectAddon.ParentRotation = Quaternion.WAxis;
|
||||
gameObjectAddon.ParentRotation = Quaternion.Identity;
|
||||
}
|
||||
|
||||
if (gameObjectAddon.WorldEffectID != 0 && !CliDB.WorldEffectStorage.ContainsKey(gameObjectAddon.WorldEffectID))
|
||||
|
||||
@@ -16,20 +16,10 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.IO;
|
||||
using Game.BattleGrounds;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Groups;
|
||||
using Game.Guilds;
|
||||
using Game.Maps;
|
||||
using Game.Misc;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.PvP;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
|
||||
@@ -16,20 +16,9 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.IO;
|
||||
using Game.BattleGrounds;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Groups;
|
||||
using Game.Guilds;
|
||||
using Game.Maps;
|
||||
using Game.Misc;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.PvP;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game
|
||||
|
||||
@@ -20,7 +20,6 @@ using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
|
||||
@@ -19,7 +19,6 @@ using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ using Game.Guilds;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.Entities;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public partial class WorldSession
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Game.Conditions;
|
||||
using Game.Entities;
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Collision;
|
||||
using Game.DataStorage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Game.Collision;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Maps
|
||||
{
|
||||
@@ -175,7 +176,7 @@ namespace Game.Maps
|
||||
|
||||
_minHeightPlanes = new Plane[8];
|
||||
for (uint quarterIndex = 0; quarterIndex < 8; ++quarterIndex)
|
||||
_minHeightPlanes[quarterIndex] = new Plane(
|
||||
_minHeightPlanes[quarterIndex] = Plane.CreateFromVertices(
|
||||
new Vector3(boundGridCoords[indices[quarterIndex][0]][0], boundGridCoords[indices[quarterIndex][0]][1], minHeights[indices[quarterIndex][0]]),
|
||||
new Vector3(boundGridCoords[indices[quarterIndex][1]][0], boundGridCoords[indices[quarterIndex][1]][1], minHeights[indices[quarterIndex][1]]),
|
||||
new Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]])
|
||||
@@ -500,8 +501,7 @@ namespace Game.Maps
|
||||
else
|
||||
quarterIndex = gx > gy ? 1u : 0;
|
||||
|
||||
|
||||
Ray ray = new(new Vector3(gx, gy, 0.0f), Vector3.ZAxis);
|
||||
Ray ray = new(new Vector3(gx, gy, 0.0f), Vector3.UnitZ);
|
||||
return ray.intersection(_minHeightPlanes[quarterIndex]).Z;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.BattleGrounds;
|
||||
using Game.Collision;
|
||||
using Game.DataStorage;
|
||||
@@ -32,6 +31,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Maps
|
||||
{
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Movement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Maps
|
||||
{
|
||||
@@ -186,9 +186,9 @@ namespace Game.Maps
|
||||
allPoints.Add(new Vector3(path[i].Loc.X, path[i].Loc.Y, path[i].Loc.Z));
|
||||
|
||||
// Add extra points to allow derivative calculations for all path nodes
|
||||
allPoints.Insert(0, allPoints.First().lerp(allPoints[1], -0.2f));
|
||||
allPoints.Add(allPoints.Last().lerp(allPoints[^2], -0.2f));
|
||||
allPoints.Add(allPoints.Last().lerp(allPoints[^2], -1.0f));
|
||||
allPoints.Insert(0, Vector3.Lerp(allPoints.First(), allPoints[1], -0.2f));
|
||||
allPoints.Add(Vector3.Lerp(allPoints.Last(), allPoints[^2], -0.2f));
|
||||
allPoints.Add(Vector3.Lerp(allPoints.Last(), allPoints[^2], -1.0f));
|
||||
|
||||
SplineRawInitializer initer = new(allPoints);
|
||||
Spline orientationSpline = new();
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Game.Entities;
|
||||
|
||||
namespace Game.Movement
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
@@ -481,7 +481,7 @@ namespace Game.Movement
|
||||
Vector3 endVec = new(endPoint[0], endPoint[1], endPoint[2]);
|
||||
Vector3 diffVec = (endVec - startVec);
|
||||
Vector3 prevVec = startVec;
|
||||
float len = diffVec.GetLength();
|
||||
float len = diffVec.Length();
|
||||
diffVec *= 4.0f / len;
|
||||
while (len > 4.0f)
|
||||
{
|
||||
@@ -861,7 +861,7 @@ namespace Game.Movement
|
||||
|
||||
float Dist3DSqr(Vector3 p1, Vector3 p2)
|
||||
{
|
||||
return (p1 - p2).GetLengthSquared();
|
||||
return (p1 - p2).LengthSquared();
|
||||
}
|
||||
|
||||
public void ShortenPathUntilDist(Position pos, float dist) { ShortenPathUntilDist(new Vector3(pos.posX, pos.posY, pos.posZ), dist); }
|
||||
@@ -878,11 +878,11 @@ namespace Game.Movement
|
||||
|
||||
// the first point of the path must be outside the specified range
|
||||
// (this should have really been checked by the caller...)
|
||||
if ((_pathPoints[0] - target).GetLengthSquared() < distSq)
|
||||
if ((_pathPoints[0] - target).LengthSquared() < distSq)
|
||||
return;
|
||||
|
||||
// check if we even need to do anything
|
||||
if ((_pathPoints[0] - target).GetLengthSquared() >= distSq)
|
||||
if ((_pathPoints[0] - target).LengthSquared() >= distSq)
|
||||
return;
|
||||
|
||||
int i = _pathPoints.Length - 1;
|
||||
@@ -893,7 +893,7 @@ namespace Game.Movement
|
||||
while (true)
|
||||
{
|
||||
// we know that pathPoints[i] is too close already (from the previous iteration)
|
||||
if ((_pathPoints[i - 1] - target).GetLengthSquared() >= distSq)
|
||||
if ((_pathPoints[i - 1] - target).LengthSquared() >= distSq)
|
||||
break; // bingo!
|
||||
|
||||
if (--i == 0)
|
||||
@@ -908,7 +908,7 @@ namespace Game.Movement
|
||||
// ok, _pathPoints[i] is too close, _pathPoints[i-1] is not, so our target point is somewhere between the two...
|
||||
// ... settle for a guesstimate since i'm not confident in doing trig on every chase motion tick...
|
||||
// (@todo review this)
|
||||
_pathPoints[i] += (_pathPoints[i - 1] - _pathPoints[i]).directionOrZero() * (dist - (_pathPoints[i] - target).GetLength());
|
||||
_pathPoints[i] += (_pathPoints[i - 1] - _pathPoints[i]).directionOrZero() * (dist - (_pathPoints[i] - target).Length());
|
||||
Array.Resize(ref _pathPoints, i + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System;
|
||||
|
||||
namespace Game.Movement
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.AI;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
@@ -52,7 +52,7 @@ namespace Game.Movement
|
||||
effect_start_time = 0;
|
||||
spell_effect_extra = args.spellEffectExtra;
|
||||
anim_tier = args.animTier;
|
||||
splineIsFacingOnly = args.path.Length == 2 && args.facing.type != MonsterMoveType.Normal && ((args.path[1] - args.path[0]).GetLength() < 0.1f);
|
||||
splineIsFacingOnly = args.path.Length == 2 && args.facing.type != MonsterMoveType.Normal && ((args.path[1] - args.path[0]).Length() < 0.1f);
|
||||
|
||||
// Check if its a stop spline
|
||||
if (args.flags.HasFlag(SplineFlag.Done))
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Movement
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user