Matrix4.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * This source file is part of rocket, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://www.librocket.com
  5. *
  6. * Copyright (c) 2014 Markus Schöngart
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. #ifndef ROCKETCOREMATRIX4_H
  28. #define ROCKETCOREMATRIX4_H
  29. #include "Debug.h"
  30. #include "Math.h"
  31. #include "Vector4.h"
  32. namespace Rocket {
  33. namespace Core {
  34. /**
  35. Templated class that acts as base strategy for vectors access patterns of matrices.
  36. @author Markus Schöngart
  37. */
  38. template< typename Component >
  39. struct MatrixStorageBase
  40. {
  41. typedef Component ComponentType;
  42. typedef Vector4< ComponentType > VectorType;
  43. typedef VectorType VectorsType[4];
  44. class StrideVector
  45. {
  46. VectorsType& vectors;
  47. int idx;
  48. public:
  49. inline StrideVector(VectorsType& vectors, int idx) noexcept
  50. : vectors(vectors), idx(idx) { }
  51. inline ComponentType& operator[](int i) noexcept
  52. { return vectors[i][idx]; }
  53. inline StrideVector& operator=(const VectorType& vec) noexcept
  54. {
  55. (*this)[0] = vec[0];
  56. (*this)[1] = vec[1];
  57. (*this)[2] = vec[2];
  58. (*this)[3] = vec[3];
  59. return *this;
  60. }
  61. operator const VectorType() const noexcept
  62. {
  63. return VectorType(
  64. (*this)[0],
  65. (*this)[1],
  66. (*this)[2],
  67. (*this)[3]
  68. );
  69. }
  70. };
  71. class StrideAccess
  72. {
  73. VectorsType& vectors;
  74. public:
  75. inline StrideAccess(VectorsType& vectors) noexcept
  76. : vectors(vectors) { }
  77. inline StrideVector operator[](int i) noexcept
  78. { return StrideVector(vectors, i); }
  79. };
  80. class ConstStrideVector
  81. {
  82. const VectorsType& vectors;
  83. int idx;
  84. public:
  85. inline ConstStrideVector(const VectorsType& vectors, int idx) noexcept
  86. : vectors(vectors), idx(idx) { }
  87. inline const ComponentType& operator[](int i) const noexcept
  88. { return vectors[i][idx]; }
  89. inline operator const VectorType() const noexcept
  90. {
  91. return VectorType(
  92. (*this)[0],
  93. (*this)[1],
  94. (*this)[2],
  95. (*this)[3]
  96. );
  97. }
  98. };
  99. class ConstStrideAccess
  100. {
  101. const VectorsType& vectors;
  102. public:
  103. inline ConstStrideAccess(const VectorsType& vectors) noexcept
  104. : vectors(vectors) { }
  105. inline ConstStrideVector operator[](int i) noexcept
  106. { return ConstStrideVector(vectors, i); }
  107. };
  108. class PackedVector
  109. {
  110. VectorType& vector;
  111. public:
  112. inline PackedVector(VectorType& vector) noexcept
  113. : vector(vector) { }
  114. inline ComponentType& operator[](int i) noexcept
  115. { return vector[i]; }
  116. inline PackedVector& operator=(const VectorType& vec) noexcept
  117. {
  118. vector = vec;
  119. return *this;
  120. }
  121. inline PackedVector& operator=(StrideVector& vec) noexcept
  122. {
  123. vector[0] = vec[0];
  124. vector[1] = vec[1];
  125. vector[2] = vec[2];
  126. vector[3] = vec[3];
  127. return *this;
  128. }
  129. inline PackedVector& operator=(ConstStrideVector& vec) noexcept
  130. {
  131. vector[0] = vec[0];
  132. vector[1] = vec[1];
  133. vector[2] = vec[2];
  134. vector[3] = vec[3];
  135. return *this;
  136. }
  137. inline operator VectorType&() noexcept { return vector; }
  138. };
  139. class PackedAccess
  140. {
  141. VectorsType& vectors;
  142. public:
  143. inline PackedAccess(VectorsType& vectors) noexcept
  144. : vectors(vectors) { }
  145. inline PackedVector operator[](int i) noexcept
  146. { return PackedVector(vectors[i]); }
  147. };
  148. #if 0
  149. class ConstPackedVector
  150. {
  151. const VectorType& vectors;
  152. public:
  153. inline ConstPackedVector(const VectorType& vectors) noexcept
  154. : vectors(vectors) { }
  155. inline const ComponentType& operator[](int i) const noexcept
  156. { return vectors[i]; }
  157. inline operator const VectorType&() noexcept { return vectors; }
  158. };
  159. #endif
  160. class ConstPackedAccess
  161. {
  162. const VectorsType& vectors;
  163. public:
  164. inline ConstPackedAccess(const VectorsType& vectors) noexcept
  165. : vectors(vectors) { }
  166. inline const VectorType& operator[](int i) noexcept
  167. { return vectors[i]; }
  168. };
  169. };
  170. template< typename Component >
  171. struct RowMajorStorage;
  172. template< typename Component >
  173. struct ColumnMajorStorage;
  174. /**
  175. Templated class that defines the vectors access pattern for row-major matrices.
  176. @author Markus Schöngart
  177. */
  178. template< typename Component >
  179. struct RowMajorStorage : public MatrixStorageBase< Component >
  180. {
  181. typedef Component ComponentType;
  182. typedef Vector4< ComponentType > VectorType;
  183. typedef RowMajorStorage< ComponentType > ThisType;
  184. typedef ColumnMajorStorage< ComponentType > TransposeType;
  185. typedef typename MatrixStorageBase< Component >::PackedVector Row;
  186. typedef typename MatrixStorageBase< Component >::PackedAccess Rows;
  187. typedef const typename MatrixStorageBase< Component >::VectorType& ConstRow;
  188. typedef typename MatrixStorageBase< Component >::ConstPackedAccess ConstRows;
  189. typedef typename MatrixStorageBase< Component >::StrideVector Column;
  190. typedef typename MatrixStorageBase< Component >::StrideAccess Columns;
  191. typedef typename MatrixStorageBase< Component >::ConstStrideVector ConstColumn;
  192. typedef typename MatrixStorageBase< Component >::ConstStrideAccess ConstColumns;
  193. };
  194. /**
  195. Templated class that defines the vectors access pattern for column-major matrices.
  196. @author Markus Schöngart
  197. */
  198. template< typename Component >
  199. struct ColumnMajorStorage
  200. {
  201. typedef Component ComponentType;
  202. typedef Vector4< ComponentType > VectorType;
  203. typedef ColumnMajorStorage< ComponentType > ThisType;
  204. typedef RowMajorStorage< ComponentType > TransposeType;
  205. typedef typename MatrixStorageBase< Component >::PackedVector Column;
  206. typedef typename MatrixStorageBase< Component >::PackedAccess Columns;
  207. typedef const typename MatrixStorageBase< Component >::VectorType& ConstColumn;
  208. typedef typename MatrixStorageBase< Component >::ConstPackedAccess ConstColumns;
  209. typedef typename MatrixStorageBase< Component >::StrideVector Row;
  210. typedef typename MatrixStorageBase< Component >::StrideAccess Rows;
  211. typedef typename MatrixStorageBase< Component >::ConstStrideVector ConstRow;
  212. typedef typename MatrixStorageBase< Component >::ConstStrideAccess ConstRows;
  213. };
  214. /**
  215. Templated class for a generic 4x4 matrix.
  216. @author Markus Schöngart
  217. */
  218. template< typename Component, class Storage = ColumnMajorStorage< Component > >
  219. class Matrix4
  220. {
  221. public:
  222. typedef Component ComponentType;
  223. typedef Vector4< ComponentType > VectorType;
  224. typedef Matrix4< ComponentType, Storage > ThisType;
  225. typedef Storage StorageType;
  226. typedef typename StorageType::Row Row;
  227. typedef typename StorageType::Rows Rows;
  228. typedef typename StorageType::ConstRow ConstRow;
  229. typedef typename StorageType::ConstRows ConstRows;
  230. typedef typename StorageType::Column Column;
  231. typedef typename StorageType::Columns Columns;
  232. typedef typename StorageType::ConstColumn ConstColumn;
  233. typedef typename StorageType::ConstColumns ConstColumns;
  234. typedef typename StorageType::TransposeType TransposeStorageType;
  235. typedef Matrix4< ComponentType, TransposeStorageType > TransposeType;
  236. friend class Matrix4< ComponentType, TransposeStorageType >;
  237. private:
  238. // The components of the matrix.
  239. VectorType vectors[4];
  240. /// Initialising constructor.
  241. Matrix4(const VectorType& vec0, const VectorType& vec1, const VectorType& vec2, const VectorType& vec3) noexcept;
  242. template< typename _Component, class _StorageA >
  243. struct VectorMultiplier
  244. {
  245. typedef _Component ComponentType;
  246. typedef _StorageA StorageAType;
  247. typedef Matrix4< ComponentType, StorageAType > MatrixAType;
  248. typedef Vector4< ComponentType > VectorType;
  249. static const VectorType Multiply(
  250. const MatrixAType& lhs,
  251. const VectorType& rhs
  252. ) noexcept;
  253. };
  254. template< typename _Component, class _StorageA, class _StorageB >
  255. struct MatrixMultiplier
  256. {
  257. typedef _Component ComponentType;
  258. typedef _StorageA StorageAType;
  259. typedef _StorageB StorageBType;
  260. typedef Matrix4< ComponentType, StorageAType > MatrixAType;
  261. typedef Matrix4< ComponentType, StorageBType > MatrixBType;
  262. static const VectorType Multiply(
  263. const MatrixAType& lhs,
  264. const VectorType& rhs
  265. );
  266. static const MatrixAType Multiply(
  267. const MatrixAType& lhs,
  268. const MatrixBType& rhs
  269. ) noexcept;
  270. };
  271. public:
  272. /// Lightweight, non-initialising constructor.
  273. inline Matrix4() noexcept;
  274. /// Initialising, copy constructor.
  275. inline Matrix4(const ThisType& other) noexcept;
  276. Matrix4(const TransposeType& other) noexcept;
  277. /// Assignment operator
  278. const ThisType& operator=(const ThisType& other) noexcept;
  279. const ThisType& operator=(const TransposeType& other) noexcept;
  280. /// Construct from row vectors.
  281. static const ThisType FromRows(const VectorType& vec0, const VectorType& vec1, const VectorType& vec2, const VectorType& vec3) noexcept;
  282. /// Construct from column vectors.
  283. static const ThisType FromColumns(const VectorType& vec0, const VectorType& vec1, const VectorType& vec2, const VectorType& vec3) noexcept;
  284. /// Construct from components.
  285. static const ThisType FromRowMajor(const ComponentType* components) noexcept;
  286. static const ThisType FromColumnMajor(const ComponentType* components) noexcept;
  287. // Convert to raw values; keep the storage mode in mind.
  288. inline Component* data() noexcept
  289. { return &vectors[0][0]; }
  290. inline const Component* data() const noexcept
  291. { return &vectors[0][0]; }
  292. /// Get the i-th row
  293. inline Row GetRow(int i) noexcept
  294. { Rows rows(vectors); return rows[i]; }
  295. /// Get the i-th row
  296. inline ConstRow GetRow(int i) const noexcept
  297. { ConstRows rows(vectors); return rows[i]; }
  298. /// Set the i-th row
  299. inline void SetRow(int i, const VectorType& vec) noexcept
  300. { Rows rows(vectors); rows[i] = vec; }
  301. /// Set all rows
  302. void SetRows(const VectorType& vec0, const VectorType& vec1, const VectorType& vec2, const VectorType& vec3) noexcept;
  303. /// Get the i-th column
  304. inline Column GetColumn(int i) noexcept
  305. { Columns columns(vectors); return columns[i]; }
  306. /// Get the i-th column
  307. inline ConstColumn GetColumn(int i) const noexcept
  308. { ConstColumns columns(vectors); return columns[i]; }
  309. /// Set the i-th column
  310. inline void SetColumn(int i, const VectorType& vec) noexcept
  311. { Columns columns(vectors); columns[i] = vec; }
  312. /// Set all columns
  313. void SetColumns(const VectorType& vec0, const VectorType& vec1, const VectorType& vec2, const VectorType& vec3) noexcept;
  314. /// Returns the transpose of this matrix.
  315. /// @return The transpose matrix.
  316. inline const TransposeType& Transpose() const noexcept
  317. { return reinterpret_cast<const TransposeType&>(*this); }
  318. /// Inverts this matrix in place, if possible.
  319. /// @return true, if the inversion succeeded.
  320. bool Invert() noexcept;
  321. /// Inverts this matrix in place, if possible.
  322. /// @return true, if the inversion succeeded.
  323. float Determinant() const noexcept;
  324. /// Returns the negation of this matrix.
  325. /// @return The negation of this matrix.
  326. ThisType operator-() const noexcept;
  327. /// Adds another matrix to this in-place.
  328. /// @param[in] other The matrix to add.
  329. /// @return This matrix, post-operation.
  330. const ThisType& operator+=(const ThisType& other) noexcept;
  331. const ThisType& operator+=(const TransposeType& other) noexcept;
  332. /// Subtracts another matrix from this in-place.
  333. /// @param[in] other The matrix to subtract.
  334. /// @return This matrix, post-operation.
  335. const ThisType& operator-=(const ThisType& other) noexcept;
  336. const ThisType& operator-=(const TransposeType& other) noexcept;
  337. /// Scales this matrix in-place.
  338. /// @param[in] other The value to scale this matrix's components by.
  339. /// @return This matrix, post-operation.
  340. const ThisType& operator*=(Component other) noexcept;
  341. /// Scales this matrix in-place by the inverse of a value.
  342. /// @param[in] other The value to divide this matrix's components by.
  343. /// @return This matrix, post-operation.
  344. const ThisType& operator/=(Component other) noexcept;
  345. inline const VectorType& operator[](size_t i) const noexcept { return vectors[i]; }
  346. inline VectorType& operator[](size_t i) noexcept { return vectors[i]; }
  347. /// Returns the sum of this matrix and another.
  348. /// @param[in] other The matrix to add this to.
  349. /// @return The sum of the two matrices.
  350. inline const ThisType operator+(const ThisType& other) const noexcept
  351. { ThisType result(*this); result += other; return result; }
  352. inline const ThisType operator+(const TransposeType& other) const noexcept
  353. { ThisType result(*this); result += other; return result; }
  354. /// Returns the result of subtracting another matrix from this matrix.
  355. /// @param[in] other The matrix to subtract from this matrix.
  356. /// @return The result of the subtraction.
  357. inline const ThisType operator-(const ThisType& other) const noexcept
  358. { ThisType result(*this); result -= other; return result; }
  359. inline const ThisType operator-(const TransposeType& other) const noexcept
  360. { ThisType result(*this); result -= other; return result; }
  361. /// Returns the result of multiplying this matrix by a scalar.
  362. /// @param[in] other The scalar value to multiply by.
  363. /// @return The result of the scale.
  364. inline const ThisType operator*(Component other) const noexcept
  365. { ThisType result(*this); result *= other; return result; }
  366. /// Returns the result of dividing this matrix by a scalar.
  367. /// @param[in] other The scalar value to divide by.
  368. /// @return The result of the scale.
  369. inline const ThisType operator/(Component other) const noexcept
  370. { ThisType result(*this); result *= other; return result; }
  371. /// Returns the result of multiplying this matrix by a vector.
  372. /// @param[in] other The scalar value to multiply by.
  373. /// @return The result of the scale.
  374. const VectorType operator*(const VectorType& other) const noexcept
  375. { return VectorMultiplier< Component, Storage >::Multiply(*this, other); }
  376. /// Returns the result of multiplying this matrix by another matrix.
  377. /// @param[in] other The matrix value to multiply by.
  378. /// @return The result of the multiplication.
  379. template< class Storage2 >
  380. const ThisType operator*(const Matrix4< Component, Storage2 >& other) const noexcept
  381. { return MatrixMultiplier< Component, Storage, Storage2 >::Multiply(*this, other); }
  382. /// Multiplies this matrix by another matrix in place.
  383. /// @param[in] other The scalar value to multiply by.
  384. /// @return The result of the scale.
  385. inline const ThisType& operator*=(const ThisType& other) noexcept
  386. { *this = *this * other; return *this; }
  387. inline const ThisType& operator*=(const TransposeType& other) noexcept
  388. { *this = *this * other; return *this; }
  389. /// Equality operator.
  390. /// @param[in] other The matrix to compare this against.
  391. /// @return True if the two matrices are equal, false otherwise.
  392. bool operator==(const ThisType& other) const noexcept;
  393. bool operator==(const TransposeType& other) const noexcept;
  394. /// Inequality operator.
  395. /// @param[in] other The matrix to compare this against.
  396. /// @return True if the two matrices are not equal, false otherwise.
  397. bool operator!=(const ThisType& other) const noexcept;
  398. bool operator!=(const TransposeType& other) const noexcept;
  399. /// Return the identity matrix.
  400. /// @return The identity matrix.
  401. inline static const ThisType& Identity() noexcept;
  402. /// Return a diagonal matrix.
  403. /// @return A diagonal matrix.
  404. static ThisType Diag(Component a, Component b, Component c, Component d = 1) noexcept;
  405. /// Create an orthographic projection matrix
  406. /// @param l The horizontal coordinate of the left clipping plane
  407. /// @param r The horizontal coordinate of the right clipping plane
  408. /// @param b The vertical coordinate of the bottom clipping plane
  409. /// @param t The vertical coordinate of the top clipping plane
  410. /// @param n The depth coordinate of the near clipping plane
  411. /// @param f The depth coordinate of the far clipping plane
  412. /// @return The specified orthographic projection matrix.
  413. static ThisType ProjectOrtho(Component l, Component r, Component b, Component t, Component n, Component f) noexcept;
  414. /// Create a perspective projection matrix
  415. /// @param l The horizontal coordinate of the left clipping plane
  416. /// @param r The horizontal coordinate of the right clipping plane
  417. /// @param b The vertical coordinate of the bottom clipping plane
  418. /// @param t The vertical coordinate of the top clipping plane
  419. /// @param n The depth coordinate of the near clipping plane
  420. /// @param f The depth coordinate of the far clipping plane
  421. /// @return The specified perspective projection matrix.
  422. static ThisType ProjectPerspective(Component l, Component r, Component b, Component t, Component n, Component f) noexcept;
  423. /// Return a translation matrix.
  424. /// @return A translation matrix.
  425. static ThisType Translate (const Vector3< Component >& v) noexcept;
  426. static ThisType Translate (Component x, Component y, Component z) noexcept;
  427. static ThisType TranslateX (Component x) noexcept;
  428. static ThisType TranslateY (Component y) noexcept;
  429. static ThisType TranslateZ (Component z) noexcept;
  430. /// Return a scaling matrix.
  431. /// @return A scaling matrix.
  432. static ThisType Scale (Component x, Component y, Component z) noexcept;
  433. static ThisType ScaleX (Component x) noexcept;
  434. static ThisType ScaleY (Component y) noexcept;
  435. static ThisType ScaleZ (Component z) noexcept;
  436. /// Return a rotation matrix.
  437. /// @return A rotation matrix.
  438. static ThisType Rotate (const Vector3< Component >& v, Component angle) noexcept;
  439. static ThisType RotateX (Component angle) noexcept;
  440. static ThisType RotateY (Component angle) noexcept;
  441. static ThisType RotateZ (Component angle) noexcept;
  442. /// Return a skew/shearing matrix.
  443. /// @return A skew matrix.
  444. static ThisType Skew (Component angle_x, Component angle_y) noexcept;
  445. static ThisType SkewX (Component angle) noexcept;
  446. static ThisType SkewY (Component angle) noexcept;
  447. static ThisType Compose(const Vector3< Component >& translation, const Vector3< Component >& scale,
  448. const Vector3< Component >& skew, const Vector4< Component >& perspective, const Vector4< Component >& quaternion) noexcept;
  449. };
  450. }
  451. }
  452. #include "Matrix4.inl"
  453. #endif