WWmatrix3.cpp 11 KB

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