matrix4.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  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/matrix4.h 15 2/03/00 4:55p Jason_a $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : WW3D *
  24. * *
  25. * File Name : MATRIX4.H *
  26. * *
  27. * Programmer : Greg Hjelstrom *
  28. * *
  29. * Start Date : 06/02/97 *
  30. * *
  31. * Last Update : June 2, 1997 [GH] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Matrix4::Matrix4 -- Constructor, optionally initialize to Identitiy matrix *
  36. * Matrix4::Matrix4 -- Copy Constructor *
  37. * Matrix4::Matrix4 -- Convert a Matrix3D (fake 4x4) to a Matrix4 *
  38. * Matrix4::Matrix4 -- Constructor *
  39. * Matrix4::Make_Identity -- Initializes the matrix to Identity *
  40. * Matrix4::Init -- Initializes from the contents of the give Matrix3D *
  41. * Matrix4::Init -- Initializes the rows from the given Vector4s *
  42. * Matrix4::Init_Ortho -- Initialize to an orthographic projection matrix *
  43. * Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
  44. * Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
  45. * Matrix4::Transpose -- Returns transpose of the matrix *
  46. * Matrix4::Inverse -- returns the inverse of the matrix *
  47. * Matrix4::operator = -- assignment operator *
  48. * Matrix4::operator += -- "plus equals" operator *
  49. * Matrix4::operator-= -- "minus equals" operator *
  50. * Matrix4::operator *= -- "times equals" operator *
  51. * Matrix4::operator /= -- "divide equals" operator *
  52. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  53. #if defined(_MSC_VER)
  54. #pragma once
  55. #endif
  56. #ifndef MATRIX4_H
  57. #define MATRIX4_H
  58. #include "always.h"
  59. #include "vector4.h"
  60. #include "matrix3d.h"
  61. #include "wwmatrix3.h"
  62. class Matrix4
  63. {
  64. public:
  65. /*
  66. ** Constructors
  67. */
  68. Matrix4(void) {};
  69. Matrix4(const Matrix4 & m);
  70. explicit Matrix4(bool identity);
  71. explicit Matrix4(const Matrix3D & m);
  72. explicit Matrix4(const Matrix3 & m);
  73. explicit Matrix4(const Vector4 & v0, const Vector4 & v1, const Vector4 & v2, const Vector4 & v3);
  74. void Make_Identity(void);
  75. void Init(const Matrix3D & m);
  76. void Init(const Matrix3 & m);
  77. void Init(const Vector4 & v0, const Vector4 & v1, const Vector4 & v2, const Vector4 & v3);
  78. void Init_Ortho(float left,float right,float bottom,float top,float znear,float zfar);
  79. void Init_Perspective(float hfov,float vfov,float znear,float zfar);
  80. void Init_Perspective(float left,float right,float bottom,float top,float znear,float zfar);
  81. /*
  82. ** Access operators
  83. */
  84. Vector4 & operator [] (int i) { return Row[i]; }
  85. const Vector4 & operator [] (int i) const { return Row[i]; }
  86. /*
  87. ** Transpose and Inverse
  88. */
  89. Matrix4 Transpose(void) const;
  90. Matrix4 Inverse(void) const;
  91. /*
  92. ** Assignment operators
  93. */
  94. Matrix4 & operator = (const Matrix4 & m);
  95. Matrix4 & operator += (const Matrix4 & m);
  96. Matrix4 & operator -= (const Matrix4 & m);
  97. Matrix4 & operator *= (float d);
  98. Matrix4 & operator /= (float d);
  99. /*
  100. ** Negation
  101. */
  102. friend Matrix4 operator - (const Matrix4& a);
  103. /*
  104. ** Scalar multiplication and division
  105. */
  106. friend Matrix4 operator * (const Matrix4& a,float d);
  107. friend Matrix4 operator * (float d,const Matrix4& a);
  108. friend Matrix4 operator / (const Matrix4& a,float d);
  109. /*
  110. ** matrix addition
  111. */
  112. friend Matrix4 operator + (const Matrix4& a, const Matrix4& b);
  113. friend Matrix4 Add(const Matrix4& a);
  114. /*
  115. ** matrix subtraction
  116. */
  117. friend Matrix4 operator - (const Matrix4 & a, const Matrix4 & b);
  118. friend Matrix4 Subtract(const Matrix4 & a, const Matrix4 & b);
  119. /*
  120. ** matrix multiplication
  121. */
  122. friend Matrix4 operator * (const Matrix4 & a, const Matrix4 & b);
  123. friend Matrix4 Multiply(const Matrix4 & a, const Matrix4 & b);
  124. /*
  125. ** Comparison operators
  126. */
  127. friend int operator == (const Matrix4 & a, const Matrix4 & b);
  128. friend int operator != (const Matrix4 & a, const Matrix4 & b);
  129. /*
  130. ** Swap two matrices in place
  131. */
  132. friend void Swap(Matrix4 & a,Matrix4 & b);
  133. /*
  134. ** Linear Transforms
  135. */
  136. friend Vector4 operator * (const Matrix4 & a, const Vector4 & v);
  137. friend Vector4 operator * (const Matrix4 & a, const Vector3 & v);
  138. /*
  139. ** Matrix multiplication without temporaries...
  140. */
  141. static void Multiply(const Matrix4 &A,const Matrix4 &B,Matrix4 * set_result);
  142. static void Multiply(const Matrix3D &A,const Matrix4 &B,Matrix4 * set_result);
  143. static void Multiply(const Matrix4 &A,const Matrix3D &B,Matrix4 * set_result);
  144. static void Transform_Vector(const Matrix4 & tm,const Vector3 & in,Vector3 * out);
  145. protected:
  146. Vector4 Row[4];
  147. };
  148. /***********************************************************************************************
  149. * Matrix4::Matrix4 -- Constructor, optionally initialize to Identitiy matrix *
  150. * *
  151. * INPUT: *
  152. * *
  153. * OUTPUT: *
  154. * *
  155. * WARNINGS: *
  156. * *
  157. * HISTORY: *
  158. * 06/02/1997 GH : Created. *
  159. *=============================================================================================*/
  160. inline Matrix4::Matrix4(bool identity)
  161. {
  162. if (identity) {
  163. Make_Identity();
  164. }
  165. }
  166. /***********************************************************************************************
  167. * Matrix4::Matrix4 -- Copy Constructor *
  168. * *
  169. * INPUT: *
  170. * *
  171. * OUTPUT: *
  172. * *
  173. * WARNINGS: *
  174. * *
  175. * HISTORY: *
  176. * 06/02/1997 GH : Created. *
  177. *=============================================================================================*/
  178. inline Matrix4::Matrix4(const Matrix4 & m)
  179. {
  180. Row[0] = m.Row[0]; Row[1] = m.Row[1]; Row[2] = m.Row[2]; Row[3] = m.Row[3];
  181. }
  182. /***********************************************************************************************
  183. * Matrix4::Matrix4 -- Convert a Matrix3D (fake 4x4) to a Matrix4 *
  184. * *
  185. * INPUT: *
  186. * *
  187. * OUTPUT: *
  188. * *
  189. * WARNINGS: *
  190. * *
  191. * HISTORY: *
  192. * 06/02/1997 GH : Created. *
  193. *=============================================================================================*/
  194. inline Matrix4::Matrix4(const Matrix3D & m)
  195. {
  196. Init(m);
  197. }
  198. /***********************************************************************************************
  199. * Matrix4::Matrix4 -- Constructor *
  200. * *
  201. * INPUT: *
  202. * *
  203. * OUTPUT: *
  204. * *
  205. * WARNINGS: *
  206. * *
  207. * HISTORY: *
  208. * 06/02/1997 GH : Created. *
  209. *=============================================================================================*/
  210. inline Matrix4::Matrix4(const Vector4 & r0, const Vector4 & r1, const Vector4 & r2, const Vector4 & r3)
  211. {
  212. Init(r0,r1,r2,r3);
  213. }
  214. /***********************************************************************************************
  215. * Matrix4::Make_Identity -- Initializes the matrix to Identity *
  216. * *
  217. * INPUT: *
  218. * *
  219. * OUTPUT: *
  220. * *
  221. * WARNINGS: *
  222. * *
  223. * HISTORY: *
  224. * 11/5/99 gth : Created. *
  225. *=============================================================================================*/
  226. inline void Matrix4::Make_Identity(void)
  227. {
  228. Row[0].Set(1.0,0.0,0.0,0.0);
  229. Row[1].Set(0.0,1.0,0.0,0.0);
  230. Row[2].Set(0.0,0.0,1.0,0.0);
  231. Row[3].Set(0.0,0.0,0.0,1.0);
  232. }
  233. /***********************************************************************************************
  234. * Matrix4::Init -- Initializes from the contents of the give Matrix3D *
  235. * *
  236. * INPUT: *
  237. * *
  238. * OUTPUT: *
  239. * *
  240. * WARNINGS: *
  241. * *
  242. * HISTORY: *
  243. * 11/5/99 gth : Created. *
  244. *=============================================================================================*/
  245. inline void Matrix4::Init(const Matrix3D & m)
  246. {
  247. Row[0] = m[0]; Row[1] = m[1]; Row[2] = m[2]; Row[3] = Vector4(0.0,0.0,0.0,1.0);
  248. }
  249. /***********************************************************************************************
  250. * Matrix4::Init -- Initializes the rows from the given Vector4s *
  251. * *
  252. * INPUT: *
  253. * *
  254. * OUTPUT: *
  255. * *
  256. * WARNINGS: *
  257. * *
  258. * HISTORY: *
  259. * 11/5/99 gth : Created. *
  260. *=============================================================================================*/
  261. inline void Matrix4::Init(const Vector4 & r0, const Vector4 & r1, const Vector4 & r2, const Vector4 & r3)
  262. {
  263. Row[0] = r0; Row[1] = r1; Row[2] = r2; Row[3] = r3;
  264. }
  265. /***********************************************************************************************
  266. * Matrix4::Init_Ortho -- Initialize to an orthographic projection matrix *
  267. * *
  268. * You can find the formulas for this in the appendix of the OpenGL programming guide. Also *
  269. * this happens to be the same convention used by Surrender. *
  270. * *
  271. * The result of this projection will be that points inside the volume will have all coords *
  272. * between -1 and +1. A point at znear will project to z=-1. A point at zfar will project *
  273. * to z=+1... *
  274. * *
  275. * INPUT: *
  276. * *
  277. * OUTPUT: *
  278. * *
  279. * WARNINGS: *
  280. * Note that the znear and zfar parameters are positive distances to the clipping planes *
  281. * even though in the camera coordinate system, the clipping planes are at negative z *
  282. * coordinates. This holds for all of the projection initializations and is consistent *
  283. * with OpenGL's convention. *
  284. * *
  285. * HISTORY: *
  286. * 11/5/99 gth : Created. *
  287. *=============================================================================================*/
  288. inline void Matrix4::Init_Ortho
  289. (
  290. float left,
  291. float right,
  292. float bottom,
  293. float top,
  294. float znear,
  295. float zfar
  296. )
  297. {
  298. assert(znear >= 0.0f);
  299. assert(zfar > znear);
  300. Make_Identity();
  301. Row[0][0] = 2.0f / (right - left);
  302. Row[0][3] = -(right + left) / (right - left);
  303. Row[1][1] = 2.0f / (top - bottom);
  304. Row[1][3] = -(top + bottom) / (top - bottom);
  305. Row[2][2] = -2.0f / (zfar - znear);
  306. Row[2][3] = -(zfar + znear) / (zfar - znear);
  307. }
  308. /***********************************************************************************************
  309. * Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
  310. * *
  311. * You can find the formulas for this matrix in the appendix of the OpenGL programming guide. *
  312. * Also, this happens to be the same convention used by Surrender. *
  313. * *
  314. * INPUT: *
  315. * hfov - horizontal field of view (in radians) *
  316. * vfov - vertical field of view (in radians) *
  317. * znear - distance to near z clipping plane (positive) *
  318. * zfar - distance to the far z clipping plane (positive) *
  319. * *
  320. * OUTPUT: *
  321. * *
  322. * WARNINGS: *
  323. * Note that the znear and zfar parameters are positive distances to the clipping planes *
  324. * even though in the camera coordinate system, the clipping planes are at negative z *
  325. * coordinates. This holds for all of the projection initializations and is consistent *
  326. * with OpenGL's convention. *
  327. * *
  328. * HISTORY: *
  329. * 11/5/99 gth : Created. *
  330. *=============================================================================================*/
  331. inline void Matrix4::Init_Perspective(float hfov,float vfov,float znear,float zfar)
  332. {
  333. assert(znear > 0.0f);
  334. assert(zfar > znear);
  335. Make_Identity();
  336. Row[0][0] = (1.0 / tan(hfov*0.5));
  337. Row[1][1] = (1.0 / tan(vfov*0.5));
  338. Row[2][2] = -(zfar + znear) / (zfar - znear);
  339. Row[2][3] = -(2.0*zfar*znear) / (zfar - znear);
  340. Row[3][2] = -1.0f;
  341. Row[3][3] = 0.0f;
  342. }
  343. /***********************************************************************************************
  344. * Matrix4::Init_Perspective -- Initialize to a perspective projection matrix *
  345. * *
  346. * You can find the formulas for this matrix in the appendix of the OpenGL programming guide. *
  347. * Also, this happens to be the same convention used by Surrender. *
  348. * *
  349. * INPUT: *
  350. * *
  351. * OUTPUT: *
  352. * *
  353. * WARNINGS: *
  354. * Note that the znear and zfar parameters are positive distances to the clipping planes *
  355. * even though in the camera coordinate system, the clipping planes are at negative z *
  356. * coordinates. This holds for all of the projection initializations and is consistent *
  357. * with OpenGL's convention. *
  358. * *
  359. * HISTORY: *
  360. * 11/5/99 gth : Created. *
  361. *=============================================================================================*/
  362. inline void Matrix4::Init_Perspective
  363. (
  364. float left,
  365. float right,
  366. float bottom,
  367. float top,
  368. float znear,
  369. float zfar
  370. )
  371. {
  372. assert(znear > 0.0f);
  373. assert(zfar > 0.0f);
  374. Make_Identity();
  375. Row[0][0] = 2.0*znear / (right - left);
  376. Row[0][2] = (right + left) / (right - left);
  377. Row[1][1] = 2.0*znear / (top - bottom);
  378. Row[1][2] = (top + bottom) / (top - bottom);
  379. Row[2][2] = -(zfar + znear) / (zfar - znear);
  380. Row[2][3] = -(2.0*zfar*znear) / (zfar - znear);
  381. Row[3][2] = -1.0f;
  382. Row[3][3] = 0.0f;
  383. }
  384. /***********************************************************************************************
  385. * Matrix4::Transpose -- Returns transpose of the matrix *
  386. * *
  387. * INPUT: *
  388. * *
  389. * OUTPUT: *
  390. * *
  391. * WARNINGS: *
  392. * *
  393. * HISTORY: *
  394. * 06/02/1997 GH : Created. *
  395. *=============================================================================================*/
  396. inline Matrix4 Matrix4::Transpose() const
  397. {
  398. return Matrix4(
  399. Vector4(Row[0][0], Row[1][0], Row[2][0], Row[3][0]),
  400. Vector4(Row[0][1], Row[1][1], Row[2][1], Row[3][1]),
  401. Vector4(Row[0][2], Row[1][2], Row[2][2], Row[3][2]),
  402. Vector4(Row[0][3], Row[1][3], Row[2][3], Row[3][3])
  403. );
  404. }
  405. /***********************************************************************************************
  406. * Matrix4::Inverse -- returns the inverse of the matrix *
  407. * *
  408. * INPUT: *
  409. * *
  410. * OUTPUT: *
  411. * *
  412. * WARNINGS: *
  413. * *
  414. * HISTORY: *
  415. * 06/02/1997 GH : Created. *
  416. *=============================================================================================*/
  417. inline Matrix4 Matrix4::Inverse() const // Gauss-Jordan elimination with partial pivoting
  418. {
  419. Matrix4 a(*this); // As a evolves from original mat into identity
  420. Matrix4 b(true); // b evolves from identity into inverse(a)
  421. int i, j, i1;
  422. // Loop over cols of a from left to right, eliminating above and below diagonal
  423. for (j=0; j<4; j++) {
  424. // Find largest pivot in column j among rows j..3
  425. i1 = j;
  426. for (i=j+1; i<4; i++) {
  427. if (WWMath::Fabs(a[i][j]) > WWMath::Fabs(a[i1][j])) {
  428. i1 = i;
  429. }
  430. }
  431. // Swap rows i1 and j in a and b to put pivot on diagonal
  432. Swap(a.Row[i1], a.Row[j]);
  433. Swap(b.Row[i1], b.Row[j]);
  434. // Scale row j to have a unit diagonal
  435. if (a[j][j]==0.) {
  436. //ALGEBRA_ERROR("Matrix4::inverse: singular matrix; can't invert\n");
  437. }
  438. b.Row[j] /= a.Row[j][j];
  439. a.Row[j] /= a.Row[j][j];
  440. // Eliminate off-diagonal elems in col j of a, doing identical ops to b
  441. for (i=0; i<4; i++) {
  442. if (i != j) {
  443. b.Row[i] -= a[i][j] * b.Row[j];
  444. a.Row[i] -= a[i][j] * a.Row[j];
  445. }
  446. }
  447. }
  448. return b;
  449. }
  450. /***********************************************************************************************
  451. * Matrix4::operator = -- assignment operator *
  452. * *
  453. * INPUT: *
  454. * *
  455. * OUTPUT: *
  456. * *
  457. * WARNINGS: *
  458. * *
  459. * HISTORY: *
  460. * 06/02/1997 GH : Created. *
  461. *=============================================================================================*/
  462. inline Matrix4 & Matrix4::operator = (const Matrix4 & m)
  463. {
  464. Row[0] = m.Row[0]; Row[1] = m.Row[1]; Row[2] = m.Row[2]; Row[3] = m.Row[3];
  465. return *this;
  466. }
  467. /***********************************************************************************************
  468. * Matrix4::operator += -- "plus equals" operator *
  469. * *
  470. * INPUT: *
  471. * *
  472. * OUTPUT: *
  473. * *
  474. * WARNINGS: *
  475. * *
  476. * HISTORY: *
  477. * 06/02/1997 GH : Created. *
  478. *=============================================================================================*/
  479. inline Matrix4& Matrix4::operator += (const Matrix4 & m)
  480. {
  481. Row[0] += m.Row[0]; Row[1] += m.Row[1]; Row[2] += m.Row[2]; Row[3] += m.Row[3];
  482. return *this;
  483. }
  484. /***********************************************************************************************
  485. * Matrix4::operator-= -- "minus equals" operator *
  486. * *
  487. * INPUT: *
  488. * *
  489. * OUTPUT: *
  490. * *
  491. * WARNINGS: *
  492. * *
  493. * HISTORY: *
  494. * 06/02/1997 GH : Created. *
  495. *=============================================================================================*/
  496. inline Matrix4& Matrix4::operator -= (const Matrix4 & m)
  497. {
  498. Row[0] -= m.Row[0]; Row[1] -= m.Row[1]; Row[2] -= m.Row[2]; Row[3] -= m.Row[3];
  499. return *this;
  500. }
  501. /***********************************************************************************************
  502. * Matrix4::operator *= -- "times equals" operator *
  503. * *
  504. * INPUT: *
  505. * *
  506. * OUTPUT: *
  507. * *
  508. * WARNINGS: *
  509. * *
  510. * HISTORY: *
  511. * 06/02/1997 GH : Created. *
  512. *=============================================================================================*/
  513. inline Matrix4& Matrix4::operator *= (float d)
  514. {
  515. Row[0] *= d; Row[1] *= d; Row[2] *= d; Row[3] *= d;
  516. return *this;
  517. }
  518. /***********************************************************************************************
  519. * Matrix4::operator /= -- "divide equals" operator *
  520. * *
  521. * INPUT: *
  522. * *
  523. * OUTPUT: *
  524. * *
  525. * WARNINGS: *
  526. * *
  527. * HISTORY: *
  528. * 06/02/1997 GH : Created. *
  529. *=============================================================================================*/
  530. inline Matrix4& Matrix4::operator /= (float d)
  531. {
  532. float ood = d;
  533. Row[0] *= ood; Row[1] *= ood; Row[2] *= ood; Row[3] *= ood;
  534. return *this;
  535. }
  536. inline Matrix4 operator - (const Matrix4 & a)
  537. {
  538. return Matrix4(-a.Row[0], -a.Row[1], -a.Row[2], -a.Row[3]);
  539. }
  540. inline Matrix4 operator * (const Matrix4 & a, float d)
  541. {
  542. return Matrix4(a.Row[0] * d, a.Row[1] * d, a.Row[2] * d, a.Row[3] * d);
  543. }
  544. inline Matrix4 operator * (float d, const Matrix4 & a)
  545. {
  546. return a*d;
  547. }
  548. inline Matrix4 operator / (const Matrix4 & a, float d)
  549. {
  550. float ood = 1.0f / d;
  551. return Matrix4(a.Row[0] * ood, a.Row[1] * ood, a.Row[2] * ood, a.Row[3] * ood);
  552. }
  553. /*
  554. ** matrix addition
  555. */
  556. inline Matrix4 operator + (const Matrix4 & a, const Matrix4 & b)
  557. {
  558. return Matrix4(
  559. a.Row[0] + b.Row[0],
  560. a.Row[1] + b.Row[1],
  561. a.Row[2] + b.Row[2],
  562. a.Row[3] + b.Row[3]
  563. );
  564. }
  565. inline Matrix4 Add(const Matrix4 & a, const Matrix4 & b)
  566. { return a+b; }
  567. /*
  568. ** matrix subtraction
  569. */
  570. inline Matrix4 operator - (const Matrix4 & a, const Matrix4 & b)
  571. {
  572. return Matrix4(
  573. a.Row[0] - b.Row[0],
  574. a.Row[1] - b.Row[1],
  575. a.Row[2] - b.Row[2],
  576. a.Row[3] - b.Row[3]
  577. );
  578. }
  579. inline Matrix4 Subtract(const Matrix4 & a, const Matrix4 & b)
  580. { return a-b; }
  581. /*
  582. ** matrix multiplication
  583. */
  584. inline Matrix4 operator * (const Matrix4 & a, const Matrix4 & b)
  585. {
  586. #define ROWCOL(i, j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j]
  587. return Matrix4(
  588. Vector4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
  589. Vector4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
  590. Vector4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
  591. Vector4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
  592. );
  593. #undef ROWCOL
  594. }
  595. inline Matrix4 Multiply(const Matrix4 & a, const Matrix4 & b)
  596. { return a*b; }
  597. /*
  598. ** Multiply a Matrix4 by a Vector3 (assumes w=1.0!!!). Yeilds a Vector4 result
  599. */
  600. inline Vector4 operator * (const Matrix4 & a, const Vector3 & v) {
  601. return Vector4(
  602. a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2] + a[0][3] * 1.0,
  603. a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2] + a[1][3] * 1.0,
  604. a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2] + a[2][3] * 1.0,
  605. a[3][0] * v[0] + a[3][1] * v[1] + a[3][2] * v[2] + a[3][3] * 1.0
  606. );
  607. }
  608. /*
  609. ** Multiply a Matrix4 by a Vector4
  610. */
  611. inline Vector4 operator * (const Matrix4 & a, const Vector4 & v) {
  612. return Vector4(
  613. a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2] + a[0][3] * v[3],
  614. a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2] + a[1][3] * v[3],
  615. a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2] + a[2][3] * v[3],
  616. a[3][0] * v[0] + a[3][1] * v[1] + a[3][2] * v[2] + a[3][3] * v[3]
  617. );
  618. }
  619. /*
  620. ** Multiply a Matrix4 by a Vector4
  621. */
  622. inline void Matrix4::Transform_Vector(const Matrix4 & A,const Vector3 & in,Vector3 * out)
  623. {
  624. Vector3 tmp;
  625. Vector3 * v;
  626. // check for aliased parameters
  627. if (out == &in) {
  628. tmp = in;
  629. v = &tmp;
  630. } else {
  631. v = (Vector3 *)&in; // whats the right way to do this...
  632. }
  633. out->X = (A[0][0] * v->X + A[0][1] * v->Y + A[0][2] * v->Z + A[0][3]);
  634. out->Y = (A[1][0] * v->X + A[1][1] * v->Y + A[1][2] * v->Z + A[1][3]);
  635. out->Z = (A[2][0] * v->X + A[2][1] * v->Y + A[2][2] * v->Z + A[2][3]);
  636. }
  637. #endif /*MATRIX4_H*/