| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- using System;
- using System.Runtime.InteropServices;
- namespace BansheeEngine
- {
- [StructLayout(LayoutKind.Sequential), SerializeObject]
- public struct Matrix4
- {
- public static readonly Matrix4 zero = new Matrix4();
- public static readonly Matrix4 identity = new Matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
- public float m00;
- public float m01;
- public float m02;
- public float m03;
- public float m10;
- public float m11;
- public float m12;
- public float m13;
- public float m20;
- public float m21;
- public float m22;
- public float m23;
- public float m30;
- public float m31;
- public float m32;
- public float m33;
- public Matrix4(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13,
- float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33)
- {
- this.m00 = m00;
- this.m01 = m01;
- this.m02 = m02;
- this.m03 = m03;
- this.m10 = m10;
- this.m11 = m11;
- this.m12 = m12;
- this.m13 = m13;
- this.m20 = m20;
- this.m21 = m21;
- this.m22 = m22;
- this.m23 = m23;
- this.m30 = m30;
- this.m31 = m31;
- this.m32 = m32;
- this.m33 = m33;
- }
- public float this[int row, int column]
- {
- get
- {
- return this[row * 4 + column];
- }
- set
- {
- this[row * 4 + column] = value;
- }
- }
- public float this[int index]
- {
- get
- {
- switch (index)
- {
- case 0:
- return m00;
- case 1:
- return m01;
- case 2:
- return m02;
- case 3:
- return m03;
- case 4:
- return m10;
- case 5:
- return m11;
- case 6:
- return m12;
- case 7:
- return m13;
- case 8:
- return m20;
- case 9:
- return m21;
- case 10:
- return m22;
- case 11:
- return m23;
- case 12:
- return m30;
- case 13:
- return m31;
- case 14:
- return m32;
- case 15:
- return m33;
- default:
- throw new IndexOutOfRangeException("Invalid matrix index.");
- }
- }
- set
- {
- switch (index)
- {
- case 0:
- m00 = value;
- break;
- case 1:
- m01 = value;
- break;
- case 2:
- m02 = value;
- break;
- case 3:
- m03 = value;
- break;
- case 4:
- m10 = value;
- break;
- case 5:
- m11 = value;
- break;
- case 6:
- m12 = value;
- break;
- case 7:
- m13 = value;
- break;
- case 8:
- m20 = value;
- break;
- case 9:
- m21 = value;
- break;
- case 10:
- m22 = value;
- break;
- case 11:
- m23 = value;
- break;
- case 12:
- m30 = value;
- break;
- case 13:
- m31 = value;
- break;
- case 14:
- m32 = value;
- break;
- case 15:
- m33 = value;
- break;
- default:
- throw new IndexOutOfRangeException("Invalid matrix index.");
- }
- }
- }
- public static Matrix4 operator *(Matrix4 lhs, Matrix4 rhs)
- {
- return new Matrix4()
- {
- m00 = lhs.m00 * rhs.m00 + lhs.m01 * rhs.m10 + lhs.m02 * rhs.m20 + lhs.m03 * rhs.m30,
- m01 = lhs.m00 * rhs.m01 + lhs.m01 * rhs.m11 + lhs.m02 * rhs.m21 + lhs.m03 * rhs.m31,
- m02 = lhs.m00 * rhs.m02 + lhs.m01 * rhs.m12 + lhs.m02 * rhs.m22 + lhs.m03 * rhs.m32,
- m03 = lhs.m00 * rhs.m03 + lhs.m01 * rhs.m13 + lhs.m02 * rhs.m23 + lhs.m03 * rhs.m33,
- m10 = lhs.m10 * rhs.m00 + lhs.m11 * rhs.m10 + lhs.m12 * rhs.m20 + lhs.m13 * rhs.m30,
- m11 = lhs.m10 * rhs.m01 + lhs.m11 * rhs.m11 + lhs.m12 * rhs.m21 + lhs.m13 * rhs.m31,
- m12 = lhs.m10 * rhs.m02 + lhs.m11 * rhs.m12 + lhs.m12 * rhs.m22 + lhs.m13 * rhs.m32,
- m13 = lhs.m10 * rhs.m03 + lhs.m11 * rhs.m13 + lhs.m12 * rhs.m23 + lhs.m13 * rhs.m33,
- m20 = lhs.m20 * rhs.m00 + lhs.m21 * rhs.m10 + lhs.m22 * rhs.m20 + lhs.m23 * rhs.m30,
- m21 = lhs.m20 * rhs.m01 + lhs.m21 * rhs.m11 + lhs.m22 * rhs.m21 + lhs.m23 * rhs.m31,
- m22 = lhs.m20 * rhs.m02 + lhs.m21 * rhs.m12 + lhs.m22 * rhs.m22 + lhs.m23 * rhs.m32,
- m23 = lhs.m20 * rhs.m03 + lhs.m21 * rhs.m13 + lhs.m22 * rhs.m23 + lhs.m23 * rhs.m33,
- m30 = lhs.m30 * rhs.m00 + lhs.m31 * rhs.m10 + lhs.m32 * rhs.m20 + lhs.m33 * rhs.m30,
- m31 = lhs.m30 * rhs.m01 + lhs.m31 * rhs.m11 + lhs.m32 * rhs.m21 + lhs.m33 * rhs.m31,
- m32 = lhs.m30 * rhs.m02 + lhs.m31 * rhs.m12 + lhs.m32 * rhs.m22 + lhs.m33 * rhs.m32,
- m33 = lhs.m30 * rhs.m03 + lhs.m31 * rhs.m13 + lhs.m32 * rhs.m23 + lhs.m33 * rhs.m33
- };
- }
- public static bool operator ==(Matrix4 lhs, Matrix4 rhs)
- {
- if (lhs.m00 == rhs.m00 && lhs.m01 == rhs.m01 && lhs.m02 == rhs.m02 && lhs.m03 == rhs.m03 &&
- lhs.m10 == rhs.m10 && lhs.m11 == rhs.m11 && lhs.m12 == rhs.m12 && lhs.m13 == rhs.m13 &&
- lhs.m20 == rhs.m20 && lhs.m21 == rhs.m21 && lhs.m22 == rhs.m22 && lhs.m23 == rhs.m23 &&
- lhs.m30 == rhs.m30 && lhs.m31 == rhs.m31 && lhs.m32 == rhs.m32 && lhs.m33 == rhs.m33)
- return true;
- else
- return false;
- }
- public static bool operator !=(Matrix4 lhs, Matrix4 rhs)
- {
- return !(lhs == rhs);
- }
- public override int GetHashCode()
- {
- float hash1 = m00.GetHashCode() ^ m10.GetHashCode() << 2 ^ m20.GetHashCode() >> 2 ^ m30.GetHashCode() >> 1;
- float hash2 = m01.GetHashCode() ^ m11.GetHashCode() << 2 ^ m21.GetHashCode() >> 2 ^ m31.GetHashCode() >> 1;
- float hash3 = m02.GetHashCode() ^ m12.GetHashCode() << 2 ^ m22.GetHashCode() >> 2 ^ m32.GetHashCode() >> 1;
- float hash4 = m03.GetHashCode() ^ m13.GetHashCode() << 2 ^ m23.GetHashCode() >> 2 ^ m33.GetHashCode() >> 1;
- return hash1.GetHashCode() ^ hash2.GetHashCode() << 2 ^ hash3.GetHashCode() >> 2 ^ hash4.GetHashCode() >> 1;
- }
- public override bool Equals(object other)
- {
- if (!(other is Matrix4))
- return false;
- Matrix4 mat = (Matrix4)other;
- if (m00 == mat.m00 && m01 == mat.m01 && m02 == mat.m02 && m03 == mat.m03 &&
- m10 == mat.m10 && m11 == mat.m11 && m12 == mat.m12 && m13 == mat.m13 &&
- m20 == mat.m20 && m21 == mat.m21 && m22 == mat.m22 && m23 == mat.m23 &&
- m30 == mat.m30 && m31 == mat.m31 && m32 == mat.m32 && m33 == mat.m33)
- return true;
- else
- return false;
- }
- public void Invert()
- {
- float v0 = m20 * m31 - m21 * m30;
- float v1 = m20 * m32 - m22 * m30;
- float v2 = m20 * m33 - m23 * m30;
- float v3 = m21 * m32 - m22 * m31;
- float v4 = m21 * m33 - m23 * m31;
- float v5 = m22 * m33 - m23 * m32;
- float t00 = +(v5 * m11 - v4 * m12 + v3 * m13);
- float t10 = -(v5 * m10 - v2 * m12 + v1 * m13);
- float t20 = +(v4 * m10 - v2 * m11 + v0 * m13);
- float t30 = -(v3 * m10 - v1 * m11 + v0 * m12);
- float invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
- float d00 = t00 * invDet;
- float d10 = t10 * invDet;
- float d20 = t20 * invDet;
- float d30 = t30 * invDet;
- float d01 = -(v5 * m01 - v4 * m02 + v3 * m03) * invDet;
- float d11 = +(v5 * m00 - v2 * m02 + v1 * m03) * invDet;
- float d21 = -(v4 * m00 - v2 * m01 + v0 * m03) * invDet;
- float d31 = +(v3 * m00 - v1 * m01 + v0 * m02) * invDet;
- v0 = m10 * m31 - m11 * m30;
- v1 = m10 * m32 - m12 * m30;
- v2 = m10 * m33 - m13 * m30;
- v3 = m11 * m32 - m12 * m31;
- v4 = m11 * m33 - m13 * m31;
- v5 = m12 * m33 - m13 * m32;
- float d02 = +(v5 * m01 - v4 * m02 + v3 * m03) * invDet;
- float d12 = -(v5 * m00 - v2 * m02 + v1 * m03) * invDet;
- float d22 = +(v4 * m00 - v2 * m01 + v0 * m03) * invDet;
- float d32 = -(v3 * m00 - v1 * m01 + v0 * m02) * invDet;
- v0 = m21 * m10 - m20 * m11;
- v1 = m22 * m10 - m20 * m12;
- v2 = m23 * m10 - m20 * m13;
- v3 = m22 * m11 - m21 * m12;
- v4 = m23 * m11 - m21 * m13;
- v5 = m23 * m12 - m22 * m13;
- float d03 = -(v5 * m01 - v4 * m02 + v3 * m03) * invDet;
- float d13 = +(v5 * m00 - v2 * m02 + v1 * m03) * invDet;
- float d23 = -(v4 * m00 - v2 * m01 + v0 * m03) * invDet;
- float d33 = +(v3 * m00 - v1 * m01 + v0 * m02) * invDet;
- this = new Matrix4(
- d00, d01, d02, d03,
- d10, d11, d12, d13,
- d20, d21, d22, d23,
- d30, d31, d32, d33);
- }
- public void InvertAffine()
- {
- float t00 = m22 * m11 - m21 * m12;
- float t10 = m20 * m12 - m22 * m10;
- float t20 = m21 * m10 - m20 * m11;
- float invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
- t00 *= invDet; t10 *= invDet; t20 *= invDet;
- m00 *= invDet; m01 *= invDet; m02 *= invDet;
- float r00 = t00;
- float r01 = m02 * m21 - m01 * m22;
- float r02 = m01 * m12 - m02 * m11;
- float r10 = t10;
- float r11 = m00 * m22 - m02 * m20;
- float r12 = m02 * m10 - m00 * m12;
- float r20 = t20;
- float r21 = m01 * m20 - m00 * m21;
- float r22 = m00 * m11 - m01 * m10;
- float r03 = -(r00 * m03 + r01 * m13 + r02 * m23);
- float r13 = -(r10 * m03 + r11 * m13 + r12 * m23);
- float r23 = -(r20 * m03 + r21 * m13 + r22 * m23);
- this = new Matrix4(
- r00, r01, r02, r03,
- r10, r11, r12, r13,
- r20, r21, r22, r23,
- 0, 0, 0, 1);
- }
- public void Transpose()
- {
- float tmp = m01;
- m01 = m10;
- m10 = tmp;
- tmp = m02;
- m02 = m20;
- m20 = tmp;
- tmp = m03;
- m03 = m30;
- m30 = tmp;
- tmp = m12;
- m12 = m21;
- m21 = tmp;
- tmp = m13;
- m13 = m31;
- m31 = tmp;
- tmp = m23;
- m23 = m32;
- m32 = tmp;
- }
- public float Determinant()
- {
- float m1 = m11 * (m22 * m33 - m32 * m23) -
- m12 * (m21 * m33 - m31 * m23) +
- m13 * (m21 * m32 - m31 * m22);
- float m2 = m10 * (m22 * m33 - m32 * m23) -
- m12 * (m20 * m33 - m30 * m23) +
- m13 * (m20 * m32 - m30 * m22);
- float m3 = m10 * (m21 * m33 - m31 * m23) -
- m11 * (m20 * m33 - m30 * m23) +
- m13 * (m20 * m31 - m30 * m21);
- float m4 = m10 * (m21 * m32 - m31 * m22) -
- m11 * (m20 * m32 - m30 * m22) +
- m12 * (m20 * m31 - m30 * m21);
- return m00 * m1 - m01 * m2 + m02 * m3 - m03 * m4;
- }
- /**
- * @brief Decompose a Matrix4 to translation, rotation and scale.
- *
- * @note Matrix must consist only of translation, rotation and uniform scale transformations,
- * otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees
- * results will not be accurate.
- */
- public void GetTRS(out Vector3 translation, out Quaternion rotation, out Vector3 scale)
- {
- Matrix3 m3x3 = ToMatrix3(this);
- Matrix3 matQ;
- Vector3 vecU;
- m3x3.QDUDecomposition(out matQ, out scale, out vecU);
- rotation = Quaternion.FromRotationMatrix(matQ);
- translation = new Vector3(m03, m13, m23);
- }
- /**
- * @brief Transform a 3D vector by this matrix.
- *
- * @note Matrix must be affine, if it is not use "Multiply" method.
- */
- public Vector3 MultiplyAffine(Vector3 v)
- {
- return new Vector3(
- m00 * v.x + m01 * v.y + m02 * v.z + m03,
- m10 * v.x + m11 * v.y + m12 * v.z + m13,
- m20 * v.x + m21 * v.y + m22 * v.z + m23);
- }
- /**
- * @brief Transform a 4D vector by this matrix.
- *
- * @note Matrix must be affine, if it is not use "Multiply" method.
- */
- public Vector4 MultiplyAffine(Vector4 v)
- {
- return new Vector4(
- m00 * v.x + m01 * v.y + m02 * v.z + m03 * v.w,
- m10 * v.x + m11 * v.y + m12 * v.z + m13 * v.w,
- m20 * v.x + m21 * v.y + m22 * v.z + m23 * v.w,
- v.w);
- }
- /**
- * @brief Transform a 3D vector by this matrix.
- *
- * @note w component of the vector is assumed to be 1. After transformation all components
- * are projected back so that w remains 1.
- *
- * If your matrix doesn't contain projection components use "MultiplyAffine" method as it is faster.
- */
- public Vector3 Multiply(Vector3 v)
- {
- Vector3 r = new Vector3();
- float fInvW = 1.0f / (m30 * v.x + m31 * v.y + m32 * v.z + m33);
- r.x = (m00 * v.x + m01 * v.y + m02 * v.z + m03) * fInvW;
- r.y = (m10 * v.x + m11 * v.y + m12 * v.z + m13) * fInvW;
- r.z = (m20 * v.x + m21 * v.y + m22 * v.z + m23) * fInvW;
- return r;
- }
- /**
- * @brief Transform a 3D vector by this matrix.
- *
- * @note After transformation all components are projected back so that w remains 1.
- *
- * If your matrix doesn't contain projection components use "MultiplyAffine" method as it is faster.
- */
- public Vector4 Multiply(Vector4 v)
- {
- return new Vector4(
- m00 * v.x + m01 * v.y + m02 * v.z + m03 * v.w,
- m10 * v.x + m11 * v.y + m12 * v.z + m13 * v.w,
- m20 * v.x + m21 * v.y + m22 * v.z + m23 * v.w,
- m30 * v.x + m31 * v.y + m32 * v.z + m33 * v.w);
- }
- public static Matrix4 TRS(Vector3 translation, Quaternion rotation, Vector3 scale)
- {
- Matrix3 rot3x3 = rotation.ToRotationMatrix();
- Matrix4 mat = new Matrix4();
- mat.m00 = scale.x * rot3x3.m00; mat.m01 = scale.y * rot3x3.m01; mat.m02 = scale.z * rot3x3.m02; mat.m03 = translation.x;
- mat.m10 = scale.x * rot3x3.m10; mat.m11 = scale.y * rot3x3.m11; mat.m12 = scale.z * rot3x3.m12; mat.m13 = translation.y;
- mat.m20 = scale.x * rot3x3.m20; mat.m21 = scale.y * rot3x3.m21; mat.m22 = scale.z * rot3x3.m22; mat.m23 = translation.z;
- // No projection term
- mat.m30 = 0; mat.m31 = 0; mat.m32 = 0; mat.m33 = 1;
- return mat;
- }
- public static Matrix3 ToMatrix3(Matrix4 mat)
- {
- return new Matrix3(
- mat.m00, mat.m01, mat.m02,
- mat.m10, mat.m11, mat.m12,
- mat.m20, mat.m21, mat.m22);
- }
- public static Matrix4 Inverse(Matrix4 mat)
- {
- Matrix4 copy = mat;
- copy.Invert();
- return copy;
- }
- public static Matrix4 InverseAffine(Matrix4 mat)
- {
- Matrix4 copy = mat;
- copy.InvertAffine();
- return copy;
- }
- public static Matrix4 Transpose(Matrix4 mat)
- {
- Matrix4 copy = mat;
- copy.Transpose();
- return copy;
- }
- public override string ToString()
- {
- return String.Format("({0}, {1}, {2}, {3},\n{4}, {5}, {6}, {7}\n{8}, {9}, {10}, {11}\n{12}, {13}, {14}, {15})",
- m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33);
- }
- }
- }
|