Mat44.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Math/MathTypes.h>
  5. namespace JPH {
  6. /// Holds a 4x4 matrix of floats, but supports also operations on the 3x3 upper left part of the matrix.
  7. class [[nodiscard]] Mat44
  8. {
  9. public:
  10. // Underlying column type
  11. using Type = Vec4::Type;
  12. /// Constructor
  13. Mat44() = default; ///< Intentionally not initialized for performance reasons
  14. JPH_INLINE Mat44(Vec4Arg inC1, Vec4Arg inC2, Vec4Arg inC3, Vec4Arg inC4);
  15. Mat44(const Mat44 &inM2) = default;
  16. JPH_INLINE Mat44(Type inC1, Type inC2, Type inC3, Type inC4);
  17. /// Zero matrix
  18. static JPH_INLINE Mat44 sZero();
  19. /// Identity matrix
  20. static JPH_INLINE Mat44 sIdentity();
  21. /// Matrix filled with NaN's
  22. static JPH_INLINE Mat44 sNaN();
  23. /// Load 16 floats from memory
  24. static JPH_INLINE Mat44 sLoadFloat4x4(const Float4 *inV);
  25. /// Load 16 floats from memory, 16 bytes aligned
  26. static JPH_INLINE Mat44 sLoadFloat4x4Aligned(const Float4 *inV);
  27. /// Rotate around X, Y or Z axis (angle in radians)
  28. static JPH_INLINE Mat44 sRotationX(float inX);
  29. static JPH_INLINE Mat44 sRotationY(float inY);
  30. static JPH_INLINE Mat44 sRotationZ(float inZ);
  31. /// Rotate around arbitrary axis
  32. static JPH_INLINE Mat44 sRotation(Vec3Arg inAxis, float inAngle);
  33. /// Rotate from quaternion
  34. static JPH_INLINE Mat44 sRotation(QuatArg inQuat);
  35. /// Get matrix that translates
  36. static JPH_INLINE Mat44 sTranslation(Vec3Arg inV);
  37. /// Get matrix that rotates and translates
  38. static JPH_INLINE Mat44 sRotationTranslation(QuatArg inR, Vec3Arg inT);
  39. /// Get inverse matrix of sRotationTranslation
  40. static JPH_INLINE Mat44 sInverseRotationTranslation(QuatArg inR, Vec3Arg inT);
  41. /// Get matrix that scales uniformly
  42. static JPH_INLINE Mat44 sScale(float inScale);
  43. /// Get matrix that scales (produces a matrix with (inV, 1) on its diagonal)
  44. static JPH_INLINE Mat44 sScale(Vec3Arg inV);
  45. /// Get outer product of inV and inV2 (equivalent to \f$inV1 \otimes inV2\f$)
  46. static JPH_INLINE Mat44 sOuterProduct(Vec3Arg inV1, Vec3Arg inV2);
  47. /// Get matrix that represents a cross product \f$A \times B = \text{sCrossProduct}(A) \: B\f$
  48. static JPH_INLINE Mat44 sCrossProduct(Vec3Arg inV);
  49. /// Returns matrix ML so that \f$ML(q) \: p = q \: p\f$ (where p and q are quaternions)
  50. static JPH_INLINE Mat44 sQuatLeftMultiply(QuatArg inQ);
  51. /// Returns matrix MR so that \f$MR(q) \: p = p \: q\f$ (where p and q are quaternions)
  52. static JPH_INLINE Mat44 sQuatRightMultiply(QuatArg inQ);
  53. /// Get float component by element index
  54. JPH_INLINE float operator () (uint inRow, uint inColumn) const { JPH_ASSERT(inRow < 4); JPH_ASSERT(inColumn < 4); return mCol[inColumn].mF32[inRow]; }
  55. JPH_INLINE float & operator () (uint inRow, uint inColumn) { JPH_ASSERT(inRow < 4); JPH_ASSERT(inColumn < 4); return mCol[inColumn].mF32[inRow]; }
  56. /// Comparsion
  57. JPH_INLINE bool operator == (Mat44Arg inM2) const;
  58. JPH_INLINE bool operator != (Mat44Arg inM2) const { return !(*this == inM2); }
  59. /// Test if two matrices are close
  60. JPH_INLINE bool IsClose(Mat44Arg inM2, float inMaxDistSq = 1.0e-12f) const;
  61. /// Multiply matrix by matrix
  62. JPH_INLINE Mat44 operator * (Mat44Arg inM) const;
  63. /// Multiply vector by matrix
  64. JPH_INLINE Vec3 operator * (Vec3Arg inV) const;
  65. JPH_INLINE Vec4 operator * (Vec4Arg inV) const;
  66. /// Multiply vector by only 3x3 part of the matrix
  67. JPH_INLINE Vec3 Multiply3x3(Vec3Arg inV) const;
  68. /// Multiply vector by only 3x3 part of the transpose of the matrix (\f$result = this^T \: inV\f$)
  69. JPH_INLINE Vec3 Multiply3x3Transposed(Vec3Arg inV) const;
  70. /// Multiply 3x3 matrix by 3x3 matrix
  71. JPH_INLINE Mat44 Multiply3x3(Mat44Arg inM) const;
  72. /// Multiply transpose of 3x3 matrix by 3x3 matrix (\f$result = this^T \: inM\f$)
  73. JPH_INLINE Mat44 Multiply3x3LeftTransposed(Mat44Arg inM) const;
  74. /// Multiply 3x3 matrix by the transpose of a 3x3 matrix (\f$result = this \: inM^T\f$)
  75. JPH_INLINE Mat44 Multiply3x3RightTransposed(Mat44Arg inM) const;
  76. /// Multiply matrix with float
  77. JPH_INLINE Mat44 operator * (float inV) const;
  78. friend JPH_INLINE Mat44 operator * (float inV, Mat44Arg inM) { return inM * inV; }
  79. /// Multiply matrix with float
  80. JPH_INLINE Mat44 & operator *= (float inV);
  81. /// Per element addition of matrix
  82. JPH_INLINE Mat44 operator + (Mat44Arg inM) const;
  83. /// Negate
  84. JPH_INLINE Mat44 operator - () const;
  85. /// Per element subtraction of matrix
  86. JPH_INLINE Mat44 operator - (Mat44Arg inM) const;
  87. /// Per element addition of matrix
  88. JPH_INLINE Mat44 & operator += (Mat44Arg inM);
  89. /// Access to the columns
  90. JPH_INLINE const Vec3 GetAxisX() const { return Vec3(mCol[0]); }
  91. JPH_INLINE void SetAxisX(Vec3Arg inV) { mCol[0] = Vec4(inV, 0.0f); }
  92. JPH_INLINE const Vec3 GetAxisY() const { return Vec3(mCol[1]); }
  93. JPH_INLINE void SetAxisY(Vec3Arg inV) { mCol[1] = Vec4(inV, 0.0f); }
  94. JPH_INLINE const Vec3 GetAxisZ() const { return Vec3(mCol[2]); }
  95. JPH_INLINE void SetAxisZ(Vec3Arg inV) { mCol[2] = Vec4(inV, 0.0f); }
  96. JPH_INLINE const Vec3 GetTranslation() const { return Vec3(mCol[3]); }
  97. JPH_INLINE void SetTranslation(Vec3Arg inV) { mCol[3] = Vec4(inV, 1.0f); }
  98. JPH_INLINE const Vec3 GetDiagonal3() const { return Vec3(mCol[0][0], mCol[1][1], mCol[2][2]); }
  99. JPH_INLINE void SetDiagonal3(Vec3Arg inV) { mCol[0][0] = inV.GetX(); mCol[1][1] = inV.GetY(); mCol[2][2] = inV.GetZ(); }
  100. JPH_INLINE const Vec4 GetDiagonal4() const { return Vec4(mCol[0][0], mCol[1][1], mCol[2][2], mCol[3][3]); }
  101. JPH_INLINE void SetDiagonal4(Vec4Arg inV) { mCol[0][0] = inV.GetX(); mCol[1][1] = inV.GetY(); mCol[2][2] = inV.GetZ(); mCol[3][3] = inV.GetW(); }
  102. JPH_INLINE const Vec3 GetColumn3(uint inCol) const { JPH_ASSERT(inCol < 4); return Vec3(mCol[inCol]); }
  103. JPH_INLINE void SetColumn3(uint inCol, Vec3Arg inV) { JPH_ASSERT(inCol < 4); mCol[inCol] = Vec4(inV, inCol == 3? 1.0f : 0.0f); }
  104. JPH_INLINE const Vec4 GetColumn4(uint inCol) const { JPH_ASSERT(inCol < 4); return mCol[inCol]; }
  105. JPH_INLINE void SetColumn4(uint inCol, Vec4Arg inV) { JPH_ASSERT(inCol < 4); mCol[inCol] = inV; }
  106. /// Store matrix to memory
  107. JPH_INLINE void StoreFloat4x4(Float4 *outV) const;
  108. /// Transpose matrix
  109. JPH_INLINE Mat44 Transposed() const;
  110. /// Transpose 3x3 subpart of matrix
  111. JPH_INLINE Mat44 Transposed3x3() const;
  112. /// Inverse 4x4 matrix
  113. JPH_INLINE Mat44 Inversed() const;
  114. /// Inverse 4x4 matrix when it only contains rotation and translation
  115. JPH_INLINE Mat44 InversedRotationTranslation() const;
  116. /// Get the determinant of a 3x3 matrix
  117. JPH_INLINE float GetDeterminant3x3() const;
  118. /// Get the adjoint of a 3x3 matrix
  119. JPH_INLINE Mat44 Adjointed3x3() const;
  120. /// Inverse 3x3 matrix
  121. JPH_INLINE Mat44 Inversed3x3() const;
  122. /// Get rotation part only (note: retains the first 3 values from the bottom row)
  123. JPH_INLINE Mat44 GetRotation() const;
  124. /// Get rotation part only (note: also clears the bottom row)
  125. JPH_INLINE Mat44 GetRotationSafe() const;
  126. /// Updates the rotation part of this matrix (the first 3 columns)
  127. JPH_INLINE void SetRotation(Mat44Arg inRotation);
  128. /// Convert to quaternion
  129. JPH_INLINE const Quat GetQuaternion() const;
  130. /// Get matrix that transforms a direction with the same transform as this matrix (length is not preserved)
  131. JPH_INLINE const Mat44 GetDirectionPreservingMatrix() const { return GetRotation().Inversed3x3().Transposed3x3(); }
  132. /// Scale a matrix: result = this * Mat44::sScale(inScale)
  133. JPH_INLINE Mat44 PreScaled(Vec3Arg inScale) const;
  134. /// Scale a matrix: result = Mat44::sScale(inScale) * this
  135. JPH_INLINE Mat44 PostScaled(Vec3Arg inScale) const;
  136. /// Decompose a matrix into a rotation & translation part and into a scale part so that:
  137. /// this = return_value * Mat44::sScale(outScale).
  138. /// This equation only holds when the matrix is orthogonal, if it is not the returned matrix
  139. /// will be made orthogonal using the modified Gram-Schmidt algorithm (see: https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)
  140. JPH_INLINE Mat44 Decompose(Vec3 &outScale) const;
  141. /// To String
  142. friend ostream & operator << (ostream &inStream, Mat44Arg inM)
  143. {
  144. inStream << inM.mCol[0] << ", " << inM.mCol[1] << ", " << inM.mCol[2] << ", " << inM.mCol[3];
  145. return inStream;
  146. }
  147. private:
  148. Vec4 mCol[4]; ///< Column
  149. };
  150. static_assert(is_trivial<Mat44>(), "Is supposed to be a trivial type!");
  151. } // JPH
  152. #include "Mat44.inl"