#region License /* MoonWorks - Game Development Framework * Copyright 2021 Evan Hemsley */ /* Derived from code by Ethan Lee (Copyright 2009-2021). * Released under the Microsoft Public License. * See fna.LICENSE for details. * Derived from code by the Mono.Xna Team (Copyright 2006). * Released under the MIT License. See monoxna.LICENSE for details. */ #endregion #region Using Statements using System; using System.Diagnostics; using System.Runtime.InteropServices; #endregion namespace MoonWorks.Math { /// /// Represents the right-handed 4x4 floating point matrix, which can store translation, scale and rotation information. /// This differs from XNA in one major way: projections are modified to give right handed NDC space. /// [Serializable] [DebuggerDisplay("{DebugDisplayString,nq}")] [StructLayout(LayoutKind.Sequential)] public struct Matrix4x4 : IEquatable { #region Public Properties /// /// The backward vector formed from the third row M31, M32, M33 elements. /// public Vector3 Backward { get { return new Vector3(M31, M32, M33); } set { M31 = value.X; M32 = value.Y; M33 = value.Z; } } /// /// The down vector formed from the second row -M21, -M22, -M23 elements. /// public Vector3 Down { get { return new Vector3(-M21, -M22, -M23); } set { M21 = -value.X; M22 = -value.Y; M23 = -value.Z; } } /// /// The forward vector formed from the third row -M31, -M32, -M33 elements. /// public Vector3 Forward { get { return new Vector3(-M31, -M32, -M33); } set { M31 = -value.X; M32 = -value.Y; M33 = -value.Z; } } /// /// Returns the identity matrix. /// public static Matrix4x4 Identity { get { return identity; } } /// /// The left vector formed from the first row -M11, -M12, -M13 elements. /// public Vector3 Left { get { return new Vector3(-M11, -M12, -M13); } set { M11 = -value.X; M12 = -value.Y; M13 = -value.Z; } } /// /// The right vector formed from the first row M11, M12, M13 elements. /// public Vector3 Right { get { return new Vector3(M11, M12, M13); } set { M11 = value.X; M12 = value.Y; M13 = value.Z; } } /// /// Position stored in this matrix. /// public Vector3 Translation { get { return new Vector3(M41, M42, M43); } set { M41 = value.X; M42 = value.Y; M43 = value.Z; } } /// /// The upper vector formed from the second row M21, M22, M23 elements. /// public Vector3 Up { get { return new Vector3(M21, M22, M23); } set { M21 = value.X; M22 = value.Y; M23 = value.Z; } } #endregion #region Internal Properties internal string DebugDisplayString { get { return string.Concat( "( ", M11.ToString(), " ", M12.ToString(), " ", M13.ToString(), " ", M14.ToString(), " ) \r\n", "( ", M21.ToString(), " ", M22.ToString(), " ", M23.ToString(), " ", M24.ToString(), " ) \r\n", "( ", M31.ToString(), " ", M32.ToString(), " ", M33.ToString(), " ", M34.ToString(), " ) \r\n", "( ", M41.ToString(), " ", M42.ToString(), " ", M43.ToString(), " ", M44.ToString(), " )" ); } } #endregion #region Public Fields /// /// A first row and first column value. /// public float M11; /// /// A first row and second column value. /// public float M12; /// /// A first row and third column value. /// public float M13; /// /// A first row and fourth column value. /// public float M14; /// /// A second row and first column value. /// public float M21; /// /// A second row and second column value. /// public float M22; /// /// A second row and third column value. /// public float M23; /// /// A second row and fourth column value. /// public float M24; /// /// A third row and first column value. /// public float M31; /// /// A third row and second column value. /// public float M32; /// /// A third row and third column value. /// public float M33; /// /// A third row and fourth column value. /// public float M34; /// /// A fourth row and first column value. /// public float M41; /// /// A fourth row and second column value. /// public float M42; /// /// A fourth row and third column value. /// public float M43; /// /// A fourth row and fourth column value. /// public float M44; #endregion #region Private Static Variables private static Matrix4x4 identity = new Matrix4x4( 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f ); #endregion #region Public Constructors /// /// Constructs a matrix. /// /// A first row and first column value. /// A first row and second column value. /// A first row and third column value. /// A first row and fourth column value. /// A second row and first column value. /// A second row and second column value. /// A second row and third column value. /// A second row and fourth column value. /// A third row and first column value. /// A third row and second column value. /// A third row and third column value. /// A third row and fourth column value. /// A fourth row and first column value. /// A fourth row and second column value. /// A fourth row and third column value. /// A fourth row and fourth column value. public Matrix4x4( 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; } #endregion #region Public Methods /// /// Decomposes this matrix to translation, rotation and scale elements. Returns true if matrix can be decomposed; false otherwise. /// /// Scale vector as an output parameter. /// Rotation quaternion as an output parameter. /// Translation vector as an output parameter. /// true if matrix can be decomposed; false otherwise. public bool Decompose( out Vector3 scale, out Quaternion rotation, out Vector3 translation ) { translation.X = M41; translation.Y = M42; translation.Z = M43; float xs = (System.Math.Sign(M11 * M12 * M13 * M14) < 0) ? -1 : 1; float ys = (System.Math.Sign(M21 * M22 * M23 * M24) < 0) ? -1 : 1; float zs = (System.Math.Sign(M31 * M32 * M33 * M34) < 0) ? -1 : 1; scale.X = xs * (float) System.Math.Sqrt(M11 * M11 + M12 * M12 + M13 * M13); scale.Y = ys * (float) System.Math.Sqrt(M21 * M21 + M22 * M22 + M23 * M23); scale.Z = zs * (float) System.Math.Sqrt(M31 * M31 + M32 * M32 + M33 * M33); if ( MathHelper.WithinEpsilon(scale.X, 0.0f) || MathHelper.WithinEpsilon(scale.Y, 0.0f) || MathHelper.WithinEpsilon(scale.Z, 0.0f) ) { rotation = Quaternion.Identity; return false; } Matrix4x4 m1 = new Matrix4x4( M11 / scale.X, M12 / scale.X, M13 / scale.X, 0, M21 / scale.Y, M22 / scale.Y, M23 / scale.Y, 0, M31 / scale.Z, M32 / scale.Z, M33 / scale.Z, 0, 0, 0, 0, 1 ); rotation = Quaternion.CreateFromRotationMatrix(m1); return true; } /// /// Returns a determinant of this . /// /// Determinant of this /// See more about determinant here - http://en.wikipedia.org/wiki/Determinant. /// public float Determinant() { float num18 = (M33 * M44) - (M34 * M43); float num17 = (M32 * M44) - (M34 * M42); float num16 = (M32 * M43) - (M33 * M42); float num15 = (M31 * M44) - (M34 * M41); float num14 = (M31 * M43) - (M33 * M41); float num13 = (M31 * M42) - (M32 * M41); return ( ( ( (M11 * (((M22 * num18) - (M23 * num17)) + (M24 * num16))) - (M12 * (((M21 * num18) - (M23 * num15)) + (M24 * num14))) ) + (M13 * (((M21 * num17) - (M22 * num15)) + (M24 * num13))) ) - (M14 * (((M21 * num16) - (M22 * num14)) + (M23 * num13))) ); } /// /// Compares whether current instance is equal to specified without any tolerance. /// /// The to compare. /// true if the instances are equal; false otherwise. public bool Equals(Matrix4x4 other) { return ( M11 == other.M11 && M12 == other.M12 && M13 == other.M13 && M14 == other.M14 && M21 == other.M21 && M22 == other.M22 && M23 == other.M23 && M24 == other.M24 && M31 == other.M31 && M32 == other.M32 && M33 == other.M33 && M34 == other.M34 && M41 == other.M41 && M42 == other.M42 && M43 == other.M43 && M44 == other.M44 ); } /// /// Compares whether current instance is equal to specified without any tolerance. /// /// The to compare. /// true if the instances are equal; false otherwise. public override bool Equals(object obj) { return (obj is Matrix4x4) && Equals((Matrix4x4) obj); } /// /// Gets the hash code of this . /// /// Hash code of this . 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 representation of this in the format: /// {M11:[] M12:[] M13:[] M14:[]} /// {M21:[] M12:[] M13:[] M14:[]} /// {M31:[] M32:[] M33:[] M34:[]} /// {M41:[] M42:[] M43:[] M44:[]} /// /// A representation of this . public override string ToString() { return ( "{M11:" + M11.ToString() + " M12:" + M12.ToString() + " M13:" + M13.ToString() + " M14:" + M14.ToString() + "} {M21:" + M21.ToString() + " M22:" + M22.ToString() + " M23:" + M23.ToString() + " M24:" + M24.ToString() + "} {M31:" + M31.ToString() + " M32:" + M32.ToString() + " M33:" + M33.ToString() + " M34:" + M34.ToString() + "} {M41:" + M41.ToString() + " M42:" + M42.ToString() + " M43:" + M43.ToString() + " M44:" + M44.ToString() + "}" ); } #endregion #region Public Static Methods /// /// Creates a new which contains sum of two matrixes. /// /// The first matrix to add. /// The second matrix to add. /// The result of the matrix addition. public static Matrix4x4 Add(Matrix4x4 matrix1, Matrix4x4 matrix2) { matrix1.M11 += matrix2.M11; matrix1.M12 += matrix2.M12; matrix1.M13 += matrix2.M13; matrix1.M14 += matrix2.M14; matrix1.M21 += matrix2.M21; matrix1.M22 += matrix2.M22; matrix1.M23 += matrix2.M23; matrix1.M24 += matrix2.M24; matrix1.M31 += matrix2.M31; matrix1.M32 += matrix2.M32; matrix1.M33 += matrix2.M33; matrix1.M34 += matrix2.M34; matrix1.M41 += matrix2.M41; matrix1.M42 += matrix2.M42; matrix1.M43 += matrix2.M43; matrix1.M44 += matrix2.M44; return matrix1; } /// /// Creates a new which contains sum of two matrixes. /// /// The first matrix to add. /// The second matrix to add. /// The result of the matrix addition as an output parameter. public static void Add(ref Matrix4x4 matrix1, ref Matrix4x4 matrix2, out Matrix4x4 result) { result.M11 = matrix1.M11 + matrix2.M11; result.M12 = matrix1.M12 + matrix2.M12; result.M13 = matrix1.M13 + matrix2.M13; result.M14 = matrix1.M14 + matrix2.M14; result.M21 = matrix1.M21 + matrix2.M21; result.M22 = matrix1.M22 + matrix2.M22; result.M23 = matrix1.M23 + matrix2.M23; result.M24 = matrix1.M24 + matrix2.M24; result.M31 = matrix1.M31 + matrix2.M31; result.M32 = matrix1.M32 + matrix2.M32; result.M33 = matrix1.M33 + matrix2.M33; result.M34 = matrix1.M34 + matrix2.M34; result.M41 = matrix1.M41 + matrix2.M41; result.M42 = matrix1.M42 + matrix2.M42; result.M43 = matrix1.M43 + matrix2.M43; result.M44 = matrix1.M44 + matrix2.M44; } /// /// Creates a new for spherical billboarding that rotates around specified object position. /// /// Position of billboard object. It will rotate around that vector. /// The camera position. /// The camera up vector. /// Optional camera forward vector. /// The for spherical billboarding. public static Matrix4x4 CreateBillboard( Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Nullable cameraForwardVector ) { Matrix4x4 result; // Delegate to the other overload of the function to do the work CreateBillboard( ref objectPosition, ref cameraPosition, ref cameraUpVector, cameraForwardVector, out result ); return result; } /// /// Creates a new for spherical billboarding that rotates around specified object position. /// /// Position of billboard object. It will rotate around that vector. /// The camera position. /// The camera up vector. /// Optional camera forward vector. /// The for spherical billboarding as an output parameter. public static void CreateBillboard( ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, Vector3? cameraForwardVector, out Matrix4x4 result ) { Vector3 vector; Vector3 vector2; Vector3 vector3; vector.X = objectPosition.X - cameraPosition.X; vector.Y = objectPosition.Y - cameraPosition.Y; vector.Z = objectPosition.Z - cameraPosition.Z; float num = vector.LengthSquared(); if (num < 0.0001f) { vector = cameraForwardVector.HasValue ? -cameraForwardVector.Value : Vector3.Forward; } else { Vector3.Multiply( ref vector, (float) (1f / ((float) System.Math.Sqrt((double) num))), out vector ); } Vector3.Cross(ref cameraUpVector, ref vector, out vector3); vector3.Normalize(); Vector3.Cross(ref vector, ref vector3, out vector2); result.M11 = vector3.X; result.M12 = vector3.Y; result.M13 = vector3.Z; result.M14 = 0; result.M21 = vector2.X; result.M22 = vector2.Y; result.M23 = vector2.Z; result.M24 = 0; result.M31 = vector.X; result.M32 = vector.Y; result.M33 = vector.Z; result.M34 = 0; result.M41 = objectPosition.X; result.M42 = objectPosition.Y; result.M43 = objectPosition.Z; result.M44 = 1; } /// /// Creates a new for cylindrical billboarding that rotates around specified axis. /// /// Object position the billboard will rotate around. /// Camera position. /// Axis of billboard for rotation. /// Optional camera forward vector. /// Optional object forward vector. /// The for cylindrical billboarding. public static Matrix4x4 CreateConstrainedBillboard( Vector3 objectPosition, Vector3 cameraPosition, Vector3 rotateAxis, Nullable cameraForwardVector, Nullable objectForwardVector ) { Matrix4x4 result; CreateConstrainedBillboard( ref objectPosition, ref cameraPosition, ref rotateAxis, cameraForwardVector, objectForwardVector, out result ); return result; } /// /// Creates a new for cylindrical billboarding that rotates around specified axis. /// /// Object position the billboard will rotate around. /// Camera position. /// Axis of billboard for rotation. /// Optional camera forward vector. /// Optional object forward vector. /// The for cylindrical billboarding as an output parameter. public static void CreateConstrainedBillboard( ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 rotateAxis, Vector3? cameraForwardVector, Vector3? objectForwardVector, out Matrix4x4 result ) { float num; Vector3 vector; Vector3 vector2; Vector3 vector3; vector2.X = objectPosition.X - cameraPosition.X; vector2.Y = objectPosition.Y - cameraPosition.Y; vector2.Z = objectPosition.Z - cameraPosition.Z; float num2 = vector2.LengthSquared(); if (num2 < 0.0001f) { vector2 = cameraForwardVector.HasValue ? -cameraForwardVector.Value : Vector3.Forward; } else { Vector3.Multiply( ref vector2, (float) (1f / ((float) System.Math.Sqrt((double) num2))), out vector2 ); } Vector3 vector4 = rotateAxis; Vector3.Dot(ref rotateAxis, ref vector2, out num); if (System.Math.Abs(num) > 0.9982547f) { if (objectForwardVector.HasValue) { vector = objectForwardVector.Value; Vector3.Dot(ref rotateAxis, ref vector, out num); if (System.Math.Abs(num) > 0.9982547f) { num = ( (rotateAxis.X * Vector3.Forward.X) + (rotateAxis.Y * Vector3.Forward.Y) ) + (rotateAxis.Z * Vector3.Forward.Z); vector = (System.Math.Abs(num) > 0.9982547f) ? Vector3.Right : Vector3.Forward; } } else { num = ( (rotateAxis.X * Vector3.Forward.X) + (rotateAxis.Y * Vector3.Forward.Y) ) + (rotateAxis.Z * Vector3.Forward.Z); vector = (System.Math.Abs(num) > 0.9982547f) ? Vector3.Right : Vector3.Forward; } Vector3.Cross(ref rotateAxis, ref vector, out vector3); vector3.Normalize(); Vector3.Cross(ref vector3, ref rotateAxis, out vector); vector.Normalize(); } else { Vector3.Cross(ref rotateAxis, ref vector2, out vector3); vector3.Normalize(); Vector3.Cross(ref vector3, ref vector4, out vector); vector.Normalize(); } result.M11 = vector3.X; result.M12 = vector3.Y; result.M13 = vector3.Z; result.M14 = 0; result.M21 = vector4.X; result.M22 = vector4.Y; result.M23 = vector4.Z; result.M24 = 0; result.M31 = vector.X; result.M32 = vector.Y; result.M33 = vector.Z; result.M34 = 0; result.M41 = objectPosition.X; result.M42 = objectPosition.Y; result.M43 = objectPosition.Z; result.M44 = 1; } /// /// Creates a new which contains the rotation moment around specified axis. /// /// The axis of rotation. /// The angle of rotation in radians. /// The rotation . public static Matrix4x4 CreateFromAxisAngle(Vector3 axis, float angle) { Matrix4x4 result; CreateFromAxisAngle(ref axis, angle, out result); return result; } /// /// Creates a new which contains the rotation moment around specified axis. /// /// The axis of rotation. /// The angle of rotation in radians. /// The rotation as an output parameter. public static void CreateFromAxisAngle( ref Vector3 axis, float angle, out Matrix4x4 result ) { float x = axis.X; float y = axis.Y; float z = axis.Z; float num2 = (float) System.Math.Sin((double) angle); float num = (float) System.Math.Cos((double) angle); float num11 = x * x; float num10 = y * y; float num9 = z * z; float num8 = x * y; float num7 = x * z; float num6 = y * z; result.M11 = num11 + (num * (1f - num11)); result.M12 = (num8 - (num * num8)) + (num2 * z); result.M13 = (num7 - (num * num7)) - (num2 * y); result.M14 = 0; result.M21 = (num8 - (num * num8)) - (num2 * z); result.M22 = num10 + (num * (1f - num10)); result.M23 = (num6 - (num * num6)) + (num2 * x); result.M24 = 0; result.M31 = (num7 - (num * num7)) + (num2 * y); result.M32 = (num6 - (num * num6)) - (num2 * x); result.M33 = num9 + (num * (1f - num9)); result.M34 = 0; result.M41 = 0; result.M42 = 0; result.M43 = 0; result.M44 = 1; } /// /// Creates a new rotation from a . /// /// of rotation moment. /// The rotation . public static Matrix4x4 CreateFromQuaternion(Quaternion quaternion) { Matrix4x4 result; CreateFromQuaternion(ref quaternion, out result); return result; } /// /// Creates a new rotation from a . /// /// of rotation moment. /// The rotation as an output parameter. public static void CreateFromQuaternion(ref Quaternion quaternion, out Matrix4x4 result) { float num9 = quaternion.X * quaternion.X; float num8 = quaternion.Y * quaternion.Y; float num7 = quaternion.Z * quaternion.Z; float num6 = quaternion.X * quaternion.Y; float num5 = quaternion.Z * quaternion.W; float num4 = quaternion.Z * quaternion.X; float num3 = quaternion.Y * quaternion.W; float num2 = quaternion.Y * quaternion.Z; float num = quaternion.X * quaternion.W; result.M11 = 1f - (2f * (num8 + num7)); result.M12 = 2f * (num6 + num5); result.M13 = 2f * (num4 - num3); result.M14 = 0f; result.M21 = 2f * (num6 - num5); result.M22 = 1f - (2f * (num7 + num9)); result.M23 = 2f * (num2 + num); result.M24 = 0f; result.M31 = 2f * (num4 + num3); result.M32 = 2f * (num2 - num); result.M33 = 1f - (2f * (num8 + num9)); result.M34 = 0f; result.M41 = 0f; result.M42 = 0f; result.M43 = 0f; result.M44 = 1f; } /// /// Creates a new rotation from the specified yaw, pitch and roll values. /// /// The yaw rotation value in radians. /// The pitch rotation value in radians. /// The roll rotation value in radians. /// The rotation . /// For more information about yaw, pitch and roll visit http://en.wikipedia.org/wiki/Euler_angles. /// public static Matrix4x4 CreateFromYawPitchRoll(float yaw, float pitch, float roll) { Matrix4x4 matrix; CreateFromYawPitchRoll(yaw, pitch, roll, out matrix); return matrix; } /// /// Creates a new rotation from the specified yaw, pitch and roll values. /// /// The yaw rotation value in radians. /// The pitch rotation value in radians. /// The roll rotation value in radians. /// The rotation as an output parameter. /// For more information about yaw, pitch and roll visit http://en.wikipedia.org/wiki/Euler_angles. /// public static void CreateFromYawPitchRoll( float yaw, float pitch, float roll, out Matrix4x4 result ) { Quaternion quaternion; Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll, out quaternion); CreateFromQuaternion(ref quaternion, out result); } /// /// Creates a new viewing . /// /// Position of the camera. /// Lookup vector of the camera. /// The direction of the upper edge of the camera. /// The viewing . public static Matrix4x4 CreateLookAt( Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector ) { Matrix4x4 matrix; CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out matrix); return matrix; } /// /// Creates a new viewing . /// /// Position of the camera. /// Lookup vector of the camera. /// The direction of the upper edge of the camera. /// The viewing as an output parameter. public static void CreateLookAt( ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector, out Matrix4x4 result ) { Vector3 vectorA = Vector3.Normalize(cameraPosition - cameraTarget); Vector3 vectorB = Vector3.Normalize(Vector3.Cross(cameraUpVector, vectorA)); Vector3 vectorC = Vector3.Cross(vectorA, vectorB); result.M11 = vectorB.X; result.M12 = vectorC.X; result.M13 = vectorA.X; result.M14 = 0f; result.M21 = vectorB.Y; result.M22 = vectorC.Y; result.M23 = vectorA.Y; result.M24 = 0f; result.M31 = vectorB.Z; result.M32 = vectorC.Z; result.M33 = vectorA.Z; result.M34 = 0f; result.M41 = -Vector3.Dot(vectorB, cameraPosition); result.M42 = -Vector3.Dot(vectorC, cameraPosition); result.M43 = -Vector3.Dot(vectorA, cameraPosition); result.M44 = 1f; } /// /// Creates a new projection for orthographic view. /// /// Width of the viewing volume. /// Height of the viewing volume. /// Depth of the near plane. /// Depth of the far plane. /// The new projection for orthographic view. public static Matrix4x4 CreateOrthographic( float width, float height, float zNearPlane, float zFarPlane ) { Matrix4x4 matrix; CreateOrthographic(width, height, zNearPlane, zFarPlane, out matrix); return matrix; } /// /// Creates a new projection for orthographic view. /// /// Width of the viewing volume. /// Height of the viewing volume. /// Depth of the near plane. /// Depth of the far plane. /// The new projection for orthographic view as an output parameter. public static void CreateOrthographic( float width, float height, float zNearPlane, float zFarPlane, out Matrix4x4 result ) { result.M11 = 2f / width; result.M12 = result.M13 = result.M14 = 0f; result.M22 = 2f / height; result.M21 = result.M23 = result.M24 = 0f; result.M33 = 1f / (zNearPlane - zFarPlane); result.M31 = result.M32 = result.M34 = 0f; result.M41 = result.M42 = 0f; result.M43 = zNearPlane / (zNearPlane - zFarPlane); result.M44 = 1f; } /// /// Creates a new projection for customized orthographic view. /// /// Lower x-value at the near plane. /// Upper x-value at the near plane. /// Lower y-coordinate at the near plane. /// Upper y-value at the near plane. /// Depth of the near plane. /// Depth of the far plane. /// The new projection for customized orthographic view. public static Matrix4x4 CreateOrthographicOffCenter( float left, float right, float bottom, float top, float zNearPlane, float zFarPlane ) { Matrix4x4 matrix; CreateOrthographicOffCenter( left, right, bottom, top, zNearPlane, zFarPlane, out matrix ); return matrix; } /// /// Creates a new projection for customized orthographic view. /// /// Lower x-value at the near plane. /// Upper x-value at the near plane. /// Lower y-coordinate at the near plane. /// Upper y-value at the near plane. /// Depth of the near plane. /// Depth of the far plane. /// The new projection for customized orthographic view as an output parameter. public static void CreateOrthographicOffCenter( float left, float right, float bottom, float top, float zNearPlane, float zFarPlane, out Matrix4x4 result ) { result.M11 = (float) (2.0 / ((double) right - (double) left)); result.M12 = 0.0f; result.M13 = 0.0f; result.M14 = 0.0f; result.M21 = 0.0f; result.M22 = (float) (2.0 / ((double) bottom - (double) top)); result.M23 = 0.0f; result.M24 = 0.0f; result.M31 = 0.0f; result.M32 = 0.0f; result.M33 = (float) (1.0 / ((double) zNearPlane - (double) zFarPlane)); result.M34 = 0.0f; result.M41 = (float) ( -((double) left + (double) right) / ((double) right - (double) left) ); result.M42 = (float) ( -((double) top + (double) bottom) / ((double) bottom - (double) top) ); result.M43 = (float) ( (double) zNearPlane / ((double) zNearPlane - (double) zFarPlane) ); result.M44 = 1.0f; } /// /// Creates a new projection for perspective view. /// /// Width of the viewing volume. /// Height of the viewing volume. /// Distance to the near plane. /// Distance to the far plane. /// The new projection for perspective view. public static Matrix4x4 CreatePerspective( float width, float height, float nearPlaneDistance, float farPlaneDistance ) { Matrix4x4 matrix; CreatePerspective(width, height, nearPlaneDistance, farPlaneDistance, out matrix); return matrix; } /// /// Creates a new projection for perspective view. /// /// Width of the viewing volume. /// Height of the viewing volume. /// Distance to the near plane. /// Distance to the far plane. /// The new projection for perspective view as an output parameter. public static void CreatePerspective( float width, float height, float nearPlaneDistance, float farPlaneDistance, out Matrix4x4 result ) { if (nearPlaneDistance <= 0f) { throw new ArgumentException("nearPlaneDistance <= 0"); } if (farPlaneDistance <= 0f) { throw new ArgumentException("farPlaneDistance <= 0"); } if (nearPlaneDistance >= farPlaneDistance) { throw new ArgumentException("nearPlaneDistance >= farPlaneDistance"); } result.M11 = (2f * nearPlaneDistance) / width; result.M12 = result.M13 = result.M14 = 0f; result.M22 = -(2f * nearPlaneDistance) / height; result.M21 = result.M23 = result.M24 = 0f; result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance); result.M31 = result.M32 = 0f; result.M34 = -1f; result.M41 = result.M42 = result.M44 = 0f; result.M43 = ( (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance) ); } /// /// Creates a new projection for perspective view with field of view. /// /// Field of view in the y direction in radians. /// Width divided by height of the viewing volume. /// Distance to the near plane. /// Distance to the far plane. /// The new projection for perspective view with FOV. public static Matrix4x4 CreatePerspectiveFieldOfView( float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance ) { Matrix4x4 result; CreatePerspectiveFieldOfView( fieldOfView, aspectRatio, nearPlaneDistance, farPlaneDistance, out result ); return result; } /// /// Creates a new projection for perspective view with field of view. /// /// Field of view in the y direction in radians. /// Width divided by height of the viewing volume. /// Distance of the near plane. /// Distance of the far plane. /// The new projection for perspective view with FOV as an output parameter. public static void CreatePerspectiveFieldOfView( float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance, out Matrix4x4 result ) { if ((fieldOfView <= 0f) || (fieldOfView >= 3.141593f)) { throw new ArgumentException("fieldOfView <= 0 or >= PI"); } if (nearPlaneDistance <= 0f) { throw new ArgumentException("nearPlaneDistance <= 0"); } if (farPlaneDistance <= 0f) { throw new ArgumentException("farPlaneDistance <= 0"); } if (nearPlaneDistance >= farPlaneDistance) { throw new ArgumentException("nearPlaneDistance >= farPlaneDistance"); } float num = 1f / ((float) System.Math.Tan((double) (fieldOfView * 0.5f))); result.M11 = num / aspectRatio; result.M12 = result.M13 = result.M14 = 0; result.M22 = -num; result.M21 = result.M23 = result.M24 = 0; result.M31 = result.M32 = 0f; result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance); result.M34 = -1; result.M41 = result.M42 = result.M44 = 0; result.M43 = ( (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance) ); } /// /// Creates a new projection for customized perspective view. /// /// Lower x-value at the near plane. /// Upper x-value at the near plane. /// Lower y-coordinate at the near plane. /// Upper y-value at the near plane. /// Distance to the near plane. /// Distance to the far plane. /// The new for customized perspective view. public static Matrix4x4 CreatePerspectiveOffCenter( float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance ) { Matrix4x4 result; CreatePerspectiveOffCenter( left, right, bottom, top, nearPlaneDistance, farPlaneDistance, out result ); return result; } /// /// Creates a new projection for customized perspective view. /// /// Lower x-value at the near plane. /// Upper x-value at the near plane. /// Lower y-coordinate at the near plane. /// Upper y-value at the near plane. /// Distance to the near plane. /// Distance to the far plane. /// The new for customized perspective view as an output parameter. public static void CreatePerspectiveOffCenter( float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance, out Matrix4x4 result ) { if (nearPlaneDistance <= 0f) { throw new ArgumentException("nearPlaneDistance <= 0"); } if (farPlaneDistance <= 0f) { throw new ArgumentException("farPlaneDistance <= 0"); } if (nearPlaneDistance >= farPlaneDistance) { throw new ArgumentException("nearPlaneDistance >= farPlaneDistance"); } result.M11 = (2f * nearPlaneDistance) / (right - left); result.M12 = result.M13 = result.M14 = 0; result.M22 = -(2f * nearPlaneDistance) / (top - bottom); result.M21 = result.M23 = result.M24 = 0; result.M31 = (left + right) / (right - left); result.M32 = (top + bottom) / (top - bottom); result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance); result.M34 = -1; result.M43 = ( (nearPlaneDistance * farPlaneDistance) / (nearPlaneDistance - farPlaneDistance) ); result.M41 = result.M42 = result.M44 = 0; } /// /// Creates a new rotation around X axis. /// /// Angle in radians. /// The rotation around X axis. public static Matrix4x4 CreateRotationX(float radians) { Matrix4x4 result; CreateRotationX(radians, out result); return result; } /// /// Creates a new rotation around X axis. /// /// Angle in radians. /// The rotation around X axis as an output parameter. public static void CreateRotationX(float radians, out Matrix4x4 result) { result = Matrix4x4.Identity; float val1 = (float) System.Math.Cos(radians); float val2 = (float) System.Math.Sin(radians); result.M22 = val1; result.M23 = val2; result.M32 = -val2; result.M33 = val1; } /// /// Creates a new rotation around Y axis. /// /// Angle in radians. /// The rotation around Y axis. public static Matrix4x4 CreateRotationY(float radians) { Matrix4x4 result; CreateRotationY(radians, out result); return result; } /// /// Creates a new rotation around Y axis. /// /// Angle in radians. /// The rotation around Y axis as an output parameter. public static void CreateRotationY(float radians, out Matrix4x4 result) { result = Matrix4x4.Identity; float val1 = (float) System.Math.Cos(radians); float val2 = (float) System.Math.Sin(radians); result.M11 = val1; result.M13 = -val2; result.M31 = val2; result.M33 = val1; } /// /// Creates a new rotation around Z axis. /// /// Angle in radians. /// The rotation around Z axis. public static Matrix4x4 CreateRotationZ(float radians) { Matrix4x4 result; CreateRotationZ(radians, out result); return result; } /// /// Creates a new rotation around Z axis. /// /// Angle in radians. /// The rotation around Z axis as an output parameter. public static void CreateRotationZ(float radians, out Matrix4x4 result) { result = Matrix4x4.Identity; float val1 = (float) System.Math.Cos(radians); float val2 = (float) System.Math.Sin(radians); result.M11 = val1; result.M12 = val2; result.M21 = -val2; result.M22 = val1; } /// /// Creates a new scaling . /// /// Scale value for all three axises. /// The scaling . public static Matrix4x4 CreateScale(float scale) { Matrix4x4 result; CreateScale(scale, scale, scale, out result); return result; } /// /// Creates a new scaling . /// /// Scale value for all three axises. /// The scaling as an output parameter. public static void CreateScale(float scale, out Matrix4x4 result) { CreateScale(scale, scale, scale, out result); } /// /// Creates a new scaling . /// /// Scale value for X axis. /// Scale value for Y axis. /// Scale value for Z axis. /// The scaling . public static Matrix4x4 CreateScale(float xScale, float yScale, float zScale) { Matrix4x4 result; CreateScale(xScale, yScale, zScale, out result); return result; } /// /// Creates a new scaling . /// /// Scale value for X axis. /// Scale value for Y axis. /// Scale value for Z axis. /// The scaling as an output parameter. public static void CreateScale( float xScale, float yScale, float zScale, out Matrix4x4 result ) { result.M11 = xScale; result.M12 = 0; result.M13 = 0; result.M14 = 0; result.M21 = 0; result.M22 = yScale; result.M23 = 0; result.M24 = 0; result.M31 = 0; result.M32 = 0; result.M33 = zScale; result.M34 = 0; result.M41 = 0; result.M42 = 0; result.M43 = 0; result.M44 = 1; } /// /// Creates a new scaling . /// /// representing x,y and z scale values. /// The scaling . public static Matrix4x4 CreateScale(Vector3 scales) { Matrix4x4 result; CreateScale(ref scales, out result); return result; } /// /// Creates a new scaling . /// /// representing x,y and z scale values. /// The scaling as an output parameter. public static void CreateScale(ref Vector3 scales, out Matrix4x4 result) { result.M11 = scales.X; result.M12 = 0; result.M13 = 0; result.M14 = 0; result.M21 = 0; result.M22 = scales.Y; result.M23 = 0; result.M24 = 0; result.M31 = 0; result.M32 = 0; result.M33 = scales.Z; result.M34 = 0; result.M41 = 0; result.M42 = 0; result.M43 = 0; result.M44 = 1; } /// /// Creates a new that flattens geometry into a specified as if casting a shadow from a specified light source. /// /// A vector specifying the direction from which the light that will cast the shadow is coming. /// The plane onto which the new matrix should flatten geometry so as to cast a shadow. /// A that can be used to flatten geometry onto the specified plane from the specified direction. public static Matrix4x4 CreateShadow(Vector3 lightDirection, Plane plane) { Matrix4x4 result; CreateShadow(ref lightDirection, ref plane, out result); return result; } /// /// Creates a new that flattens geometry into a specified as if casting a shadow from a specified light source. /// /// A vector specifying the direction from which the light that will cast the shadow is coming. /// The plane onto which the new matrix should flatten geometry so as to cast a shadow. /// A that can be used to flatten geometry onto the specified plane from the specified direction as an output parameter. public static void CreateShadow( ref Vector3 lightDirection, ref Plane plane, out Matrix4x4 result) { float dot = ( (plane.Normal.X * lightDirection.X) + (plane.Normal.Y * lightDirection.Y) + (plane.Normal.Z * lightDirection.Z) ); float x = -plane.Normal.X; float y = -plane.Normal.Y; float z = -plane.Normal.Z; float d = -plane.D; result.M11 = (x * lightDirection.X) + dot; result.M12 = x * lightDirection.Y; result.M13 = x * lightDirection.Z; result.M14 = 0; result.M21 = y * lightDirection.X; result.M22 = (y * lightDirection.Y) + dot; result.M23 = y * lightDirection.Z; result.M24 = 0; result.M31 = z * lightDirection.X; result.M32 = z * lightDirection.Y; result.M33 = (z * lightDirection.Z) + dot; result.M34 = 0; result.M41 = d * lightDirection.X; result.M42 = d * lightDirection.Y; result.M43 = d * lightDirection.Z; result.M44 = dot; } /// /// Creates a new translation . /// /// X coordinate of translation. /// Y coordinate of translation. /// Z coordinate of translation. /// The translation . public static Matrix4x4 CreateTranslation( float xPosition, float yPosition, float zPosition ) { Matrix4x4 result; CreateTranslation(xPosition, yPosition, zPosition, out result); return result; } /// /// Creates a new translation . /// /// X,Y and Z coordinates of translation. /// The translation as an output parameter. public static void CreateTranslation(ref Vector3 position, out Matrix4x4 result) { result.M11 = 1; result.M12 = 0; result.M13 = 0; result.M14 = 0; result.M21 = 0; result.M22 = 1; result.M23 = 0; result.M24 = 0; result.M31 = 0; result.M32 = 0; result.M33 = 1; result.M34 = 0; result.M41 = position.X; result.M42 = position.Y; result.M43 = position.Z; result.M44 = 1; } /// /// Creates a new translation . /// /// X,Y and Z coordinates of translation. /// The translation . public static Matrix4x4 CreateTranslation(Vector3 position) { Matrix4x4 result; CreateTranslation(ref position, out result); return result; } /// /// Creates a new translation . /// /// X coordinate of translation. /// Y coordinate of translation. /// Z coordinate of translation. /// The translation as an output parameter. public static void CreateTranslation( float xPosition, float yPosition, float zPosition, out Matrix4x4 result ) { result.M11 = 1; result.M12 = 0; result.M13 = 0; result.M14 = 0; result.M21 = 0; result.M22 = 1; result.M23 = 0; result.M24 = 0; result.M31 = 0; result.M32 = 0; result.M33 = 1; result.M34 = 0; result.M41 = xPosition; result.M42 = yPosition; result.M43 = zPosition; result.M44 = 1; } /// /// Creates a new reflection . /// /// The plane that used for reflection calculation. /// The reflection . public static Matrix4x4 CreateReflection(Plane value) { Matrix4x4 result; CreateReflection(ref value, out result); return result; } /// /// Creates a new reflection . /// /// The plane that used for reflection calculation. /// The reflection as an output parameter. public static void CreateReflection(ref Plane value, out Matrix4x4 result) { Plane plane; Plane.Normalize(ref value, out plane); float x = plane.Normal.X; float y = plane.Normal.Y; float z = plane.Normal.Z; float num3 = -2f * x; float num2 = -2f * y; float num = -2f * z; result.M11 = (num3 * x) + 1f; result.M12 = num2 * x; result.M13 = num * x; result.M14 = 0; result.M21 = num3 * y; result.M22 = (num2 * y) + 1; result.M23 = num * y; result.M24 = 0; result.M31 = num3 * z; result.M32 = num2 * z; result.M33 = (num * z) + 1; result.M34 = 0; result.M41 = num3 * plane.D; result.M42 = num2 * plane.D; result.M43 = num * plane.D; result.M44 = 1; } /// /// Creates a new world . /// /// The position vector. /// The forward direction vector. /// The upward direction vector. Usually . /// The world . public static Matrix4x4 CreateWorld(Vector3 position, Vector3 forward, Vector3 up) { Matrix4x4 ret; CreateWorld(ref position, ref forward, ref up, out ret); return ret; } /// /// Creates a new world . /// /// The position vector. /// The forward direction vector. /// The upward direction vector. Usually . /// The world as an output parameter. public static void CreateWorld( ref Vector3 position, ref Vector3 forward, ref Vector3 up, out Matrix4x4 result ) { Vector3 x, y, z; Vector3.Normalize(ref forward, out z); Vector3.Cross(ref forward, ref up, out x); Vector3.Cross(ref x, ref forward, out y); x.Normalize(); y.Normalize(); result = new Matrix4x4(); result.Right = x; result.Up = y; result.Forward = z; result.Translation = position; result.M44 = 1f; } /// /// Divides the elements of a by the elements of another matrix. /// /// Source . /// Divisor . /// The result of dividing the matrix. public static Matrix4x4 Divide(Matrix4x4 matrix1, Matrix4x4 matrix2) { matrix1.M11 = matrix1.M11 / matrix2.M11; matrix1.M12 = matrix1.M12 / matrix2.M12; matrix1.M13 = matrix1.M13 / matrix2.M13; matrix1.M14 = matrix1.M14 / matrix2.M14; matrix1.M21 = matrix1.M21 / matrix2.M21; matrix1.M22 = matrix1.M22 / matrix2.M22; matrix1.M23 = matrix1.M23 / matrix2.M23; matrix1.M24 = matrix1.M24 / matrix2.M24; matrix1.M31 = matrix1.M31 / matrix2.M31; matrix1.M32 = matrix1.M32 / matrix2.M32; matrix1.M33 = matrix1.M33 / matrix2.M33; matrix1.M34 = matrix1.M34 / matrix2.M34; matrix1.M41 = matrix1.M41 / matrix2.M41; matrix1.M42 = matrix1.M42 / matrix2.M42; matrix1.M43 = matrix1.M43 / matrix2.M43; matrix1.M44 = matrix1.M44 / matrix2.M44; return matrix1; } /// /// Divides the elements of a by the elements of another matrix. /// /// Source . /// Divisor . /// The result of dividing the matrix as an output parameter. public static void Divide(ref Matrix4x4 matrix1, ref Matrix4x4 matrix2, out Matrix4x4 result) { result.M11 = matrix1.M11 / matrix2.M11; result.M12 = matrix1.M12 / matrix2.M12; result.M13 = matrix1.M13 / matrix2.M13; result.M14 = matrix1.M14 / matrix2.M14; result.M21 = matrix1.M21 / matrix2.M21; result.M22 = matrix1.M22 / matrix2.M22; result.M23 = matrix1.M23 / matrix2.M23; result.M24 = matrix1.M24 / matrix2.M24; result.M31 = matrix1.M31 / matrix2.M31; result.M32 = matrix1.M32 / matrix2.M32; result.M33 = matrix1.M33 / matrix2.M33; result.M34 = matrix1.M34 / matrix2.M34; result.M41 = matrix1.M41 / matrix2.M41; result.M42 = matrix1.M42 / matrix2.M42; result.M43 = matrix1.M43 / matrix2.M43; result.M44 = matrix1.M44 / matrix2.M44; } /// /// Divides the elements of a by a scalar. /// /// Source . /// Divisor scalar. /// The result of dividing a matrix by a scalar. public static Matrix4x4 Divide(Matrix4x4 matrix1, float divider) { float num = 1f / divider; matrix1.M11 = matrix1.M11 * num; matrix1.M12 = matrix1.M12 * num; matrix1.M13 = matrix1.M13 * num; matrix1.M14 = matrix1.M14 * num; matrix1.M21 = matrix1.M21 * num; matrix1.M22 = matrix1.M22 * num; matrix1.M23 = matrix1.M23 * num; matrix1.M24 = matrix1.M24 * num; matrix1.M31 = matrix1.M31 * num; matrix1.M32 = matrix1.M32 * num; matrix1.M33 = matrix1.M33 * num; matrix1.M34 = matrix1.M34 * num; matrix1.M41 = matrix1.M41 * num; matrix1.M42 = matrix1.M42 * num; matrix1.M43 = matrix1.M43 * num; matrix1.M44 = matrix1.M44 * num; return matrix1; } /// /// Divides the elements of a by a scalar. /// /// Source . /// Divisor scalar. /// The result of dividing a matrix by a scalar as an output parameter. public static void Divide(ref Matrix4x4 matrix1, float divider, out Matrix4x4 result) { float num = 1f / divider; result.M11 = matrix1.M11 * num; result.M12 = matrix1.M12 * num; result.M13 = matrix1.M13 * num; result.M14 = matrix1.M14 * num; result.M21 = matrix1.M21 * num; result.M22 = matrix1.M22 * num; result.M23 = matrix1.M23 * num; result.M24 = matrix1.M24 * num; result.M31 = matrix1.M31 * num; result.M32 = matrix1.M32 * num; result.M33 = matrix1.M33 * num; result.M34 = matrix1.M34 * num; result.M41 = matrix1.M41 * num; result.M42 = matrix1.M42 * num; result.M43 = matrix1.M43 * num; result.M44 = matrix1.M44 * num; } /// /// Creates a new which contains inversion of the specified matrix. /// /// Source . /// The inverted matrix. public static Matrix4x4 Invert(Matrix4x4 matrix) { Invert(ref matrix, out matrix); return matrix; } /// /// Creates a new which contains inversion of the specified matrix. /// /// Source . /// The inverted matrix as output parameter. public static void Invert(ref Matrix4x4 matrix, out Matrix4x4 result) { /* * Use Laplace expansion theorem to calculate the inverse of a 4x4 matrix. * * 1. Calculate the 2x2 determinants needed the 4x4 determinant based on * the 2x2 determinants. * 3. Create the adjugate matrix, which satisfies: A * adj(A) = det(A) * I. * 4. Divide adjugate matrix with the determinant to find the inverse. */ float num1 = matrix.M11; float num2 = matrix.M12; float num3 = matrix.M13; float num4 = matrix.M14; float num5 = matrix.M21; float num6 = matrix.M22; float num7 = matrix.M23; float num8 = matrix.M24; float num9 = matrix.M31; float num10 = matrix.M32; float num11 = matrix.M33; float num12 = matrix.M34; float num13 = matrix.M41; float num14 = matrix.M42; float num15 = matrix.M43; float num16 = matrix.M44; float num17 = (float) ( (double) num11 * (double) num16 - (double) num12 * (double) num15 ); float num18 = (float) ( (double) num10 * (double) num16 - (double) num12 * (double) num14 ); float num19 = (float) ( (double) num10 * (double) num15 - (double) num11 * (double) num14 ); float num20 = (float) ( (double) num9 * (double) num16 - (double) num12 * (double) num13 ); float num21 = (float) ( (double) num9 * (double) num15 - (double) num11 * (double) num13 ); float num22 = (float) ( (double) num9 * (double) num14 - (double) num10 * (double) num13 ); float num23 = (float) ( (double) num6 * (double) num17 - (double) num7 * (double) num18 + (double) num8 * (double) num19 ); float num24 = (float) -( (double) num5 * (double) num17 - (double) num7 * (double) num20 + (double) num8 * (double) num21 ); float num25 = (float) ( (double) num5 * (double) num18 - (double) num6 * (double) num20 + (double) num8 * (double) num22 ); float num26 = (float) -( (double) num5 * (double) num19 - (double) num6 * (double) num21 + (double) num7 * (double) num22 ); float num27 = (float) ( 1.0 / ( (double) num1 * (double) num23 + (double) num2 * (double) num24 + (double) num3 * (double) num25 + (double) num4 * (double) num26 ) ); result.M11 = num23 * num27; result.M21 = num24 * num27; result.M31 = num25 * num27; result.M41 = num26 * num27; result.M12 = (float) ( -( (double) num2 * (double) num17 - (double) num3 * (double) num18 + (double) num4 * (double) num19 ) * num27 ); result.M22 = (float) ( ( (double) num1 * (double) num17 - (double) num3 * (double) num20 + (double) num4 * (double) num21 ) * num27 ); result.M32 = (float) ( -( (double) num1 * (double) num18 - (double) num2 * (double) num20 + (double) num4 * (double) num22 ) * num27 ); result.M42 = (float) ( ( (double) num1 * (double) num19 - (double) num2 * (double) num21 + (double) num3 * (double) num22 ) * num27 ); float num28 = (float) ( (double) num7 * (double) num16 - (double) num8 * (double) num15 ); float num29 = (float) ( (double) num6 * (double) num16 - (double) num8 * (double) num14 ); float num30 = (float) ( (double) num6 * (double) num15 - (double) num7 * (double) num14 ); float num31 = (float) ( (double) num5 * (double) num16 - (double) num8 * (double) num13 ); float num32 = (float) ( (double) num5 * (double) num15 - (double) num7 * (double) num13 ); float num33 = (float) ( (double) num5 * (double) num14 - (double) num6 * (double) num13 ); result.M13 = (float) ( ( (double) num2 * (double) num28 - (double) num3 * (double) num29 + (double) num4 * (double) num30 ) * num27 ); result.M23 = (float) ( -( (double) num1 * (double) num28 - (double) num3 * (double) num31 + (double) num4 * (double) num32 ) * num27 ); result.M33 = (float) ( ( (double) num1 * (double) num29 - (double) num2 * (double) num31 + (double) num4 * (double) num33 ) * num27 ); result.M43 = (float) ( -( (double) num1 * (double) num30 - (double) num2 * (double) num32 + (double) num3 * (double) num33 ) * num27 ); float num34 = (float) ( (double) num7 * (double) num12 - (double) num8 * (double) num11 ); float num35 = (float) ( (double) num6 * (double) num12 - (double) num8 * (double) num10 ); float num36 = (float) ( (double) num6 * (double) num11 - (double) num7 * (double) num10 ); float num37 = (float) ( (double) num5 * (double) num12 - (double) num8 * (double) num9); float num38 = (float) ( (double) num5 * (double) num11 - (double) num7 * (double) num9 ); float num39 = (float) ( (double) num5 * (double) num10 - (double) num6 * (double) num9 ); result.M14 = (float) ( -( (double) num2 * (double) num34 - (double) num3 * (double) num35 + (double) num4 * (double) num36 ) * num27 ); result.M24 = (float) ( ( (double) num1 * (double) num34 - (double) num3 * (double) num37 + (double) num4 * (double) num38 ) * num27 ); result.M34 = (float) ( -( (double) num1 * (double) num35 - (double) num2 * (double) num37 + (double) num4 * (double) num39 ) * num27 ); result.M44 = (float) ( ( (double) num1 * (double) num36 - (double) num2 * (double) num38 + (double) num3 * (double) num39 ) * num27 ); } /// /// Creates a new that contains linear interpolation of the values in specified matrixes. /// /// The first . /// The second . /// Weighting value(between 0.0 and 1.0). /// >The result of linear interpolation of the specified matrixes. public static Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount) { matrix1.M11 = matrix1.M11 + ((matrix2.M11 - matrix1.M11) * amount); matrix1.M12 = matrix1.M12 + ((matrix2.M12 - matrix1.M12) * amount); matrix1.M13 = matrix1.M13 + ((matrix2.M13 - matrix1.M13) * amount); matrix1.M14 = matrix1.M14 + ((matrix2.M14 - matrix1.M14) * amount); matrix1.M21 = matrix1.M21 + ((matrix2.M21 - matrix1.M21) * amount); matrix1.M22 = matrix1.M22 + ((matrix2.M22 - matrix1.M22) * amount); matrix1.M23 = matrix1.M23 + ((matrix2.M23 - matrix1.M23) * amount); matrix1.M24 = matrix1.M24 + ((matrix2.M24 - matrix1.M24) * amount); matrix1.M31 = matrix1.M31 + ((matrix2.M31 - matrix1.M31) * amount); matrix1.M32 = matrix1.M32 + ((matrix2.M32 - matrix1.M32) * amount); matrix1.M33 = matrix1.M33 + ((matrix2.M33 - matrix1.M33) * amount); matrix1.M34 = matrix1.M34 + ((matrix2.M34 - matrix1.M34) * amount); matrix1.M41 = matrix1.M41 + ((matrix2.M41 - matrix1.M41) * amount); matrix1.M42 = matrix1.M42 + ((matrix2.M42 - matrix1.M42) * amount); matrix1.M43 = matrix1.M43 + ((matrix2.M43 - matrix1.M43) * amount); matrix1.M44 = matrix1.M44 + ((matrix2.M44 - matrix1.M44) * amount); return matrix1; } /// /// Creates a new that contains linear interpolation of the values in specified matrixes. /// /// The first . /// The second . /// Weighting value(between 0.0 and 1.0). /// The result of linear interpolation of the specified matrixes as an output parameter. public static void Lerp( ref Matrix4x4 matrix1, ref Matrix4x4 matrix2, float amount, out Matrix4x4 result ) { result.M11 = matrix1.M11 + ((matrix2.M11 - matrix1.M11) * amount); result.M12 = matrix1.M12 + ((matrix2.M12 - matrix1.M12) * amount); result.M13 = matrix1.M13 + ((matrix2.M13 - matrix1.M13) * amount); result.M14 = matrix1.M14 + ((matrix2.M14 - matrix1.M14) * amount); result.M21 = matrix1.M21 + ((matrix2.M21 - matrix1.M21) * amount); result.M22 = matrix1.M22 + ((matrix2.M22 - matrix1.M22) * amount); result.M23 = matrix1.M23 + ((matrix2.M23 - matrix1.M23) * amount); result.M24 = matrix1.M24 + ((matrix2.M24 - matrix1.M24) * amount); result.M31 = matrix1.M31 + ((matrix2.M31 - matrix1.M31) * amount); result.M32 = matrix1.M32 + ((matrix2.M32 - matrix1.M32) * amount); result.M33 = matrix1.M33 + ((matrix2.M33 - matrix1.M33) * amount); result.M34 = matrix1.M34 + ((matrix2.M34 - matrix1.M34) * amount); result.M41 = matrix1.M41 + ((matrix2.M41 - matrix1.M41) * amount); result.M42 = matrix1.M42 + ((matrix2.M42 - matrix1.M42) * amount); result.M43 = matrix1.M43 + ((matrix2.M43 - matrix1.M43) * amount); result.M44 = matrix1.M44 + ((matrix2.M44 - matrix1.M44) * amount); } /// /// Creates a new that contains a multiplication of two matrix. /// /// Source . /// Source . /// Result of the matrix multiplication. public static Matrix4x4 Multiply( Matrix4x4 matrix1, Matrix4x4 matrix2 ) { float m11 = ( (matrix1.M11 * matrix2.M11) + (matrix1.M12 * matrix2.M21) + (matrix1.M13 * matrix2.M31) + (matrix1.M14 * matrix2.M41) ); float m12 = ( (matrix1.M11 * matrix2.M12) + (matrix1.M12 * matrix2.M22) + (matrix1.M13 * matrix2.M32) + (matrix1.M14 * matrix2.M42) ); float m13 = ( (matrix1.M11 * matrix2.M13) + (matrix1.M12 * matrix2.M23) + (matrix1.M13 * matrix2.M33) + (matrix1.M14 * matrix2.M43) ); float m14 = ( (matrix1.M11 * matrix2.M14) + (matrix1.M12 * matrix2.M24) + (matrix1.M13 * matrix2.M34) + (matrix1.M14 * matrix2.M44) ); float m21 = ( (matrix1.M21 * matrix2.M11) + (matrix1.M22 * matrix2.M21) + (matrix1.M23 * matrix2.M31) + (matrix1.M24 * matrix2.M41) ); float m22 = ( (matrix1.M21 * matrix2.M12) + (matrix1.M22 * matrix2.M22) + (matrix1.M23 * matrix2.M32) + (matrix1.M24 * matrix2.M42) ); float m23 = ( (matrix1.M21 * matrix2.M13) + (matrix1.M22 * matrix2.M23) + (matrix1.M23 * matrix2.M33) + (matrix1.M24 * matrix2.M43) ); float m24 = ( (matrix1.M21 * matrix2.M14) + (matrix1.M22 * matrix2.M24) + (matrix1.M23 * matrix2.M34) + (matrix1.M24 * matrix2.M44) ); float m31 = ( (matrix1.M31 * matrix2.M11) + (matrix1.M32 * matrix2.M21) + (matrix1.M33 * matrix2.M31) + (matrix1.M34 * matrix2.M41) ); float m32 = ( (matrix1.M31 * matrix2.M12) + (matrix1.M32 * matrix2.M22) + (matrix1.M33 * matrix2.M32) + (matrix1.M34 * matrix2.M42) ); float m33 = ( (matrix1.M31 * matrix2.M13) + (matrix1.M32 * matrix2.M23) + (matrix1.M33 * matrix2.M33) + (matrix1.M34 * matrix2.M43) ); float m34 = ( (matrix1.M31 * matrix2.M14) + (matrix1.M32 * matrix2.M24) + (matrix1.M33 * matrix2.M34) + (matrix1.M34 * matrix2.M44) ); float m41 = ( (matrix1.M41 * matrix2.M11) + (matrix1.M42 * matrix2.M21) + (matrix1.M43 * matrix2.M31) + (matrix1.M44 * matrix2.M41) ); float m42 = ( (matrix1.M41 * matrix2.M12) + (matrix1.M42 * matrix2.M22) + (matrix1.M43 * matrix2.M32) + (matrix1.M44 * matrix2.M42) ); float m43 = ( (matrix1.M41 * matrix2.M13) + (matrix1.M42 * matrix2.M23) + (matrix1.M43 * matrix2.M33) + (matrix1.M44 * matrix2.M43) ); float m44 = ( (matrix1.M41 * matrix2.M14) + (matrix1.M42 * matrix2.M24) + (matrix1.M43 * matrix2.M34) + (matrix1.M44 * matrix2.M44) ); matrix1.M11 = m11; matrix1.M12 = m12; matrix1.M13 = m13; matrix1.M14 = m14; matrix1.M21 = m21; matrix1.M22 = m22; matrix1.M23 = m23; matrix1.M24 = m24; matrix1.M31 = m31; matrix1.M32 = m32; matrix1.M33 = m33; matrix1.M34 = m34; matrix1.M41 = m41; matrix1.M42 = m42; matrix1.M43 = m43; matrix1.M44 = m44; return matrix1; } /// /// Creates a new that contains a multiplication of two matrix. /// /// Source . /// Source . /// Result of the matrix multiplication as an output parameter. public static void Multiply(ref Matrix4x4 matrix1, ref Matrix4x4 matrix2, out Matrix4x4 result) { float m11 = ( (matrix1.M11 * matrix2.M11) + (matrix1.M12 * matrix2.M21) + (matrix1.M13 * matrix2.M31) + (matrix1.M14 * matrix2.M41) ); float m12 = ( (matrix1.M11 * matrix2.M12) + (matrix1.M12 * matrix2.M22) + (matrix1.M13 * matrix2.M32) + (matrix1.M14 * matrix2.M42) ); float m13 = ( (matrix1.M11 * matrix2.M13) + (matrix1.M12 * matrix2.M23) + (matrix1.M13 * matrix2.M33) + (matrix1.M14 * matrix2.M43) ); float m14 = ( (matrix1.M11 * matrix2.M14) + (matrix1.M12 * matrix2.M24) + (matrix1.M13 * matrix2.M34) + (matrix1.M14 * matrix2.M44) ); float m21 = ( (matrix1.M21 * matrix2.M11) + (matrix1.M22 * matrix2.M21) + (matrix1.M23 * matrix2.M31) + (matrix1.M24 * matrix2.M41) ); float m22 = ( (matrix1.M21 * matrix2.M12) + (matrix1.M22 * matrix2.M22) + (matrix1.M23 * matrix2.M32) + (matrix1.M24 * matrix2.M42) ); float m23 = ( (matrix1.M21 * matrix2.M13) + (matrix1.M22 * matrix2.M23) + (matrix1.M23 * matrix2.M33) + (matrix1.M24 * matrix2.M43) ); float m24 = ( (matrix1.M21 * matrix2.M14) + (matrix1.M22 * matrix2.M24) + (matrix1.M23 * matrix2.M34) + (matrix1.M24 * matrix2.M44) ); float m31 = ( (matrix1.M31 * matrix2.M11) + (matrix1.M32 * matrix2.M21) + (matrix1.M33 * matrix2.M31) + (matrix1.M34 * matrix2.M41) ); float m32 = ( (matrix1.M31 * matrix2.M12) + (matrix1.M32 * matrix2.M22) + (matrix1.M33 * matrix2.M32) + (matrix1.M34 * matrix2.M42) ); float m33 = ( (matrix1.M31 * matrix2.M13) + (matrix1.M32 * matrix2.M23) + (matrix1.M33 * matrix2.M33) + (matrix1.M34 * matrix2.M43) ); float m34 = ( (matrix1.M31 * matrix2.M14) + (matrix1.M32 * matrix2.M24) + (matrix1.M33 * matrix2.M34) + (matrix1.M34 * matrix2.M44) ); float m41 = ( (matrix1.M41 * matrix2.M11) + (matrix1.M42 * matrix2.M21) + (matrix1.M43 * matrix2.M31) + (matrix1.M44 * matrix2.M41) ); float m42 = ( (matrix1.M41 * matrix2.M12) + (matrix1.M42 * matrix2.M22) + (matrix1.M43 * matrix2.M32) + (matrix1.M44 * matrix2.M42) ); float m43 = ( (matrix1.M41 * matrix2.M13) + (matrix1.M42 * matrix2.M23) + (matrix1.M43 * matrix2.M33) + (matrix1.M44 * matrix2.M43) ); float m44 = ( (matrix1.M41 * matrix2.M14) + (matrix1.M42 * matrix2.M24) + (matrix1.M43 * matrix2.M34) + (matrix1.M44 * matrix2.M44) ); result.M11 = m11; result.M12 = m12; result.M13 = m13; result.M14 = m14; result.M21 = m21; result.M22 = m22; result.M23 = m23; result.M24 = m24; result.M31 = m31; result.M32 = m32; result.M33 = m33; result.M34 = m34; result.M41 = m41; result.M42 = m42; result.M43 = m43; result.M44 = m44; } /// /// Creates a new that contains a multiplication of and a scalar. /// /// Source . /// Scalar value. /// Result of the matrix multiplication with a scalar. public static Matrix4x4 Multiply(Matrix4x4 matrix1, float scaleFactor) { matrix1.M11 *= scaleFactor; matrix1.M12 *= scaleFactor; matrix1.M13 *= scaleFactor; matrix1.M14 *= scaleFactor; matrix1.M21 *= scaleFactor; matrix1.M22 *= scaleFactor; matrix1.M23 *= scaleFactor; matrix1.M24 *= scaleFactor; matrix1.M31 *= scaleFactor; matrix1.M32 *= scaleFactor; matrix1.M33 *= scaleFactor; matrix1.M34 *= scaleFactor; matrix1.M41 *= scaleFactor; matrix1.M42 *= scaleFactor; matrix1.M43 *= scaleFactor; matrix1.M44 *= scaleFactor; return matrix1; } /// /// Creates a new that contains a multiplication of and a scalar. /// /// Source . /// Scalar value. /// Result of the matrix multiplication with a scalar as an output parameter. public static void Multiply(ref Matrix4x4 matrix1, float scaleFactor, out Matrix4x4 result) { result.M11 = matrix1.M11 * scaleFactor; result.M12 = matrix1.M12 * scaleFactor; result.M13 = matrix1.M13 * scaleFactor; result.M14 = matrix1.M14 * scaleFactor; result.M21 = matrix1.M21 * scaleFactor; result.M22 = matrix1.M22 * scaleFactor; result.M23 = matrix1.M23 * scaleFactor; result.M24 = matrix1.M24 * scaleFactor; result.M31 = matrix1.M31 * scaleFactor; result.M32 = matrix1.M32 * scaleFactor; result.M33 = matrix1.M33 * scaleFactor; result.M34 = matrix1.M34 * scaleFactor; result.M41 = matrix1.M41 * scaleFactor; result.M42 = matrix1.M42 * scaleFactor; result.M43 = matrix1.M43 * scaleFactor; result.M44 = matrix1.M44 * scaleFactor; } /// /// Returns a matrix with the all values negated. /// /// Source . /// Result of the matrix negation. public static Matrix4x4 Negate(Matrix4x4 matrix) { matrix.M11 = -matrix.M11; matrix.M12 = -matrix.M12; matrix.M13 = -matrix.M13; matrix.M14 = -matrix.M14; matrix.M21 = -matrix.M21; matrix.M22 = -matrix.M22; matrix.M23 = -matrix.M23; matrix.M24 = -matrix.M24; matrix.M31 = -matrix.M31; matrix.M32 = -matrix.M32; matrix.M33 = -matrix.M33; matrix.M34 = -matrix.M34; matrix.M41 = -matrix.M41; matrix.M42 = -matrix.M42; matrix.M43 = -matrix.M43; matrix.M44 = -matrix.M44; return matrix; } /// /// Returns a matrix with the all values negated. /// /// Source . /// Result of the matrix negation as an output parameter. public static void Negate(ref Matrix4x4 matrix, out Matrix4x4 result) { result.M11 = -matrix.M11; result.M12 = -matrix.M12; result.M13 = -matrix.M13; result.M14 = -matrix.M14; result.M21 = -matrix.M21; result.M22 = -matrix.M22; result.M23 = -matrix.M23; result.M24 = -matrix.M24; result.M31 = -matrix.M31; result.M32 = -matrix.M32; result.M33 = -matrix.M33; result.M34 = -matrix.M34; result.M41 = -matrix.M41; result.M42 = -matrix.M42; result.M43 = -matrix.M43; result.M44 = -matrix.M44; } /// /// Creates a new that contains subtraction of one matrix from another. /// /// The first . /// The second . /// The result of the matrix subtraction. public static Matrix4x4 Subtract(Matrix4x4 matrix1, Matrix4x4 matrix2) { matrix1.M11 -= matrix2.M11; matrix1.M12 -= matrix2.M12; matrix1.M13 -= matrix2.M13; matrix1.M14 -= matrix2.M14; matrix1.M21 -= matrix2.M21; matrix1.M22 -= matrix2.M22; matrix1.M23 -= matrix2.M23; matrix1.M24 -= matrix2.M24; matrix1.M31 -= matrix2.M31; matrix1.M32 -= matrix2.M32; matrix1.M33 -= matrix2.M33; matrix1.M34 -= matrix2.M34; matrix1.M41 -= matrix2.M41; matrix1.M42 -= matrix2.M42; matrix1.M43 -= matrix2.M43; matrix1.M44 -= matrix2.M44; return matrix1; } /// /// Creates a new that contains subtraction of one matrix from another. /// /// The first . /// The second . /// The result of the matrix subtraction as an output parameter. public static void Subtract(ref Matrix4x4 matrix1, ref Matrix4x4 matrix2, out Matrix4x4 result) { result.M11 = matrix1.M11 - matrix2.M11; result.M12 = matrix1.M12 - matrix2.M12; result.M13 = matrix1.M13 - matrix2.M13; result.M14 = matrix1.M14 - matrix2.M14; result.M21 = matrix1.M21 - matrix2.M21; result.M22 = matrix1.M22 - matrix2.M22; result.M23 = matrix1.M23 - matrix2.M23; result.M24 = matrix1.M24 - matrix2.M24; result.M31 = matrix1.M31 - matrix2.M31; result.M32 = matrix1.M32 - matrix2.M32; result.M33 = matrix1.M33 - matrix2.M33; result.M34 = matrix1.M34 - matrix2.M34; result.M41 = matrix1.M41 - matrix2.M41; result.M42 = matrix1.M42 - matrix2.M42; result.M43 = matrix1.M43 - matrix2.M43; result.M44 = matrix1.M44 - matrix2.M44; } /// /// Swap the matrix rows and columns. /// /// The matrix for transposing operation. /// The new which contains the transposing result. public static Matrix4x4 Transpose(Matrix4x4 matrix) { Matrix4x4 ret; Transpose(ref matrix, out ret); return ret; } /// /// Swap the matrix rows and columns. /// /// The matrix for transposing operation. /// The new which contains the transposing result as an output parameter. public static void Transpose(ref Matrix4x4 matrix, out Matrix4x4 result) { Matrix4x4 ret; ret.M11 = matrix.M11; ret.M12 = matrix.M21; ret.M13 = matrix.M31; ret.M14 = matrix.M41; ret.M21 = matrix.M12; ret.M22 = matrix.M22; ret.M23 = matrix.M32; ret.M24 = matrix.M42; ret.M31 = matrix.M13; ret.M32 = matrix.M23; ret.M33 = matrix.M33; ret.M34 = matrix.M43; ret.M41 = matrix.M14; ret.M42 = matrix.M24; ret.M43 = matrix.M34; ret.M44 = matrix.M44; result = ret; } public static Matrix4x4 Transform(Matrix4x4 value, Quaternion rotation) { Matrix4x4 result; Transform(ref value, ref rotation, out result); return result; } public static void Transform( ref Matrix4x4 value, ref Quaternion rotation, out Matrix4x4 result ) { Matrix4x4 rotMatrix = CreateFromQuaternion(rotation); Multiply(ref value, ref rotMatrix, out result); } #endregion #region Public Static Operator Overloads /// /// Adds two matrixes. /// /// Source on the left of the add sign. /// Source on the right of the add sign. /// Sum of the matrixes. public static Matrix4x4 operator +(Matrix4x4 matrix1, Matrix4x4 matrix2) { return Matrix4x4.Add(matrix1, matrix2); } /// /// Divides the elements of a by the elements of another . /// /// Source on the left of the div sign. /// Divisor on the right of the div sign. /// The result of dividing the matrixes. public static Matrix4x4 operator /(Matrix4x4 matrix1, Matrix4x4 matrix2) { return Matrix4x4.Divide(matrix1, matrix2); } /// /// Divides the elements of a by a scalar. /// /// Source on the left of the div sign. /// Divisor scalar on the right of the div sign. /// The result of dividing a matrix by a scalar. public static Matrix4x4 operator /(Matrix4x4 matrix, float divider) { return Matrix4x4.Divide(matrix, divider); } /// /// Compares whether two instances are equal without any tolerance. /// /// Source on the left of the equal sign. /// Source on the right of the equal sign. /// true if the instances are equal; false otherwise. public static bool operator ==(Matrix4x4 matrix1, Matrix4x4 matrix2) { return matrix1.Equals(matrix2); } /// /// Compares whether two instances are not equal without any tolerance. /// /// Source on the left of the not equal sign. /// Source on the right of the not equal sign. /// true if the instances are not equal; false otherwise. public static bool operator !=(Matrix4x4 matrix1, Matrix4x4 matrix2) { return !matrix1.Equals(matrix2); } /// /// Multiplies two matrixes. /// /// Source on the left of the mul sign. /// Source on the right of the mul sign. /// Result of the matrix multiplication. /// /// Using matrix multiplication algorithm - see http://en.wikipedia.org/wiki/Matrix_multiplication. /// public static Matrix4x4 operator *(Matrix4x4 matrix1, Matrix4x4 matrix2) { return Multiply(matrix1, matrix2); } /// /// Multiplies the elements of matrix by a scalar. /// /// Source on the left of the mul sign. /// Scalar value on the right of the mul sign. /// Result of the matrix multiplication with a scalar. public static Matrix4x4 operator *(Matrix4x4 matrix, float scaleFactor) { return Multiply(matrix, scaleFactor); } /// /// Subtracts the values of one from another . /// /// Source on the left of the sub sign. /// Source on the right of the sub sign. /// Result of the matrix subtraction. public static Matrix4x4 operator -(Matrix4x4 matrix1, Matrix4x4 matrix2) { return Subtract(matrix1, matrix2); } /// /// Inverts values in the specified . /// /// Source on the right of the sub sign. /// Result of the inversion. public static Matrix4x4 operator -(Matrix4x4 matrix) { return Negate(matrix); } #endregion } }