More cleanups of custom classes in favor of .NET runtime types.

This commit is contained in:
hondacrx
2021-11-15 18:04:57 -05:00
parent a9a51d0641
commit b026ee7ef8
132 changed files with 373 additions and 6833 deletions
+5 -5
View File
@@ -16,8 +16,8 @@
*/ */
using System; using System;
using System.Numerics;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security.Permissions;
namespace Framework.GameMath namespace Framework.GameMath
{ {
@@ -233,14 +233,14 @@ namespace Framework.GameMath
public void merge(AxisAlignedBox a) public void merge(AxisAlignedBox a)
{ {
Lo = Lo.Min(a.Lo); Lo = Vector3.Min(_lo, a.Lo);
Hi = Hi.Max(a.Hi); Hi = Vector3.Max(Hi, a.Hi);
} }
public void merge(Vector3 a) public void merge(Vector3 a)
{ {
_lo = _lo.Min(a); _lo = Vector3.Min(_lo, a);
_hi = _hi.Max(a); _hi = Vector3.Max(_hi, a);
} }
public static AxisAlignedBox Zero() public static AxisAlignedBox Zero()
+17 -16
View File
@@ -16,6 +16,7 @@
*/ */
using System; using System;
using System.Numerics;
namespace Framework.GameMath namespace Framework.GameMath
{ {
@@ -26,7 +27,7 @@ namespace Framework.GameMath
Vector3 normal = Vector3.Zero; Vector3 normal = Vector3.Zero;
if (collisionLocationForMovingPointFixedAABox(origin, dir, box, ref location, out Inside, ref normal)) if (collisionLocationForMovingPointFixedAABox(origin, dir, box, ref location, out Inside, ref normal))
{ {
return (location - origin).magnitude(); return Vector3.Distance(location, origin);
} }
else else
{ {
@@ -43,26 +44,26 @@ namespace Framework.GameMath
// Find candidate planes. // Find candidate planes.
for (int i = 0; i < 3; ++i) 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; Inside = false;
// Calculate T distances to candidate planes // 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; Inside = false;
// Calculate T distances to candidate planes // 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 // Get largest of the maxT's for final choice of intersection
int WhichPlane = 0; int WhichPlane = 0;
if (MaxT[1] > MaxT[WhichPlane]) if (MaxT.Y > MaxT.GetAt(WhichPlane))
{ {
WhichPlane = 1; WhichPlane = 1;
} }
if (MaxT[2] > MaxT[WhichPlane]) if (MaxT.Z > MaxT.GetAt(WhichPlane))
{ {
WhichPlane = 2; WhichPlane = 2;
} }
// Check final candidate actually inside box // Check final candidate actually inside box
if (Convert.ToBoolean((uint)MaxT[WhichPlane] & 0x80000000)) if (Convert.ToBoolean((uint)MaxT.GetAt(WhichPlane) & 0x80000000))
{ {
// Miss the box // Miss the box
return false; return false;
@@ -97,9 +98,9 @@ namespace Framework.GameMath
{ {
if (i != WhichPlane) if (i != WhichPlane)
{ {
location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; location.SetAt(origin.GetAt(i) + MaxT.GetAt(WhichPlane) * dir.GetAt(i), i);
if ((location[i] < MinB[i]) || if ((location.GetAt(i) < MinB.GetAt(i)) ||
(location[i] > MaxB[i])) (location.GetAt(i) > MaxB.GetAt(i)))
{ {
// On this plane we're outside the box extents, so // On this plane we're outside the box extents, so
// we miss the box // we miss the box
@@ -110,7 +111,7 @@ namespace Framework.GameMath
// Choose the normal to be the plane normal facing into the ray // Choose the normal to be the plane normal facing into the ray
normal = Vector3.Zero; 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; return true;
} }
-614
View File
@@ -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
}
}
-807
View File
@@ -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
}
}
-900
View File
@@ -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
}
}
-260
View File
@@ -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
}
}
-825
View File
@@ -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
}
}
+8 -9
View File
@@ -18,6 +18,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Numerics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace Framework.GameMath namespace Framework.GameMath
@@ -33,6 +34,8 @@ namespace Framework.GameMath
public struct Ray : ICloneable public struct Ray : ICloneable
{ {
#region Private Fields #region Private Fields
private static Vector3 _inf = new(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
private Vector3 _origin; private Vector3 _origin;
private Vector3 _direction; private Vector3 _direction;
#endregion #endregion
@@ -110,8 +113,8 @@ namespace Framework.GameMath
if (m.Success) if (m.Success)
{ {
return new Ray( return new Ray(
Vector3.Parse(m.Result("${origin}")), m.Result("${origin}").ParseVector3(),
Vector3.Parse(m.Result("${direction}")) m.Result("${direction}").ParseVector3()
); );
} }
else else
@@ -194,18 +197,14 @@ namespace Framework.GameMath
public Vector3 intersection(Plane plane) public Vector3 intersection(Plane plane)
{ {
float d; float rate = Vector3.Dot(Direction, plane.Normal);
Vector3 normal = plane.Normal;
plane.getEquation(ref normal, out d);
float rate = Direction.dot(normal);
if (rate >= 0.0f) if (rate >= 0.0f)
{ {
return Vector3.Inf; return _inf;
} }
else else
{ {
float t = -(d + Origin.dot(normal)) / rate; float t = -(-plane.D + Vector3.Dot(Origin, plane.Normal)) / rate;
return Origin + Direction * t; return Origin + Direction * t;
} }
} }
-947
View File
@@ -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
+1 -1
View File
@@ -15,9 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.GameMath;
using System; using System;
using System.IO; using System.IO;
using System.Numerics;
using System.Text; using System.Text;
namespace Framework.IO namespace Framework.IO
-2
View File
@@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Framework.IO namespace Framework.IO
{ {
+114
View File
@@ -182,6 +182,102 @@ namespace System
return list; 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 #region Strings
public static bool IsEmpty(this string str) public static bool IsEmpty(this string str)
{ {
@@ -255,6 +351,24 @@ namespace System
return true; return true;
return false; 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 #endregion
#region BinaryReader #region BinaryReader
-2
View File
@@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Framework.Web.API namespace Framework.Web.API
{ {
-1
View File
@@ -18,7 +18,6 @@
using Framework.Constants; using Framework.Constants;
using Game.Entities; using Game.Entities;
using Game.Spells; using Game.Spells;
using System.Collections.Generic;
namespace Game.AI namespace Game.AI
{ {
+13 -13
View File
@@ -16,7 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Chat; using Game.Chat;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
@@ -27,6 +26,7 @@ using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.AI namespace Game.AI
{ {
@@ -1195,20 +1195,20 @@ namespace Game.AI
if (!summoner) if (!summoner)
break; break;
foreach (var target in targets) foreach (var target in targets)
{ {
Position pos = target.GetPositionWithOffset(new Position(e.Target.x, e.Target.y, e.Target.z, e.Target.o)); 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); summoner.SummonGameObject(e.Action.summonGO.entry, pos, rot, e.Action.summonGO.despawnTime, (GameObjectSummonType)e.Action.summonGO.summonType);
} }
if (e.GetTargetType() != SmartTargets.Position) if (e.GetTargetType() != SmartTargets.Position)
break;
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; break;
}
Quaternion _rot = Quaternion.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;
}
case SmartActions.KillUnit: case SmartActions.KillUnit:
{ {
foreach (var target in targets) foreach (var target in targets)
@@ -18,7 +18,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Game.Arenas; using Game.Arenas;
using Game.BattleFields;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
@@ -24,9 +24,7 @@ using Game.Mails;
using Game.Networking.Packets; using Game.Networking.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using Framework.Networking;
using Framework.IO; using Framework.IO;
using System.Collections; using System.Collections;
+1 -2
View File
@@ -16,8 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Groups; using Game.Groups;
using Game.Maps; using Game.Maps;
@@ -25,6 +23,7 @@ using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.BattleFields namespace Game.BattleFields
{ {
@@ -16,8 +16,8 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Entities; using Game.Entities;
using System.Numerics;
namespace Game.BattleFields namespace Game.BattleFields
{ {
+2 -2
View File
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Game.Chat; using Game.Chat;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
@@ -30,6 +29,7 @@ using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.BattleGrounds 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, " + 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"); "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 // 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 Framework.Constants;
using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Networking.Packets; using Game.Networking.Packets;
using System; using System;
@@ -20,7 +20,6 @@ using Framework.Constants;
using System.Collections.Generic; using System.Collections.Generic;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.DataStorage; using Game.DataStorage;
using Game.BattleGrounds;
namespace Game.BattleGrounds.Zones namespace Game.BattleGrounds.Zones
{ {
@@ -16,11 +16,10 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Networking.Packets; using Game.Networking.Packets;
using System.Collections.Generic; using System.Collections.Generic;
using Framework.GameMath; using System.Numerics;
namespace Game.BattleGrounds.Zones namespace Game.BattleGrounds.Zones
{ {
@@ -16,10 +16,8 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Networking.Packets; using Game.Networking.Packets;
using System.Collections.Generic;
namespace Game.BattleGrounds.Zones namespace Game.BattleGrounds.Zones
{ {
@@ -19,7 +19,6 @@ using Framework.Constants;
using Game.Cache; using Game.Cache;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
namespace Game.Chat namespace Game.Chat
@@ -19,7 +19,6 @@ using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.IO; using Framework.IO;
using System; using System;
using System.Linq;
namespace Game.Chat.Commands namespace Game.Chat.Commands
{ {
@@ -17,13 +17,13 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Framework.IO; using Framework.IO;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
using System.Text; using System.Text;
namespace Game.Chat namespace Game.Chat
@@ -614,7 +614,7 @@ namespace Game.Chat
Player player = handler.GetPlayer(); Player player = handler.GetPlayer();
Map map = player.GetMap(); 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) if (!obj)
return false; return false;
@@ -658,7 +658,7 @@ namespace Game.Chat
if (spawntime != 0) if (spawntime != 0)
spawntm = spawntime; 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) if (Global.ObjectMgr.GetGameObjectTemplate(id) == null)
{ {
-4
View File
@@ -19,12 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Game.DataStorage; using Game.DataStorage;
using Framework.Constants; using Framework.Constants;
using Game.Spells;
using Framework.Dynamic;
using Framework.Collections; using Framework.Collections;
namespace Game.Chat namespace Game.Chat
@@ -19,6 +19,7 @@ using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Game.Collision namespace Game.Collision
@@ -76,12 +77,12 @@ namespace Game.Collision
Vector3 d = gridBox.hi - gridBox.lo; Vector3 d = gridBox.hi - gridBox.lo;
for (int i = 0; i < 3; i++) 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); Log.outError(LogFilter.Server, "Reached tree area in error - discarding node with: {0} objects", right - left + 1);
} }
// find longest axis // find longest axis
axis = (int)d.primaryAxis(); 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 // partition L/R subsets
clipL = float.NegativeInfinity; clipL = float.NegativeInfinity;
clipR = float.PositiveInfinity; clipR = float.PositiveInfinity;
@@ -91,8 +92,8 @@ namespace Game.Collision
for (int i = left; i <= right; ) for (int i = left; i <= right; )
{ {
int obj = (int)dat.indices[i]; int obj = (int)dat.indices[i];
float minb = dat.primBound[obj].Lo[axis]; float minb = dat.primBound[obj].Lo.GetAt(axis);
float maxb = dat.primBound[obj].Hi[axis]; float maxb = dat.primBound[obj].Hi.GetAt(axis);
float center = (minb + maxb) * 0.5f; float center = (minb + maxb) * 0.5f;
if (center <= split) if (center <= split)
{ {
@@ -115,9 +116,9 @@ namespace Game.Collision
nodeR = Math.Max(nodeR, maxb); nodeR = Math.Max(nodeR, maxb);
} }
// check for empty space // 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; float nodeNewW = nodeR - nodeL;
// node box is too big compare to space occupied by primitives? // node box is too big compare to space occupied by primitives?
if (1.3f * nodeNewW < nodeBoxW) if (1.3f * nodeNewW < nodeBoxW)
@@ -134,8 +135,8 @@ namespace Game.Collision
tempTree[nodeIndex + 1] = FloatToRawIntBits(nodeL); tempTree[nodeIndex + 1] = FloatToRawIntBits(nodeL);
tempTree[nodeIndex + 2] = FloatToRawIntBits(nodeR); tempTree[nodeIndex + 2] = FloatToRawIntBits(nodeR);
// update nodebox and recurse // update nodebox and recurse
nodeBox.lo[axis] = nodeL; nodeBox.lo.SetAt(nodeL, axis);
nodeBox.hi[axis] = nodeR; nodeBox.hi.SetAt(nodeR, axis);
Subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex1, depth + 1, stats); Subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex1, depth + 1, stats);
return; return;
} }
@@ -154,12 +155,12 @@ namespace Game.Collision
if (clipL <= split) if (clipL <= split)
{ {
// keep looping on left half // keep looping on left half
gridBox.hi[axis] = split; gridBox.hi.SetAt(split, axis);
prevClip = clipL; prevClip = clipL;
wasLeft = true; wasLeft = true;
continue; continue;
} }
gridBox.hi[axis] = split; gridBox.hi.SetAt(split, axis);
prevClip = float.NaN; prevClip = float.NaN;
} }
else if (left > right) else if (left > right)
@@ -177,12 +178,12 @@ namespace Game.Collision
if (clipR >= split) if (clipR >= split)
{ {
// keep looping on right half // keep looping on right half
gridBox.lo[axis] = split; gridBox.lo.SetAt(split, axis);
prevClip = clipR; prevClip = clipR;
wasLeft = false; wasLeft = false;
continue; continue;
} }
gridBox.lo[axis] = split; gridBox.lo.SetAt(split, axis);
prevClip = float.NaN; prevClip = float.NaN;
} }
else else
@@ -254,9 +255,12 @@ namespace Game.Collision
AABound gridBoxR = gridBox; AABound gridBoxR = gridBox;
AABound nodeBoxL = nodeBox; AABound nodeBoxL = nodeBox;
AABound nodeBoxR = nodeBox; AABound nodeBoxR = nodeBox;
gridBoxL.hi[axis] = gridBoxR.lo[axis] = split;
nodeBoxL.hi[axis] = clipL; gridBoxR.lo.SetAt(split, axis);
nodeBoxR.lo[axis] = clipR; gridBoxL.hi.SetAt(split, axis);
nodeBoxL.hi.SetAt(clipL, axis);
nodeBoxR.lo.SetAt(clipR, axis);
// recurse // recurse
if (nl > 0) if (nl > 0)
Subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); Subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
@@ -325,11 +329,11 @@ namespace Game.Collision
Vector3 invDir = new(); Vector3 invDir = new();
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
invDir[i] = 1.0f / dir[i]; invDir.SetAt(1.0f / dir.GetAt(i), i);
if (MathFunctions.fuzzyNe(dir[i], 0.0f)) if (MathFunctions.fuzzyNe(dir.GetAt(i), 0.0f))
{ {
float t1 = (bounds.Lo[i] - org[i]) * invDir[i]; float t1 = (bounds.Lo.GetAt(i) - org.GetAt(i)) * invDir.GetAt(i);
float t2 = (bounds.Hi[i] - org[i]) * invDir[i]; float t2 = (bounds.Hi.GetAt(i) - org.GetAt(i)) * invDir.GetAt(i);
if (t1 > t2) if (t1 > t2)
MathFunctions.Swap<float>(ref t1, ref t2); MathFunctions.Swap<float>(ref t1, ref t2);
if (t1 > intervalMin) if (t1 > intervalMin)
@@ -356,7 +360,7 @@ namespace Game.Collision
for (int i = 0; i < 3; ++i) 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; offsetBack[i] = offsetFront[i] ^ 1;
offsetFront3[i] = offsetFront[i] * 3; offsetFront3[i] = offsetFront[i] * 3;
offsetBack3[i] = offsetBack[i] * 3; offsetBack3[i] = offsetBack[i] * 3;
@@ -383,8 +387,8 @@ namespace Game.Collision
if (axis < 3) if (axis < 3)
{ {
// "normal" interior node // "normal" interior node
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[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[axis]) * invDir[axis]; float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
// ray passes between clip zones // ray passes between clip zones
if (tf < intervalMin && tb > intervalMax) if (tf < intervalMin && tb > intervalMax)
break; break;
@@ -432,8 +436,8 @@ namespace Game.Collision
{ {
if (axis > 2) if (axis > 2)
return; // should not happen return; // should not happen
float tf = (IntBitsToFloat(tree[(int)(node + offsetFront[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[axis]) * invDir[axis]; float tb = (IntBitsToFloat(tree[(int)(node + offsetBack[axis])]) - org.GetAt(axis)) * invDir.GetAt(axis);
node = offset; node = offset;
intervalMin = (tf >= intervalMin) ? tf : intervalMin; intervalMin = (tf >= intervalMin) ? tf : intervalMin;
intervalMax = (tb <= intervalMax) ? tb : intervalMax; intervalMax = (tb <= intervalMax) ? tb : intervalMax;
@@ -484,18 +488,18 @@ namespace Game.Collision
float tl = IntBitsToFloat(tree[node + 1]); float tl = IntBitsToFloat(tree[node + 1]);
float tr = IntBitsToFloat(tree[node + 2]); float tr = IntBitsToFloat(tree[node + 2]);
// point is between clip zones // point is between clip zones
if (tl < p[(int)axis] && tr > p[axis]) if (tl < p.GetAt(axis) && tr > p.GetAt(axis))
break; break;
int right = offset + 3; int right = offset + 3;
node = right; node = right;
// point is in right node only // point is in right node only
if (tl < p[(int)axis]) if (tl < p.GetAt(axis))
{ {
continue; continue;
} }
node = offset; // left node = offset; // left
// point is in left node only // point is in left node only
if (tr > p[axis]) if (tr > p.GetAt(axis))
{ {
continue; continue;
} }
@@ -525,7 +529,7 @@ namespace Game.Collision
float tl = IntBitsToFloat(tree[node + 1]); float tl = IntBitsToFloat(tree[node + 1]);
float tr = IntBitsToFloat(tree[node + 2]); float tr = IntBitsToFloat(tree[node + 2]);
node = offset; node = offset;
if (tl > p[axis] || tr < p[axis]) if (tl > p.GetAt(axis) || tr < p.GetAt(axis))
break; break;
continue; continue;
} }
@@ -17,6 +17,7 @@
using Framework.GameMath; using Framework.GameMath;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
+10 -9
View File
@@ -19,6 +19,7 @@ using Framework.Constants;
using Framework.GameMath; using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -43,8 +44,8 @@ namespace Game.Collision
Vector3 lo = vertices[(int)tri.idx0]; Vector3 lo = vertices[(int)tri.idx0];
Vector3 hi = lo; Vector3 hi = lo;
lo = (lo.Min(vertices[(int)tri.idx1])).Min(vertices[(int)tri.idx2]); lo = Vector3.Min(Vector3.Min(lo, vertices[(int)tri.idx1]), vertices[(int)tri.idx2]);
hi = (hi.Max(vertices[(int)tri.idx1])).Max(vertices[(int)tri.idx2]); hi = Vector3.Max(Vector3.Max(hi, vertices[(int)tri.idx1]), vertices[(int)tri.idx2]);
value = new AxisAlignedBox(lo, hi); value = new AxisAlignedBox(lo, hi);
} }
@@ -119,8 +120,8 @@ namespace Game.Collision
Vector3 e1 = points[(int)tri.idx1] - points[(int)tri.idx0]; Vector3 e1 = points[(int)tri.idx1] - points[(int)tri.idx0];
Vector3 e2 = points[(int)tri.idx2] - points[(int)tri.idx0]; Vector3 e2 = points[(int)tri.idx2] - points[(int)tri.idx0];
Vector3 p = new(ray.Direction.cross(e2)); Vector3 p = Vector3.Cross(ray.Direction, e2);
float a = e1.dot(p); float a = Vector3.Dot(e1, p);
if (Math.Abs(a) < EPS) if (Math.Abs(a) < EPS)
{ {
@@ -129,8 +130,8 @@ namespace Game.Collision
} }
float f = 1.0f / a; float f = 1.0f / a;
Vector3 s = new(ray.Origin - points[(int)tri.idx0]); Vector3 s = ray.Origin - points[(int)tri.idx0];
float u = f * s.dot(p); float u = f * Vector3.Dot(s, p);
if ((u < 0.0f) || (u > 1.0f)) if ((u < 0.0f) || (u > 1.0f))
{ {
@@ -138,8 +139,8 @@ namespace Game.Collision
return false; return false;
} }
Vector3 q = new(s.cross(e1)); Vector3 q = Vector3.Cross(s, e1);
float v = f * ray.Direction.dot(q); float v = f * Vector3.Dot(ray.Direction, q);
if ((v < 0.0f) || ((u + v) > 1.0f)) if ((v < 0.0f) || ((u + v) > 1.0f))
{ {
@@ -147,7 +148,7 @@ namespace Game.Collision
return false; return false;
} }
float t = f * e2.dot(q); float t = f * Vector3.Dot(e2, q);
if ((t > 0.0f) && (t < distance)) if ((t > 0.0f) && (t < distance))
{ {
+4 -3
View File
@@ -16,6 +16,7 @@
*/ */
using Framework.GameMath; using Framework.GameMath;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -64,7 +65,7 @@ namespace Game.Collision
public bool GetObjectHitPos(Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist, PhaseShift phaseShift) public bool GetObjectHitPos(Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist, PhaseShift phaseShift)
{ {
bool result; 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 // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
Cypher.Assert(maxDist < float.MaxValue); Cypher.Assert(maxDist < float.MaxValue);
// prevent NaN values which can cause BIH intersection to enter infinite loop // prevent NaN values which can cause BIH intersection to enter infinite loop
@@ -81,7 +82,7 @@ namespace Game.Collision
resultHitPos = startPos + dir * dist; resultHitPos = startPos + dir * dist;
if (modifyDist < 0) if (modifyDist < 0)
{ {
if ((resultHitPos - startPos).magnitude() > -modifyDist) if ((resultHitPos - startPos).Length() > -modifyDist)
resultHitPos += dir * modifyDist; resultHitPos += dir * modifyDist;
else else
resultHitPos = startPos; resultHitPos = startPos;
@@ -101,7 +102,7 @@ namespace Game.Collision
public bool IsInLineOfSight(Vector3 startPos, Vector3 endPos, PhaseShift phaseShift) public bool IsInLineOfSight(Vector3 startPos, Vector3 endPos, PhaseShift phaseShift)
{ {
float maxDist = (endPos - startPos).magnitude(); float maxDist = (endPos - startPos).Length();
if (!MathFunctions.fuzzyGt(maxDist, 0)) if (!MathFunctions.fuzzyGt(maxDist, 0))
return true; return true;
@@ -16,10 +16,10 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using Framework.Dynamic;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Framework.Dynamic; using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
+4 -3
View File
@@ -20,6 +20,7 @@ using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -346,7 +347,7 @@ namespace Game.Collision
public bool GetObjectHitPos(Vector3 pPos1, Vector3 pPos2, out Vector3 pResultHitPos, float pModifyDist) public bool GetObjectHitPos(Vector3 pPos1, Vector3 pPos2, out Vector3 pResultHitPos, float pModifyDist)
{ {
bool result; 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 // valid map coords should *never ever* produce float overflow, but this would produce NaNs too
Cypher.Assert(maxDist < float.MaxValue); Cypher.Assert(maxDist < float.MaxValue);
// prevent NaN values which can cause BIH intersection to enter infinite loop // prevent NaN values which can cause BIH intersection to enter infinite loop
@@ -363,7 +364,7 @@ namespace Game.Collision
pResultHitPos = pPos1 + dir * dist; pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0) if (pModifyDist < 0)
{ {
if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) if ((pResultHitPos - pPos1).Length() > -pModifyDist)
{ {
pResultHitPos += dir * pModifyDist; pResultHitPos += dir * pModifyDist;
} }
@@ -388,7 +389,7 @@ namespace Game.Collision
public bool IsInLineOfSight(Vector3 pos1, Vector3 pos2, ModelIgnoreFlags ignoreFlags) 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 // return false if distance is over max float, in case of cheater teleporting to the end of the universe
if (maxDist == float.MaxValue || if (maxDist == float.MaxValue ||
maxDist == float.PositiveInfinity) maxDist == float.PositiveInfinity)
+18 -17
View File
@@ -15,11 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.Constants;
using Framework.GameMath; using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Framework.Constants; using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -64,13 +65,13 @@ namespace Game.Collision
iScale = modelOwner.GetScale(); iScale = modelOwner.GetScale();
iInvScale = 1.0f / iScale; iInvScale = 1.0f / iScale;
Matrix3 iRotation = Matrix3.fromEulerAnglesZYX(modelOwner.GetOrientation(), 0, 0); Matrix4x4 iRotation = Extensions.fromEulerAnglesZYX(modelOwner.GetOrientation(), 0, 0);
iInvRot = iRotation.inverse(); Matrix4x4.Invert(iRotation, out iInvRot);
// transform bounding box: // transform bounding box:
mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale); mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale);
AxisAlignedBox rotated_bounds = new(); AxisAlignedBox rotated_bounds = new();
for (int i = 0; i < 8; ++i) 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; iBound = rotated_bounds + iPos;
owner = modelOwner; owner = modelOwner;
@@ -100,8 +101,8 @@ namespace Game.Collision
return false; return false;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 p = iInvRot * (ray.Origin - iPos) * iInvScale; Vector3 p = Vector3.Transform((ray.Origin - iPos) * iInvScale, iInvRot);
Ray modRay = new(p, iInvRot * ray.Direction); Ray modRay = new Ray(p, Vector3.Transform(ray.Direction, iInvRot));
float distance = maxDist * iInvScale; float distance = maxDist * iInvScale;
bool hit = iModel.IntersectRay(modRay, ref distance, stopAtFirstHit, ignoreFlags); bool hit = iModel.IntersectRay(modRay, ref distance, stopAtFirstHit, ignoreFlags);
if (hit) if (hit)
@@ -124,13 +125,13 @@ namespace Game.Collision
return; return;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (point - iPos) * iInvScale; Vector3 pModel = Vector3.Transform((point - iPos) * iInvScale, iInvRot);
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f); Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
float zDist; float zDist;
if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info)) if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; 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) if (info.ground_Z < world_Z)
{ {
info.ground_Z = world_Z; info.ground_Z = world_Z;
@@ -151,13 +152,13 @@ namespace Game.Collision
return false; return false;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (point - iPos) * iInvScale; Vector3 pModel = Vector3.Transform((point - iPos) * iInvScale, iInvRot);
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f); Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
float zDist; float zDist;
if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info)) if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; 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) if (info.ground_Z < world_Z)
{ {
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) public bool GetLiquidLevel(Vector3 point, LocationInfo info, ref float liqHeight)
{ {
// child bounds are defined in object space: // 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); //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (info.hitModel.GetLiquidLevel(pModel, out zDist)) if (info.hitModel.GetLiquidLevel(pModel, out zDist))
@@ -203,13 +204,13 @@ namespace Game.Collision
iPos = owner.GetPosition(); iPos = owner.GetPosition();
Matrix3 iRotation = Matrix3.fromEulerAnglesZYX(owner.GetOrientation(), 0, 0); Matrix4x4 iRotation = Extensions.fromEulerAnglesZYX(owner.GetOrientation(), 0, 0);
iInvRot = iRotation.inverse(); Matrix4x4.Invert(iRotation, out iInvRot);
// transform bounding box: // transform bounding box:
mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale); mdl_box = new AxisAlignedBox(mdl_box.Lo * iScale, mdl_box.Hi * iScale);
AxisAlignedBox rotated_bounds = new(); AxisAlignedBox rotated_bounds = new();
for (int i = 0; i < 8; ++i) 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; iBound = rotated_bounds + iPos;
@@ -269,7 +270,7 @@ namespace Game.Collision
bool _collisionEnabled; bool _collisionEnabled;
AxisAlignedBox iBound; AxisAlignedBox iBound;
Matrix3 iInvRot; Matrix4x4 iInvRot;
Vector3 iPos; Vector3 iPos;
float iInvScale; float iInvScale;
float iScale; float iScale;
+2 -1
View File
@@ -15,8 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.GameMath;
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
+13 -11
View File
@@ -19,6 +19,7 @@ using Framework.Constants;
using Framework.GameMath; using Framework.GameMath;
using System; using System;
using System.IO; using System.IO;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -85,7 +86,7 @@ namespace Game.Collision
public class ModelInstance : ModelMinimalData public class ModelInstance : ModelMinimalData
{ {
Matrix3 iInvRot; Matrix4x4 iInvRot;
float iInvScale; float iInvScale;
WorldModel iModel; WorldModel iModel;
@@ -107,7 +108,8 @@ namespace Game.Collision
iModel = model; 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; iInvScale = 1.0f / iScale;
} }
@@ -121,8 +123,8 @@ namespace Game.Collision
return false; return false;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 p = iInvRot * (pRay.Origin - iPos) * iInvScale; Vector3 p = Vector3.Transform((pRay.Origin - iPos) * iInvScale, iInvRot);
Ray modRay = new(p, iInvRot * pRay.Direction); Ray modRay = new Ray(p, Vector3.Transform(pRay.Direction, iInvRot));
float distance = pMaxDist * iInvScale; float distance = pMaxDist * iInvScale;
bool hit = iModel.IntersectRay(modRay, ref distance, pStopAtFirstHit, ignoreFlags); bool hit = iModel.IntersectRay(modRay, ref distance, pStopAtFirstHit, ignoreFlags);
if (hit) if (hit)
@@ -144,8 +146,8 @@ namespace Game.Collision
if (!iBound.contains(p)) if (!iBound.contains(p))
return; return;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = Vector3.Transform((p - iPos) * iInvScale, iInvRot);
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f); Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
float zDist; float zDist;
if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info)) if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info))
{ {
@@ -153,7 +155,7 @@ namespace Game.Collision
// Transform back to world space. Note that: // Transform back to world space. Note that:
// Mat * vec == vec * Mat.transpose() // Mat * vec == vec * Mat.transpose()
// and for rotation matrices: Mat.inverse() == 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) if (info.ground_Z < world_Z)
{ {
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) public bool GetLiquidLevel(Vector3 p, LocationInfo info, ref float liqHeight)
{ {
// child bounds are defined in object space: // 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); //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (info.hitModel.GetLiquidLevel(pModel, out zDist)) if (info.hitModel.GetLiquidLevel(pModel, out zDist))
@@ -189,8 +191,8 @@ namespace Game.Collision
if (!iBound.contains(p)) if (!iBound.contains(p))
return false; return false;
// child bounds are defined in object space: // child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = Vector3.Transform((p - iPos) * iInvScale, iInvRot);
Vector3 zDirModel = iInvRot * new Vector3(0.0f, 0.0f, -1.0f); Vector3 zDirModel = Vector3.Transform(new Vector3(0.0f, 0.0f, -1.0f), iInvRot);
float zDist; float zDist;
if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info)) if (iModel.GetLocationInfo(pModel, zDirModel, out zDist, info))
{ {
@@ -198,7 +200,7 @@ namespace Game.Collision
// Transform back to world space. Note that: // Transform back to world space. Note that:
// Mat * vec == vec * Mat.transpose() // Mat * vec == vec * Mat.transpose()
// and for rotation matrices: Mat.inverse() == 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? if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
{ {
info.ground_Z = world_Z; info.ground_Z = world_Z;
@@ -20,6 +20,7 @@ using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
+1
View File
@@ -18,6 +18,7 @@
using Framework.GameMath; using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Collision namespace Game.Collision
{ {
@@ -17,10 +17,10 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
@@ -18,12 +18,12 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Framework.IO; using Framework.IO;
using System; using System;
using System.Collections.Generic;
using System.Reflection;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using System.Reflection;
namespace Game.DataStorage namespace Game.DataStorage
{ {
@@ -19,15 +19,15 @@ using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Collections;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+2 -3
View File
@@ -17,13 +17,12 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Game.Networking; using Game.Networking;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Collections; using System.Numerics;
using Framework.Dynamic;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -15,10 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,8 +16,8 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using System; using System;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,7 +16,7 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,7 +16,7 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -2
View File
@@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.Constants; using System.Numerics;
using Framework.GameMath;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,7 +16,7 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
@@ -17,6 +17,7 @@
using Framework.GameMath; using Framework.GameMath;
using System.IO; using System.IO;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+2 -1
View File
@@ -14,8 +14,9 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,7 +16,7 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+2 -1
View File
@@ -14,8 +14,9 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.GameMath;
using Framework.Constants; using Framework.Constants;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
+1 -1
View File
@@ -16,8 +16,8 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using System; using System;
using System.Numerics;
namespace Game.DataStorage namespace Game.DataStorage
{ {
@@ -16,7 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
namespace Game.DataStorage namespace Game.DataStorage
{ {
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.Maps; using Game.Maps;
using Game.Movement; using Game.Movement;
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
@@ -17,10 +17,10 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.Networking; using Game.Networking;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Game.Entities namespace Game.Entities
@@ -19,7 +19,6 @@ using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Game.AI; using Game.AI;
using Game.Combat;
using Game.DataStorage; using Game.DataStorage;
using Game.Groups; using Game.Groups;
using Game.Loots; using Game.Loots;
@@ -19,7 +19,6 @@ using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Framework.Dynamic;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Maps; using Game.Maps;
+1 -1
View File
@@ -17,13 +17,13 @@
using Framework.Collections; using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Conditions; using Game.Conditions;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Misc namespace Game.Misc
{ {
-1
View File
@@ -18,7 +18,6 @@
using Framework.Constants; using Framework.Constants;
using Game.Spells; using Game.Spells;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets;
namespace Game.Entities namespace Game.Entities
{ {
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.Collision; using Game.Collision;
@@ -25,12 +24,13 @@ using Game.DataStorage;
using Game.Groups; using Game.Groups;
using Game.Loots; using Game.Loots;
using Game.Maps; using Game.Maps;
using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Game.Networking; using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
@@ -246,7 +246,7 @@ namespace Game.Entities
GameObjectAddon gameObjectAddon = Global.ObjectMgr.GetGameObjectAddon(GetSpawnId()); 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 // 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) if (gameObjectAddon != null)
parentRotation = gameObjectAddon.ParentRotation; parentRotation = gameObjectAddon.ParentRotation;
@@ -2191,8 +2191,9 @@ namespace Game.Entities
public void SetWorldRotation(float qx, float qy, float qz, float qw) public void SetWorldRotation(float qx, float qy, float qz, float qw)
{ {
Quaternion rotation = new(qx, qy, qz, qw); Quaternion rotation = new Quaternion(qx, qy, qz, qw);
rotation.unitize(); rotation = Quaternion.Multiply(rotation, 1.0f / MathF.Sqrt(Quaternion.Dot(rotation, rotation)));
m_worldRotation.X = rotation.X; m_worldRotation.X = rotation.X;
m_worldRotation.Y = rotation.Y; m_worldRotation.Y = rotation.Y;
m_worldRotation.Z = rotation.Z; m_worldRotation.Z = rotation.Z;
@@ -2207,7 +2208,7 @@ namespace Game.Entities
public void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot) 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); SetWorldRotation(quat.X, quat.Y, quat.Z, quat.W);
} }
@@ -17,11 +17,10 @@
using Framework.Collections; using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Game.Networking.Packets;
using Game.Maps; using Game.Maps;
using Game.Networking.Packets;
using System.Numerics;
using System.Runtime.InteropServices;
namespace Game.Entities namespace Game.Entities
{ {
@@ -15,13 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Game.Networking; using Game.Networking;
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Game.Networking.Packets;
using Game.DataStorage; using Game.DataStorage;
using System.Linq; using System.Linq;
-1
View File
@@ -17,7 +17,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Game.Networking; using Game.Networking;
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
+1 -1
View File
@@ -15,9 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Framework.GameMath;
using Game.Maps; using Game.Maps;
using System; using System;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
@@ -17,13 +17,13 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
+1 -1
View File
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.BattleFields; using Game.BattleFields;
using Game.DataStorage; using Game.DataStorage;
@@ -28,6 +27,7 @@ using Game.Scenarios;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Game.Arenas;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Groups; using Game.Groups;
@@ -32,7 +31,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Game.BattleFields; using Game.BattleFields;
using Framework.Dynamic;
namespace Game.Entities namespace Game.Entities
{ {
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Game.BattlePets;
using Game.DataStorage; using Game.DataStorage;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
+1 -1
View File
@@ -18,10 +18,10 @@
using Framework.Algorithms; using Framework.Algorithms;
using Framework.Collections; using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
+2 -2
View File
@@ -16,12 +16,12 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using Game.Maps; using Game.Maps;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
@@ -132,7 +132,7 @@ namespace Game.Entities
SetGoAnimProgress(animprogress); SetGoAnimProgress(animprogress);
SetName(goinfo.name); SetName(goinfo.name);
SetWorldRotation(0.0f, 0.0f, 0.0f, 1.0f); SetWorldRotation(0.0f, 0.0f, 0.0f, 1.0f);
SetParentRotation(Quaternion.WAxis); SetParentRotation(Quaternion.Identity);
CreateModel(); CreateModel();
return true; return true;
+1 -1
View File
@@ -17,10 +17,10 @@
using Framework.Collections; using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Networking; using Game.Networking;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
-3
View File
@@ -17,13 +17,10 @@
using Framework.Collections; using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic;
using Game.AI; using Game.AI;
using Game.Combat; using Game.Combat;
using Game.DataStorage; using Game.DataStorage;
using Game.Maps;
using Game.Movement; using Game.Movement;
using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
+1 -1
View File
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Maps; using Game.Maps;
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
-1
View File
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Game.AI; using Game.AI;
using Game.Movement;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells; using Game.Spells;
using System.Collections.Generic; using System.Collections.Generic;
+1 -2
View File
@@ -16,8 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.Chat; using Game.Chat;
@@ -32,6 +30,7 @@ using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Entities namespace Game.Entities
{ {
+2 -2
View File
@@ -18,7 +18,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
@@ -26,6 +25,7 @@ using Game.Networking.Packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Garrisons namespace Game.Garrisons
{ {
@@ -735,7 +735,7 @@ namespace Game.Garrisons
if (finalizeInfo != null) if (finalizeInfo != null)
{ {
Position pos2 = finalizeInfo.factionInfo[faction].Pos; 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) if (finalizer)
{ {
// set some spell id to make the object delete itself after use // set some spell id to make the object delete itself after use
+3 -3
View File
@@ -19,7 +19,6 @@ using Framework.Collections;
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Framework.IO; using Framework.IO;
using Game.Conditions; using Game.Conditions;
using Game.DataStorage; using Game.DataStorage;
@@ -32,6 +31,7 @@ using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Game namespace Game
@@ -4257,10 +4257,10 @@ namespace Game
gameObjectAddon.invisibilityValue = 1; 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"); 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)) if (gameObjectAddon.WorldEffectID != 0 && !CliDB.WorldEffectStorage.ContainsKey(gameObjectAddon.WorldEffectID))
@@ -16,20 +16,10 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.IO;
using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities;
using Game.Groups;
using Game.Guilds;
using Game.Maps;
using Game.Misc;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.PvP;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
namespace Game namespace Game
{ {
@@ -16,20 +16,9 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.IO;
using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities;
using Game.Groups;
using Game.Guilds;
using Game.Maps;
using Game.Misc;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.PvP;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq; using System.Linq;
namespace Game namespace Game
-1
View File
@@ -20,7 +20,6 @@ using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System;
namespace Game namespace Game
{ {
-1
View File
@@ -19,7 +19,6 @@ using Framework.Constants;
using Game.DataStorage; using Game.DataStorage;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System.Collections.Generic;
namespace Game namespace Game
{ {
-1
View File
@@ -22,7 +22,6 @@ using Game.Guilds;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
namespace Game namespace Game
{ {
-5
View File
@@ -15,11 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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 namespace Game
{ {
public partial class WorldSession public partial class WorldSession
-1
View File
@@ -16,7 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Game.Conditions; using Game.Conditions;
using Game.Entities; using Game.Entities;
+4 -4
View File
@@ -17,11 +17,12 @@
using Framework.Constants; using Framework.Constants;
using Framework.GameMath; using Framework.GameMath;
using Game.Collision;
using Game.DataStorage; using Game.DataStorage;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Game.Collision; using System.Numerics;
namespace Game.Maps namespace Game.Maps
{ {
@@ -175,7 +176,7 @@ namespace Game.Maps
_minHeightPlanes = new Plane[8]; _minHeightPlanes = new Plane[8];
for (uint quarterIndex = 0; quarterIndex < 8; ++quarterIndex) 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][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][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]]) new Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]])
@@ -500,8 +501,7 @@ namespace Game.Maps
else else
quarterIndex = gx > gy ? 1u : 0; quarterIndex = gx > gy ? 1u : 0;
Ray ray = new(new Vector3(gx, gy, 0.0f), Vector3.UnitZ);
Ray ray = new(new Vector3(gx, gy, 0.0f), Vector3.ZAxis);
return ray.intersection(_minHeightPlanes[quarterIndex]).Z; return ray.intersection(_minHeightPlanes[quarterIndex]).Z;
} }
+1 -1
View File
@@ -18,7 +18,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.Collision; using Game.Collision;
using Game.DataStorage; using Game.DataStorage;
@@ -32,6 +31,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Maps namespace Game.Maps
{ {
+4 -4
View File
@@ -17,13 +17,13 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Movement; using Game.Movement;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Maps 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)); 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 // Add extra points to allow derivative calculations for all path nodes
allPoints.Insert(0, allPoints.First().lerp(allPoints[1], -0.2f)); allPoints.Insert(0, Vector3.Lerp(allPoints.First(), allPoints[1], -0.2f));
allPoints.Add(allPoints.Last().lerp(allPoints[^2], -0.2f)); allPoints.Add(Vector3.Lerp(allPoints.Last(), allPoints[^2], -0.2f));
allPoints.Add(allPoints.Last().lerp(allPoints[^2], -1.0f)); allPoints.Add(Vector3.Lerp(allPoints.Last(), allPoints[^2], -1.0f));
SplineRawInitializer initer = new(allPoints); SplineRawInitializer initer = new(allPoints);
Spline orientationSpline = new(); Spline orientationSpline = new();
-5
View File
@@ -15,11 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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; using Game.Entities;
namespace Game.Movement namespace Game.Movement
@@ -16,13 +16,13 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Game.Entities; using Game.Entities;
using System;
namespace Game.Movement namespace Game.Movement
{ {
@@ -16,10 +16,10 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Entities; using Game.Entities;
using Game.Maps; using Game.Maps;
using System; using System;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {
@@ -481,7 +481,7 @@ namespace Game.Movement
Vector3 endVec = new(endPoint[0], endPoint[1], endPoint[2]); Vector3 endVec = new(endPoint[0], endPoint[1], endPoint[2]);
Vector3 diffVec = (endVec - startVec); Vector3 diffVec = (endVec - startVec);
Vector3 prevVec = startVec; Vector3 prevVec = startVec;
float len = diffVec.GetLength(); float len = diffVec.Length();
diffVec *= 4.0f / len; diffVec *= 4.0f / len;
while (len > 4.0f) while (len > 4.0f)
{ {
@@ -861,7 +861,7 @@ namespace Game.Movement
float Dist3DSqr(Vector3 p1, Vector3 p2) 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); } 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 // the first point of the path must be outside the specified range
// (this should have really been checked by the caller...) // (this should have really been checked by the caller...)
if ((_pathPoints[0] - target).GetLengthSquared() < distSq) if ((_pathPoints[0] - target).LengthSquared() < distSq)
return; return;
// check if we even need to do anything // check if we even need to do anything
if ((_pathPoints[0] - target).GetLengthSquared() >= distSq) if ((_pathPoints[0] - target).LengthSquared() >= distSq)
return; return;
int i = _pathPoints.Length - 1; int i = _pathPoints.Length - 1;
@@ -893,7 +893,7 @@ namespace Game.Movement
while (true) while (true)
{ {
// we know that pathPoints[i] is too close already (from the previous iteration) // 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! break; // bingo!
if (--i == 0) 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... // 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... // ... settle for a guesstimate since i'm not confident in doing trig on every chase motion tick...
// (@todo review this) // (@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); Array.Resize(ref _pathPoints, i + 1);
} }
@@ -17,7 +17,6 @@
using Framework.Constants; using Framework.Constants;
using Game.Entities; using Game.Entities;
using Game.Maps;
using System; using System;
namespace Game.Movement namespace Game.Movement
@@ -16,11 +16,11 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.Entities; using Game.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {
+1 -1
View File
@@ -16,13 +16,13 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.AI; using Game.AI;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {
+2 -2
View File
@@ -17,9 +17,9 @@
using Framework.Constants; using Framework.Constants;
using Framework.Dynamic; using Framework.Dynamic;
using Framework.GameMath;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {
@@ -52,7 +52,7 @@ namespace Game.Movement
effect_start_time = 0; effect_start_time = 0;
spell_effect_extra = args.spellEffectExtra; spell_effect_extra = args.spellEffectExtra;
anim_tier = args.animTier; 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 // Check if its a stop spline
if (args.flags.HasFlag(SplineFlag.Done)) if (args.flags.HasFlag(SplineFlag.Done))
+1 -1
View File
@@ -16,10 +16,10 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Game.Entities; using Game.Entities;
using Game.Networking.Packets; using Game.Networking.Packets;
using System; using System;
using System.Numerics;
namespace Game.Movement namespace Game.Movement
{ {

Some files were not shown because too many files have changed in this diff Show More