m3math.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file m3math.cpp
  3.  * @brief LLMatrix3 class implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, 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. #include "linden_common.h"
  33. //#include "vmath.h"
  34. #include "v3math.h"
  35. #include "v3dmath.h"
  36. #include "v4math.h"
  37. #include "m4math.h"
  38. #include "m3math.h"
  39. #include "llquaternion.h"
  40. // LLMatrix3
  41. //              ji  
  42. // LLMatrix3 = |00 01 02 |
  43. //             |10 11 12 |
  44. //             |20 21 22 |
  45. // LLMatrix3 = |fx fy fz |  forward-axis
  46. //             |lx ly lz |  left-axis
  47. //             |ux uy uz |  up-axis
  48. // Constructors
  49. LLMatrix3::LLMatrix3(const LLQuaternion &q)
  50. {
  51. setRot(q);
  52. }
  53. LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec)
  54. {
  55. LLQuaternion quat(angle, vec);
  56. setRot(quat);
  57. }
  58. LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec)
  59. {
  60. LLVector3 vec_f;
  61. vec_f.setVec(vec);
  62. LLQuaternion quat(angle, vec_f);
  63. setRot(quat);
  64. }
  65. LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
  66. {
  67. LLQuaternion quat(angle, vec);
  68. setRot(quat);
  69. }
  70. LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
  71. {
  72. LLVector3 vec(x, y, z);
  73. LLQuaternion quat(angle, vec);
  74. setRot(quat);
  75. }
  76. LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
  77. {
  78. setRot(roll,pitch,yaw);
  79. }
  80. // From Matrix and Quaternion FAQ
  81. void LLMatrix3::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
  82. {
  83. F64 angle_x, angle_y, angle_z;
  84. F64 cx, cy, cz; // cosine of angle_x, angle_y, angle_z
  85. F64 sx,     sz; // sine of angle_x, angle_y, angle_z
  86. angle_y = asin(llclamp(mMatrix[2][0], -1.f, 1.f));
  87. cy = cos(angle_y);
  88. if (fabs(cy) > 0.005) // non-zero
  89. {
  90. // no gimbal lock
  91. cx = mMatrix[2][2] / cy;
  92. sx = - mMatrix[2][1] / cy;
  93. angle_x = (F32) atan2(sx, cx);
  94. cz = mMatrix[0][0] / cy;
  95. sz = - mMatrix[1][0] / cy;
  96. angle_z = (F32) atan2(sz, cz);
  97. }
  98. else
  99. {
  100. // yup, gimbal lock
  101. angle_x = 0;
  102. // some tricky math thereby avoided, see article
  103. cz = mMatrix[1][1];
  104. sz = mMatrix[0][1];
  105. angle_z = atan2(sz, cz);
  106. }
  107. *roll = (F32)angle_x;
  108. *pitch = (F32)angle_y;
  109. *yaw = (F32)angle_z;
  110. }
  111. // Clear and Assignment Functions
  112. const LLMatrix3& LLMatrix3::setIdentity()
  113. {
  114. mMatrix[0][0] = 1.f;
  115. mMatrix[0][1] = 0.f;
  116. mMatrix[0][2] = 0.f;
  117. mMatrix[1][0] = 0.f;
  118. mMatrix[1][1] = 1.f;
  119. mMatrix[1][2] = 0.f;
  120. mMatrix[2][0] = 0.f;
  121. mMatrix[2][1] = 0.f;
  122. mMatrix[2][2] = 1.f;
  123. return (*this);
  124. }
  125. const LLMatrix3& LLMatrix3::clear()
  126. {
  127. mMatrix[0][0] = 0.f;
  128. mMatrix[0][1] = 0.f;
  129. mMatrix[0][2] = 0.f;
  130. mMatrix[1][0] = 0.f;
  131. mMatrix[1][1] = 0.f;
  132. mMatrix[1][2] = 0.f;
  133. mMatrix[2][0] = 0.f;
  134. mMatrix[2][1] = 0.f;
  135. mMatrix[2][2] = 0.f;
  136. return (*this);
  137. }
  138. const LLMatrix3& LLMatrix3::setZero()
  139. {
  140. mMatrix[0][0] = 0.f;
  141. mMatrix[0][1] = 0.f;
  142. mMatrix[0][2] = 0.f;
  143. mMatrix[1][0] = 0.f;
  144. mMatrix[1][1] = 0.f;
  145. mMatrix[1][2] = 0.f;
  146. mMatrix[2][0] = 0.f;
  147. mMatrix[2][1] = 0.f;
  148. mMatrix[2][2] = 0.f;
  149. return (*this);
  150. }
  151. // various useful mMatrix functions
  152. const LLMatrix3& LLMatrix3::transpose() 
  153. {
  154. // transpose the matrix
  155. F32 temp;
  156. temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
  157. temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
  158. temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
  159. return *this;
  160. }
  161. F32 LLMatrix3::determinant() const
  162. {
  163. // Is this a useful method when we assume the matrices are valid rotation
  164. // matrices throughout this implementation?
  165. return mMatrix[0][0] * (mMatrix[1][1] * mMatrix[2][2] - mMatrix[1][2] * mMatrix[2][1]) +
  166.    mMatrix[0][1] * (mMatrix[1][2] * mMatrix[2][0] - mMatrix[1][0] * mMatrix[2][2]) +
  167.    mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); 
  168. }
  169. // inverts this matrix
  170. void LLMatrix3::invert()
  171. {
  172. // fails silently if determinant is zero too small
  173. F32 det = determinant();
  174. const F32 VERY_SMALL_DETERMINANT = 0.000001f;
  175. if (fabs(det) > VERY_SMALL_DETERMINANT)
  176. {
  177. // invertiable
  178. LLMatrix3 t(*this);
  179. mMatrix[VX][VX] = ( t.mMatrix[VY][VY] * t.mMatrix[VZ][VZ] - t.mMatrix[VY][VZ] * t.mMatrix[VZ][VY] ) / det;
  180. mMatrix[VY][VX] = ( t.mMatrix[VY][VZ] * t.mMatrix[VZ][VX] - t.mMatrix[VY][VX] * t.mMatrix[VZ][VZ] ) / det;
  181. mMatrix[VZ][VX] = ( t.mMatrix[VY][VX] * t.mMatrix[VZ][VY] - t.mMatrix[VY][VY] * t.mMatrix[VZ][VX] ) / det;
  182. mMatrix[VX][VY] = ( t.mMatrix[VZ][VY] * t.mMatrix[VX][VZ] - t.mMatrix[VZ][VZ] * t.mMatrix[VX][VY] ) / det;
  183. mMatrix[VY][VY] = ( t.mMatrix[VZ][VZ] * t.mMatrix[VX][VX] - t.mMatrix[VZ][VX] * t.mMatrix[VX][VZ] ) / det;
  184. mMatrix[VZ][VY] = ( t.mMatrix[VZ][VX] * t.mMatrix[VX][VY] - t.mMatrix[VZ][VY] * t.mMatrix[VX][VX] ) / det;
  185. mMatrix[VX][VZ] = ( t.mMatrix[VX][VY] * t.mMatrix[VY][VZ] - t.mMatrix[VX][VZ] * t.mMatrix[VY][VY] ) / det;
  186. mMatrix[VY][VZ] = ( t.mMatrix[VX][VZ] * t.mMatrix[VY][VX] - t.mMatrix[VX][VX] * t.mMatrix[VY][VZ] ) / det;
  187. mMatrix[VZ][VZ] = ( t.mMatrix[VX][VX] * t.mMatrix[VY][VY] - t.mMatrix[VX][VY] * t.mMatrix[VY][VX] ) / det;
  188. }
  189. }
  190. // does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized
  191. const LLMatrix3& LLMatrix3::adjointTranspose()
  192. {
  193. LLMatrix3 adjoint_transpose;
  194. adjoint_transpose.mMatrix[VX][VX] = mMatrix[VY][VY] * mMatrix[VZ][VZ] - mMatrix[VY][VZ] * mMatrix[VZ][VY] ;
  195. adjoint_transpose.mMatrix[VY][VX] = mMatrix[VY][VZ] * mMatrix[VZ][VX] - mMatrix[VY][VX] * mMatrix[VZ][VZ] ;
  196. adjoint_transpose.mMatrix[VZ][VX] = mMatrix[VY][VX] * mMatrix[VZ][VY] - mMatrix[VY][VY] * mMatrix[VZ][VX] ;
  197. adjoint_transpose.mMatrix[VX][VY] = mMatrix[VZ][VY] * mMatrix[VX][VZ] - mMatrix[VZ][VZ] * mMatrix[VX][VY] ;
  198. adjoint_transpose.mMatrix[VY][VY] = mMatrix[VZ][VZ] * mMatrix[VX][VX] - mMatrix[VZ][VX] * mMatrix[VX][VZ] ;
  199. adjoint_transpose.mMatrix[VZ][VY] = mMatrix[VZ][VX] * mMatrix[VX][VY] - mMatrix[VZ][VY] * mMatrix[VX][VX] ;
  200. adjoint_transpose.mMatrix[VX][VZ] = mMatrix[VX][VY] * mMatrix[VY][VZ] - mMatrix[VX][VZ] * mMatrix[VY][VY] ;
  201. adjoint_transpose.mMatrix[VY][VZ] = mMatrix[VX][VZ] * mMatrix[VY][VX] - mMatrix[VX][VX] * mMatrix[VY][VZ] ;
  202. adjoint_transpose.mMatrix[VZ][VZ] = mMatrix[VX][VX] * mMatrix[VY][VY] - mMatrix[VX][VY] * mMatrix[VY][VX] ;
  203. *this = adjoint_transpose;
  204. return *this;
  205. }
  206. // SJB: This code is correct for a logicly stored (non-transposed) matrix;
  207. // Our matrices are stored transposed, OpenGL style, so this generates the
  208. // INVERSE quaternion (-x, -y, -z, w)!
  209. // Because we use similar logic in LLQuaternion::getMatrix3,
  210. // we are internally consistant so everything works OK :)
  211. LLQuaternion LLMatrix3::quaternion() const
  212. {
  213. LLQuaternion quat;
  214. F32 tr, s, q[4];
  215. U32 i, j, k;
  216. U32 nxt[3] = {1, 2, 0};
  217. tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2];
  218. // check the diagonal
  219. if (tr > 0.f) 
  220. {
  221. s = (F32)sqrt (tr + 1.f);
  222. quat.mQ[VS] = s / 2.f;
  223. s = 0.5f / s;
  224. quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s;
  225. quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s;
  226. quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s;
  227. else
  228. {
  229. // diagonal is negative
  230. i = 0;
  231. if (mMatrix[1][1] > mMatrix[0][0]) 
  232. i = 1;
  233. if (mMatrix[2][2] > mMatrix[i][i]) 
  234. i = 2;
  235. j = nxt[i];
  236. k = nxt[j];
  237. s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f);
  238. q[i] = s * 0.5f;
  239. if (s != 0.f) 
  240. s = 0.5f / s;
  241. q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s;
  242. q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s;
  243. q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s;
  244. quat.setQuat(q);
  245. }
  246. return quat;
  247. }
  248. // These functions take Rotation arguments
  249. const LLMatrix3& LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
  250. {
  251. setRot(LLQuaternion(angle,x,y,z));
  252. return *this;
  253. }
  254. const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
  255. {
  256. setRot(LLQuaternion(angle, vec));
  257. return *this;
  258. }
  259. const LLMatrix3& LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw)
  260. {
  261. // Rotates RH about x-axis by 'roll'  then
  262. // rotates RH about the old y-axis by 'pitch' then
  263. // rotates RH about the original z-axis by 'yaw'.
  264. //                .
  265. //               /| yaw axis
  266. //                |     __.
  267. //   ._        ___|      /| pitch axis
  268. //  _||       \ |-.   /
  269. //  || ________|___/_______
  270. //   | _ _   o o o_o_o_o o   /__  ________ roll axis
  271. //   //  /_______/    /__________>         /   
  272. //  /_,-'       //   /
  273. //             /__,-'
  274. F32 cx, sx, cy, sy, cz, sz;
  275. F32 cxsy, sxsy;
  276.     cx = (F32)cos(roll); //A
  277.     sx = (F32)sin(roll); //B
  278.     cy = (F32)cos(pitch); //C
  279.     sy = (F32)sin(pitch); //D
  280.     cz = (F32)cos(yaw); //E
  281.     sz = (F32)sin(yaw); //F
  282.     cxsy = cx * sy; //AD
  283.     sxsy = sx * sy; //BD 
  284.     mMatrix[0][0] =  cy * cz;
  285.     mMatrix[1][0] = -cy * sz;
  286.     mMatrix[2][0] = sy;
  287.     mMatrix[0][1] = sxsy * cz + cx * sz;
  288.     mMatrix[1][1] = -sxsy * sz + cx * cz;
  289.     mMatrix[2][1] = -sx * cy;
  290.     mMatrix[0][2] =  -cxsy * cz + sx * sz;
  291.     mMatrix[1][2] =  cxsy * sz + sx * cz;
  292.     mMatrix[2][2] =  cx * cy;
  293. return *this;
  294. }
  295. const LLMatrix3& LLMatrix3::setRot(const LLQuaternion &q)
  296. {
  297. *this = q.getMatrix3();
  298. return *this;
  299. }
  300. const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up)
  301. {
  302. mMatrix[0][0] = fwd.mV[0];
  303. mMatrix[0][1] = fwd.mV[1];
  304. mMatrix[0][2] = fwd.mV[2];
  305. mMatrix[1][0] = left.mV[0];
  306. mMatrix[1][1] = left.mV[1];
  307. mMatrix[1][2] = left.mV[2];
  308. mMatrix[2][0] = up.mV[0];
  309. mMatrix[2][1] = up.mV[1];
  310. mMatrix[2][2] = up.mV[2];
  311. return *this;
  312. }
  313. const LLMatrix3& LLMatrix3::setRow( U32 rowIndex, const LLVector3& row )
  314. {
  315. llassert( rowIndex >= 0 && rowIndex < NUM_VALUES_IN_MAT3 );
  316. mMatrix[rowIndex][0] = row[0];
  317. mMatrix[rowIndex][1] = row[1];
  318. mMatrix[rowIndex][2] = row[2];
  319. return *this;
  320. }
  321. const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col )
  322. {
  323. llassert( colIndex >= 0 && colIndex < NUM_VALUES_IN_MAT3 );
  324. mMatrix[0][colIndex] = col[0];
  325. mMatrix[1][colIndex] = col[1];
  326. mMatrix[2][colIndex] = col[2];
  327. return *this;
  328. }
  329. // Rotate exisitng mMatrix
  330. const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
  331. {
  332. LLMatrix3 mat(angle, x, y, z);
  333. *this *= mat;
  334. return *this;
  335. }
  336. const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec)
  337. {
  338. LLMatrix3 mat(angle, vec);
  339. *this *= mat;
  340. return *this;
  341. }
  342. const LLMatrix3& LLMatrix3::rotate(const F32 roll, const F32 pitch, const F32 yaw)
  343. {
  344. LLMatrix3 mat(roll, pitch, yaw); 
  345. *this *= mat;
  346. return *this;
  347. }
  348. const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q)
  349. {
  350. LLMatrix3 mat(q);
  351. *this *= mat;
  352. return *this;
  353. }
  354. void LLMatrix3::add(const LLMatrix3& other_matrix)
  355. {
  356. for (S32 i = 0; i < 3; ++i)
  357. {
  358. for (S32 j = 0; j < 3; ++j)
  359. {
  360. mMatrix[i][j] += other_matrix.mMatrix[i][j];
  361. }
  362. }
  363. }
  364. LLVector3 LLMatrix3::getFwdRow() const
  365. {
  366. return LLVector3(mMatrix[VX]);
  367. }
  368. LLVector3 LLMatrix3::getLeftRow() const
  369. {
  370. return LLVector3(mMatrix[VY]);
  371. }
  372. LLVector3 LLMatrix3::getUpRow() const
  373. {
  374. return LLVector3(mMatrix[VZ]);
  375. }
  376. const LLMatrix3& LLMatrix3::orthogonalize()
  377. {
  378. LLVector3 x_axis(mMatrix[VX]);
  379. LLVector3 y_axis(mMatrix[VY]);
  380. LLVector3 z_axis(mMatrix[VZ]);
  381. x_axis.normVec();
  382. y_axis -= x_axis * (x_axis * y_axis);
  383. y_axis.normVec();
  384. z_axis = x_axis % y_axis;
  385. setRows(x_axis, y_axis, z_axis);
  386. return (*this);
  387. }
  388. // LLMatrix3 Operators
  389. LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b)
  390. {
  391. U32 i, j;
  392. LLMatrix3 mat;
  393. for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
  394. {
  395. for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
  396. {
  397. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
  398.     a.mMatrix[j][1] * b.mMatrix[1][i] + 
  399.     a.mMatrix[j][2] * b.mMatrix[2][i];
  400. }
  401. }
  402. return mat;
  403. }
  404. /* Not implemented to help enforce code consistency with the syntax of 
  405.    row-major notation.  This is a Good Thing.
  406. LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b)
  407. {
  408. LLVector3 vec;
  409. // matrix operates "from the left" on column vector
  410. vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] + 
  411.  a.mMatrix[VX][VY] * b.mV[VY] + 
  412.  a.mMatrix[VX][VZ] * b.mV[VZ];
  413. vec.mV[VY] = a.mMatrix[VY][VX] * b.mV[VX] + 
  414.  a.mMatrix[VY][VY] * b.mV[VY] + 
  415.  a.mMatrix[VY][VZ] * b.mV[VZ];
  416. vec.mV[VZ] = a.mMatrix[VZ][VX] * b.mV[VX] + 
  417.  a.mMatrix[VZ][VY] * b.mV[VY] + 
  418.  a.mMatrix[VZ][VZ] * b.mV[VZ];
  419. return vec;
  420. }
  421. */
  422. LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b)
  423. {
  424. // matrix operates "from the right" on row vector
  425. return LLVector3(
  426. a.mV[VX] * b.mMatrix[VX][VX] + 
  427. a.mV[VY] * b.mMatrix[VY][VX] + 
  428. a.mV[VZ] * b.mMatrix[VZ][VX],
  429. a.mV[VX] * b.mMatrix[VX][VY] + 
  430. a.mV[VY] * b.mMatrix[VY][VY] + 
  431. a.mV[VZ] * b.mMatrix[VZ][VY],
  432. a.mV[VX] * b.mMatrix[VX][VZ] + 
  433. a.mV[VY] * b.mMatrix[VY][VZ] + 
  434. a.mV[VZ] * b.mMatrix[VZ][VZ] );
  435. }
  436. LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b)
  437. {
  438. // matrix operates "from the right" on row vector
  439. return LLVector3d(
  440. a.mdV[VX] * b.mMatrix[VX][VX] + 
  441. a.mdV[VY] * b.mMatrix[VY][VX] + 
  442. a.mdV[VZ] * b.mMatrix[VZ][VX],
  443. a.mdV[VX] * b.mMatrix[VX][VY] + 
  444. a.mdV[VY] * b.mMatrix[VY][VY] + 
  445. a.mdV[VZ] * b.mMatrix[VZ][VY],
  446. a.mdV[VX] * b.mMatrix[VX][VZ] + 
  447. a.mdV[VY] * b.mMatrix[VY][VZ] + 
  448. a.mdV[VZ] * b.mMatrix[VZ][VZ] );
  449. }
  450. bool operator==(const LLMatrix3 &a, const LLMatrix3 &b)
  451. {
  452. U32 i, j;
  453. for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
  454. {
  455. for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
  456. {
  457. if (a.mMatrix[j][i] != b.mMatrix[j][i])
  458. return FALSE;
  459. }
  460. }
  461. return TRUE;
  462. }
  463. bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b)
  464. {
  465. U32 i, j;
  466. for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
  467. {
  468. for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
  469. {
  470. if (a.mMatrix[j][i] != b.mMatrix[j][i])
  471. return TRUE;
  472. }
  473. }
  474. return FALSE;
  475. }
  476. const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b)
  477. {
  478. U32 i, j;
  479. LLMatrix3 mat;
  480. for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
  481. {
  482. for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
  483. {
  484. mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
  485.     a.mMatrix[j][1] * b.mMatrix[1][i] + 
  486.     a.mMatrix[j][2] * b.mMatrix[2][i];
  487. }
  488. }
  489. a = mat;
  490. return a;
  491. }
  492. const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar )
  493. {
  494. for( U32 i = 0; i < NUM_VALUES_IN_MAT3; ++i )
  495. {
  496. for( U32 j = 0; j < NUM_VALUES_IN_MAT3; ++j )
  497. {
  498. a.mMatrix[i][j] *= scalar;
  499. }
  500. }
  501. return a;
  502. }
  503. std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) 
  504. {
  505. s << "{ " 
  506. << a.mMatrix[VX][VX] << ", " << a.mMatrix[VX][VY] << ", " << a.mMatrix[VX][VZ] << "; "
  507. << a.mMatrix[VY][VX] << ", " << a.mMatrix[VY][VY] << ", " << a.mMatrix[VY][VZ] << "; "
  508. << a.mMatrix[VZ][VX] << ", " << a.mMatrix[VZ][VY] << ", " << a.mMatrix[VZ][VZ] 
  509.   << " }";
  510. return s;
  511. }