matrix3.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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. /***********************************************************************************************
  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 : WWMath *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/matrix3.cpp $*
  25. * *
  26. * Org Author:: Greg_h *
  27. * *
  28. * Author : Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 17 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #include "matrix3.h"
  39. #include "matrix3d.h"
  40. #include "matrix4.h"
  41. #include "quat.h"
  42. /*
  43. ** Some pre-initialized Matrix3x3's
  44. */
  45. const Matrix3x3 Matrix3x3::Identity
  46. (
  47. 1.0, 0.0, 0.0,
  48. 0.0, 1.0, 0.0,
  49. 0.0, 0.0, 1.0
  50. );
  51. const Matrix3x3 Matrix3x3::RotateX90
  52. (
  53. 1.0, 0.0, 0.0,
  54. 0.0, 0.0, -1.0,
  55. 0.0, 1.0, 0.0
  56. );
  57. const Matrix3x3 Matrix3x3::RotateX180
  58. (
  59. 1.0, 0.0, 0.0,
  60. 0.0, -1.0, 0.0,
  61. 0.0, 0.0, -1.0
  62. );
  63. const Matrix3x3 Matrix3x3::RotateX270
  64. (
  65. 1.0, 0.0, 0.0,
  66. 0.0, 0.0, 1.0,
  67. 0.0, -1.0, 0.0
  68. );
  69. const Matrix3x3 Matrix3x3::RotateY90
  70. (
  71. 0.0, 0.0, 1.0,
  72. 0.0, 1.0, 0.0,
  73. -1.0, 0.0, 0.0
  74. );
  75. const Matrix3x3 Matrix3x3::RotateY180
  76. (
  77. -1.0, 0.0, 0.0,
  78. 0.0, 1.0, 0.0,
  79. 0.0, 0.0, -1.0
  80. );
  81. const Matrix3x3 Matrix3x3::RotateY270
  82. (
  83. 0.0, 0.0, -1.0,
  84. 0.0, 1.0, 0.0,
  85. 1.0, 0.0, 0.0
  86. );
  87. const Matrix3x3 Matrix3x3::RotateZ90
  88. (
  89. 0.0, -1.0, 0.0,
  90. 1.0, 0.0, 0.0,
  91. 0.0, 0.0, 1.0
  92. );
  93. const Matrix3x3 Matrix3x3::RotateZ180
  94. (
  95. -1.0, 0.0, 0.0,
  96. 0.0, -1.0, 0.0,
  97. 0.0, 0.0, 1.0
  98. );
  99. const Matrix3x3 Matrix3x3::RotateZ270
  100. (
  101. 0.0, 1.0, 0.0,
  102. -1.0, 0.0, 0.0,
  103. 0.0, 0.0, 1.0
  104. );
  105. /***********************************************************************************************
  106. * Matrix3x3::Matrix3x3 -- Convert a Matrix3D (fake 4x4) to a Matrix3x3 *
  107. * *
  108. * INPUT: *
  109. * *
  110. * OUTPUT: *
  111. * *
  112. * WARNINGS: *
  113. * *
  114. * HISTORY: *
  115. * 06/02/1997 GH : Created. *
  116. *=============================================================================================*/
  117. Matrix3x3::Matrix3x3(const Matrix3D & m)
  118. {
  119. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  120. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  121. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  122. }
  123. Matrix3x3::Matrix3x3(const Matrix4x4 & m)
  124. {
  125. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  126. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  127. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  128. }
  129. void Matrix3x3::Set(const Matrix3D & m)
  130. {
  131. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  132. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  133. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  134. }
  135. void Matrix3x3::Set(const Matrix4x4 & m)
  136. {
  137. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  138. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  139. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  140. }
  141. void Matrix3x3::Set(const Quaternion & q)
  142. {
  143. Row[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
  144. Row[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
  145. Row[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
  146. Row[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
  147. Row[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
  148. Row[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
  149. Row[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
  150. Row[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
  151. Row[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
  152. }
  153. Matrix3x3 & Matrix3x3::operator = (const Matrix3D & m)
  154. {
  155. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  156. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  157. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  158. return *this;
  159. }
  160. Matrix3x3 & Matrix3x3::operator = (const Matrix4x4 & m)
  161. {
  162. Row[0].Set(m[0][0],m[0][1],m[0][2]);
  163. Row[1].Set(m[1][0],m[1][1],m[1][2]);
  164. Row[2].Set(m[2][0],m[2][1],m[2][2]);
  165. return *this;
  166. }
  167. void Matrix3x3::Multiply(const Matrix3D & a, const Matrix3x3 & b,Matrix3x3 * res)
  168. {
  169. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  170. (*res)[0][0] = ROWCOL(0,0);
  171. (*res)[0][1] = ROWCOL(0,1);
  172. (*res)[0][2] = ROWCOL(0,2);
  173. (*res)[1][0] = ROWCOL(1,0);
  174. (*res)[1][1] = ROWCOL(1,1);
  175. (*res)[1][2] = ROWCOL(1,2);
  176. (*res)[2][0] = ROWCOL(2,0);
  177. (*res)[2][1] = ROWCOL(2,1);
  178. (*res)[2][2] = ROWCOL(2,2);
  179. #undef ROWCOL
  180. }
  181. void Matrix3x3::Multiply(const Matrix3x3 & a, const Matrix3D & b,Matrix3x3 * res)
  182. {
  183. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  184. (*res)[0][0] = ROWCOL(0,0);
  185. (*res)[0][1] = ROWCOL(0,1);
  186. (*res)[0][2] = ROWCOL(0,2);
  187. (*res)[1][0] = ROWCOL(1,0);
  188. (*res)[1][1] = ROWCOL(1,1);
  189. (*res)[1][2] = ROWCOL(1,2);
  190. (*res)[2][0] = ROWCOL(2,0);
  191. (*res)[2][1] = ROWCOL(2,1);
  192. (*res)[2][2] = ROWCOL(2,2);
  193. #undef ROWCOL
  194. }
  195. Matrix3x3 operator * (const Matrix3D & a, const Matrix3x3 & b)
  196. {
  197. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  198. return Matrix3x3(
  199. Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
  200. Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
  201. Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
  202. );
  203. #undef ROWCOL
  204. }
  205. Matrix3x3 operator * (const Matrix3x3 & a, const Matrix3D & b)
  206. {
  207. #define ROWCOL(i,j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
  208. return Matrix3x3(
  209. Vector3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2) ),
  210. Vector3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2) ),
  211. Vector3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2) )
  212. );
  213. #undef ROWCOL
  214. }
  215. #if 0
  216. void Matrix3x3::Compute_Jacobi_Rotation(int i,int j,Matrix3x3 * r,Matrix3x3 * rinv)
  217. {
  218. }
  219. void Matrix3x3::Symmetric_Eigen_Solve(void)
  220. {
  221. Matrix3x3 eigen_vals = *this;
  222. Matrix3x3 eigen_vecs(1);
  223. Matrix3x3 jr,jrinv;
  224. while (!done) {
  225. eigen_vals.Compute_Jacobi_Rotation(i,j,&jr,&jrinv);
  226. eigen_vals = jr * (eigenvals) * jrinv;
  227. eigen_vecs = eigen_vecs * jr;
  228. }
  229. /*
  230. ** Done! Eigen values are the diagonals of
  231. ** the eigen_vals matrix and the eigen vectors
  232. ** are the columns of the eigen_vecs matrix
  233. */
  234. }
  235. #endif
  236. void Matrix3x3::Multiply(const Matrix3x3 & A,const Matrix3x3 & B,Matrix3x3 * set_res)
  237. {
  238. Matrix3x3 tmp;
  239. Matrix3x3 * Aptr;
  240. float tmp1,tmp2,tmp3;
  241. // Check for aliased parameters, copy the 'A' matrix into a temporary if the
  242. // result is going into 'A'. (in this case, this function is no better than
  243. // the overloaded C++ operator...)
  244. if (set_res == &A) {
  245. tmp = A;
  246. Aptr = &tmp;
  247. } else {
  248. Aptr = (Matrix3x3 *)&A;
  249. }
  250. tmp1 = B[0][0];
  251. tmp2 = B[1][0];
  252. tmp3 = B[2][0];
  253. (*set_res)[0][0] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  254. (*set_res)[1][0] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  255. (*set_res)[2][0] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  256. tmp1 = B[0][1];
  257. tmp2 = B[1][1];
  258. tmp3 = B[2][1];
  259. (*set_res)[0][1] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  260. (*set_res)[1][1] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  261. (*set_res)[2][1] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  262. tmp1 = B[0][2];
  263. tmp2 = B[1][2];
  264. tmp3 = B[2][2];
  265. (*set_res)[0][2] = (float)((*Aptr)[0][0]*tmp1 + (*Aptr)[0][1]*tmp2 + (*Aptr)[0][2]*tmp3);
  266. (*set_res)[1][2] = (float)((*Aptr)[1][0]*tmp1 + (*Aptr)[1][1]*tmp2 + (*Aptr)[1][2]*tmp3);
  267. (*set_res)[2][2] = (float)((*Aptr)[2][0]*tmp1 + (*Aptr)[2][1]*tmp2 + (*Aptr)[2][2]*tmp3);
  268. }
  269. int Matrix3x3::Is_Orthogonal(void) const
  270. {
  271. Vector3 x(Row[0].X,Row[0].Y,Row[0].Z);
  272. Vector3 y(Row[1].X,Row[1].Y,Row[1].Z);
  273. Vector3 z(Row[2].X,Row[2].Y,Row[2].Z);
  274. if (Vector3::Dot_Product(x,y) > WWMATH_EPSILON) return 0;
  275. if (Vector3::Dot_Product(y,z) > WWMATH_EPSILON) return 0;
  276. if (Vector3::Dot_Product(z,x) > WWMATH_EPSILON) return 0;
  277. if (WWMath::Fabs(x.Length() - 1.0f) > WWMATH_EPSILON) return 0;
  278. if (WWMath::Fabs(y.Length() - 1.0f) > WWMATH_EPSILON) return 0;
  279. if (WWMath::Fabs(z.Length() - 1.0f) > WWMATH_EPSILON) return 0;
  280. return 1;
  281. }
  282. void Matrix3x3::Re_Orthogonalize(void)
  283. {
  284. Vector3 x(Row[0][0],Row[0][1],Row[0][2]);
  285. Vector3 y(Row[1][0],Row[1][1],Row[1][2]);
  286. Vector3 z;
  287. Vector3::Cross_Product(x,y,&z);
  288. Vector3::Cross_Product(z,x,&y);
  289. float len = x.Length();
  290. if (len < WWMATH_EPSILON) {
  291. Make_Identity();
  292. return;
  293. } else {
  294. x /= len;
  295. }
  296. len = y.Length();
  297. if (len < WWMATH_EPSILON) {
  298. Make_Identity();
  299. return;
  300. } else {
  301. y /= len;
  302. }
  303. len = z.Length();
  304. if (len < WWMATH_EPSILON) {
  305. Make_Identity();
  306. return;
  307. } else {
  308. z /= len;
  309. }
  310. Row[0][0] = x.X;
  311. Row[0][1] = x.Y;
  312. Row[0][2] = x.Z;
  313. Row[1][0] = y.X;
  314. Row[1][1] = y.Y;
  315. Row[1][2] = y.Z;
  316. Row[2][0] = z.X;
  317. Row[2][1] = z.Y;
  318. Row[2][2] = z.Z;
  319. }