matrixutils.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright 2019 Google Inc. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "matrixutils.h"
  17. #include "vectorutils.h"
  18. namespace cardboard {
  19. namespace {
  20. // Returns true if the cofactor for a given row and column should be negated.
  21. static bool IsCofactorNegated(int row, int col)
  22. {
  23. // Negated iff (row + col) is odd.
  24. return ((row + col) & 1) != 0;
  25. }
  26. static double CofactorElement3(const Matrix3x3& m, int row, int col)
  27. {
  28. static const int index[3][2] = { { 1, 2 }, { 0, 2 }, { 0, 1 } };
  29. const int i0 = index[row][0];
  30. const int i1 = index[row][1];
  31. const int j0 = index[col][0];
  32. const int j1 = index[col][1];
  33. const double cofactor = m(i0, j0) * m(i1, j1) - m(i0, j1) * m(i1, j0);
  34. return IsCofactorNegated(row, col) ? -cofactor : cofactor;
  35. }
  36. // Multiplies a matrix and some type of column vector to
  37. // produce another column vector of the same type.
  38. Vector3 MultiplyMatrixAndVector(const Matrix3x3& m, const Vector3& v)
  39. {
  40. Vector3 result = Vector3::Zero();
  41. for (int row = 0; row < 3; ++row) {
  42. for (int col = 0; col < 3; ++col)
  43. result[row] += m(row, col) * v[col];
  44. }
  45. return result;
  46. }
  47. // Sets the upper 3x3 of a Matrix to represent a 3D rotation.
  48. void RotationMatrix3x3(const Rotation& r, Matrix3x3* matrix)
  49. {
  50. //
  51. // Given a quaternion (a,b,c,d) where d is the scalar part, the 3x3 rotation
  52. // matrix is:
  53. //
  54. // a^2 - b^2 - c^2 + d^2 2ab - 2cd 2ac + 2bd
  55. // 2ab + 2cd -a^2 + b^2 - c^2 + d^2 2bc - 2ad
  56. // 2ac - 2bd 2bc + 2ad -a^2 - b^2 + c^2 + d^2
  57. //
  58. const Vector<4>& quat = r.GetQuaternion();
  59. const double aa = quat[0] * quat[0];
  60. const double bb = quat[1] * quat[1];
  61. const double cc = quat[2] * quat[2];
  62. const double dd = quat[3] * quat[3];
  63. const double ab = quat[0] * quat[1];
  64. const double ac = quat[0] * quat[2];
  65. const double bc = quat[1] * quat[2];
  66. const double ad = quat[0] * quat[3];
  67. const double bd = quat[1] * quat[3];
  68. const double cd = quat[2] * quat[3];
  69. Matrix3x3& m = *matrix;
  70. m[0][0] = aa - bb - cc + dd;
  71. m[0][1] = 2 * ab - 2 * cd;
  72. m[0][2] = 2 * ac + 2 * bd;
  73. m[1][0] = 2 * ab + 2 * cd;
  74. m[1][1] = -aa + bb - cc + dd;
  75. m[1][2] = 2 * bc - 2 * ad;
  76. m[2][0] = 2 * ac - 2 * bd;
  77. m[2][1] = 2 * bc + 2 * ad;
  78. m[2][2] = -aa - bb + cc + dd;
  79. }
  80. } // anonymous namespace
  81. Vector3 operator*(const Matrix3x3& m, const Vector3& v) { return MultiplyMatrixAndVector(m, v); }
  82. Matrix3x3 CofactorMatrix(const Matrix3x3& m)
  83. {
  84. Matrix3x3 result;
  85. for (int row = 0; row < 3; ++row) {
  86. for (int col = 0; col < 3; ++col)
  87. result(row, col) = CofactorElement3(m, row, col);
  88. }
  89. return result;
  90. }
  91. Matrix3x3 AdjugateWithDeterminant(const Matrix3x3& m, double* determinant)
  92. {
  93. const Matrix3x3 cofactor_matrix = CofactorMatrix(m);
  94. if (determinant) {
  95. *determinant = m(0, 0) * cofactor_matrix(0, 0) + m(0, 1) * cofactor_matrix(0, 1)
  96. + m(0, 2) * cofactor_matrix(0, 2);
  97. }
  98. return Transpose(cofactor_matrix);
  99. }
  100. // Returns the transpose of a matrix.
  101. Matrix3x3 Transpose(const Matrix3x3& m)
  102. {
  103. Matrix3x3 result;
  104. for (int row = 0; row < 3; ++row) {
  105. for (int col = 0; col < 3; ++col)
  106. result(row, col) = m(col, row);
  107. }
  108. return result;
  109. }
  110. Matrix3x3 InverseWithDeterminant(const Matrix3x3& m, double* determinant)
  111. {
  112. // The inverse is the adjugate divided by the determinant.
  113. double det;
  114. Matrix3x3 adjugate = AdjugateWithDeterminant(m, &det);
  115. if (determinant)
  116. *determinant = det;
  117. if (det == 0)
  118. return Matrix3x3::Zero();
  119. else
  120. return adjugate * (1 / det);
  121. }
  122. Matrix3x3 Inverse(const Matrix3x3& m) { return InverseWithDeterminant(m, nullptr); }
  123. Matrix3x3 RotationMatrixNH(const Rotation& r)
  124. {
  125. Matrix3x3 m;
  126. RotationMatrix3x3(r, &m);
  127. return m;
  128. }
  129. } // namespace cardboard