PageRenderTime 37ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llmath/m4math.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 403 lines | 202 code | 67 blank | 134 comment | 24 complexity | 562c24543942fb453c5aaa0b507e4362 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file m4math.h
  3. * @brief LLMatrix4 class header file.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_M4MATH_H
  27. #define LL_M4MATH_H
  28. #include "v3math.h"
  29. class LLVector4;
  30. class LLMatrix3;
  31. class LLQuaternion;
  32. // NOTA BENE: Currently assuming a right-handed, x-forward, y-left, z-up universe
  33. // Us versus OpenGL:
  34. // Even though OpenGL uses column vectors and we use row vectors, we can plug our matrices
  35. // directly into OpenGL. This is because OpenGL numbers its matrices going columnwise:
  36. //
  37. // OpenGL indexing: Our indexing:
  38. // 0 4 8 12 [0][0] [0][1] [0][2] [0][3]
  39. // 1 5 9 13 [1][0] [1][1] [1][2] [1][3]
  40. // 2 6 10 14 [2][0] [2][1] [2][2] [2][3]
  41. // 3 7 11 15 [3][0] [3][1] [3][2] [3][3]
  42. //
  43. // So when you're looking at OpenGL related matrices online, our matrices will be
  44. // "transposed". But our matrices can be plugged directly into OpenGL and work fine!
  45. //
  46. // We're using row vectors - [vx, vy, vz, vw]
  47. //
  48. // There are several different ways of thinking of matrices, if you mix them up, you'll get very confused.
  49. //
  50. // One way to think about it is a matrix that takes the origin frame A
  51. // and rotates it into B': i.e. A*M = B
  52. //
  53. // Vectors:
  54. // f - forward axis of B expressed in A
  55. // l - left axis of B expressed in A
  56. // u - up axis of B expressed in A
  57. //
  58. // | 0: fx 1: fy 2: fz 3:0 |
  59. // M = | 4: lx 5: ly 6: lz 7:0 |
  60. // | 8: ux 9: uy 10: uz 11:0 |
  61. // | 12: 0 13: 0 14: 0 15:1 |
  62. //
  63. //
  64. //
  65. //
  66. // Another way to think of matrices is matrix that takes a point p in frame A, and puts it into frame B:
  67. // This is used most commonly for the modelview matrix.
  68. //
  69. // so p*M = p'
  70. //
  71. // Vectors:
  72. // f - forward of frame B in frame A
  73. // l - left of frame B in frame A
  74. // u - up of frame B in frame A
  75. // o - origin of frame frame B in frame A
  76. //
  77. // | 0: fx 1: lx 2: ux 3:0 |
  78. // M = | 4: fy 5: ly 6: uy 7:0 |
  79. // | 8: fz 9: lz 10: uz 11:0 |
  80. // | 12:-of 13:-ol 14:-ou 15:1 |
  81. //
  82. // of, ol, and ou mean the component of the "global" origin o in the f axis, l axis, and u axis.
  83. //
  84. static const U32 NUM_VALUES_IN_MAT4 = 4;
  85. class LLMatrix4
  86. {
  87. public:
  88. F32 mMatrix[NUM_VALUES_IN_MAT4][NUM_VALUES_IN_MAT4];
  89. // Initializes Matrix to identity matrix
  90. LLMatrix4()
  91. {
  92. setIdentity();
  93. }
  94. explicit LLMatrix4(const F32 *mat); // Initializes Matrix to values in mat
  95. explicit LLMatrix4(const LLMatrix3 &mat); // Initializes Matrix to values in mat and sets position to (0,0,0)
  96. explicit LLMatrix4(const LLQuaternion &q); // Initializes Matrix with rotation q and sets position to (0,0,0)
  97. LLMatrix4(const LLMatrix3 &mat, const LLVector4 &pos); // Initializes Matrix to values in mat and pos
  98. // These are really, really, inefficient as implemented! - djs
  99. LLMatrix4(const LLQuaternion &q, const LLVector4 &pos); // Initializes Matrix with rotation q and position pos
  100. LLMatrix4(F32 angle,
  101. const LLVector4 &vec,
  102. const LLVector4 &pos); // Initializes Matrix with axis-angle and position
  103. LLMatrix4(F32 angle, const LLVector4 &vec); // Initializes Matrix with axis-angle and sets position to (0,0,0)
  104. LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw,
  105. const LLVector4 &pos); // Initializes Matrix with Euler angles
  106. LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles
  107. ~LLMatrix4(void); // Destructor
  108. LLSD getValue() const;
  109. void setValue(const LLSD&);
  110. //////////////////////////////
  111. //
  112. // Matrix initializers - these replace any existing values in the matrix
  113. //
  114. void initRows(const LLVector4 &row0,
  115. const LLVector4 &row1,
  116. const LLVector4 &row2,
  117. const LLVector4 &row3);
  118. // various useful matrix functions
  119. const LLMatrix4& setIdentity(); // Load identity matrix
  120. bool isIdentity() const;
  121. const LLMatrix4& setZero(); // Clears matrix to all zeros.
  122. const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z)
  123. const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec
  124. const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles
  125. const LLMatrix4& initRotation(const LLQuaternion &q); // Set with Quaternion and position
  126. // Position Only
  127. const LLMatrix4& initMatrix(const LLMatrix3 &mat); //
  128. const LLMatrix4& initMatrix(const LLMatrix3 &mat, const LLVector4 &translation);
  129. // These operation create a matrix that will rotate and translate by the
  130. // specified amounts.
  131. const LLMatrix4& initRotTrans(const F32 angle,
  132. const F32 rx, const F32 ry, const F32 rz,
  133. const F32 px, const F32 py, const F32 pz);
  134. const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation); // Rotation from axis angle + translation
  135. const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation
  136. const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position
  137. const LLMatrix4& initScale(const LLVector3 &scale);
  138. // Set all
  139. const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos);
  140. ///////////////////////////
  141. //
  142. // Matrix setters - set some properties without modifying others
  143. //
  144. const LLMatrix4& setTranslation(const F32 x, const F32 y, const F32 z); // Sets matrix to translate by (x,y,z)
  145. void setFwdRow(const LLVector3 &row);
  146. void setLeftRow(const LLVector3 &row);
  147. void setUpRow(const LLVector3 &row);
  148. void setFwdCol(const LLVector3 &col);
  149. void setLeftCol(const LLVector3 &col);
  150. void setUpCol(const LLVector3 &col);
  151. const LLMatrix4& setTranslation(const LLVector4 &translation);
  152. const LLMatrix4& setTranslation(const LLVector3 &translation);
  153. ///////////////////////////
  154. //
  155. // Get properties of a matrix
  156. //
  157. F32 determinant(void) const; // Return determinant
  158. LLQuaternion quaternion(void) const; // Returns quaternion
  159. LLVector4 getFwdRow4() const;
  160. LLVector4 getLeftRow4() const;
  161. LLVector4 getUpRow4() const;
  162. LLMatrix3 getMat3() const;
  163. const LLVector3& getTranslation() const { return *(LLVector3*)&mMatrix[3][0]; }
  164. ///////////////////////////
  165. //
  166. // Operations on an existing matrix
  167. //
  168. const LLMatrix4& transpose(); // Transpose LLMatrix4
  169. const LLMatrix4& invert(); // Invert LLMatrix4
  170. // Rotate existing matrix
  171. // These are really, really, inefficient as implemented! - djs
  172. const LLMatrix4& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z)
  173. const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec); // Rotate matrix by rotating angle radians about vec
  174. const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by Euler angles
  175. const LLMatrix4& rotate(const LLQuaternion &q); // Rotate matrix by Quaternion
  176. // Translate existing matrix
  177. const LLMatrix4& translate(const LLVector3 &vec); // Translate matrix by (vec[VX], vec[VY], vec[VZ])
  178. ///////////////////////
  179. //
  180. // Operators
  181. //
  182. // friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
  183. friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b
  184. friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
  185. friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate
  186. friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate
  187. friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b
  188. friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b
  189. friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b
  190. friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b
  191. friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b
  192. friend const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
  193. friend const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b); // Return a * b
  194. friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a
  195. };
  196. inline const LLMatrix4& LLMatrix4::setIdentity()
  197. {
  198. mMatrix[0][0] = 1.f;
  199. mMatrix[0][1] = 0.f;
  200. mMatrix[0][2] = 0.f;
  201. mMatrix[0][3] = 0.f;
  202. mMatrix[1][0] = 0.f;
  203. mMatrix[1][1] = 1.f;
  204. mMatrix[1][2] = 0.f;
  205. mMatrix[1][3] = 0.f;
  206. mMatrix[2][0] = 0.f;
  207. mMatrix[2][1] = 0.f;
  208. mMatrix[2][2] = 1.f;
  209. mMatrix[2][3] = 0.f;
  210. mMatrix[3][0] = 0.f;
  211. mMatrix[3][1] = 0.f;
  212. mMatrix[3][2] = 0.f;
  213. mMatrix[3][3] = 1.f;
  214. return (*this);
  215. }
  216. inline bool LLMatrix4::isIdentity() const
  217. {
  218. return
  219. mMatrix[0][0] == 1.f &&
  220. mMatrix[0][1] == 0.f &&
  221. mMatrix[0][2] == 0.f &&
  222. mMatrix[0][3] == 0.f &&
  223. mMatrix[1][0] == 0.f &&
  224. mMatrix[1][1] == 1.f &&
  225. mMatrix[1][2] == 0.f &&
  226. mMatrix[1][3] == 0.f &&
  227. mMatrix[2][0] == 0.f &&
  228. mMatrix[2][1] == 0.f &&
  229. mMatrix[2][2] == 1.f &&
  230. mMatrix[2][3] == 0.f &&
  231. mMatrix[3][0] == 0.f &&
  232. mMatrix[3][1] == 0.f &&
  233. mMatrix[3][2] == 0.f &&
  234. mMatrix[3][3] == 1.f;
  235. }
  236. /*
  237. inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b)
  238. {
  239. U32 i, j;
  240. LLMatrix4 mat;
  241. for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
  242. {
  243. for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
  244. {
  245. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
  246. a.mMatrix[j][1] * b.mMatrix[1][i] +
  247. a.mMatrix[j][2] * b.mMatrix[2][i] +
  248. a.mMatrix[j][3] * b.mMatrix[3][i];
  249. }
  250. }
  251. return mat;
  252. }
  253. */
  254. inline const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b)
  255. {
  256. U32 i, j;
  257. LLMatrix4 mat;
  258. for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
  259. {
  260. for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
  261. {
  262. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] +
  263. a.mMatrix[j][1] * b.mMatrix[1][i] +
  264. a.mMatrix[j][2] * b.mMatrix[2][i] +
  265. a.mMatrix[j][3] * b.mMatrix[3][i];
  266. }
  267. }
  268. a = mat;
  269. return a;
  270. }
  271. inline const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b)
  272. {
  273. U32 i, j;
  274. LLMatrix4 mat;
  275. for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
  276. {
  277. for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
  278. {
  279. mat.mMatrix[j][i] = a.mMatrix[j][i] * b;
  280. }
  281. }
  282. a = mat;
  283. return a;
  284. }
  285. inline const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b)
  286. {
  287. LLMatrix4 mat;
  288. U32 i, j;
  289. for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
  290. {
  291. for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
  292. {
  293. mat.mMatrix[j][i] = a.mMatrix[j][i] + b.mMatrix[j][i];
  294. }
  295. }
  296. a = mat;
  297. return a;
  298. }
  299. inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b)
  300. {
  301. LLMatrix4 mat;
  302. U32 i, j;
  303. for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
  304. {
  305. for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
  306. {
  307. mat.mMatrix[j][i] = a.mMatrix[j][i] - b.mMatrix[j][i];
  308. }
  309. }
  310. a = mat;
  311. return a;
  312. }
  313. // Operates "to the left" on row-vector a
  314. //
  315. // When avatar vertex programs are off, this function is a hot spot in profiles
  316. // due to software skinning in LLViewerJointMesh::updateGeometry(). JC
  317. inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
  318. {
  319. // This is better than making a temporary LLVector3. This eliminates an
  320. // unnecessary LLVector3() constructor and also helps the compiler to
  321. // realize that the output floats do not alias the input floats, hence
  322. // eliminating redundant loads of a.mV[0], etc. JC
  323. return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
  324. a.mV[VY] * b.mMatrix[VY][VX] +
  325. a.mV[VZ] * b.mMatrix[VZ][VX] +
  326. b.mMatrix[VW][VX],
  327. a.mV[VX] * b.mMatrix[VX][VY] +
  328. a.mV[VY] * b.mMatrix[VY][VY] +
  329. a.mV[VZ] * b.mMatrix[VZ][VY] +
  330. b.mMatrix[VW][VY],
  331. a.mV[VX] * b.mMatrix[VX][VZ] +
  332. a.mV[VY] * b.mMatrix[VY][VZ] +
  333. a.mV[VZ] * b.mMatrix[VZ][VZ] +
  334. b.mMatrix[VW][VZ]);
  335. }
  336. #endif