2
0

IceMatrix4x4.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /**
  3. * Contains code for 4x4 matrices.
  4. * \file IceMatrix4x4.cpp
  5. * \author Pierre Terdiman
  6. * \date April, 4, 2000
  7. */
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. /**
  11. * 4x4 matrix.
  12. * DirectX-compliant, ie row-column order, ie m[Row][Col].
  13. * Same as:
  14. * m11 m12 m13 m14 first row.
  15. * m21 m22 m23 m24 second row.
  16. * m31 m32 m33 m34 third row.
  17. * m41 m42 m43 m44 fourth row.
  18. * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1).
  19. * Stored in memory as m11 m12 m13 m14 m21...
  20. *
  21. * Multiplication rules:
  22. *
  23. * [x'y'z'1] = [xyz1][M]
  24. *
  25. * x' = x*m11 + y*m21 + z*m31 + m41
  26. * y' = x*m12 + y*m22 + z*m32 + m42
  27. * z' = x*m13 + y*m23 + z*m33 + m43
  28. * 1' = 0 + 0 + 0 + m44
  29. *
  30. * \class Matrix4x4
  31. * \author Pierre Terdiman
  32. * \version 1.0
  33. */
  34. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  36. #include "../Opcode.h"
  37. using namespace IceMaths;
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  39. /**
  40. * Inverts a PR matrix. (which only contains a rotation and a translation)
  41. * This is faster and less subject to FPU errors than the generic inversion code.
  42. *
  43. * \relates Matrix4x4
  44. * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
  45. * \param dest [out] destination matrix
  46. * \param src [in] source matrix
  47. */
  48. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  49. ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
  50. {
  51. dest.m[0][0] = src.m[0][0];
  52. dest.m[1][0] = src.m[0][1];
  53. dest.m[2][0] = src.m[0][2];
  54. dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]);
  55. dest.m[0][1] = src.m[1][0];
  56. dest.m[1][1] = src.m[1][1];
  57. dest.m[2][1] = src.m[1][2];
  58. dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]);
  59. dest.m[0][2] = src.m[2][0];
  60. dest.m[1][2] = src.m[2][1];
  61. dest.m[2][2] = src.m[2][2];
  62. dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]);
  63. dest.m[0][3] = 0.0f;
  64. dest.m[1][3] = 0.0f;
  65. dest.m[2][3] = 0.0f;
  66. dest.m[3][3] = 1.0f;
  67. }
  68. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. // Compute the cofactor of the Matrix at a specified location
  70. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  71. float Matrix4x4::CoFactor(udword row, udword col) const
  72. {
  73. return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] +
  74. m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] +
  75. m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3])
  76. - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] +
  77. m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] +
  78. m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f);
  79. }
  80. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. // Compute the determinant of the Matrix
  82. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  83. float Matrix4x4::Determinant() const
  84. {
  85. return m[0][0] * CoFactor(0, 0) +
  86. m[0][1] * CoFactor(0, 1) +
  87. m[0][2] * CoFactor(0, 2) +
  88. m[0][3] * CoFactor(0, 3);
  89. }
  90. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. // Compute the inverse of the matrix
  92. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. Matrix4x4& Matrix4x4::Invert()
  94. {
  95. float Det = Determinant();
  96. Matrix4x4 Temp;
  97. if(fabsf(Det) < MATRIX4X4_EPSILON)
  98. return *this; // The matrix is not invertible! Singular case!
  99. float IDet = 1.0f / Det;
  100. Temp.m[0][0] = CoFactor(0,0) * IDet;
  101. Temp.m[1][0] = CoFactor(0,1) * IDet;
  102. Temp.m[2][0] = CoFactor(0,2) * IDet;
  103. Temp.m[3][0] = CoFactor(0,3) * IDet;
  104. Temp.m[0][1] = CoFactor(1,0) * IDet;
  105. Temp.m[1][1] = CoFactor(1,1) * IDet;
  106. Temp.m[2][1] = CoFactor(1,2) * IDet;
  107. Temp.m[3][1] = CoFactor(1,3) * IDet;
  108. Temp.m[0][2] = CoFactor(2,0) * IDet;
  109. Temp.m[1][2] = CoFactor(2,1) * IDet;
  110. Temp.m[2][2] = CoFactor(2,2) * IDet;
  111. Temp.m[3][2] = CoFactor(2,3) * IDet;
  112. Temp.m[0][3] = CoFactor(3,0) * IDet;
  113. Temp.m[1][3] = CoFactor(3,1) * IDet;
  114. Temp.m[2][3] = CoFactor(3,2) * IDet;
  115. Temp.m[3][3] = CoFactor(3,3) * IDet;
  116. *this = Temp;
  117. return *this;
  118. }