matrix3d.cpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /Commando/Code/wwmath/matrix3d.cpp 41 5/09/01 2:38p Greg_h $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Voxel Technology *
  24. * *
  25. * File Name : MATRIX3D.CPP *
  26. * *
  27. * Programmer : Greg Hjelstrom *
  28. * *
  29. * Start Date : 02/24/97 *
  30. * *
  31. * Last Update : February 28, 1997 [GH] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  36. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  37. * Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
  38. * Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
  39. * Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
  40. * Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
  41. * Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
  42. * Matrix3D::Multiply -- matrix multiplication without temporaries. *
  43. * Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
  44. * Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
  45. * Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
  46. * Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
  47. * Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
  48. * Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
  49. * Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
  50. * Lerp - linearly interpolate matrices (orientation is slerped) *
  51. * Matrix3D::Solve_Linear_System -- 3x3 Gauss-Jordan elimination *
  52. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  53. #include "matrix3d.h"
  54. #include <math.h>
  55. #include <assert.h>
  56. #include <stdlib.h>
  57. //#include <stdio.h>
  58. #include "vector3.h"
  59. #include "matrix3.h"
  60. #include "matrix4.h"
  61. #include "quat.h"
  62. #include "D3dx8math.h"
  63. // some static matrices which are sometimes useful
  64. const Matrix3D Matrix3D::Identity
  65. (
  66. 1.0, 0.0, 0.0, 0.0,
  67. 0.0, 1.0, 0.0, 0.0,
  68. 0.0, 0.0, 1.0, 0.0
  69. );
  70. const Matrix3D Matrix3D::RotateX90
  71. (
  72. 1.0, 0.0, 0.0, 0.0,
  73. 0.0, 0.0, -1.0, 0.0,
  74. 0.0, 1.0, 0.0, 0.0
  75. );
  76. const Matrix3D Matrix3D::RotateX180
  77. (
  78. 1.0, 0.0, 0.0, 0.0,
  79. 0.0, -1.0, 0.0, 0.0,
  80. 0.0, 0.0, -1.0, 0.0
  81. );
  82. const Matrix3D Matrix3D::RotateX270
  83. (
  84. 1.0, 0.0, 0.0, 0.0,
  85. 0.0, 0.0, 1.0, 0.0,
  86. 0.0, -1.0, 0.0, 0.0
  87. );
  88. const Matrix3D Matrix3D::RotateY90
  89. (
  90. 0.0, 0.0, 1.0, 0.0,
  91. 0.0, 1.0, 0.0, 0.0,
  92. -1.0, 0.0, 0.0, 0.0
  93. );
  94. const Matrix3D Matrix3D::RotateY180
  95. (
  96. -1.0, 0.0, 0.0, 0.0,
  97. 0.0, 1.0, 0.0, 0.0,
  98. 0.0, 0.0, -1.0, 0.0
  99. );
  100. const Matrix3D Matrix3D::RotateY270
  101. (
  102. 0.0, 0.0, -1.0, 0.0,
  103. 0.0, 1.0, 0.0, 0.0,
  104. 1.0, 0.0, 0.0, 0.0
  105. );
  106. const Matrix3D Matrix3D::RotateZ90
  107. (
  108. 0.0, -1.0, 0.0, 0.0,
  109. 1.0, 0.0, 0.0, 0.0,
  110. 0.0, 0.0, 1.0, 0.0
  111. );
  112. const Matrix3D Matrix3D::RotateZ180
  113. (
  114. -1.0, 0.0, 0.0, 0.0,
  115. 0.0, -1.0, 0.0, 0.0,
  116. 0.0, 0.0, 1.0, 0.0
  117. );
  118. const Matrix3D Matrix3D::RotateZ270
  119. (
  120. 0.0, 1.0, 0.0, 0.0,
  121. -1.0, 0.0, 0.0, 0.0,
  122. 0.0, 0.0, 1.0, 0.0
  123. );
  124. /***********************************************************************************************
  125. * Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
  126. * *
  127. * INPUT: *
  128. * *
  129. * OUTPUT: *
  130. * *
  131. * WARNINGS: *
  132. * *
  133. * HISTORY: *
  134. *=============================================================================================*/
  135. void Matrix3D::Set(const Matrix3 & rot,const Vector3 & pos)
  136. {
  137. Row[0].Set( rot[0][0], rot[0][1], rot[0][2], pos[0]);
  138. Row[1].Set( rot[1][0], rot[1][1], rot[1][2], pos[1]);
  139. Row[2].Set( rot[2][0], rot[2][1], rot[2][2], pos[2]);
  140. }
  141. /***********************************************************************************************
  142. * Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
  143. * *
  144. * INPUT: *
  145. * *
  146. * OUTPUT: *
  147. * *
  148. * WARNINGS: *
  149. * *
  150. * HISTORY: *
  151. *=============================================================================================*/
  152. void Matrix3D::Set(const Quaternion & rot,const Vector3 & pos)
  153. {
  154. Set_Rotation(rot);
  155. Set_Translation(pos);
  156. }
  157. /***********************************************************************************************
  158. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  159. * *
  160. * INPUT: *
  161. * *
  162. * OUTPUT: *
  163. * *
  164. * WARNINGS: *
  165. * *
  166. * HISTORY: *
  167. * 5/11/98 GTH : Created. *
  168. *=============================================================================================*/
  169. void Matrix3D::Set_Rotation(const Matrix3 & m)
  170. {
  171. Row[0][0] = m[0][0];
  172. Row[0][1] = m[0][1];
  173. Row[0][2] = m[0][2];
  174. Row[1][0] = m[1][0];
  175. Row[1][1] = m[1][1];
  176. Row[1][2] = m[1][2];
  177. Row[2][0] = m[2][0];
  178. Row[2][1] = m[2][1];
  179. Row[2][2] = m[2][2];
  180. }
  181. /***********************************************************************************************
  182. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  183. * *
  184. * INPUT: *
  185. * *
  186. * OUTPUT: *
  187. * *
  188. * WARNINGS: *
  189. * *
  190. * HISTORY: *
  191. * 5/11/98 GTH : Created. *
  192. *=============================================================================================*/
  193. void Matrix3D::Set_Rotation(const Quaternion & q)
  194. {
  195. Row[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
  196. Row[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
  197. Row[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
  198. Row[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
  199. Row[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
  200. Row[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
  201. Row[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
  202. Row[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
  203. Row[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
  204. }
  205. /***********************************************************************************************
  206. * Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
  207. * *
  208. * INPUT: *
  209. * *
  210. * OUTPUT: *
  211. * *
  212. * WARNINGS: *
  213. * *
  214. * HISTORY: *
  215. * 08/11/1997 GH : Created. *
  216. *=============================================================================================*/
  217. float Matrix3D::Get_X_Rotation(void) const
  218. {
  219. return WWMath::Atan2(Row[2][1], Row[1][1]);
  220. }
  221. /***********************************************************************************************
  222. * Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
  223. * *
  224. * INPUT: *
  225. * *
  226. * OUTPUT: *
  227. * *
  228. * WARNINGS: *
  229. * *
  230. * HISTORY: *
  231. * 08/11/1997 GH : Created. *
  232. *=============================================================================================*/
  233. float Matrix3D::Get_Y_Rotation(void) const
  234. {
  235. return WWMath::Atan2(Row[0][2], Row[2][2]);
  236. }
  237. /***********************************************************************************************
  238. * Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
  239. * *
  240. * INPUT: *
  241. * *
  242. * OUTPUT: *
  243. * *
  244. * WARNINGS: *
  245. * *
  246. * HISTORY: *
  247. * 08/11/1997 GH : Created. *
  248. *=============================================================================================*/
  249. float Matrix3D::Get_Z_Rotation(void) const
  250. {
  251. return WWMath::Atan2(Row[1][0], Row[0][0]);
  252. }
  253. /***********************************************************************************************
  254. * M3DC::Rotate_Vector -- Uses the 3x3 sub-matrix to rotate a vector *
  255. * *
  256. * INPUT: *
  257. * *
  258. * OUTPUT: *
  259. * *
  260. * WARNINGS: *
  261. * *
  262. * HISTORY: *
  263. *=============================================================================================*/
  264. Vector3 Matrix3D::Rotate_Vector(const Vector3 &vect) const
  265. {
  266. return Vector3(
  267. (Row[0][0]*vect[0] + Row[0][1]*vect[1] + Row[0][2]*vect[2]),
  268. (Row[1][0]*vect[0] + Row[1][1]*vect[1] + Row[1][2]*vect[2]),
  269. (Row[2][0]*vect[0] + Row[2][1]*vect[1] + Row[2][2]*vect[2])
  270. );
  271. }
  272. /***********************************************************************************************
  273. * Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
  274. * *
  275. * INPUT: *
  276. * *
  277. * OUTPUT: *
  278. * *
  279. * WARNINGS: *
  280. * *
  281. * HISTORY: *
  282. * 4/27/98 GTH : Created. *
  283. *=============================================================================================*/
  284. Vector3 Matrix3D::Inverse_Rotate_Vector(const Vector3 &vect) const
  285. {
  286. return Vector3(
  287. (Row[0][0]*vect[0] + Row[1][0]*vect[1] + Row[2][0]*vect[2]),
  288. (Row[0][1]*vect[0] + Row[1][1]*vect[1] + Row[2][1]*vect[2]),
  289. (Row[0][2]*vect[0] + Row[1][2]*vect[1] + Row[2][2]*vect[2])
  290. );
  291. }
  292. /***********************************************************************************************
  293. * M3DC::Look_At -- Creates a "look at" transformation. *
  294. * *
  295. * Builds a transformation matrix which positions the origin at p, *
  296. * points the negative z-axis towards a target t, and rolls about the z-axis *
  297. * by the angle specified by roll. *
  298. * *
  299. * This can be useful for creating a camera matrix, just invert *
  300. * the matrix after initializing it with this function... *
  301. * *
  302. * INPUT: *
  303. * p - position of the coordinate system *
  304. * t - target of the coordinate system *
  305. * roll - roll angle (in radians) *
  306. * *
  307. * OUTPUT: *
  308. * *
  309. * WARNINGS: *
  310. * This function is written assuming the convention that the "ground" is the X-Y plane and *
  311. * Z is altitude. *
  312. * *
  313. * HISTORY: *
  314. *=============================================================================================*/
  315. void Matrix3D::Look_At(const Vector3 &p,const Vector3 &t,float roll)
  316. {
  317. float dx,dy,dz; //vector from p to t
  318. float len1,len2;
  319. float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about x)
  320. float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
  321. dx = (t[0] - p[0]);
  322. dy = (t[1] - p[1]);
  323. dz = (t[2] - p[2]);
  324. len1 = (float)WWMath::Sqrt(dx*dx + dy*dy + dz*dz);
  325. len2 = (float)WWMath::Sqrt(dx*dx + dy*dy);
  326. if (len1 != 0.0f) {
  327. sinp = dz/len1;
  328. cosp = len2/len1;
  329. } else {
  330. sinp = 0.0f;
  331. cosp = 1.0f;
  332. }
  333. if (len2 != 0.0f) {
  334. siny = dy/len2;
  335. cosy = dx/len2;
  336. } else {
  337. siny = 0.0f;
  338. cosy = 1.0f;
  339. }
  340. // init the matrix with position p and -z pointing down +x and +y up
  341. Row[0].X = 0.0f; Row[0].Y = 0.0f; Row[0].Z = -1.0f;
  342. Row[1].X = -1.0f; Row[1].Y = 0.0f; Row[1].Z = 0.0f;
  343. Row[2].X = 0.0f; Row[2].Y = 1.0f; Row[2].Z = 0.0f;
  344. Row[0].W = p.X;
  345. Row[1].W = p.Y;
  346. Row[2].W = p.Z;
  347. // Yaw rotation to make the matrix look at the projection of the target
  348. // into the x-y plane
  349. Rotate_Y(siny,cosy);
  350. // rotate about local x axis to pitch up to the targets position
  351. Rotate_X(sinp,cosp);
  352. // roll about the local z axis (negate since we look down -z)
  353. Rotate_Z(-roll);
  354. }
  355. // Create a matrix given a position and a direction (x axis will point in direction)
  356. // Make sure you pass in UNITIZED direction!!!
  357. void Matrix3D::buildTransformMatrix( const Vector3 &pos, const Vector3 &dir )
  358. {
  359. float sinp, cosp; // sine and cosine of the pitch ("up-down" tilt about y)
  360. float siny, cosy; // sine and cosine of the yaw ("left-right"tilt about z)
  361. float len2 = (float)sqrt( (dir.X * dir.X) + (dir.Y * dir.Y) );
  362. sinp = dir.Z;
  363. cosp = len2;
  364. if( len2 != 0.0f )
  365. {
  366. siny = dir.Y / len2;
  367. cosy = dir.X / len2;
  368. }
  369. else
  370. {
  371. siny = 0.0f;
  372. cosy = 1.0f;
  373. }
  374. Make_Identity();
  375. Translate( pos );
  376. // Yaw rotation to projection of target in x-y plane
  377. Rotate_Z( siny, cosy );
  378. // Pitch rotation
  379. Rotate_Y( -sinp, cosp );
  380. }
  381. /***********************************************************************************************
  382. * M3DC::Obj_Look_At -- Commando Object "look at" transformation. *
  383. * *
  384. * Builds a transformation matrix which positions the origin at p, *
  385. * points the positive X axis towards a target t, and rolls about the X axis *
  386. * by the angle specified by roll. *
  387. * *
  388. * The object convention used by Commando and G is Forward = +X, Left = +Y, Up = +Z. The *
  389. * world is basically the x-y plane with z as altitude and +x is the default "forward". *
  390. * *
  391. * INPUT: *
  392. * p - position of the coordinate system *
  393. * t - target of the coordinate system *
  394. * roll - roll angle (in radians) *
  395. * *
  396. * OUTPUT: *
  397. * *
  398. * WARNINGS: *
  399. * *
  400. * HISTORY: *
  401. *=============================================================================================*/
  402. void Matrix3D::Obj_Look_At(const Vector3 &p,const Vector3 &t,float roll)
  403. {
  404. float dx,dy,dz; //vector from p to t
  405. float len1,len2;
  406. float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about y)
  407. float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
  408. dx = (t[0] - p[0]);
  409. dy = (t[1] - p[1]);
  410. dz = (t[2] - p[2]);
  411. len1 = (float)sqrt(dx*dx + dy*dy + dz*dz);
  412. len2 = (float)sqrt(dx*dx + dy*dy);
  413. if (len1 != 0.0f) {
  414. sinp = dz/len1;
  415. cosp = len2/len1;
  416. } else {
  417. sinp = 0.0f;
  418. cosp = 1.0f;
  419. }
  420. if (len2 != 0.0f) {
  421. siny = dy/len2;
  422. cosy = dx/len2;
  423. } else {
  424. siny = 0.0f;
  425. cosy = 1.0f;
  426. }
  427. Make_Identity();
  428. Translate(p);
  429. // Yaw rotation to projection of target in x-y plane
  430. Rotate_Z(siny,cosy);
  431. // Pitch rotation
  432. Rotate_Y(-sinp,cosp);
  433. // Roll rotation
  434. Rotate_X(roll);
  435. }
  436. /***********************************************************************************************
  437. * Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
  438. * *
  439. * INPUT: *
  440. * *
  441. * OUTPUT: *
  442. * *
  443. * WARNINGS: *
  444. * *
  445. * HISTORY: *
  446. * 8/7/98 GTH : Created. *
  447. *=============================================================================================*/
  448. void Matrix3D::Get_Inverse(Matrix3D & inv) const
  449. {
  450. // TODO: Implement the general purpose inverse function here (once we need it :-)
  451. //Get_Orthogonal_Inverse(inv);
  452. Matrix4 mat4(*this);
  453. Matrix4 mat4Inv;
  454. float det;
  455. D3DXMatrixInverse((D3DXMATRIX *)&mat4Inv, &det, (D3DXMATRIX*)&mat4);
  456. inv.Row[0][0]=mat4Inv[0][0];
  457. inv.Row[0][1]=mat4Inv[0][1];
  458. inv.Row[0][2]=mat4Inv[0][2];
  459. inv.Row[0][3]=mat4Inv[0][3];
  460. inv.Row[1][0]=mat4Inv[1][0];
  461. inv.Row[1][1]=mat4Inv[1][1];
  462. inv.Row[1][2]=mat4Inv[1][2];
  463. inv.Row[1][3]=mat4Inv[1][3];
  464. inv.Row[2][0]=mat4Inv[2][0];
  465. inv.Row[2][1]=mat4Inv[2][1];
  466. inv.Row[2][2]=mat4Inv[2][2];
  467. inv.Row[2][3]=mat4Inv[2][3];
  468. }
  469. /***********************************************************************************************
  470. * Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
  471. * *
  472. * NOTE!!! This only works if the matrix is really ORTHOGONAL!!! *
  473. * *
  474. ***********************************************************************************************
  475. * Inverting an orthogonal Matrix3D *
  476. * *
  477. * M is the original transform, *
  478. * R is rotation submatrix, *
  479. * T is translation vector in M. *
  480. * *
  481. * To build MINV *
  482. * *
  483. * R' = transpose of R (inverse of orthogonal 3x3 matrix is transpose) *
  484. * T' = -R'T *
  485. * *
  486. * Build MINV with R'and T' *
  487. * MINV is the inverse of M *
  488. * *
  489. ***********************************************************************************************
  490. * INPUT: *
  491. * *
  492. * OUTPUT: *
  493. * *
  494. * WARNINGS: *
  495. * *
  496. * HISTORY: *
  497. *=============================================================================================*/
  498. void Matrix3D::Get_Orthogonal_Inverse(Matrix3D & inv) const
  499. {
  500. // Transposing the rotation submatrix
  501. inv.Row[0][0] = Row[0][0];
  502. inv.Row[0][1] = Row[1][0];
  503. inv.Row[0][2] = Row[2][0];
  504. inv.Row[1][0] = Row[0][1];
  505. inv.Row[1][1] = Row[1][1];
  506. inv.Row[1][2] = Row[2][1];
  507. inv.Row[2][0] = Row[0][2];
  508. inv.Row[2][1] = Row[1][2];
  509. inv.Row[2][2] = Row[2][2];
  510. // Now, calculate translation portion of matrix:
  511. // T' = -R'T
  512. Vector3 trans = Get_Translation();
  513. trans = inv.Rotate_Vector(trans);
  514. trans = -trans;
  515. inv.Row[0][3] = trans[0];
  516. inv.Row[1][3] = trans[1];
  517. inv.Row[2][3] = trans[2];
  518. }
  519. /***********************************************************************************************
  520. * Copy_3x3_Matrix(float *matrix) -- Copies a 3x3 (float[9]) matrix into this matrix *
  521. * *
  522. * INPUT: *
  523. * *
  524. * OUTPUT: *
  525. * *
  526. * WARNINGS: *
  527. * *
  528. * HISTORY: *
  529. * 1/16/98 EHC : Created. *
  530. *=============================================================================================*/
  531. void Matrix3D::Copy_3x3_Matrix(float matrix[3][3])
  532. {
  533. Row[0][0] = matrix[0][0];
  534. Row[0][1] = matrix[0][1];
  535. Row[0][2] = matrix[0][2];
  536. Row[0][3] = 0;
  537. Row[1][0] = matrix[1][0];
  538. Row[1][1] = matrix[1][1];
  539. Row[1][2] = matrix[1][2];
  540. Row[1][3] = 0;
  541. Row[2][0] = matrix[2][0];
  542. Row[2][1] = matrix[2][1];
  543. Row[2][2] = matrix[2][2];
  544. Row[2][3] = 0;
  545. }
  546. /***********************************************************************************************
  547. * Matrix3D::Multiply -- matrix multiplication without temporaries. *
  548. * *
  549. * INPUT: *
  550. * *
  551. * OUTPUT: *
  552. * *
  553. * WARNINGS: *
  554. * *
  555. * HISTORY: *
  556. * 4/22/98 GTH : Created. *
  557. *=============================================================================================*/
  558. //void print_matrix(const Matrix3D & m);
  559. void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
  560. {
  561. assert(set_res != NULL);
  562. Matrix3D tmp;
  563. Matrix3D * Aptr;
  564. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  565. // result is going into 'A'. (in this case, this function is no better than
  566. // the overloaded C++ operator...)
  567. if (set_res == &A) {
  568. tmp = A;
  569. Aptr = &tmp;
  570. } else {
  571. Aptr = (Matrix3D *)&A;
  572. }
  573. #ifdef ALLOW_TEMPORARIES
  574. float tmp1,tmp2,tmp3;
  575. tmp1 = B[0][0];
  576. tmp2 = B[1][0];
  577. tmp3 = B[2][0];
  578. (*set_res)[0][0] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  579. (*set_res)[1][0] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  580. (*set_res)[2][0] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  581. tmp1 = B[0][1];
  582. tmp2 = B[1][1];
  583. tmp3 = B[2][1];
  584. (*set_res)[0][1] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  585. (*set_res)[1][1] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  586. (*set_res)[2][1] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  587. tmp1 = B[0][2];
  588. tmp2 = B[1][2];
  589. tmp3 = B[2][2];
  590. (*set_res)[0][2] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  591. (*set_res)[1][2] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  592. (*set_res)[2][2] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  593. tmp1 = B[0][3];
  594. tmp2 = B[1][3];
  595. tmp3 = B[2][3];
  596. (*set_res)[0][3] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3];
  597. (*set_res)[1][3] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3];
  598. (*set_res)[2][3] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3];
  599. #else
  600. set_res->mul(*Aptr, B);
  601. #endif
  602. }
  603. #if 0
  604. void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
  605. {
  606. assert(set_res != NULL);
  607. float tmp[12];
  608. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  609. // result is going into 'A'. (in this case, this function is no better than
  610. // the overloaded C++ operator...)
  611. /* if (set_res == &A)
  612. {
  613. Matrix3D tmp;
  614. Matrix3D * Aptr;
  615. float tmp1,tmp2,tmp3;
  616. tmp = A;
  617. Aptr = &tmp;
  618. tmp1 = B[0][0];
  619. tmp2 = B[1][0];
  620. tmp3 = B[2][0];
  621. (*set_res)[0][0] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  622. (*set_res)[1][0] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  623. (*set_res)[2][0] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  624. tmp1 = B[0][1];
  625. tmp2 = B[1][1];
  626. tmp3 = B[2][1];
  627. (*set_res)[0][1] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  628. (*set_res)[1][1] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  629. (*set_res)[2][1] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  630. tmp1 = B[0][2];
  631. tmp2 = B[1][2];
  632. tmp3 = B[2][2];
  633. (*set_res)[0][2] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  634. (*set_res)[1][2] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  635. (*set_res)[2][2] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  636. tmp1 = B[0][3];
  637. tmp2 = B[1][3];
  638. tmp3 = B[2][3];
  639. (*set_res)[0][3] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3];
  640. (*set_res)[1][3] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3];
  641. (*set_res)[2][3] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3];
  642. return;
  643. }
  644. */
  645. __asm {
  646. mov ecx,B
  647. fld dword ptr [ecx+32] // B[2][0]
  648. mov edx,A
  649. lea ebx,tmp
  650. mov eax,set_res
  651. cmp eax,edx
  652. jne not_equal
  653. mov eax,ebx
  654. not_equal:
  655. fld dword ptr [ecx+16] // B[1][0]
  656. fld dword ptr [ecx] // B[0][0]
  657. // tmp1 = B[0][0];
  658. // tmp2 = B[1][0];
  659. // tmp3 = B[2][0];
  660. // (*set_res)[0][0] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  661. fld dword ptr [edx+8] // A[0][2]
  662. fmul st(0),st(3) // A[0][2] * B[2][0]
  663. fld dword ptr [edx+4] // A[0][1]
  664. fmul st(0),st(3) // A[0][1] * B[1][0]
  665. fld dword ptr [edx] // A[0][0]
  666. fmul st(0),st(3) // A[0][2] * B[0][0]
  667. faddp st(1),st(0)
  668. faddp st(1),st(0)
  669. fstp dword ptr [eax] // res[0][0]
  670. // (*set_res)[1][0] = A[1][0]*tmp1 + A[1][1]*tmp2 + A[1][2]*tmp3;
  671. fld dword ptr [edx+24] // A[1][2]
  672. fmul st(0),st(3) // A[1][2] * B[2][0]
  673. fld dword ptr [edx+20] // A[1][1]
  674. fmul st(0),st(3) // A[1][1] * B[1][0]
  675. fld dword ptr [edx+16] // A[1][0]
  676. fmul st(0),st(3) // A[1][0] * B[0][0]
  677. faddp st(1),st(0)
  678. faddp st(1),st(0)
  679. fstp dword ptr [eax+16] // res[1][0]
  680. // (*set_res)[2][0] = A[2][0]*tmp1 + A[2][1]*tmp2 + A[2][2]*tmp3;
  681. fld dword ptr [edx+40] // A[2][2]
  682. fmul st(0),st(3) // A[2][2] * B[2][0]
  683. fld dword ptr [edx+36] // A[2][1]
  684. fmul st(0),st(3) // A[2][1] * B[1][0]
  685. fld dword ptr [edx+32] // A[2][0]
  686. fmul st(0),st(3) // A[2][0] * B[0][0]
  687. faddp st(1),st(0)
  688. faddp st(1),st(0)
  689. fstp dword ptr [eax+32] // res[2][0]
  690. // tmp1 = B[0][1];
  691. // tmp2 = B[1][1];
  692. // tmp3 = B[2][1];
  693. fstp st(0)
  694. fstp st(0)
  695. fstp st(0)
  696. fld dword ptr [ecx+36] // B[2][1]
  697. fld dword ptr [ecx+20] // B[1][1]
  698. fld dword ptr [ecx+4] // B[0][1]
  699. // (*set_res)[0][1] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  700. fld dword ptr [edx+8] // A[0][2]
  701. fmul st(0),st(3) // A[0][2] * B[2][1]
  702. fld dword ptr [edx+4] // A[0][1]
  703. fmul st(0),st(3) // A[0][1] * B[1][1]
  704. fld dword ptr [edx] // A[0][0]
  705. fmul st(0),st(3) // A[0][2] * B[0][1]
  706. faddp st(1),st(0)
  707. faddp st(1),st(0)
  708. fstp dword ptr [eax+4] // res[0][1]
  709. // (*set_res)[1][1] = A[1][0]*tmp1 + A[1][1]*tmp2 + A[1][2]*tmp3;
  710. fld dword ptr [edx+24] // A[1][2]
  711. fmul st(0),st(3) // A[1][2] * B[2][1]
  712. fld dword ptr [edx+20] // A[1][1]
  713. fmul st(0),st(3) // A[1][1] * B[1][1]
  714. fld dword ptr [edx+16] // A[1][0]
  715. fmul st(0),st(3) // A[1][0] * B[0][1]
  716. faddp st(1),st(0)
  717. faddp st(1),st(0)
  718. fstp dword ptr [eax+20] // res[1][1]
  719. // (*set_res)[2][1] = A[2][0]*tmp1 + A[2][1]*tmp2 + A[2][2]*tmp3;
  720. fld dword ptr [edx+40] // A[2][2]
  721. fmul st(0),st(3) // A[2][2] * B[2][1]
  722. fld dword ptr [edx+36] // A[2][1]
  723. fmul st(0),st(3) // A[2][1] * B[1][1]
  724. fld dword ptr [edx+32] // A[2][0]
  725. fmul st(0),st(3) // A[2][0] * B[0][1]
  726. faddp st(1),st(0)
  727. faddp st(1),st(0)
  728. fstp dword ptr [eax+36] // res[2][1]
  729. // tmp1 = B[0][2];
  730. // tmp2 = B[1][2];
  731. // tmp3 = B[2][2];
  732. fstp st(0)
  733. fstp st(0)
  734. fstp st(0)
  735. fld dword ptr [ecx+40] // B[2][2]
  736. fld dword ptr [ecx+24] // B[1][2]
  737. fld dword ptr [ecx+8] // B[0][2]
  738. // (*set_res)[0][2] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  739. fld dword ptr [edx+8] // A[0][2]
  740. fmul st(0),st(3) // A[0][2] * B[2][2]
  741. fld dword ptr [edx+4] // A[0][1]
  742. fmul st(0),st(3) // A[0][1] * B[1][2]
  743. fld dword ptr [edx] // A[0][0]
  744. fmul st(0),st(3) // A[0][2] * B[0][2]
  745. faddp st(1),st(0)
  746. faddp st(1),st(0)
  747. fstp dword ptr [eax+8] // res[0][2]
  748. // (*set_res)[1][2] = A[1][0]*tmp1 + A[1][1]*tmp2 + A[1][2]*tmp3;
  749. fld dword ptr [edx+24] // A[1][2]
  750. fmul st(0),st(3) // A[1][2] * B[2][2]
  751. fld dword ptr [edx+20] // A[1][1]
  752. fmul st(0),st(3) // A[1][1] * B[1][2]
  753. fld dword ptr [edx+16] // A[1][0]
  754. fmul st(0),st(3) // A[1][0] * B[0][2]
  755. faddp st(1),st(0)
  756. faddp st(1),st(0)
  757. fstp dword ptr [eax+24] // res[1][2]
  758. // (*set_res)[2][2] = A[2][0]*tmp1 + A[2][1]*tmp2 + A[2][2]*tmp3;
  759. fld dword ptr [edx+40] // A[2][2]
  760. fmul st(0),st(3) // A[2][2] * B[2][2]
  761. fld dword ptr [edx+36] // A[2][1]
  762. fmul st(0),st(3) // A[2][1] * B[1][2]
  763. fld dword ptr [edx+32] // A[2][0]
  764. fmul st(0),st(3) // A[2][0] * B[0][2]
  765. faddp st(1),st(0)
  766. faddp st(1),st(0)
  767. fstp dword ptr [eax+40] // res[2][2]
  768. // -------------------------------
  769. // tmp1 = B[0][3];
  770. // tmp2 = B[1][3];
  771. // tmp3 = B[2][3];
  772. fstp st(0)
  773. fstp st(0)
  774. fstp st(0)
  775. fld dword ptr [ecx+44] // B[2][3]
  776. fld dword ptr [ecx+28] // B[1][3]
  777. fld dword ptr [ecx+12] // B[0][3]
  778. // (*set_res)[0][3] = A[0][0]*tmp1 + A[0][1]*tmp2 + A[0][2]*tmp3 + A[0][3];
  779. fld dword ptr [edx+8] // A[0][2]
  780. fmul st(0),st(3) // A[0][2] * B[2][3]
  781. fld dword ptr [edx+4] // A[0][1]
  782. fmul st(0),st(3) // A[0][1] * B[1][3]
  783. fld dword ptr [edx] // A[0][0]
  784. fmul st(0),st(3) // A[0][2] * B[0][3]
  785. faddp st(1),st(0)
  786. faddp st(1),st(0)
  787. fadd dword ptr [edx+12] // + A[0][3]
  788. fstp dword ptr [eax+12] // res[0][3]
  789. // (*set_res)[1][3] = A[1][0]*tmp1 + A[1][1]*tmp2 + A[1][2]*tmp3 + A[1][3];
  790. fld dword ptr [edx+24] // A[1][2]
  791. fmul st(0),st(3) // A[1][2] * B[2][3]
  792. fld dword ptr [edx+20] // A[1][1]
  793. fmul st(0),st(3) // A[1][1] * B[1][3]
  794. fld dword ptr [edx+16] // A[1][0]
  795. fmul st(0),st(3) // A[1][0] * B[0][3]
  796. faddp st(1),st(0)
  797. faddp st(1),st(0)
  798. fadd dword ptr [edx+28] // + A[1][3]
  799. fstp dword ptr [eax+28] // res[1][3]
  800. // (*set_res)[2][3] = A[2][0]*tmp1 + A[2][1]*tmp2 + A[2][2]*tmp3 + A[2][3];
  801. fld dword ptr [edx+40] // A[2][2]
  802. fmul st(0),st(3) // A[2][2] * B[2][3]
  803. fld dword ptr [edx+36] // A[2][1]
  804. fmul st(0),st(3) // A[2][1] * B[1][3]
  805. fld dword ptr [edx+32] // A[2][0]
  806. fmul st(0),st(3) // A[2][0] * B[0][3]
  807. faddp st(1),st(0)
  808. faddp st(1),st(0)
  809. fadd dword ptr [edx+44] // + A[2][3]
  810. fstp dword ptr [eax+44] // res[2][3]
  811. fstp st(0)
  812. fstp st(0)
  813. fstp st(0)
  814. cmp eax,ebx
  815. jne not_equal2
  816. mov ecx,12 // copy 12 dwords
  817. mov esi,eax // set source to tmp
  818. mov edi,set_res // set destination to set_res
  819. rep movsd // copy
  820. not_equal2:
  821. }
  822. /*
  823. WWDEBUG_SAY(("{%2.2f, %2.2f, %2.2f, %2.2f}, {%2.2f, %2.2f, %2.2f, %2.2f}, {%2.2f, %2.2f, %2.2f, %2.2f}\n"
  824. ,res[0][0],res[0][1],res[0][2],res[0][3]
  825. ,res[1][0],res[1][1],res[1][2],res[1][3]
  826. ,res[2][0],res[2][1],res[2][2],res[2][3]));
  827. WWDEBUG_SAY(("{%2.2f, %2.2f, %2.2f, %2.2f}, {%2.2f, %2.2f, %2.2f, %2.2f}, {%2.2f, %2.2f, %2.2f, %2.2f}\n"
  828. ,res2[0][0],res2[0][1],res2[0][2],res2[0][3]
  829. ,res2[1][0],res2[1][1],res2[1][2],res2[1][3]
  830. ,res2[2][0],res2[2][1],res2[2][2],res2[2][3]));
  831. // res[2][3]=res2[2][3];
  832. // res=res2;
  833. */
  834. /* for (int y=0;y<3;++y) {
  835. for (int x=0;x<4;++x) {
  836. if (fabs(res2[y][x]-res[y][x])>0.001f) {
  837. WWDEBUG_SAY(("x: %d, y: %d, %f != %f\n",x,y,res2[y][x],res[y][x]));
  838. __asm nop
  839. }
  840. }
  841. }
  842. */
  843. /* WWASSERT(res2[0][0]==res[0][0]);
  844. WWASSERT(res2[0][1]==res[0][1]);
  845. WWASSERT(res2[0][2]==res[0][2]);
  846. WWASSERT(res2[0][3]==res[0][3]);
  847. WWASSERT(res2[1][0]==res[1][0]);
  848. WWASSERT(res2[1][1]==res[1][1]);
  849. WWASSERT(res2[1][2]==res[1][2]);
  850. WWASSERT(res2[1][3]==res[1][3]);
  851. WWASSERT(res2[2][0]==res[2][0]);
  852. WWASSERT(res2[2][1]==res[2][1]);
  853. WWASSERT(res2[2][2]==res[2][2]);
  854. WWASSERT(res2[2][3]==res[2][3]);
  855. */
  856. }
  857. #endif
  858. /***********************************************************************************************
  859. * Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
  860. * *
  861. * INPUT: *
  862. * *
  863. * OUTPUT: *
  864. * *
  865. * WARNINGS: *
  866. * *
  867. * HISTORY: *
  868. * 7/17/98 GTH : Created. *
  869. *=============================================================================================*/
  870. void Matrix3D::Transform_Min_Max_AABox
  871. (
  872. const Vector3 & min,
  873. const Vector3 & max,
  874. Vector3 * set_min,
  875. Vector3 * set_max
  876. ) const
  877. {
  878. WWASSERT(set_min != &min);
  879. WWASSERT(set_max != &max);
  880. float tmp0,tmp1;
  881. // init the min and max to the translation of the transform
  882. set_min->X = set_max->X = Row[0][3];
  883. set_min->Y = set_max->Y = Row[1][3];
  884. set_min->Z = set_max->Z = Row[2][3];
  885. // now push them both out by the projections of the original intervals
  886. for (int i=0; i<3; i++) {
  887. for (int j=0; j<3; j++) {
  888. tmp0 = Row[i][j] * min[j];
  889. tmp1 = Row[i][j] * max[j];
  890. if (tmp0 < tmp1) {
  891. (*set_min)[i] += tmp0;
  892. (*set_max)[i] += tmp1;
  893. } else {
  894. (*set_min)[i] += tmp1;
  895. (*set_max)[i] += tmp0;
  896. }
  897. }
  898. }
  899. }
  900. /***********************************************************************************************
  901. * Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
  902. * *
  903. * INPUT: *
  904. * *
  905. * OUTPUT: *
  906. * *
  907. * WARNINGS: *
  908. * *
  909. * HISTORY: *
  910. * 7/17/98 GTH : Created. *
  911. *=============================================================================================*/
  912. void Matrix3D::Transform_Center_Extent_AABox
  913. (
  914. const Vector3 & center,
  915. const Vector3 & extent,
  916. Vector3 * set_center,
  917. Vector3 * set_extent
  918. ) const
  919. {
  920. WWASSERT(set_center != &center);
  921. WWASSERT(set_extent != &extent);
  922. // push each extent out to the projections of the original extents
  923. for (int i=0; i<3; i++) {
  924. // start the center out at the translation portion of the matrix
  925. // and the extent at zero
  926. (*set_center)[i] = Row[i][3];
  927. (*set_extent)[i] = 0.0f;
  928. for (int j=0; j<3; j++) {
  929. (*set_center)[i] += Row[i][j] * center[j];
  930. (*set_extent)[i] += WWMath::Fabs(Row[i][j] * extent[j]);
  931. }
  932. }
  933. }
  934. /***********************************************************************************************
  935. * Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
  936. * *
  937. * INPUT: *
  938. * *
  939. * OUTPUT: *
  940. * *
  941. * WARNINGS: *
  942. * *
  943. * HISTORY: *
  944. * 9/16/98 GTH : Created. *
  945. *=============================================================================================*/
  946. int Matrix3D::Is_Orthogonal(void) const
  947. {
  948. Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
  949. Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
  950. Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
  951. if (Vector3::Dot_Product(x,y) > WWMATH_EPSILON) return 0;
  952. if (Vector3::Dot_Product(y,z) > WWMATH_EPSILON) return 0;
  953. if (Vector3::Dot_Product(z,x) > WWMATH_EPSILON) return 0;
  954. if (WWMath::Fabs(x.Length2() - 1.0f) > WWMATH_EPSILON) return 0;
  955. if (WWMath::Fabs(y.Length2() - 1.0f) > WWMATH_EPSILON) return 0;
  956. if (WWMath::Fabs(z.Length2() - 1.0f) > WWMATH_EPSILON) return 0;
  957. return 1;
  958. }
  959. /***********************************************************************************************
  960. * Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
  961. * *
  962. * INPUT: *
  963. * *
  964. * OUTPUT: *
  965. * *
  966. * WARNINGS: *
  967. * This function is rather expensive, should only be used if you *know* numerical error is *
  968. * killing you. *
  969. * *
  970. * HISTORY: *
  971. * 9/16/98 GTH : Created. *
  972. *=============================================================================================*/
  973. void Matrix3D::Re_Orthogonalize(void)
  974. {
  975. Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
  976. Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
  977. Vector3 z;
  978. Vector3::Cross_Product(x,y,&z);
  979. Vector3::Cross_Product(z,x,&y);
  980. float len = x.Length();
  981. if (len < WWMATH_EPSILON) {
  982. Make_Identity();
  983. return;
  984. } else {
  985. x *= 1.0f/len;
  986. }
  987. len = y.Length();
  988. if (len < WWMATH_EPSILON) {
  989. Make_Identity();
  990. return;
  991. } else {
  992. y *= 1.0f/len;
  993. }
  994. len = z.Length();
  995. if (len < WWMATH_EPSILON) {
  996. Make_Identity();
  997. return;
  998. } else {
  999. z *= 1.0f/len;
  1000. }
  1001. Row[0][0] = x.X;
  1002. Row[0][1] = x.Y;
  1003. Row[0][2] = x.Z;
  1004. Row[1][0] = y.X;
  1005. Row[1][1] = y.Y;
  1006. Row[1][2] = y.Z;
  1007. Row[2][0] = z.X;
  1008. Row[2][1] = z.Y;
  1009. Row[2][2] = z.Z;
  1010. }
  1011. /***********************************************************************************************
  1012. * Lerp - linearly interpolate matrices (orientation is slerped) *
  1013. * *
  1014. * INPUT: *
  1015. * *
  1016. * OUTPUT: *
  1017. * *
  1018. * WARNINGS: *
  1019. * *
  1020. * HISTORY: *
  1021. * 10/05/1998 NH : Created. *
  1022. *=============================================================================================*/
  1023. void Matrix3D::Lerp(const Matrix3D &A, const Matrix3D &B, float factor, Matrix3D& result)
  1024. {
  1025. assert(factor >= 0.0f);
  1026. assert(factor <= 1.0f);
  1027. // Lerp position
  1028. #ifdef ALLOW_TEMPORARIES
  1029. Vector3 pos = Lerp(A.Get_Translation(), B.Get_Translation(), factor);
  1030. #else
  1031. Vector3 pos;
  1032. Vector3::Lerp(A.Get_Translation(), B.Get_Translation(), factor, &pos);
  1033. #endif
  1034. Quaternion rot;
  1035. Slerp(rot,Build_Quaternion(A), Build_Quaternion(B), factor);
  1036. result.Set(rot, pos);
  1037. }
  1038. /***********************************************************************************************
  1039. * Matrix3D::Solve_Linear_System -- 3x3 Gauss-Jordan elimination *
  1040. * *
  1041. * The result of this function will be that the 3x3 sub-matrix is inverted and the *
  1042. * final column will contain the result. False is returned if the system cannot be solved. *
  1043. * *
  1044. * INPUT: *
  1045. * *
  1046. * OUTPUT: *
  1047. * *
  1048. * WARNINGS: *
  1049. * *
  1050. * HISTORY: *
  1051. * 2/18/2001 gth : Created. *
  1052. *=============================================================================================*/
  1053. bool Matrix3D::Solve_Linear_System(Matrix3D & system)
  1054. {
  1055. /*
  1056. ** Gauss-Jordan Elimination
  1057. ** We repeatedly replace rows in the matrix with a linear combination of itself and
  1058. ** another row in the system in order to reduce the matrix to the identity matrix.
  1059. ** TODO: optimize away all unnecessary math operations!
  1060. */
  1061. if (system[0][0] == 0.0f) return false;
  1062. system[0] *= 1.0f / system[0][0]; // (0,0) now equals 1.0 (row,col)
  1063. system[1] -= system[1][0] * system[0]; // (1,0) now equals 0.0
  1064. system[2] -= system[2][0] * system[0]; // (2,0) now equals 0.0
  1065. if (system[1][1] == 0.0f) return false;
  1066. system[1] *= 1.0f / system[1][1]; // (1,1) now equals 1.0
  1067. system[2] -= system[2][1] * system[1]; // (2,1) now equals 0.0
  1068. if (system[2][2] == 0.0f) return false;
  1069. system[2] *= 1.0f / system[2][2]; // (2,2) now equals 1.0, and we already have one answer
  1070. system[1] -= system[1][2] * system[2]; // (1,2) now equals 0.0, and we have another answer
  1071. system[0] -= system[0][2] * system[2]; // (0,2) now equals 0.0
  1072. system[0] -= system[0][1] * system[1]; // (0,1) now equals 0.0, and we are done!
  1073. return true;
  1074. }