matrix3d.cpp 40 KB

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