FMatrix3x3.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2017 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_GEOMETRY_FMATRIX3x3
  24. #define DFPSR_GEOMETRY_FMATRIX3x3
  25. #include <cassert>
  26. #include "FVector.h"
  27. namespace dsr {
  28. struct FMatrix3x3 {
  29. FVector3D xAxis, yAxis, zAxis;
  30. FMatrix3x3() :
  31. xAxis(FVector3D(1.0f, 0.0f, 0.0f)),
  32. yAxis(FVector3D(0.0f, 1.0f, 0.0f)),
  33. zAxis(FVector3D(0.0f, 0.0f, 1.0f)) {}
  34. explicit FMatrix3x3(float uniformScale) :
  35. xAxis(FVector3D(uniformScale, 0.0f, 0.0f)),
  36. yAxis(FVector3D(0.0f, uniformScale, 0.0f)),
  37. zAxis(FVector3D(0.0f, 0.0f, uniformScale)) {}
  38. FMatrix3x3(const FVector3D &xAxis, const FVector3D &yAxis, const FVector3D &zAxis) :
  39. xAxis(xAxis),
  40. yAxis(yAxis),
  41. zAxis(zAxis) {}
  42. static FMatrix3x3 makeAxisSystem(const FVector3D &forward, const FVector3D &up) {
  43. FMatrix3x3 result;
  44. FVector3D forwardNormalized = normalize(forward);
  45. result.zAxis = forwardNormalized;
  46. result.xAxis = normalize(crossProduct(normalize(up), forwardNormalized));
  47. result.yAxis = normalize(crossProduct(forwardNormalized, result.xAxis));
  48. return result;
  49. }
  50. // Transform the a vector by multiplying with the matrix
  51. FVector3D transform(const FVector3D &p) const {
  52. return FVector3D(
  53. p.x * this->xAxis.x + p.y * this->yAxis.x + p.z * this->zAxis.x,
  54. p.x * this->xAxis.y + p.y * this->yAxis.y + p.z * this->zAxis.y,
  55. p.x * this->xAxis.z + p.y * this->yAxis.z + p.z * this->zAxis.z
  56. );
  57. }
  58. // Transform the a vector by multiplying with the transpose of the matrix
  59. // The transpose is the inverse for axis aligned normalized matrices
  60. // Axis aligned: Each non-self axis dot-product equals zero.
  61. // Normalized: The length of each axis equals one.
  62. FVector3D transformTransposed(const FVector3D &p) const {
  63. return FVector3D(
  64. p.x * this->xAxis.x + p.y * this->xAxis.y + p.z * this->xAxis.z,
  65. p.x * this->yAxis.x + p.y * this->yAxis.y + p.z * this->yAxis.z,
  66. p.x * this->zAxis.x + p.y * this->zAxis.y + p.z * this->zAxis.z
  67. );
  68. }
  69. };
  70. inline FMatrix3x3 operator*(const FMatrix3x3 &m, const float &scale) {
  71. return FMatrix3x3(m.xAxis * scale, m.yAxis * scale, m.zAxis * scale);
  72. }
  73. inline FMatrix3x3 operator*(const FMatrix3x3 &left, const FMatrix3x3 &right) {
  74. return FMatrix3x3(right.transform(left.xAxis), right.transform(left.yAxis), right.transform(left.zAxis));
  75. }
  76. inline float determinant(const FMatrix3x3& m) {
  77. return m.xAxis.x * m.yAxis.y * m.zAxis.z
  78. + m.zAxis.x * m.xAxis.y * m.yAxis.z
  79. + m.yAxis.x * m.zAxis.y * m.xAxis.z
  80. - m.xAxis.x * m.zAxis.y * m.yAxis.z
  81. - m.yAxis.x * m.xAxis.y * m.zAxis.z
  82. - m.zAxis.x * m.yAxis.y * m.xAxis.z;
  83. }
  84. inline FMatrix3x3 inverseUsingInvDet(const FMatrix3x3& m, float invDet) {
  85. FMatrix3x3 result;
  86. result.xAxis.x = invDet * (m.yAxis.y * m.zAxis.z - m.yAxis.z * m.zAxis.y);
  87. result.xAxis.y = -invDet * (m.xAxis.y * m.zAxis.z - m.xAxis.z * m.zAxis.y);
  88. result.xAxis.z = invDet * (m.xAxis.y * m.yAxis.z - m.xAxis.z * m.yAxis.y);
  89. result.yAxis.x = -invDet * (m.yAxis.x * m.zAxis.z - m.yAxis.z * m.zAxis.x);
  90. result.yAxis.y = invDet * (m.xAxis.x * m.zAxis.z - m.xAxis.z * m.zAxis.x);
  91. result.yAxis.z = -invDet * (m.xAxis.x * m.yAxis.z - m.xAxis.z * m.yAxis.x);
  92. result.zAxis.x = invDet * (m.yAxis.x * m.zAxis.y - m.yAxis.y * m.zAxis.x);
  93. result.zAxis.y = -invDet * (m.xAxis.x * m.zAxis.y - m.xAxis.y * m.zAxis.x);
  94. result.zAxis.z = invDet * (m.xAxis.x * m.yAxis.y - m.xAxis.y * m.yAxis.x);
  95. return result;
  96. }
  97. inline FMatrix3x3 inverse(const FMatrix3x3& m) {
  98. return inverseUsingInvDet(m, 1.0f / determinant(m));
  99. }
  100. inline FMatrix3x3 transpose(const FMatrix3x3& m) {
  101. FMatrix3x3 result;
  102. result.xAxis.x = m.xAxis.x;
  103. result.xAxis.y = m.yAxis.x;
  104. result.xAxis.z = m.zAxis.x;
  105. result.yAxis.x = m.xAxis.y;
  106. result.yAxis.y = m.yAxis.y;
  107. result.yAxis.z = m.zAxis.y;
  108. result.zAxis.x = m.xAxis.z;
  109. result.zAxis.y = m.yAxis.z;
  110. result.zAxis.z = m.zAxis.z;
  111. return result;
  112. }
  113. inline String& string_toStreamIndented(String& target, const FMatrix3x3& source, const ReadableString& indentation) {
  114. string_append(target, indentation, U"XAxis(", source.xAxis, U"), YAxis(", source.yAxis, U"), ZAxis(", source.zAxis, U")");
  115. return target;
  116. }
  117. }
  118. #endif