matrix4.h 45 KB

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