matrix3d.cpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /*
  2. ** Command & Conquer Renegade(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/Tools/W3DShellExt/External/matrix3d.cpp 1 1/02/02 1:18p Moumine_ballo $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : WW3D PS2 *
  24. * *
  25. * File Name : MATRIX3D.CPP *
  26. * *
  27. * Programmer : Kenny Mitchell *
  28. * *
  29. * Start Date : 11/16/99 *
  30. * *
  31. * Last Update : 11/16/99 *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Based on Greg Hjelstrom 97 *
  35. * Functions: *
  36. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  37. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  38. * Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
  39. * Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
  40. * Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
  41. * Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
  42. * Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
  43. * Matrix3D::Multiply -- matrix multiplication without temporaries. *
  44. * Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
  45. * Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
  46. * Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
  47. * Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
  48. * Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
  49. * Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
  50. * Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
  51. * Lerp - linearly interpolate matrices (orientation is slerped) *
  52. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  53. #include "matrix3d.h"
  54. #include <math.h>
  55. #include <stdlib.h>
  56. #include "vector3.h"
  57. #include "matrix3.h"
  58. #include "matrix4.h"
  59. #include "quat.h"
  60. // some static matrices which are sometimes useful
  61. const Matrix3D Matrix3D::Identity
  62. (
  63. 1.0f, 0.0f, 0.0f, 0.0f,
  64. 0.0f, 1.0f, 0.0f, 0.0f,
  65. 0.0f, 0.0f, 1.0f, 0.0f
  66. );
  67. const Matrix3D Matrix3D::RotateX90
  68. (
  69. 1.0f, 0.0f, 0.0f, 0.0f,
  70. 0.0f, 0.0f, -1.0f,0.0f,
  71. 0.0f, 1.0f, 0.0f, 0.0f
  72. );
  73. const Matrix3D Matrix3D::RotateX180
  74. (
  75. 1.0f, 0.0f, 0.0f, 0.0f,
  76. 0.0f, -1.0f,0.0f, 0.0f,
  77. 0.0f, 0.0f,-1.0f, 0.0f
  78. );
  79. const Matrix3D Matrix3D::RotateX270
  80. (
  81. 1.0f, 0.0f, 0.0f, 0.0f,
  82. 0.0f, 0.0f, 1.0f, 0.0f,
  83. 0.0f, -1.0f,0.0f, 0.0f
  84. );
  85. const Matrix3D Matrix3D::RotateY90
  86. (
  87. 0.0f, 0.0f, 1.0f, 0.0f,
  88. 0.0f, 1.0f, 0.0f, 0.0f,
  89. -1.0f, 0.0f, 0.0f, 0.0f
  90. );
  91. const Matrix3D Matrix3D::RotateY180
  92. (
  93. -1.0f, 0.0f, 0.0f, 0.0f,
  94. 0.0f, 1.0f, 0.0f, 0.0f,
  95. 0.0f, 0.0f, -1.0f,0.0f
  96. );
  97. const Matrix3D Matrix3D::RotateY270
  98. (
  99. 0.0f, 0.0f, -1.0f,0.0f,
  100. 0.0f, 1.0f, 0.0f, 0.0f,
  101. 1.0f, 0.0f, 0.0f, 0.0f
  102. );
  103. const Matrix3D Matrix3D::RotateZ90
  104. (
  105. 0.0f, -1.0f,0.0f, 0.0f,
  106. 1.0f, 0.0f, 0.0f, 0.0f,
  107. 0.0f, 0.0f, 1.0f, 0.0f
  108. );
  109. const Matrix3D Matrix3D::RotateZ180
  110. (
  111. -1.0f, 0.0f, 0.0f, 0.0f,
  112. 0.0f, -1.0f,0.0f, 0.0f,
  113. 0.0f, 0.0f, 1.0f, 0.0f
  114. );
  115. const Matrix3D Matrix3D::RotateZ270
  116. (
  117. 0.0f, 1.0f, 0.0f, 0.0f,
  118. -1.0f, 0.0f, 0.0f, 0.0f,
  119. 0.0f, 0.0f, 1.0f, 0.0f
  120. );
  121. /***********************************************************************************************
  122. * Matrix3D::Set -- Init a matrix3D from a matrix3 and a position *
  123. * *
  124. * INPUT: *
  125. * *
  126. * OUTPUT: *
  127. * *
  128. * WARNINGS: *
  129. * *
  130. * HISTORY: *
  131. *=============================================================================================*/
  132. void Matrix3D::Set(const Matrix3 & rot,const Vector3 & pos)
  133. {
  134. Row[0].Set( rot[0][0], rot[0][1], rot[0][2], pos[0]);
  135. Row[1].Set( rot[1][0], rot[1][1], rot[1][2], pos[1]);
  136. Row[2].Set( rot[2][0], rot[2][1], rot[2][2], pos[2]);
  137. }
  138. /***********************************************************************************************
  139. * Matrix3D::Set -- Init a matrix3D from a quaternion and a position *
  140. * *
  141. * INPUT: *
  142. * *
  143. * OUTPUT: *
  144. * *
  145. * WARNINGS: *
  146. * *
  147. * HISTORY: *
  148. *=============================================================================================*/
  149. void Matrix3D::Set(const Quaternion & rot,const Vector3 & pos)
  150. {
  151. Set_Rotation(rot);
  152. Set_Translation(pos);
  153. }
  154. /***********************************************************************************************
  155. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  156. * *
  157. * INPUT: *
  158. * *
  159. * OUTPUT: *
  160. * *
  161. * WARNINGS: *
  162. * *
  163. * HISTORY: *
  164. * 5/11/98 GTH : Created. *
  165. *=============================================================================================*/
  166. void Matrix3D::Set_Rotation(const Matrix3 & m)
  167. {
  168. Row[0][0] = m[0][0];
  169. Row[0][1] = m[0][1];
  170. Row[0][2] = m[0][2];
  171. Row[1][0] = m[1][0];
  172. Row[1][1] = m[1][1];
  173. Row[1][2] = m[1][2];
  174. Row[2][0] = m[2][0];
  175. Row[2][1] = m[2][1];
  176. Row[2][2] = m[2][2];
  177. }
  178. /***********************************************************************************************
  179. * Matrix3D::Set_Rotation -- Sets the rotation part of the matrix *
  180. * *
  181. * INPUT: *
  182. * *
  183. * OUTPUT: *
  184. * *
  185. * WARNINGS: *
  186. * *
  187. * HISTORY: *
  188. * 5/11/98 GTH : Created. *
  189. *=============================================================================================*/
  190. void Matrix3D::Set_Rotation(const Quaternion & q)
  191. {
  192. Row[0][0] = (float)(1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
  193. Row[0][1] = (float)(2.0f * (q[0] * q[1] - q[2] * q[3]));
  194. Row[0][2] = (float)(2.0f * (q[2] * q[0] + q[1] * q[3]));
  195. Row[1][0] = (float)(2.0f * (q[0] * q[1] + q[2] * q[3]));
  196. Row[1][1] = (float)(1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
  197. Row[1][2] = (float)(2.0f * (q[1] * q[2] - q[0] * q[3]));
  198. Row[2][0] = (float)(2.0f * (q[2] * q[0] - q[1] * q[3]));
  199. Row[2][1] = (float)(2.0f * (q[1] * q[2] + q[0] * q[3]));
  200. Row[2][2] =(float)(1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]));
  201. }
  202. /***********************************************************************************************
  203. * Matrix3D::Get_X_Rotation -- approximates the rotation about the X axis *
  204. * *
  205. * INPUT: *
  206. * *
  207. * OUTPUT: *
  208. * *
  209. * WARNINGS: *
  210. * *
  211. * HISTORY: *
  212. * 08/11/1997 GH : Created. *
  213. *=============================================================================================*/
  214. float Matrix3D::Get_X_Rotation(void) const
  215. {
  216. return atan2f(Row[2][1], Row[1][1]);
  217. }
  218. /***********************************************************************************************
  219. * Matrix3D::Get_Y_Rotation -- approximates the rotation about the Y axis *
  220. * *
  221. * INPUT: *
  222. * *
  223. * OUTPUT: *
  224. * *
  225. * WARNINGS: *
  226. * *
  227. * HISTORY: *
  228. * 08/11/1997 GH : Created. *
  229. *=============================================================================================*/
  230. float Matrix3D::Get_Y_Rotation(void) const
  231. {
  232. return atan2f(Row[0][2], Row[2][2]);
  233. }
  234. /***********************************************************************************************
  235. * Matrix3D::Get_Z_Rotation -- approximates the rotation about the Z axis *
  236. * *
  237. * INPUT: *
  238. * *
  239. * OUTPUT: *
  240. * *
  241. * WARNINGS: *
  242. * *
  243. * HISTORY: *
  244. * 08/11/1997 GH : Created. *
  245. *=============================================================================================*/
  246. float Matrix3D::Get_Z_Rotation(void) const
  247. {
  248. return atan2f(Row[1][0], Row[0][0]);
  249. }
  250. /***********************************************************************************************
  251. * M3DC::Rotate_Vector -- Uses the 3x3 sub-matrix to rotate a vector *
  252. * *
  253. * INPUT: *
  254. * *
  255. * OUTPUT: *
  256. * *
  257. * WARNINGS: *
  258. * *
  259. * HISTORY: *
  260. *=============================================================================================*/
  261. Vector3 Matrix3D::Rotate_Vector(const Vector3 &vect) const
  262. {
  263. return Vector3(
  264. (Row[0][0]*vect[0] + Row[0][1]*vect[1] + Row[0][2]*vect[2]),
  265. (Row[1][0]*vect[0] + Row[1][1]*vect[1] + Row[1][2]*vect[2]),
  266. (Row[2][0]*vect[0] + Row[2][1]*vect[1] + Row[2][2]*vect[2])
  267. );
  268. }
  269. /***********************************************************************************************
  270. * Matrix3D::Inverse_Rotate_Vector -- rotates a vector by the inverse of the 3x3 sub-matrix *
  271. * *
  272. * INPUT: *
  273. * *
  274. * OUTPUT: *
  275. * *
  276. * WARNINGS: *
  277. * *
  278. * HISTORY: *
  279. * 4/27/98 GTH : Created. *
  280. *=============================================================================================*/
  281. Vector3 Matrix3D::Inverse_Rotate_Vector(const Vector3 &vect) const
  282. {
  283. return Vector3(
  284. (Row[0][0]*vect[0] + Row[1][0]*vect[1] + Row[2][0]*vect[2]),
  285. (Row[0][1]*vect[0] + Row[1][1]*vect[1] + Row[2][1]*vect[2]),
  286. (Row[0][2]*vect[0] + Row[1][2]*vect[1] + Row[2][2]*vect[2])
  287. );
  288. }
  289. /***********************************************************************************************
  290. * M3DC::Look_At -- Creates a "look at" transformation. *
  291. * *
  292. * Builds a transformation matrix which positions the origin at p, *
  293. * points the negative z-axis towards a target t, and rolls about the z-axis *
  294. * by the angle specified by roll. *
  295. * *
  296. * This can be useful for creating a camera matrix, just invert *
  297. * the matrix after initializing it with this function... *
  298. * *
  299. * INPUT: *
  300. * p - position of the coordinate system *
  301. * t - target of the coordinate system *
  302. * roll - roll angle (in radians) *
  303. * *
  304. * OUTPUT: *
  305. * *
  306. * WARNINGS: *
  307. * This function is written assuming the convention that the "ground" is the X-Y plane and *
  308. * Z is altitude. *
  309. * *
  310. * HISTORY: *
  311. *=============================================================================================*/
  312. void Matrix3D::Look_At(const Vector3 &p,const Vector3 &t,float roll)
  313. {
  314. float dx,dy,dz; //vector from p to t
  315. float len1,len2;
  316. float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about x)
  317. float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
  318. dx = (t[0] - p[0]);
  319. dy = (t[1] - p[1]);
  320. dz = (t[2] - p[2]);
  321. len1 = 1.0f / (float)sqrt(dx*dx + dy*dy + dz*dz);
  322. len2 = 1.0f / (float)sqrt(dx*dx + dy*dy);
  323. sinp = dz*len1;
  324. cosp = len2*len1;
  325. // sinp = 0.0f;
  326. // cosp = 1.0f;
  327. siny = dy*len2;
  328. cosy = dx*len2;
  329. // siny = 0.0f;
  330. // cosy = 1.0f;
  331. // init the matrix with position p and -z pointing down +x and +y up
  332. Row[0].X = 0.0f; Row[0].Y = 0.0f; Row[0].Z = -1.0f;
  333. Row[1].X = -1.0f; Row[1].Y = 0.0f; Row[1].Z = 0.0f;
  334. Row[2].X = 0.0f; Row[2].Y = 1.0f; Row[2].Z = 0.0f;
  335. Row[0].W = p.X;
  336. Row[1].W = p.Y;
  337. Row[2].W = p.Z;
  338. // Yaw rotation to make the matrix look at the projection of the target
  339. // into the x-y plane
  340. Rotate_Y(siny,cosy);
  341. // rotate about local x axis to pitch up to the targets position
  342. Rotate_X(sinp,cosp);
  343. // roll about the local z axis (negate since we look down -z)
  344. Rotate_Z(-roll);
  345. }
  346. /***********************************************************************************************
  347. * M3DC::Obj_Look_At -- Commando Object "look at" transformation. *
  348. * *
  349. * Builds a transformation matrix which positions the origin at p, *
  350. * points the positive X axis towards a target t, and rolls about the X axis *
  351. * by the angle specified by roll. *
  352. * *
  353. * The object convention used by Commando and G is Forward = +X, Left = +Y, Up = +Z. The *
  354. * world is basically the x-y plane with z as altitude and +x is the default "forward". *
  355. * *
  356. * INPUT: *
  357. * p - position of the coordinate system *
  358. * t - target of the coordinate system *
  359. * roll - roll angle (in radians) *
  360. * *
  361. * OUTPUT: *
  362. * *
  363. * WARNINGS: *
  364. * *
  365. * HISTORY: *
  366. *=============================================================================================*/
  367. void Matrix3D::Obj_Look_At(const Vector3 &p,const Vector3 &t,float roll)
  368. {
  369. float dx,dy,dz; //vector from p to t
  370. float len1,len2;
  371. float sinp,cosp; //sine and cosine of the pitch ("up-down" tilt about y)
  372. float siny,cosy; //sine and cosine of the yaw ("left-right"tilt about z)
  373. dx = (t[0] - p[0]);
  374. dy = (t[1] - p[1]);
  375. dz = (t[2] - p[2]);
  376. len1 = 1.0f / (float)sqrt(dx*dx + dy*dy + dz*dz);
  377. len2 = 1.0f / (float)sqrt(dx*dx + dy*dy);
  378. sinp = dz*len1;
  379. cosp = len2*len1;
  380. siny = dy*len2;
  381. cosy = dx*len2;
  382. Make_Identity();
  383. Translate(p);
  384. // Yaw rotation to projection of target in x-y plane
  385. Rotate_Z(siny,cosy);
  386. // Pitch rotation
  387. Rotate_Y(-sinp,cosp);
  388. // Roll rotation
  389. Rotate_X(roll);
  390. }
  391. /***********************************************************************************************
  392. * Matrix3D::Get_Inverse -- calculate the inverse of this matrix *
  393. * *
  394. * INPUT: *
  395. * *
  396. * OUTPUT: *
  397. * *
  398. * WARNINGS: *
  399. * *
  400. * HISTORY: *
  401. * 8/7/98 GTH : Created. *
  402. *=============================================================================================*/
  403. void Matrix3D::Get_Inverse(Matrix3D & inv) const
  404. {
  405. // TODO: Implement the general purpose inverse function here (once we need it :-)
  406. Get_Orthogonal_Inverse(inv);
  407. }
  408. /***********************************************************************************************
  409. * Matrix3D::Get_Orthogonal_Inverse -- Returns the inverse of the matrix *
  410. * *
  411. * NOTE!!! This only works if the matrix is really ORTHOGONAL!!! *
  412. * *
  413. ***********************************************************************************************
  414. * Inverting an orthogonal Matrix3D *
  415. * *
  416. * M is the original transform, *
  417. * R is rotation submatrix, *
  418. * T is translation vector in M. *
  419. * *
  420. * To build MINV *
  421. * *
  422. * R' = transpose of R (inverse of orthogonal 3x3 matrix is transpose) *
  423. * T' = -R'T *
  424. * *
  425. * Build MINV with R'and T' *
  426. * MINV is the inverse of M *
  427. * *
  428. ***********************************************************************************************
  429. * INPUT: *
  430. * *
  431. * OUTPUT: *
  432. * *
  433. * WARNINGS: *
  434. * *
  435. * HISTORY: *
  436. *=============================================================================================*/
  437. void Matrix3D::Get_Orthogonal_Inverse(Matrix3D & inv) const
  438. {
  439. // Transposing the rotation submatrix
  440. inv.Row[0][0] = Row[0][0];
  441. inv.Row[0][1] = Row[1][0];
  442. inv.Row[0][2] = Row[2][0];
  443. inv.Row[1][0] = Row[0][1];
  444. inv.Row[1][1] = Row[1][1];
  445. inv.Row[1][2] = Row[2][1];
  446. inv.Row[2][0] = Row[0][2];
  447. inv.Row[2][1] = Row[1][2];
  448. inv.Row[2][2] = Row[2][2];
  449. // Now, calculate translation portion of matrix:
  450. // T' = -R'T
  451. Vector3 trans = Get_Translation();
  452. trans = inv.Rotate_Vector(trans);
  453. trans = -trans;
  454. inv.Row[0][3] = trans[0];
  455. inv.Row[1][3] = trans[1];
  456. inv.Row[2][3] = trans[2];
  457. }
  458. /***********************************************************************************************
  459. * Copy_3x3_Matrix(float *matrix) -- Copies a 3x3 (float[9]) matrix into this matrix *
  460. * *
  461. * INPUT: *
  462. * *
  463. * OUTPUT: *
  464. * *
  465. * WARNINGS: *
  466. * *
  467. * HISTORY: *
  468. * 1/16/98 EHC : Created. *
  469. *=============================================================================================*/
  470. void Matrix3D::Copy_3x3_Matrix(float matrix[3][3])
  471. {
  472. Row[0][0] = matrix[0][0];
  473. Row[0][1] = matrix[0][1];
  474. Row[0][2] = matrix[0][2];
  475. Row[0][3] = 0;
  476. Row[1][0] = matrix[1][0];
  477. Row[1][1] = matrix[1][1];
  478. Row[1][2] = matrix[1][2];
  479. Row[1][3] = 0;
  480. Row[2][0] = matrix[2][0];
  481. Row[2][1] = matrix[2][1];
  482. Row[2][2] = matrix[2][2];
  483. Row[2][3] = 0;
  484. }
  485. /***********************************************************************************************
  486. * Matrix3D::Multiply -- matrix multiplication without temporaries. *
  487. * *
  488. * INPUT: *
  489. * *
  490. * OUTPUT: *
  491. * *
  492. * WARNINGS: *
  493. * *
  494. * HISTORY: *
  495. * 4/22/98 GTH : Created. *
  496. *=============================================================================================*/
  497. void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
  498. {
  499. assert(set_res );
  500. Matrix3D tmp;
  501. Matrix3D * Aptr;
  502. float tmp1,tmp2,tmp3;
  503. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  504. // result is going into 'A'. (in this case, this function is no better than
  505. // the overloaded C++ operator...)
  506. if (set_res == &A)
  507. {
  508. tmp = A;
  509. Aptr = &tmp;
  510. }
  511. else
  512. {
  513. Aptr = (Matrix3D *)&A;
  514. }
  515. tmp1 = B[0][0];
  516. tmp2 = B[1][0];
  517. tmp3 = B[2][0];
  518. (*set_res)[0][0] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  519. (*set_res)[1][0] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  520. (*set_res)[2][0] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  521. tmp1 = B[0][1];
  522. tmp2 = B[1][1];
  523. tmp3 = B[2][1];
  524. (*set_res)[0][1] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  525. (*set_res)[1][1] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  526. (*set_res)[2][1] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  527. tmp1 = B[0][2];
  528. tmp2 = B[1][2];
  529. tmp3 = B[2][2];
  530. (*set_res)[0][2] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3;
  531. (*set_res)[1][2] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3;
  532. (*set_res)[2][2] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3;
  533. tmp1 = B[0][3];
  534. tmp2 = B[1][3];
  535. tmp3 = B[2][3];
  536. (*set_res)[0][3] = (*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3];
  537. (*set_res)[1][3] = (*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3];
  538. (*set_res)[2][3] = (*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3];
  539. }
  540. /***********************************************************************************************
  541. * Matrix3D::Transform_Min_Max_AABox -- compute transformed axis-aligned box *
  542. * *
  543. * INPUT: *
  544. * *
  545. * OUTPUT: *
  546. * *
  547. * WARNINGS: *
  548. * *
  549. * HISTORY: *
  550. * 7/17/98 GTH : Created. *
  551. *=============================================================================================*/
  552. void Matrix3D::Transform_Min_Max_AABox
  553. (
  554. const Vector3 & min,
  555. const Vector3 & max,
  556. Vector3 * set_min,
  557. Vector3 * set_max
  558. ) const
  559. {
  560. assert(set_min != &min);
  561. assert(set_max != &max);
  562. float tmp0,tmp1;
  563. // init the min and max to the translation of the transform
  564. set_min->X = set_max->X = Row[0][3];
  565. set_min->Y = set_max->Y = Row[1][3];
  566. set_min->Z = set_max->Z = Row[2][3];
  567. // now push them both out by the projections of the original intervals
  568. for (int i=0; i<3; i++)
  569. {
  570. for (int j=0; j<3; j++)
  571. {
  572. tmp0 = Row[i][j] * min[j];
  573. tmp1 = Row[i][j] * max[j];
  574. if (tmp0 < tmp1)
  575. {
  576. (*set_min)[i] += tmp0;
  577. (*set_max)[i] += tmp1;
  578. }
  579. else
  580. {
  581. (*set_min)[i] += tmp1;
  582. (*set_max)[i] += tmp0;
  583. }
  584. }
  585. }
  586. }
  587. /***********************************************************************************************
  588. * Matrix3D::Transform_Center_Extent_AABox -- compute transformed axis-aligned box *
  589. * *
  590. * INPUT: *
  591. * *
  592. * OUTPUT: *
  593. * *
  594. * WARNINGS: *
  595. * *
  596. * HISTORY: *
  597. * 7/17/98 GTH : Created. *
  598. *=============================================================================================*/
  599. void Matrix3D::Transform_Center_Extent_AABox
  600. (
  601. const Vector3 & center,
  602. const Vector3 & extent,
  603. Vector3 * set_center,
  604. Vector3 * set_extent
  605. ) const
  606. {
  607. assert(set_center != &center);
  608. assert(set_extent != &extent);
  609. float tmp;
  610. // now push them both out by the projections of the original intervals
  611. for (int i=0; i<3; i++)
  612. {
  613. // start the center out at the translation portion of the matrix
  614. // and the extent at zero
  615. (*set_center)[i] = Row[i][3];
  616. (*set_extent)[i] = 0.0f;
  617. for (int j=0; j<3; j++)
  618. {
  619. (*set_center)[i] += Row[i][j] * center[j];
  620. tmp = Row[i][j] * extent[j];
  621. if (tmp > 0.0f)
  622. {
  623. (*set_extent)[i] += tmp;
  624. }
  625. else
  626. {
  627. (*set_extent)[i] -= tmp;
  628. }
  629. }
  630. }
  631. }
  632. /***********************************************************************************************
  633. * Matrix3D::Is_Orthogonal -- checks whether this matrix is orthogonal *
  634. * *
  635. * INPUT: *
  636. * *
  637. * OUTPUT: *
  638. * *
  639. * WARNINGS: *
  640. * *
  641. * HISTORY: *
  642. * 9/16/98 GTH : Created. *
  643. *=============================================================================================*/
  644. int Matrix3D::Is_Orthogonal(void) const
  645. {
  646. #if 0
  647. Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
  648. Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
  649. Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
  650. if (Vector3::Dot_Product(x,y) > EPSILON) return 0;
  651. if (Vector3::Dot_Product(y,z) > EPSILON) return 0;
  652. if (Vector3::Dot_Product(z,x) > EPSILON) return 0;
  653. if (Get_Float_ABS(x.Length() - 1.0f) > EPSILON) return 0;
  654. if (Get_Float_ABS(y.Length() - 1.0f) > EPSILON) return 0;
  655. if (Get_Float_ABS(z.Length() - 1.0f) > EPSILON) return 0;
  656. #endif
  657. return 1;
  658. }
  659. /***********************************************************************************************
  660. * Matrix3D::Re_Orthogonalize -- makes this matrix orthogonal. *
  661. * *
  662. * INPUT: *
  663. * *
  664. * OUTPUT: *
  665. * *
  666. * WARNINGS: *
  667. * This function is rather expensive, should only be used if you *know* numerical error is *
  668. * killing you. *
  669. * *
  670. * HISTORY: *
  671. * 9/16/98 GTH : Created. *
  672. *=============================================================================================*/
  673. void Matrix3D::Re_Orthogonalize(void)
  674. {
  675. Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
  676. Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
  677. Vector3 z;
  678. Vector3::Cross_Product(x,y,&z);
  679. Vector3::Cross_Product(z,x,&y);
  680. x*=1.0f / (float)sqrt(x.Length2());
  681. y*=1.0f / (float)sqrt(y.Length2());
  682. z*=1.0f / (float)sqrt(z.Length2());
  683. Row[0][0] = x.X;
  684. Row[0][1] = x.Y;
  685. Row[0][2] = x.Z;
  686. Row[1][0] = y.X;
  687. Row[1][1] = y.Y;
  688. Row[1][2] = y.Z;
  689. Row[2][0] = z.X;
  690. Row[2][1] = z.Y;
  691. Row[2][2] = z.Z;
  692. }
  693. #if 0
  694. void Matrix3D::Multiply(const Matrix3D & A,const Matrix3D & B,Matrix3D * set_res)
  695. {
  696. assert(set_res );
  697. #if 0
  698. Matrix3D tmpa = A;
  699. Matrix3D tmpb = B;
  700. *set_res = tmpa * tmpb;
  701. #else
  702. Matrix3D tmp;
  703. Matrix3D * Aptr;
  704. float tmp1,tmp2,tmp3;
  705. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  706. // result is going into 'A'. (in this case, this function is no better than
  707. // the overloaded C++ operator...)
  708. if (set_res == &A)
  709. {
  710. tmp = A;
  711. Aptr = &tmp;
  712. }
  713. else
  714. {
  715. Aptr = (Matrix3D *)&A;
  716. }
  717. tmp1 = B[0][0];
  718. tmp2 = B[1][0];
  719. tmp3 = B[2][0];
  720. #if 1
  721. (*set_res)[0][0] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  722. (*set_res)[1][0] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  723. // (*set_res)[2][0] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  724. #else
  725. (*set_res)[0][0] = (float)(Aptr->Row[0].X*tmp1 + Aptr->Row[0].Y*tmp2 + Aptr->Row[0].Z*tmp3);
  726. (*set_res)[1][0] = (float)(Aptr->Row[1].X*tmp1 + Aptr->Row[1].Y*tmp2 + Aptr->Row[1].Z*tmp3);
  727. (*set_res)[2][0] = (float)(Aptr->Row[2].X*tmp1 + Aptr->Row[2].Y*tmp2 + Aptr->Row[2].Z*tmp3);
  728. #endif
  729. // printf("tmp1 = %f\n",tmp1);
  730. // printf("B[0][0] = %f\n",B[0][0]);
  731. // printf("Row A: %f %f %f\n",Aptr->Row[0].X,Aptr->Row[0].Y,Aptr->Row[0].Z);
  732. // printf("Col B: %f %f %f\n",tmp1,tmp2,tmp3);
  733. // printf("tmp1 = %f\n",tmp1);
  734. // printf("B[0][0] = %f\n",B[0][0]);
  735. // (*set_res)[0][0] = Aptr->Row[0].X * tmp1 + Aptr->Row[0].Y * tmp2 + Aptr->Row[0].Z * tmp3;
  736. // printf("result: %f\n",(*set_res)[0][0]);
  737. //print_matrix(*set_res);
  738. tmp1 = B[0][1];
  739. tmp2 = B[1][1];
  740. tmp3 = B[2][1];
  741. (*set_res)[0][1] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  742. (*set_res)[1][1] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  743. (*set_res)[2][1] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  744. //print_matrix(*set_res);
  745. tmp1 = B[0][2];
  746. tmp2 = B[1][2];
  747. tmp3 = B[2][2];
  748. (*set_res)[0][2] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  749. (*set_res)[1][2] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  750. (*set_res)[2][2] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  751. //print_matrix(*set_res);
  752. tmp1 = B[0][3];
  753. tmp2 = B[1][3];
  754. tmp3 = B[2][3];
  755. (*set_res)[0][3] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3 + (*Aptr)[0][3]);
  756. (*set_res)[1][3] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3 + (*Aptr)[1][3]);
  757. (*set_res)[2][3] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3 + (*Aptr)[2][3]);
  758. //print_matrix(*set_res);
  759. #endif
  760. }
  761. #endif
  762. /***********************************************************************************************
  763. * Lerp - linearly interpolate matrices (orientation is slerped) *
  764. * *
  765. * INPUT: *
  766. * *
  767. * OUTPUT: *
  768. * *
  769. * WARNINGS: *
  770. * *
  771. * HISTORY: *
  772. * 10/05/1998 NH : Created. *
  773. *=============================================================================================*/
  774. Matrix3D Lerp(const Matrix3D &A, const Matrix3D &B, float factor)
  775. {
  776. assert(factor >= 0.0f);
  777. assert(factor <= 1.0f);
  778. // Lerp position
  779. Vector3 pos = Lerp(A.Get_Translation(), B.Get_Translation(), factor);
  780. Quaternion rot = Slerp(Build_Quaternion(A), Build_Quaternion(B), factor);
  781. return Matrix3D(rot, pos);
  782. }