llmatrix4.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /**
  2. * @file llmatrix4.h
  3. * @brief LLMatrix4 class header file.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewergpl$
  6. *
  7. * Copyright (c) 2000-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_M4MATH_H
  33. #define LL_M4MATH_H
  34. #include "llvector3.h"
  35. #include "llvector4.h"
  36. class LLMatrix3;
  37. class LLQuaternion;
  38. // NOTA BENE: Currently assuming a right-handed, x-forward, y-left, z-up
  39. // universe
  40. // Us versus OpenGL:
  41. // Even though OpenGL uses column vectors and we use row vectors, we can plug
  42. // our matrices directly into OpenGL. This is because OpenGL numbers its
  43. // matrices going columnwise:
  44. //
  45. // OpenGL indexing: Our indexing:
  46. // 0 4 8 12 [0][0] [0][1] [0][2] [0][3]
  47. // 1 5 9 13 [1][0] [1][1] [1][2] [1][3]
  48. // 2 6 10 14 [2][0] [2][1] [2][2] [2][3]
  49. // 3 7 11 15 [3][0] [3][1] [3][2] [3][3]
  50. //
  51. // So when you're looking at OpenGL related matrices online, our matrices will
  52. // be "transposed". But our matrices can be plugged directly into OpenGL and
  53. // work fine!
  54. //
  55. // We're using row vectors - [vx, vy, vz, vw]
  56. //
  57. // There are several different ways of thinking of matrices, if you mix them
  58. // up, you'll get very confused.
  59. //
  60. // One way to think about it is a matrix that takes the origin frame A
  61. // and rotates it into B': i.e. A*M = B
  62. //
  63. // Vectors:
  64. // f - forward axis of B expressed in A
  65. // l - left axis of B expressed in A
  66. // u - up axis of B expressed in A
  67. //
  68. // | 0: fx 1: fy 2: fz 3:0 |
  69. // M = | 4: lx 5: ly 6: lz 7:0 |
  70. // | 8: ux 9: uy 10: uz 11:0 |
  71. // | 12: 0 13: 0 14: 0 15:1 |
  72. //
  73. //
  74. //
  75. //
  76. // Another way to think of matrices is matrix that takes a point p in frame A,
  77. // and puts it into frame B:
  78. // This is used most commonly for the modelview matrix.
  79. //
  80. // so p*M = p'
  81. //
  82. // Vectors:
  83. // f - forward of frame B in frame A
  84. // l - left of frame B in frame A
  85. // u - up of frame B in frame A
  86. // o - origin of frame frame B in frame A
  87. //
  88. // | 0: fx 1: lx 2: ux 3:0 |
  89. // M = | 4: fy 5: ly 6: uy 7:0 |
  90. // | 8: fz 9: lz 10: uz 11:0 |
  91. // | 12:-of 13:-ol 14:-ou 15:1 |
  92. //
  93. // of, ol, and ou mean the component of the "global" origin o in the f
  94. // axis, l axis, and u axis.
  95. //
  96. constexpr U32 NUM_VALUES_IN_MAT4 = 4;
  97. class LLMatrix4
  98. {
  99. public:
  100. // Initializes Matrix to identity matrix
  101. LLMatrix4()
  102. {
  103. setIdentity();
  104. }
  105. // Initializes Matrix to values in mat
  106. LL_INLINE explicit LLMatrix4(const F32* mat) { set(mat); }
  107. // Initializes Matrix to values in mat and sets position to (0,0,0)
  108. explicit LLMatrix4(const LLMatrix3& mat);
  109. // Initializes Matrix with rotation q and sets position to (0,0,0)
  110. explicit LLMatrix4(const LLQuaternion& q);
  111. // Initializes Matrix to values in mat and pos
  112. LLMatrix4(const LLMatrix3& mat, const LLVector4& pos);
  113. // These are really, really, inefficient as implemented! - djs
  114. // Initializes Matrix with rotation q and position pos
  115. LLMatrix4(const LLQuaternion& q, const LLVector4& pos);
  116. // Initializes Matrix with axis-angle and position
  117. LLMatrix4(F32 angle, const LLVector4& vec, const LLVector4& pos);
  118. // Initializes Matrix with axis-angle and sets position to (0,0,0)
  119. LLMatrix4(F32 angle, const LLVector4& vec);
  120. // Initializes Matrix with Euler angles
  121. LLMatrix4(F32 roll, F32 pitch, F32 yaw, const LLVector4& pos);
  122. // Initializes Matrix with Euler angles
  123. LLMatrix4(F32 roll, F32 pitch, F32 yaw);
  124. void set(const F32* mat);
  125. // Returns a "this" as an F32 pointer.
  126. LL_INLINE F32* getF32ptr()
  127. {
  128. return (F32*)mMatrix;
  129. }
  130. // Returns a "this" as a const F32 pointer.
  131. LL_INLINE const F32* const getF32ptr() const
  132. {
  133. return (const F32* const)mMatrix;
  134. }
  135. LLSD getValue() const;
  136. void setValue(const LLSD&);
  137. //////////////////////////////
  138. //
  139. // Matrix initializers - these replace any existing values in the matrix
  140. //
  141. void initRows(const LLVector4& row0, const LLVector4& row1,
  142. const LLVector4& row2, const LLVector4& row3);
  143. // various useful matrix functions
  144. LL_INLINE const LLMatrix4& setIdentity(); // Load identity matrix
  145. LL_INLINE bool isIdentity() const;
  146. const LLMatrix4& setZero(); // Clears matrix to all zeros.
  147. // Calculate rotation matrix for rotating angle radians about vec
  148. const LLMatrix4& initRotation(F32 angle, const LLVector4& axis);
  149. // Calculate rotation matrix from Euler angles
  150. const LLMatrix4& initRotation(F32 roll, F32 pitch, F32 yaw);
  151. // Set with Quaternion and position
  152. const LLMatrix4& initRotation(const LLQuaternion& q);
  153. // Position Only
  154. const LLMatrix4& initMatrix(const LLMatrix3& mat);
  155. const LLMatrix4& initMatrix(const LLMatrix3& mat,
  156. const LLVector4& translation);
  157. // Rotation from axis angle + translation
  158. const LLMatrix4& initRotTrans(F32 angle, const LLVector3& axis,
  159. const LLVector3& translation);
  160. // Rotation from Euler + translation
  161. const LLMatrix4& initRotTrans(F32 roll, F32 pitch, F32 yaw,
  162. const LLVector4& pos);
  163. // Set with Quaternion and position
  164. const LLMatrix4& initRotTrans(const LLQuaternion& q, const LLVector4& pos);
  165. const LLMatrix4& initScale(const LLVector3& scale);
  166. // Set all
  167. const LLMatrix4& initAll(const LLVector3& scale, const LLQuaternion& q,
  168. const LLVector3& pos);
  169. ///////////////////////////
  170. //
  171. // Matrix setters - set some properties without modifying others
  172. //
  173. // Sets matrix to translate by (x,y,z)
  174. const LLMatrix4& setTranslation(F32 x, F32 y, F32 z);
  175. void setFwdRow(const LLVector3& row);
  176. void setLeftRow(const LLVector3& row);
  177. void setUpRow(const LLVector3& row);
  178. void setFwdCol(const LLVector3& col);
  179. void setLeftCol(const LLVector3& col);
  180. void setUpCol(const LLVector3& col);
  181. const LLMatrix4& setTranslation(const LLVector4& translation);
  182. const LLMatrix4& setTranslation(const LLVector3& translation);
  183. // Convenience function for simplifying comparison-heavy code by
  184. // intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f
  185. void condition();
  186. ///////////////////////////
  187. //
  188. // Get properties of a matrix
  189. //
  190. F32 determinant() const; // Returns determinant
  191. LLQuaternion quaternion() const; // Returns quaternion
  192. LL_INLINE LLVector4 getFwdRow4() const;
  193. LL_INLINE LLVector4 getLeftRow4() const;
  194. LL_INLINE LLVector4 getUpRow4() const;
  195. LLMatrix3 getMat3() const;
  196. const LLVector3& getTranslation() const { return *(LLVector3*)&mMatrix[3][0]; }
  197. ///////////////////////////
  198. //
  199. // Operations on an existing matrix
  200. //
  201. const LLMatrix4& transpose(); // Transpose LLMatrix4
  202. const LLMatrix4& invert(); // Invert LLMatrix4
  203. const LLMatrix4& invert_real(); // Invert LLMatrix4, works for all matrices
  204. // Rotate existing matrix
  205. // These are really, really, inefficient as implemented ! - djs
  206. // Rotate matrix by rotating angle radians about vec
  207. const LLMatrix4& rotate(F32 angle, const LLVector4& vec);
  208. // Rotate matrix by Euler angles
  209. const LLMatrix4& rotate(F32 roll, F32 pitch, F32 yaw);
  210. // Rotate matrix by Quaternion
  211. const LLMatrix4& rotate(const LLQuaternion& q);
  212. // Translate existing matrix
  213. // Translate matrix by (vec[VX], vec[VY], vec[VZ])
  214. const LLMatrix4& translate(const LLVector3& vec);
  215. ///////////////////////
  216. //
  217. // Operators
  218. //
  219. #if 0
  220. // Return a * b
  221. friend LL_INLINE LLMatrix4 operator*(const LLMatrix4& a,
  222. const LLMatrix4& b);
  223. #endif
  224. // Return transform of vector a by matrix b
  225. friend LLVector4 operator*(const LLVector4& a, const LLMatrix4& b);
  226. // Return full transform of a by matrix b
  227. friend LL_INLINE const LLVector3 operator*(const LLVector3& a,
  228. const LLMatrix4& b);
  229. // Rotates a but does not translate
  230. friend LLVector4 rotate_vector(const LLVector4& a, const LLMatrix4& b);
  231. // Rotates a but does not translate
  232. friend LLVector3 rotate_vector(const LLVector3& a, const LLMatrix4& b);
  233. // Returns a == b
  234. friend bool operator==(const LLMatrix4& a, const LLMatrix4& b);
  235. // Returns a != b
  236. friend bool operator!=(const LLMatrix4& a, const LLMatrix4& b);
  237. // Returns a < b
  238. friend bool operator<(const LLMatrix4& a, const LLMatrix4& b);
  239. // Returns a + b
  240. friend LL_INLINE const LLMatrix4& operator+=(LLMatrix4& a, const LLMatrix4& b);
  241. // Returns a - b
  242. friend LL_INLINE const LLMatrix4& operator-=(LLMatrix4& a, const LLMatrix4& b);
  243. // Returns a * b
  244. friend LL_INLINE const LLMatrix4& operator*=(LLMatrix4& a, const LLMatrix4& b);
  245. // Returns a * b
  246. friend LL_INLINE const LLMatrix4& operator*=(LLMatrix4& a, const F32& b);
  247. // Streams a
  248. friend std::ostream& operator<<(std::ostream& s, const LLMatrix4& a);
  249. public:
  250. F32 mMatrix[NUM_VALUES_IN_MAT4][NUM_VALUES_IN_MAT4];
  251. };
  252. LL_INLINE LLVector4 LLMatrix4::getFwdRow4() const
  253. {
  254. return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ],
  255. mMatrix[VX][VW]);
  256. }
  257. LL_INLINE LLVector4 LLMatrix4::getLeftRow4() const
  258. {
  259. return LLVector4(mMatrix[VY][VX], mMatrix[VY][VY], mMatrix[VY][VZ],
  260. mMatrix[VY][VW]);
  261. }
  262. LL_INLINE LLVector4 LLMatrix4::getUpRow4() const
  263. {
  264. return LLVector4(mMatrix[VZ][VX], mMatrix[VZ][VY], mMatrix[VZ][VZ],
  265. mMatrix[VZ][VW]);
  266. }
  267. LL_INLINE const LLMatrix4& LLMatrix4::setIdentity()
  268. {
  269. mMatrix[0][0] = 1.f;
  270. mMatrix[0][1] = 0.f;
  271. mMatrix[0][2] = 0.f;
  272. mMatrix[0][3] = 0.f;
  273. mMatrix[1][0] = 0.f;
  274. mMatrix[1][1] = 1.f;
  275. mMatrix[1][2] = 0.f;
  276. mMatrix[1][3] = 0.f;
  277. mMatrix[2][0] = 0.f;
  278. mMatrix[2][1] = 0.f;
  279. mMatrix[2][2] = 1.f;
  280. mMatrix[2][3] = 0.f;
  281. mMatrix[3][0] = 0.f;
  282. mMatrix[3][1] = 0.f;
  283. mMatrix[3][2] = 0.f;
  284. mMatrix[3][3] = 1.f;
  285. return *this;
  286. }
  287. LL_INLINE bool LLMatrix4::isIdentity() const
  288. {
  289. return mMatrix[0][0] == 1.f && mMatrix[0][1] == 0.f &&
  290. mMatrix[0][2] == 0.f && mMatrix[0][3] == 0.f &&
  291. mMatrix[1][0] == 0.f && mMatrix[1][1] == 1.f &&
  292. mMatrix[1][2] == 0.f && mMatrix[1][3] == 0.f &&
  293. mMatrix[2][0] == 0.f && mMatrix[2][1] == 0.f &&
  294. mMatrix[2][2] == 1.f && mMatrix[2][3] == 0.f &&
  295. mMatrix[3][0] == 0.f && mMatrix[3][1] == 0.f &&
  296. mMatrix[3][2] == 0.f && mMatrix[3][3] == 1.f;
  297. }
  298. #if 0
  299. LL_INLINE LLMatrix4 operator*(const LLMatrix4& a, const LLMatrix4& b)
  300. {
  301. LLMatrix4 mat;
  302. for (U32 i = 0; i < NUM_VALUES_IN_MAT4; ++i)
  303. {
  304. for (U32 j = 0; j < NUM_VALUES_IN_MAT4; ++j)
  305. {
  306. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
  307. a.mMatrix[j][1] * b.mMatrix[1][i] +
  308. a.mMatrix[j][2] * b.mMatrix[2][i] +
  309. a.mMatrix[j][3] * b.mMatrix[3][i];
  310. }
  311. }
  312. return mat;
  313. }
  314. #endif
  315. LL_INLINE const LLMatrix4& operator*=(LLMatrix4& a, const LLMatrix4& b)
  316. {
  317. LLMatrix4 mat;
  318. for (U32 i = 0; i < NUM_VALUES_IN_MAT4; ++i)
  319. {
  320. for (U32 j = 0; j < NUM_VALUES_IN_MAT4; ++j)
  321. {
  322. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
  323. a.mMatrix[j][1] * b.mMatrix[1][i] +
  324. a.mMatrix[j][2] * b.mMatrix[2][i] +
  325. a.mMatrix[j][3] * b.mMatrix[3][i];
  326. }
  327. }
  328. a = mat;
  329. return a;
  330. }
  331. LL_INLINE const LLMatrix4& operator*=(LLMatrix4& a, const F32& b)
  332. {
  333. LLMatrix4 mat;
  334. for (U32 i = 0; i < NUM_VALUES_IN_MAT4; ++i)
  335. {
  336. for (U32 j = 0; j < NUM_VALUES_IN_MAT4; ++j)
  337. {
  338. mat.mMatrix[j][i] = a.mMatrix[j][i] * b;
  339. }
  340. }
  341. a = mat;
  342. return a;
  343. }
  344. LL_INLINE const LLMatrix4& operator+=(LLMatrix4& a, const LLMatrix4& b)
  345. {
  346. LLMatrix4 mat;
  347. for (U32 i = 0; i < NUM_VALUES_IN_MAT4; ++i)
  348. {
  349. for (U32 j = 0; j < NUM_VALUES_IN_MAT4; ++j)
  350. {
  351. mat.mMatrix[j][i] = a.mMatrix[j][i] + b.mMatrix[j][i];
  352. }
  353. }
  354. a = mat;
  355. return a;
  356. }
  357. LL_INLINE const LLMatrix4& operator-=(LLMatrix4& a, const LLMatrix4& b)
  358. {
  359. LLMatrix4 mat;
  360. for (U32 i = 0; i < NUM_VALUES_IN_MAT4; ++i)
  361. {
  362. for (U32 j = 0; j < NUM_VALUES_IN_MAT4; ++j)
  363. {
  364. mat.mMatrix[j][i] = a.mMatrix[j][i] - b.mMatrix[j][i];
  365. }
  366. }
  367. a = mat;
  368. return a;
  369. }
  370. // Operates "to the left" on row-vector a
  371. //
  372. // When avatar vertex programs are off, this function is a hot spot in profiles
  373. // due to software skinning in LLViewerJointMesh::updateGeometry(). JC
  374. LL_INLINE const LLVector3 operator*(const LLVector3& a, const LLMatrix4& b)
  375. {
  376. // This is better than making a temporary LLVector3. This eliminates an
  377. // unnecessary LLVector3() constructor and also helps the compiler to
  378. // realize that the output floats do not alias the input floats, hence
  379. // eliminating redundant loads of a.mV[0], etc. JC
  380. return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
  381. a.mV[VY] * b.mMatrix[VY][VX] +
  382. a.mV[VZ] * b.mMatrix[VZ][VX] +
  383. b.mMatrix[VW][VX],
  384. a.mV[VX] * b.mMatrix[VX][VY] +
  385. a.mV[VY] * b.mMatrix[VY][VY] +
  386. a.mV[VZ] * b.mMatrix[VZ][VY] +
  387. b.mMatrix[VW][VY],
  388. a.mV[VX] * b.mMatrix[VX][VZ] +
  389. a.mV[VY] * b.mMatrix[VY][VZ] +
  390. a.mV[VZ] * b.mMatrix[VZ][VZ] +
  391. b.mMatrix[VW][VZ]);
  392. }
  393. #endif