/* * Copyright (C) 2012-2018 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 . */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text.RegularExpressions; namespace Framework.GameMath { /// /// Represents a 4-dimentional single-precision floating point matrix. /// [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 /// /// Initializes a new instance of the structure with the specified values. /// 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; } /// /// Initializes a new instance of the structure with the specified values. /// /// An array containing the matrix values in row-major order. 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]; } /// /// Initializes a new instance of the structure with the specified values. /// /// An array containing the matrix values in row-major order. public Matrix4(List 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]; } /// /// Initializes a new instance of the structure with the specified values. /// /// A instance holding values for the first column. /// A instance holding values for the second column. /// A instance holding values for the third column. /// A instance holding values for the fourth column. 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; } /// /// Initializes a new instance of the class using a given matrix. /// 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 /// /// 4-dimentional single-precision floating point zero matrix. /// public static readonly Matrix4 Zero = new Matrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); /// /// 4-dimentional single-precision floating point identity matrix. /// public static readonly Matrix4 Identity = new Matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); #endregion #region Public Properties /// /// Gets or sets the value of the [1,1] matrix element. /// /// A single-precision floating-point number. public float M11 { get { return _m11; } set { _m11 = value; } } /// /// Gets or sets the value of the [1,2] matrix element. /// /// A single-precision floating-point number. public float M12 { get { return _m12; } set { _m12 = value; } } /// /// Gets or sets the value of the [1,3] matrix element. /// /// A single-precision floating-point number. public float M13 { get { return _m13; } set { _m13 = value; } } /// /// Gets or sets the value of the [1,4] matrix element. /// /// A single-precision floating-point number. public float M14 { get { return _m14; } set { _m14 = value; } } /// /// Gets or sets the value of the [2,1] matrix element. /// /// A single-precision floating-point number. public float M21 { get { return _m21; } set { _m21 = value; } } /// /// Gets or sets the value of the [2,2] matrix element. /// /// A single-precision floating-point number. public float M22 { get { return _m22; } set { _m22 = value; } } /// /// Gets or sets the value of the [2,3] matrix element. /// /// A single-precision floating-point number. public float M23 { get { return _m23; } set { _m23 = value; } } /// /// Gets or sets the value of the [2,4] matrix element. /// /// A single-precision floating-point number. public float M24 { get { return _m24; } set { _m24 = value; } } /// /// Gets or sets the value of the [3,1] matrix element. /// /// A single-precision floating-point number. public float M31 { get { return _m31; } set { _m31 = value; } } /// /// Gets or sets the value of the [3,2] matrix element. /// /// A single-precision floating-point number. public float M32 { get { return _m32; } set { _m32 = value; } } /// /// Gets or sets the value of the [3,3] matrix element. /// /// A single-precision floating-point number. public float M33 { get { return _m33; } set { _m33 = value; } } /// /// Gets or sets the value of the [3,4] matrix element. /// /// A single-precision floating-point number. public float M34 { get { return _m34; } set { _m34 = value; } } /// /// Gets or sets the value of the [4,1] matrix element. /// /// A single-precision floating-point number. public float M41 { get { return _m41; } set { _m41 = value; } } /// /// Gets or sets the value of the [4,2] matrix element. /// /// A single-precision floating-point number. public float M42 { get { return _m42; } set { _m42 = value; } } /// /// Gets or sets the value of the [4,3] matrix element. /// /// A single-precision floating-point number. public float M43 { get { return _m43; } set { _m43 = value; } } /// /// Gets or sets the value of the [4,4] matrix element. /// /// A single-precision floating-point number. public float M44 { get { return _m44; } set { _m44 = value; } } /// /// Gets the matrix's trace value. /// /// A single-precision floating-point number. public float Trace { get { return _m11 + _m22 + _m33 + _m44; } } #endregion #region ICloneable Members /// /// Creates an exact copy of this object. /// /// The object this method creates, cast as an object. object ICloneable.Clone() { return new Matrix4(this); } /// /// Creates an exact copy of this object. /// /// The object this method creates. public Matrix4 Clone() { return new Matrix4(this); } #endregion #region Public Static Parse Methods private const string regularExp = @"4x4\s*\[(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*),(?.*)\]"; /// /// Converts the specified string to its equivalent. /// /// A string representation of a . /// A that represents the vector specified by the parameter. /// /// The string should be in the following form: "4x4..matrix elements..>".
/// Exmaple : "4x4[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]" ///
public static Matrix4 Parse(string value) { Regex r = new Regex(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."); } } /// /// Converts the specified string to its equivalent. /// A return value indicates whether the conversion succeeded or failed. /// /// A string representation of a . /// /// When this method returns, if the conversion succeeded, /// contains a representing the vector specified by . /// /// if value was converted successfully; otherwise, . /// /// The string should be in the following form: "4x4..matrix elements..>".
/// Exmaple : "4x4[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]" ///
public static bool TryParse(string value, out Matrix4 result) { Regex r = new Regex(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 /// /// Adds two matrices. /// /// A instance. /// A instance. /// A new instance containing the sum. 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 ); } /// /// Adds a matrix and a scalar. /// /// A instance. /// A single-precision floating-point number. /// A new instance containing the sum. 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 ); } /// /// Adds two matrices and put the result in a third matrix. /// /// A instance. /// A instance. /// A instance to hold the result. 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; } /// /// Adds a matrix and a scalar and put the result in a third matrix. /// /// A instance. /// A single-precision floating-point number. /// A instance to hold the result. 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; } /// /// Subtracts a matrix from a matrix. /// /// A instance to subtract from. /// A instance to subtract. /// A new instance containing the difference. /// result[x][y] = left[x][y] - right[x][y] 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 ); } /// /// Subtracts a scalar from a matrix. /// /// A instance. /// A single-precision floating-point number. /// A new instance containing the difference. 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 ); } /// /// Subtracts a matrix from a matrix and put the result in a third matrix. /// /// A instance to subtract from. /// A instance to subtract. /// A instance to hold the result. /// result[x][y] = left[x][y] - right[x][y] 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; } /// /// Subtracts a scalar from a matrix and put the result in a third matrix. /// /// A instance. /// A single-precision floating-point number. /// A instance to hold the result. 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; } /// /// Multiplies two matrices. /// /// A instance. /// A instance. /// A new instance containing the result. 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 ); } /// /// Multiplies two matrices and put the result in a third matrix. /// /// A instance. /// A instance. /// A instance to hold the result. 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; } /// /// Transforms a given vector by a matrix. /// /// A instance. /// A instance. /// A new instance containing the result. 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)); } /// /// Transforms a given vector by a matrix and put the result in a vector. /// /// A instance. /// A instance. /// A instance to hold the result. 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); } /// /// Transposes a matrix. /// /// A instance. /// A new instance containing the transposed matrix. public static Matrix4 Transpose(Matrix4 m) { Matrix4 t = new Matrix4(m); t.Transpose(); return t; } #endregion #region System.Object overrides /// /// Returns the hashcode for this instance. /// /// A 32-bit signed integer hash code. 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(); } /// /// Returns a value indicating whether this instance is equal to /// the specified object. /// /// An object to compare to this instance. /// if is a and has the same values as this instance; otherwise, . 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; } /// /// Returns a string representation of this object. /// /// A string representation of this object. public override string ToString() { return string.Format("4x4[{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}]", _m11, _m12, _m13, _m14, _m21, _m22, _m23, _m24, _m31, _m32, _m33, _m34, _m41, _m42, _m43, _m44); } #endregion #region Public Methods /// /// Calculates the determinant value of the matrix. /// /// The determinant value of the matrix. 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; } /// /// Transposes this matrix. /// public void Transpose() { MathFunctions.Swap(ref _m12, ref _m21); MathFunctions.Swap(ref _m13, ref _m31); MathFunctions.Swap(ref _m14, ref _m41); MathFunctions.Swap(ref _m23, ref _m32); MathFunctions.Swap(ref _m24, ref _m42); MathFunctions.Swap(ref _m34, ref _m43); } #endregion #region Comparison Operators /// /// Tests whether two specified matrices are equal. /// /// A instance. /// A instance. /// if the two matrices are equal; otherwise, . public static bool operator ==(Matrix4 left, Matrix4 right) { return ValueType.Equals(left, right); } /// /// Tests whether two specified matrices are not equal. /// /// A instance. /// A instance. /// if the two matrices are not equal; otherwise, . public static bool operator !=(Matrix4 left, Matrix4 right) { return !ValueType.Equals(left, right); } #endregion #region Binary Operators /// /// Adds two matrices. /// /// A instance. /// A instance. /// A new instance containing the sum. public static Matrix4 operator +(Matrix4 left, Matrix4 right) { return Matrix4.Add(left, right); ; } /// /// Adds a matrix and a scalar. /// /// A instance. /// A single-precision floating-point number. /// A new instance containing the sum. public static Matrix4 operator +(Matrix4 matrix, float scalar) { return Matrix4.Add(matrix, scalar); } /// /// Adds a matrix and a scalar. /// /// A instance. /// A single-precision floating-point number. /// A new instance containing the sum. public static Matrix4 operator +(float scalar, Matrix4 matrix) { return Matrix4.Add(matrix, scalar); } /// /// Subtracts a matrix from a matrix. /// /// A instance. /// A instance. /// A new instance containing the difference. public static Matrix4 operator -(Matrix4 left, Matrix4 right) { return Matrix4.Subtract(left, right); ; } /// /// Subtracts a scalar from a matrix. /// /// A instance. /// A single-precision floating-point number. /// A new instance containing the difference. public static Matrix4 operator -(Matrix4 matrix, float scalar) { return Matrix4.Subtract(matrix, scalar); } /// /// Multiplies two matrices. /// /// A instance. /// A instance. /// A new instance containing the result. public static Matrix4 operator *(Matrix4 left, Matrix4 right) { return Matrix4.Multiply(left, right); ; } /// /// Transforms a given vector by a matrix. /// /// A instance. /// A instance. /// A new instance containing the result. public static Vector4 operator *(Matrix4 matrix, Vector4 vector) { Vector4 result = new Vector4(); 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 /// /// Indexer allowing to access the matrix elements by an index /// where index = 2*row + column. /// 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; } } } /// /// Indexer allowing to access the matrix elements by row and column. /// public float this[int row, int column] { get { return this[(row) * 4 + (column)]; } set { this[(row) * 4 + (column)] = value; } } #endregion } }