matrix4.h 41 KB

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