Matrix4x4.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Matrix.h>
  9. #include <Mathematics/Vector4.h>
  10. namespace WwiseGTE
  11. {
  12. // Template alias for convenience.
  13. template <typename Real>
  14. using Matrix4x4 = Matrix<4, 4, Real>;
  15. // Geometric operations.
  16. template <typename Real>
  17. Matrix4x4<Real> Inverse(Matrix4x4<Real> const& M, bool* reportInvertibility = nullptr)
  18. {
  19. Matrix4x4<Real> inverse;
  20. bool invertible;
  21. Real a0 = M(0, 0) * M(1, 1) - M(0, 1) * M(1, 0);
  22. Real a1 = M(0, 0) * M(1, 2) - M(0, 2) * M(1, 0);
  23. Real a2 = M(0, 0) * M(1, 3) - M(0, 3) * M(1, 0);
  24. Real a3 = M(0, 1) * M(1, 2) - M(0, 2) * M(1, 1);
  25. Real a4 = M(0, 1) * M(1, 3) - M(0, 3) * M(1, 1);
  26. Real a5 = M(0, 2) * M(1, 3) - M(0, 3) * M(1, 2);
  27. Real b0 = M(2, 0) * M(3, 1) - M(2, 1) * M(3, 0);
  28. Real b1 = M(2, 0) * M(3, 2) - M(2, 2) * M(3, 0);
  29. Real b2 = M(2, 0) * M(3, 3) - M(2, 3) * M(3, 0);
  30. Real b3 = M(2, 1) * M(3, 2) - M(2, 2) * M(3, 1);
  31. Real b4 = M(2, 1) * M(3, 3) - M(2, 3) * M(3, 1);
  32. Real b5 = M(2, 2) * M(3, 3) - M(2, 3) * M(3, 2);
  33. Real det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
  34. if (det != (Real)0)
  35. {
  36. Real invDet = (Real)1 / det;
  37. inverse = Matrix4x4<Real>
  38. {
  39. (+M(1, 1) * b5 - M(1, 2) * b4 + M(1, 3) * b3) * invDet,
  40. (-M(0, 1) * b5 + M(0, 2) * b4 - M(0, 3) * b3) * invDet,
  41. (+M(3, 1) * a5 - M(3, 2) * a4 + M(3, 3) * a3) * invDet,
  42. (-M(2, 1) * a5 + M(2, 2) * a4 - M(2, 3) * a3) * invDet,
  43. (-M(1, 0) * b5 + M(1, 2) * b2 - M(1, 3) * b1) * invDet,
  44. (+M(0, 0) * b5 - M(0, 2) * b2 + M(0, 3) * b1) * invDet,
  45. (-M(3, 0) * a5 + M(3, 2) * a2 - M(3, 3) * a1) * invDet,
  46. (+M(2, 0) * a5 - M(2, 2) * a2 + M(2, 3) * a1) * invDet,
  47. (+M(1, 0) * b4 - M(1, 1) * b2 + M(1, 3) * b0) * invDet,
  48. (-M(0, 0) * b4 + M(0, 1) * b2 - M(0, 3) * b0) * invDet,
  49. (+M(3, 0) * a4 - M(3, 1) * a2 + M(3, 3) * a0) * invDet,
  50. (-M(2, 0) * a4 + M(2, 1) * a2 - M(2, 3) * a0) * invDet,
  51. (-M(1, 0) * b3 + M(1, 1) * b1 - M(1, 2) * b0) * invDet,
  52. (+M(0, 0) * b3 - M(0, 1) * b1 + M(0, 2) * b0) * invDet,
  53. (-M(3, 0) * a3 + M(3, 1) * a1 - M(3, 2) * a0) * invDet,
  54. (+M(2, 0) * a3 - M(2, 1) * a1 + M(2, 2) * a0) * invDet
  55. };
  56. invertible = true;
  57. }
  58. else
  59. {
  60. inverse.MakeZero();
  61. invertible = false;
  62. }
  63. if (reportInvertibility)
  64. {
  65. *reportInvertibility = invertible;
  66. }
  67. return inverse;
  68. }
  69. template <typename Real>
  70. Matrix4x4<Real> Adjoint(Matrix4x4<Real> const& M)
  71. {
  72. Real a0 = M(0, 0) * M(1, 1) - M(0, 1) * M(1, 0);
  73. Real a1 = M(0, 0) * M(1, 2) - M(0, 2) * M(1, 0);
  74. Real a2 = M(0, 0) * M(1, 3) - M(0, 3) * M(1, 0);
  75. Real a3 = M(0, 1) * M(1, 2) - M(0, 2) * M(1, 1);
  76. Real a4 = M(0, 1) * M(1, 3) - M(0, 3) * M(1, 1);
  77. Real a5 = M(0, 2) * M(1, 3) - M(0, 3) * M(1, 2);
  78. Real b0 = M(2, 0) * M(3, 1) - M(2, 1) * M(3, 0);
  79. Real b1 = M(2, 0) * M(3, 2) - M(2, 2) * M(3, 0);
  80. Real b2 = M(2, 0) * M(3, 3) - M(2, 3) * M(3, 0);
  81. Real b3 = M(2, 1) * M(3, 2) - M(2, 2) * M(3, 1);
  82. Real b4 = M(2, 1) * M(3, 3) - M(2, 3) * M(3, 1);
  83. Real b5 = M(2, 2) * M(3, 3) - M(2, 3) * M(3, 2);
  84. return Matrix4x4<Real>
  85. {
  86. +M(1, 1) * b5 - M(1, 2) * b4 + M(1, 3) * b3,
  87. -M(0, 1) * b5 + M(0, 2) * b4 - M(0, 3) * b3,
  88. +M(3, 1) * a5 - M(3, 2) * a4 + M(3, 3) * a3,
  89. -M(2, 1) * a5 + M(2, 2) * a4 - M(2, 3) * a3,
  90. -M(1, 0) * b5 + M(1, 2) * b2 - M(1, 3) * b1,
  91. +M(0, 0) * b5 - M(0, 2) * b2 + M(0, 3) * b1,
  92. -M(3, 0) * a5 + M(3, 2) * a2 - M(3, 3) * a1,
  93. +M(2, 0) * a5 - M(2, 2) * a2 + M(2, 3) * a1,
  94. +M(1, 0) * b4 - M(1, 1) * b2 + M(1, 3) * b0,
  95. -M(0, 0) * b4 + M(0, 1) * b2 - M(0, 3) * b0,
  96. +M(3, 0) * a4 - M(3, 1) * a2 + M(3, 3) * a0,
  97. -M(2, 0) * a4 + M(2, 1) * a2 - M(2, 3) * a0,
  98. -M(1, 0) * b3 + M(1, 1) * b1 - M(1, 2) * b0,
  99. +M(0, 0) * b3 - M(0, 1) * b1 + M(0, 2) * b0,
  100. -M(3, 0) * a3 + M(3, 1) * a1 - M(3, 2) * a0,
  101. +M(2, 0) * a3 - M(2, 1) * a1 + M(2, 2) * a0
  102. };
  103. }
  104. template <typename Real>
  105. Real Determinant(Matrix4x4<Real> const& M)
  106. {
  107. Real a0 = M(0, 0) * M(1, 1) - M(0, 1) * M(1, 0);
  108. Real a1 = M(0, 0) * M(1, 2) - M(0, 2) * M(1, 0);
  109. Real a2 = M(0, 0) * M(1, 3) - M(0, 3) * M(1, 0);
  110. Real a3 = M(0, 1) * M(1, 2) - M(0, 2) * M(1, 1);
  111. Real a4 = M(0, 1) * M(1, 3) - M(0, 3) * M(1, 1);
  112. Real a5 = M(0, 2) * M(1, 3) - M(0, 3) * M(1, 2);
  113. Real b0 = M(2, 0) * M(3, 1) - M(2, 1) * M(3, 0);
  114. Real b1 = M(2, 0) * M(3, 2) - M(2, 2) * M(3, 0);
  115. Real b2 = M(2, 0) * M(3, 3) - M(2, 3) * M(3, 0);
  116. Real b3 = M(2, 1) * M(3, 2) - M(2, 2) * M(3, 1);
  117. Real b4 = M(2, 1) * M(3, 3) - M(2, 3) * M(3, 1);
  118. Real b5 = M(2, 2) * M(3, 3) - M(2, 3) * M(3, 2);
  119. Real det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
  120. return det;
  121. }
  122. template <typename Real>
  123. Real Trace(Matrix4x4<Real> const& M)
  124. {
  125. Real trace = M(0, 0) + M(1, 1) + M(2, 2) + M(3, 3);
  126. return trace;
  127. }
  128. // Multiply M and V according to the user-selected convention. If it is
  129. // GTE_USE_MAT_VEC, the function returns M*V. If it is GTE_USE_VEC_MAT,
  130. // the function returns V*M. This function is provided to hide the
  131. // preprocessor symbols in the GTEngine sample applications.
  132. template <typename Real>
  133. Vector4<Real> DoTransform(Matrix4x4<Real> const& M, Vector4<Real> const& V)
  134. {
  135. #if defined(GTE_USE_MAT_VEC)
  136. return M * V;
  137. #else
  138. return V * M;
  139. #endif
  140. }
  141. template <typename Real>
  142. Matrix4x4<Real> DoTransform(Matrix4x4<Real> const& A, Matrix4x4<Real> const& B)
  143. {
  144. #if defined(GTE_USE_MAT_VEC)
  145. return A * B;
  146. #else
  147. return B * A;
  148. #endif
  149. }
  150. // For GTE_USE_MAT_VEC, the columns of an invertible matrix form a basis
  151. // for the range of the matrix. For GTE_USE_VEC_MAT, the rows of an
  152. // invertible matrix form a basis for the range of the matrix. These
  153. // functions allow you to access the basis vectors. The caller is
  154. // responsible for ensuring that the matrix is invertible (although the
  155. // inverse is not calculated by these functions).
  156. template <typename Real>
  157. void SetBasis(Matrix4x4<Real>& M, int i, Vector4<Real> const& V)
  158. {
  159. #if defined(GTE_USE_MAT_VEC)
  160. return M.SetCol(i, V);
  161. #else
  162. return M.SetRow(i, V);
  163. #endif
  164. }
  165. template <typename Real>
  166. Vector4<Real> GetBasis(Matrix4x4<Real> const& M, int i)
  167. {
  168. #if defined(GTE_USE_MAT_VEC)
  169. return M.GetCol(i);
  170. #else
  171. return M.GetRow(i);
  172. #endif
  173. }
  174. // Special matrices. In the comments, the matrices are shown using the
  175. // GTE_USE_MAT_VEC multiplication convention.
  176. // The projection plane is Dot(N,X-P) = 0 where N is a 3-by-1 unit-length
  177. // normal vector and P is a 3-by-1 point on the plane. The projection is
  178. // oblique to the plane, in the direction of the 3-by-1 vector D.
  179. // Necessarily Dot(N,D) is not zero for this projection to make sense.
  180. // Given a 3-by-1 point U, compute the intersection of the line U+t*D with
  181. // the plane to obtain t = -Dot(N,U-P)/Dot(N,D); then
  182. //
  183. // projection(U) = P + [I - D*N^T/Dot(N,D)]*(U-P)
  184. //
  185. // A 4-by-4 homogeneous transformation representing the projection is
  186. //
  187. // +- -+
  188. // M = | D*N^T - Dot(N,D)*I -Dot(N,P)D |
  189. // | 0^T -Dot(N,D) |
  190. // +- -+
  191. //
  192. // where M applies to [U^T 1]^T by M*[U^T 1]^T. The matrix is chosen so
  193. // that M[3][3] > 0 whenever Dot(N,D) < 0; the projection is onto the
  194. // "positive side" of the plane.
  195. template <typename Real>
  196. Matrix4x4<Real> MakeObliqueProjection(Vector4<Real> const& origin,
  197. Vector4<Real> const& normal, Vector4<Real> const& direction)
  198. {
  199. Matrix4x4<Real> M;
  200. Real const zero = (Real)0;
  201. Real dotND = Dot(normal, direction);
  202. Real dotNO = Dot(origin, normal);
  203. #if defined(GTE_USE_MAT_VEC)
  204. M(0, 0) = direction[0] * normal[0] - dotND;
  205. M(0, 1) = direction[0] * normal[1];
  206. M(0, 2) = direction[0] * normal[2];
  207. M(0, 3) = -dotNO * direction[0];
  208. M(1, 0) = direction[1] * normal[0];
  209. M(1, 1) = direction[1] * normal[1] - dotND;
  210. M(1, 2) = direction[1] * normal[2];
  211. M(1, 3) = -dotNO * direction[1];
  212. M(2, 0) = direction[2] * normal[0];
  213. M(2, 1) = direction[2] * normal[1];
  214. M(2, 2) = direction[2] * normal[2] - dotND;
  215. M(2, 3) = -dotNO * direction[2];
  216. M(3, 0) = zero;
  217. M(3, 1) = zero;
  218. M(3, 2) = zero;
  219. M(3, 3) = -dotND;
  220. #else
  221. M(0, 0) = direction[0] * normal[0] - dotND;
  222. M(1, 0) = direction[0] * normal[1];
  223. M(2, 0) = direction[0] * normal[2];
  224. M(3, 0) = -dotNO * direction[0];
  225. M(0, 1) = direction[1] * normal[0];
  226. M(1, 1) = direction[1] * normal[1] - dotND;
  227. M(2, 1) = direction[1] * normal[2];
  228. M(3, 1) = -dotNO * direction[1];
  229. M(0, 2) = direction[2] * normal[0];
  230. M(1, 2) = direction[2] * normal[1];
  231. M(2, 2) = direction[2] * normal[2] - dotND;
  232. M(3, 2) = -dotNO * direction[2];
  233. M(0, 2) = zero;
  234. M(1, 3) = zero;
  235. M(2, 3) = zero;
  236. M(3, 3) = -dotND;
  237. #endif
  238. return M;
  239. }
  240. // The perspective projection of a point onto a plane is
  241. //
  242. // +- -+
  243. // M = | Dot(N,E-P)*I - E*N^T -(Dot(N,E-P)*I - E*N^T)*E |
  244. // | -N^t Dot(N,E) |
  245. // +- -+
  246. //
  247. // where E is the eye point, P is a point on the plane, and N is a
  248. // unit-length plane normal.
  249. template <typename Real>
  250. Matrix4x4<Real> MakePerspectiveProjection(Vector4<Real> const& origin,
  251. Vector4<Real> const& normal, Vector4<Real> const& eye)
  252. {
  253. Matrix4x4<Real> M;
  254. Real dotND = Dot(normal, eye - origin);
  255. #if defined(GTE_USE_MAT_VEC)
  256. M(0, 0) = dotND - eye[0] * normal[0];
  257. M(0, 1) = -eye[0] * normal[1];
  258. M(0, 2) = -eye[0] * normal[2];
  259. M(0, 3) = -(M(0, 0) * eye[0] + M(0, 1) * eye[1] + M(0, 2) * eye[2]);
  260. M(1, 0) = -eye[1] * normal[0];
  261. M(1, 1) = dotND - eye[1] * normal[1];
  262. M(1, 2) = -eye[1] * normal[2];
  263. M(1, 3) = -(M(1, 0) * eye[0] + M(1, 1) * eye[1] + M(1, 2) * eye[2]);
  264. M(2, 0) = -eye[2] * normal[0];
  265. M(2, 1) = -eye[2] * normal[1];
  266. M(2, 2) = dotND - eye[2] * normal[2];
  267. M(2, 3) = -(M(2, 0) * eye[0] + M(2, 1) * eye[1] + M(2, 2) * eye[2]);
  268. M(3, 0) = -normal[0];
  269. M(3, 1) = -normal[1];
  270. M(3, 2) = -normal[2];
  271. M(3, 3) = Dot(eye, normal);
  272. #else
  273. M(0, 0) = dotND - eye[0] * normal[0];
  274. M(1, 0) = -eye[0] * normal[1];
  275. M(2, 0) = -eye[0] * normal[2];
  276. M(3, 0) = -(M(0, 0) * eye[0] + M(0, 1) * eye[1] + M(0, 2) * eye[2]);
  277. M(0, 1) = -eye[1] * normal[0];
  278. M(1, 1) = dotND - eye[1] * normal[1];
  279. M(2, 1) = -eye[1] * normal[2];
  280. M(3, 1) = -(M(1, 0) * eye[0] + M(1, 1) * eye[1] + M(1, 2) * eye[2]);
  281. M(0, 2) = -eye[2] * normal[0];
  282. M(1, 2) = -eye[2] * normal[1];
  283. M(2, 2) = dotND - eye[2] * normal[2];
  284. M(3, 2) = -(M(2, 0) * eye[0] + M(2, 1) * eye[1] + M(2, 2) * eye[2]);
  285. M(0, 3) = -normal[0];
  286. M(1, 3) = -normal[1];
  287. M(2, 3) = -normal[2];
  288. M(3, 3) = Dot(eye, normal);
  289. #endif
  290. return M;
  291. }
  292. // The reflection of a point through a plane is
  293. // +- -+
  294. // M = | I-2*N*N^T 2*Dot(N,P)*N |
  295. // | 0^T 1 |
  296. // +- -+
  297. //
  298. // where P is a point on the plane and N is a unit-length plane normal.
  299. template <typename Real>
  300. Matrix4x4<Real> MakeReflection(Vector4<Real> const& origin,
  301. Vector4<Real> const& normal)
  302. {
  303. Matrix4x4<Real> M;
  304. Real const zero = (Real)0, one = (Real)1, two = (Real)2;
  305. Real twoDotNO = two * Dot(origin, normal);
  306. #if defined(GTE_USE_MAT_VEC)
  307. M(0, 0) = one - two * normal[0] * normal[0];
  308. M(0, 1) = -two * normal[0] * normal[1];
  309. M(0, 2) = -two * normal[0] * normal[2];
  310. M(0, 3) = twoDotNO * normal[0];
  311. M(1, 0) = M(0, 1);
  312. M(1, 1) = one - two * normal[1] * normal[1];
  313. M(1, 2) = -two * normal[1] * normal[2];
  314. M(1, 3) = twoDotNO * normal[1];
  315. M(2, 0) = M(0, 2);
  316. M(2, 1) = M(1, 2);
  317. M(2, 2) = one - two * normal[2] * normal[2];
  318. M(2, 3) = twoDotNO * normal[2];
  319. M(3, 0) = zero;
  320. M(3, 1) = zero;
  321. M(3, 2) = zero;
  322. M(3, 3) = one;
  323. #else
  324. M(0, 0) = one - two * normal[0] * normal[0];
  325. M(1, 0) = -two * normal[0] * normal[1];
  326. M(2, 0) = -two * normal[0] * normal[2];
  327. M(3, 0) = twoDotNO * normal[0];
  328. M(0, 1) = M(1, 0);
  329. M(1, 1) = one - two * normal[1] * normal[1];
  330. M(2, 1) = -two * normal[1] * normal[2];
  331. M(3, 1) = twoDotNO * normal[1];
  332. M(0, 2) = M(2, 0);
  333. M(1, 2) = M(2, 1);
  334. M(2, 2) = one - two * normal[2] * normal[2];
  335. M(3, 2) = twoDotNO * normal[2];
  336. M(0, 3) = zero;
  337. M(1, 3) = zero;
  338. M(2, 3) = zero;
  339. M(3, 3) = one;
  340. #endif
  341. return M;
  342. }
  343. }