matrix3.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D PS2 *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/W3DShellExt/External/matrix3.cpp $*
  25. * *
  26. * Programmer : Kenny Mitchell *
  27. * *
  28. * Start Date : 11/16/99 *
  29. * *
  30. * Last Update : 11/16/99 *
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Based on Greg Hjelstrom 97 *
  34. * Functions: *
  35. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  36. #include "matrix3.h"
  37. #include "matrix3d.h"
  38. #include "matrix4.h"
  39. #include "quat.h"
  40. /*
  41. ** Some pre-initialized Matrix3's
  42. */
  43. const Matrix3 Matrix3::Identity
  44. (
  45. 1.0f, 0.0f, 0.0f,
  46. 0.0f, 1.0f, 0.0f,
  47. 0.0f, 0.0f, 1.0f
  48. );
  49. const Matrix3 Matrix3::RotateX90
  50. (
  51. 1.0f, 0.0f, 0.0f,
  52. 0.0f, 0.0f, -1.0f,
  53. 0.0f, 1.0f, 0.0f
  54. );
  55. const Matrix3 Matrix3::RotateX180
  56. (
  57. 1.0f, 0.0f, 0.0f,
  58. 0.0f, -1.0f, 0.0f,
  59. 0.0f, 0.0f, -1.0f
  60. );
  61. const Matrix3 Matrix3::RotateX270
  62. (
  63. 1.0f, 0.0f, 0.0f,
  64. 0.0f, 0.0f, 1.0f,
  65. 0.0f, -1.0f, 0.0f
  66. );
  67. const Matrix3 Matrix3::RotateY90
  68. (
  69. 0.0f, 0.0f, 1.0f,
  70. 0.0f, 1.0f, 0.0f,
  71. -1.0f, 0.0f, 0.0f
  72. );
  73. const Matrix3 Matrix3::RotateY180
  74. (
  75. -1.0f, 0.0f, 0.0f,
  76. 0.0f, 1.0f, 0.0f,
  77. 0.0f, 0.0f, -1.0f
  78. );
  79. const Matrix3 Matrix3::RotateY270
  80. (
  81. 0.0f, 0.0f, -1.0f,
  82. 0.0f, 1.0f, 0.0f,
  83. 1.0f, 0.0f, 0.0f
  84. );
  85. const Matrix3 Matrix3::RotateZ90
  86. (
  87. 0.0f, -1.0f, 0.0f,
  88. 1.0f, 0.0f, 0.0f,
  89. 0.0f, 0.0f, 1.0f
  90. );
  91. const Matrix3 Matrix3::RotateZ180
  92. (
  93. -1.0f, 0.0f, 0.0f,
  94. 0.0f, -1.0f, 0.0f,
  95. 0.0f, 0.0f, 1.0f
  96. );
  97. const Matrix3 Matrix3::RotateZ270
  98. (
  99. 0.0f, 1.0f, 0.0f,
  100. -1.0f, 0.0f, 0.0f,
  101. 0.0f, 0.0f, 1.0f
  102. );
  103. /***********************************************************************************************
  104. * Matrix3::Matrix3 -- Convert a Matrix3D (fake 4x4) to a Matrix3 *
  105. * *
  106. * INPUT: *
  107. * *
  108. * OUTPUT: *
  109. * *
  110. * WARNINGS: *
  111. * *
  112. * HISTORY: *
  113. * 06/02/1997 GH : Created. *
  114. *=============================================================================================*/
  115. Matrix3::Matrix3(const Matrix3D & m)
  116. {
  117. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  118. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  119. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  120. }
  121. Matrix3::Matrix3(const Matrix4 & m)
  122. {
  123. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  124. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  125. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  126. }
  127. void Matrix3::Set(const Matrix3D & m)
  128. {
  129. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  130. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  131. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  132. }
  133. void Matrix3::Set(const Matrix4 & m)
  134. {
  135. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  136. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  137. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  138. }
  139. void Matrix3::Set(const Quaternion & q)
  140. {
  141. Row[0][0] = (float)(1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]));
  142. Row[0][1] = (float)(2.0f * (q[0] * q[1] - q[2] * q[3]));
  143. Row[0][2] = (float)(2.0f * (q[2] * q[0] + q[1] * q[3]));
  144. Row[1][0] = (float)(2.0f * (q[0] * q[1] + q[2] * q[3]));
  145. Row[1][1] = (float)(1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]));
  146. Row[1][2] = (float)(2.0f * (q[1] * q[2] - q[0] * q[3]));
  147. Row[2][0] = (float)(2.0f * (q[2] * q[0] - q[1] * q[3]));
  148. Row[2][1] = (float)(2.0f * (q[1] * q[2] + q[0] * q[3]));
  149. Row[2][2] =(float)(1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]));
  150. }
  151. Matrix3 & Matrix3::operator = (const Matrix3D & m)
  152. {
  153. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  154. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  155. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  156. return *this;
  157. }
  158. Matrix3 & Matrix3::operator = (const Matrix4 & m)
  159. {
  160. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  161. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  162. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  163. return *this;
  164. }
  165. void Matrix3::Multiply(const Matrix3D & a, const Matrix3 & b,Matrix3 * res)
  166. {
  167. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  168. (*res)[0][0] = ROWCOL(0,0);
  169. (*res)[0][1] = ROWCOL(0,1);
  170. (*res)[0][2] = ROWCOL(0,2);
  171. (*res)[1][0] = ROWCOL(1,0);
  172. (*res)[1][1] = ROWCOL(1,1);
  173. (*res)[1][2] = ROWCOL(1,2);
  174. (*res)[2][0] = ROWCOL(2,0);
  175. (*res)[2][1] = ROWCOL(2,1);
  176. (*res)[2][2] = ROWCOL(2,2);
  177. #undef ROWCOL
  178. }
  179. void Matrix3::Multiply(const Matrix3 & a, const Matrix3D & b,Matrix3 * res)
  180. {
  181. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  182. (*res)[0][0] = ROWCOL(0,0);
  183. (*res)[0][1] = ROWCOL(0,1);
  184. (*res)[0][2] = ROWCOL(0,2);
  185. (*res)[1][0] = ROWCOL(1,0);
  186. (*res)[1][1] = ROWCOL(1,1);
  187. (*res)[1][2] = ROWCOL(1,2);
  188. (*res)[2][0] = ROWCOL(2,0);
  189. (*res)[2][1] = ROWCOL(2,1);
  190. (*res)[2][2] = ROWCOL(2,2);
  191. #undef ROWCOL
  192. }
  193. Matrix3 operator * (const Matrix3D & a, const Matrix3 & b)
  194. {
  195. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  196. return Matrix3(
  197. Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
  198. Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
  199. Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
  200. );
  201. #undef ROWCOL
  202. }
  203. Matrix3 operator * (const Matrix3 & a, const Matrix3D & b)
  204. {
  205. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  206. return Matrix3(
  207. Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
  208. Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
  209. Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
  210. );
  211. #undef ROWCOL
  212. }
  213. #if 0
  214. void Matrix3::Compute_Jacobi_Rotation(int i,int j,Matrix3 * r,Matrix3 * rinv)
  215. {
  216. }
  217. void Matrix3::Symmetric_Eigen_Solve(void)
  218. {
  219. Matrix3 eigen_vals = *this;
  220. Matrix3 eigen_vecs(1);
  221. Matrix3 jr,jrinv;
  222. while (!done)
  223. {
  224. eigen_vals.Compute_Jacobi_Rotation(i,j,&jr,&jrinv);
  225. eigen_vals = jr * (eigenvals) * jrinv;
  226. eigen_vecs = eigen_vecs * jr;
  227. }
  228. /*
  229. ** Done! Eigen values are the diagonals of
  230. ** the eigen_vals matrix and the eigen vectors
  231. ** are the columns of the eigen_vecs matrix
  232. */
  233. }
  234. #endif
  235. void Matrix3::Multiply(const Matrix3 & A,const Matrix3 & B,Matrix3 * set_res)
  236. {
  237. Matrix3 tmp;
  238. Matrix3 * Aptr;
  239. float tmp1,tmp2,tmp3;
  240. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  241. // result is going into 'A'. (in this case, this function is no better than
  242. // the overloaded C++ operator...)
  243. if (set_res == &A)
  244. {
  245. tmp = A;
  246. Aptr = &tmp;
  247. }
  248. else
  249. {
  250. Aptr = (Matrix3 *)&A;
  251. }
  252. tmp1 = B[0][0];
  253. tmp2 = B[1][0];
  254. tmp3 = B[2][0];
  255. (*set_res)[0][0] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  256. (*set_res)[1][0] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  257. (*set_res)[2][0] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  258. tmp1 = B[0][1];
  259. tmp2 = B[1][1];
  260. tmp3 = B[2][1];
  261. (*set_res)[0][1] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  262. (*set_res)[1][1] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  263. (*set_res)[2][1] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  264. tmp1 = B[0][2];
  265. tmp2 = B[1][2];
  266. tmp3 = B[2][2];
  267. (*set_res)[0][2] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  268. (*set_res)[1][2] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  269. (*set_res)[2][2] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  270. }
  271. int Matrix3::Is_Orthogonal(void) const
  272. {
  273. Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
  274. Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
  275. Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
  276. #if 0
  277. if (Vector3::Dot_Product(x,y) > EPSILON) return 0;
  278. if (Vector3::Dot_Product(y,z) > EPSILON) return 0;
  279. if (Vector3::Dot_Product(z,x) > EPSILON) return 0;
  280. if (Get_Float_ABS(x.Length() - 1.0f) > EPSILON) return 0;
  281. if (Get_Float_ABS(y.Length() - 1.0f) > EPSILON) return 0;
  282. if (Get_Float_ABS(z.Length() - 1.0f) > EPSILON) return 0;
  283. #endif
  284. return 1;
  285. }
  286. void Matrix3::Re_Orthogonalize(void)
  287. {
  288. Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
  289. Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
  290. Vector3 z;
  291. Vector3::Cross_Product(x,y,&z);
  292. Vector3::Cross_Product(z,x,&y);
  293. #if 0
  294. x*=Inv_Sqrt(x.Length2());
  295. y*=Inv_Sqrt(y.Length2());
  296. z*=Inv_Sqrt(z.Length2());
  297. #endif
  298. Row[0][0] = x.X;
  299. Row[0][1] = x.Y;
  300. Row[0][2] = x.Z;
  301. Row[1][0] = y.X;
  302. Row[1][1] = y.Y;
  303. Row[1][2] = y.Z;
  304. Row[2][0] = z.X;
  305. Row[2][1] = z.Y;
  306. Row[2][2] = z.Z;
  307. }