sr_util.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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/ww3d2/sr_util.cpp 3 2/06/01 6:18p Greg_h $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Commando / G 3D Library *
  24. * *
  25. * $Archive:: /Commando/Code/ww3d2/sr_util.cpp $*
  26. * *
  27. * Author:: Greg_h *
  28. * *
  29. * $Modtime:: 2/06/01 2:51p $*
  30. * *
  31. * $Revision:: 3 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Set_SR_Transform -- copies our object transform into a Surrender object *
  36. * Set_SR_Camera_Transform -- copies our camera transform into a Surrender object *
  37. * Get_SR_Camera_Transform -- creates a Matrix3D from a surrender camera transform *
  38. * Get_SR_Transform -- Creates a Matrix3D from a surrender object transform *
  39. * Get_Camera_Frustum_Corners -- Returns 8 camera frustum corner points. *
  40. * Get_ZClamped_Camera_Frustum_Corners -- Gets zclamped frustum corners. *
  41. * Push_Multiply_Westwood_Matrix -- push and multiply a matrix into the gerd *
  42. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  43. #include "sr_util.h"
  44. #include "wwdebug.h"
  45. #include "camera.h"
  46. #include "matrix4.h"
  47. #ifdef WW3D_DX8
  48. #include <srNode.hpp>
  49. #include <srCamera.hpp>
  50. #include <srMeshModel.hpp>
  51. #include <srGERD.hpp>
  52. /***********************************************************************************************
  53. * Set_SR_Transform -- copies our object transform into a Surrender object *
  54. * *
  55. * INPUT: *
  56. * *
  57. * OUTPUT: *
  58. * *
  59. * WARNINGS: *
  60. * *
  61. * HISTORY: *
  62. * 08/11/1997 GH : Created. *
  63. *=============================================================================================*/
  64. void Set_SR_Transform(srNode * obj,const Matrix3D & tm)
  65. {
  66. srMatrix3 srtm;
  67. obj->setLocation(tm[0][3], tm[1][3], tm[2][3]);
  68. srtm[0][0] = tm[0][0];
  69. srtm[0][1] = tm[0][1];
  70. srtm[0][2] = tm[0][2];
  71. srtm[1][0] = tm[1][0];
  72. srtm[1][1] = tm[1][1];
  73. srtm[1][2] = tm[1][2];
  74. srtm[2][0] = tm[2][0];
  75. srtm[2][1] = tm[2][1];
  76. srtm[2][2] = tm[2][2];
  77. obj->setRotation(srtm);
  78. }
  79. /***********************************************************************************************
  80. * Get_SR_Transform -- Creates a Matrix3D from a surrender object transform *
  81. * *
  82. * INPUT: *
  83. * *
  84. * OUTPUT: *
  85. * *
  86. * WARNINGS: *
  87. * *
  88. * HISTORY: *
  89. * 11/3/97 GTH : Created. *
  90. *=============================================================================================*/
  91. Matrix3D Get_SR_Transform(srNode * obj)
  92. {
  93. Matrix3D tm;
  94. srVector3 pos = obj->getLocation();
  95. srMatrix3 rot;
  96. obj->getRotation(rot);
  97. tm[0][3] = pos[0];
  98. tm[1][3] = pos[1];
  99. tm[2][3] = pos[2];
  100. tm[0][0] = rot[0][0];
  101. tm[0][1] = rot[0][1];
  102. tm[0][2] = rot[0][2];
  103. tm[1][0] = rot[1][0];
  104. tm[1][1] = rot[1][1];
  105. tm[1][2] = rot[1][2];
  106. tm[2][0] = rot[2][0];
  107. tm[2][1] = rot[2][1];
  108. tm[2][2] = rot[2][2];
  109. return(tm);
  110. }
  111. /***********************************************************************************************
  112. * Set_SR_Camera_Transform -- copies our camera transform into a Surrender object *
  113. * *
  114. * INPUT: *
  115. * *
  116. * OUTPUT: *
  117. * *
  118. * WARNINGS: *
  119. * *
  120. * HISTORY: *
  121. * 08/11/1997 GH : Created. *
  122. *=============================================================================================*/
  123. void Set_SR_Camera_Transform(srCamera * obj,const Matrix3D & transform)
  124. {
  125. srMatrix3 srtm;
  126. Matrix3D tm = transform;
  127. obj->setLocation(tm[0][3], tm[1][3], tm[2][3]);
  128. srtm[0][0] = tm[0][0];
  129. srtm[0][1] = tm[0][1];
  130. srtm[0][2] = -tm[0][2];
  131. srtm[1][0] = tm[1][0];
  132. srtm[1][1] = tm[1][1];
  133. srtm[1][2] = -tm[1][2];
  134. srtm[2][0] = tm[2][0];
  135. srtm[2][1] = tm[2][1];
  136. srtm[2][2] = -tm[2][2];
  137. obj->setRotation(srtm);
  138. }
  139. /***********************************************************************************************
  140. * Get_SR_Camera_Transform -- creates a Matrix3D from a surrender camera transform *
  141. * *
  142. * INPUT: *
  143. * *
  144. * OUTPUT: *
  145. * *
  146. * WARNINGS: *
  147. * *
  148. * HISTORY: *
  149. * 11/3/97 GTH : Created. *
  150. *=============================================================================================*/
  151. Matrix3D Get_SR_Camera_Transform(srCamera * obj)
  152. {
  153. Matrix3D tm;
  154. tm[0][3] = obj->getLocationX();
  155. tm[1][3] = obj->getLocationY();
  156. tm[2][3] = obj->getLocationZ();
  157. srMatrix3 srtm;
  158. obj->getRotation(srtm);
  159. tm[0][0] = srtm[0][0];
  160. tm[0][1] = srtm[0][1];
  161. tm[0][2] = -srtm[0][2];
  162. tm[1][0] = srtm[1][0];
  163. tm[1][1] = srtm[1][1];
  164. tm[1][2] = -srtm[1][2];
  165. tm[2][0] = srtm[2][0];
  166. tm[2][1] = srtm[2][1];
  167. tm[2][2] = -srtm[2][2];
  168. return tm;
  169. }
  170. /***********************************************************************************************
  171. * Push_Multiply_Westwood_Matrix -- push and multiply a matrix into the gerd *
  172. * *
  173. * INPUT: *
  174. * *
  175. * OUTPUT: *
  176. * *
  177. * WARNINGS: *
  178. * *
  179. * HISTORY: *
  180. * 12/10/98 GTH : Created. *
  181. *=============================================================================================*/
  182. void Push_Multiply_Westwood_Matrix(srGERD * gerd,const Matrix3D & tm)
  183. {
  184. WWASSERT(gerd);
  185. gerd->matrixMode(srGERD::MODELVIEW);
  186. srMatrix4x3 srtm;
  187. Convert_Westwood_Matrix(tm,&srtm);
  188. gerd->pushMultMatrix(srtm);
  189. }
  190. void Convert_Westwood_Matrix(const Matrix3D & tm,srMatrix4 * set_sr_tm)
  191. {
  192. (*set_sr_tm)[0][0] = tm[0][0];
  193. (*set_sr_tm)[0][1] = tm[0][1];
  194. (*set_sr_tm)[0][2] = tm[0][2];
  195. (*set_sr_tm)[0][3] = tm[0][3];
  196. (*set_sr_tm)[1][0] = tm[1][0];
  197. (*set_sr_tm)[1][1] = tm[1][1];
  198. (*set_sr_tm)[1][2] = tm[1][2];
  199. (*set_sr_tm)[1][3] = tm[1][3];
  200. (*set_sr_tm)[2][0] = tm[2][0];
  201. (*set_sr_tm)[2][1] = tm[2][1];
  202. (*set_sr_tm)[2][2] = tm[2][2];
  203. (*set_sr_tm)[2][3] = tm[2][3];
  204. (*set_sr_tm)[3][0] = 0.0f;
  205. (*set_sr_tm)[3][1] = 0.0f;
  206. (*set_sr_tm)[3][2] = 0.0f;
  207. (*set_sr_tm)[3][3] = 1.0f;
  208. }
  209. void Convert_Westwood_Matrix(const Matrix3D & wtm,srMatrix4d * set_sr_tm)
  210. {
  211. (*set_sr_tm)[0][0] = wtm[0][0];
  212. (*set_sr_tm)[0][1] = wtm[0][1];
  213. (*set_sr_tm)[0][2] = wtm[0][2];
  214. (*set_sr_tm)[0][3] = wtm[0][3];
  215. (*set_sr_tm)[1][0] = wtm[1][0];
  216. (*set_sr_tm)[1][1] = wtm[1][1];
  217. (*set_sr_tm)[1][2] = wtm[1][2];
  218. (*set_sr_tm)[1][3] = wtm[1][3];
  219. (*set_sr_tm)[2][0] = wtm[2][0];
  220. (*set_sr_tm)[2][1] = wtm[2][1];
  221. (*set_sr_tm)[2][2] = wtm[2][2];
  222. (*set_sr_tm)[2][3] = wtm[2][3];
  223. (*set_sr_tm)[3][0] = 0.0;
  224. (*set_sr_tm)[3][1] = 0.0;
  225. (*set_sr_tm)[3][2] = 0.0;
  226. (*set_sr_tm)[3][3] = 1.0;
  227. }
  228. void Convert_Westwood_Matrix(const Matrix3D & wtm,srMatrix4x3 * set_sr_tm)
  229. {
  230. (*set_sr_tm)[0][0] = wtm[0][0];
  231. (*set_sr_tm)[0][1] = wtm[0][1];
  232. (*set_sr_tm)[0][2] = wtm[0][2];
  233. (*set_sr_tm)[0][3] = wtm[0][3];
  234. (*set_sr_tm)[1][0] = wtm[1][0];
  235. (*set_sr_tm)[1][1] = wtm[1][1];
  236. (*set_sr_tm)[1][2] = wtm[1][2];
  237. (*set_sr_tm)[1][3] = wtm[1][3];
  238. (*set_sr_tm)[2][0] = wtm[2][0];
  239. (*set_sr_tm)[2][1] = wtm[2][1];
  240. (*set_sr_tm)[2][2] = wtm[2][2];
  241. (*set_sr_tm)[2][3] = wtm[2][3];
  242. }
  243. void Convert_Westwood_Matrix(const Matrix3D & wtm,srMatrix3 * set_sr_tm,srVector3 * set_sr_translation)
  244. {
  245. (*set_sr_tm)[0][0] = wtm[0][0];
  246. (*set_sr_tm)[0][1] = wtm[0][1];
  247. (*set_sr_tm)[0][2] = wtm[0][2];
  248. (*set_sr_translation)[0] = wtm[0][3];
  249. (*set_sr_tm)[1][0] = wtm[1][0];
  250. (*set_sr_tm)[1][1] = wtm[1][1];
  251. (*set_sr_tm)[1][2] = wtm[1][2];
  252. (*set_sr_translation)[1] = wtm[1][3];
  253. (*set_sr_tm)[2][0] = wtm[2][0];
  254. (*set_sr_tm)[2][1] = wtm[2][1];
  255. (*set_sr_tm)[2][2] = wtm[2][2];
  256. (*set_sr_translation)[2] = wtm[2][3];
  257. }
  258. void Convert_Westwood_Matrix(const Matrix4 & wtm,srMatrix4 * set_sr_tm)
  259. {
  260. (*set_sr_tm)[0][0] = wtm[0][0];
  261. (*set_sr_tm)[0][1] = wtm[0][1];
  262. (*set_sr_tm)[0][2] = wtm[0][2];
  263. (*set_sr_tm)[0][3] = wtm[0][3];
  264. (*set_sr_tm)[1][0] = wtm[1][0];
  265. (*set_sr_tm)[1][1] = wtm[1][1];
  266. (*set_sr_tm)[1][2] = wtm[1][2];
  267. (*set_sr_tm)[1][3] = wtm[1][3];
  268. (*set_sr_tm)[2][0] = wtm[2][0];
  269. (*set_sr_tm)[2][1] = wtm[2][1];
  270. (*set_sr_tm)[2][2] = wtm[2][2];
  271. (*set_sr_tm)[2][3] = wtm[2][3];
  272. (*set_sr_tm)[3][0] = wtm[3][0];
  273. (*set_sr_tm)[3][1] = wtm[3][1];
  274. (*set_sr_tm)[3][2] = wtm[3][2];
  275. (*set_sr_tm)[3][3] = wtm[3][3];
  276. }
  277. void Convert_Surrender_Matrix(const srMatrix4 & srtm,Matrix3D * set_w3d_tm)
  278. {
  279. (*set_w3d_tm)[0][0] = srtm[0][0];
  280. (*set_w3d_tm)[0][1] = srtm[0][1];
  281. (*set_w3d_tm)[0][2] = srtm[0][2];
  282. (*set_w3d_tm)[0][3] = srtm[0][3];
  283. (*set_w3d_tm)[1][0] = srtm[1][0];
  284. (*set_w3d_tm)[1][1] = srtm[1][1];
  285. (*set_w3d_tm)[1][2] = srtm[1][2];
  286. (*set_w3d_tm)[1][3] = srtm[1][3];
  287. (*set_w3d_tm)[2][0] = srtm[2][0];
  288. (*set_w3d_tm)[2][1] = srtm[2][1];
  289. (*set_w3d_tm)[2][2] = srtm[2][2];
  290. (*set_w3d_tm)[2][3] = srtm[2][3];
  291. }
  292. void Convert_Surrender_Matrix(const srMatrix4x3 & srtm,Matrix3D * set_w3d_tm)
  293. {
  294. (*set_w3d_tm)[0][0] = srtm[0][0];
  295. (*set_w3d_tm)[0][1] = srtm[0][1];
  296. (*set_w3d_tm)[0][2] = srtm[0][2];
  297. (*set_w3d_tm)[0][3] = srtm[0][3];
  298. (*set_w3d_tm)[1][0] = srtm[1][0];
  299. (*set_w3d_tm)[1][1] = srtm[1][1];
  300. (*set_w3d_tm)[1][2] = srtm[1][2];
  301. (*set_w3d_tm)[1][3] = srtm[1][3];
  302. (*set_w3d_tm)[2][0] = srtm[2][0];
  303. (*set_w3d_tm)[2][1] = srtm[2][1];
  304. (*set_w3d_tm)[2][2] = srtm[2][2];
  305. (*set_w3d_tm)[2][3] = srtm[2][3];
  306. }
  307. void Multiply_Westwood_And_Surrender_Matrix(const Matrix3D& n,const srMatrix4& m,srMatrix4& srtm_d)
  308. {
  309. srtm_d[0].make(m[0][0]*n[0][0] + m[0][1]*n[1][0] + m[0][2]*n[2][0],
  310. m[0][0]*n[0][1] + m[0][1]*n[1][1] + m[0][2]*n[2][1],
  311. m[0][0]*n[0][2] + m[0][1]*n[1][2] + m[0][2]*n[2][2],
  312. m[0][0]*n[0][3] + m[0][1]*n[1][3] + m[0][2]*n[2][3] + m[0][3]);
  313. srtm_d[1].make(m[1][0]*n[0][0] + m[1][1]*n[1][0] + m[1][2]*n[2][0],
  314. m[1][0]*n[0][1] + m[1][1]*n[1][1] + m[1][2]*n[2][1],
  315. m[1][0]*n[0][2] + m[1][1]*n[1][2] + m[1][2]*n[2][2],
  316. m[1][0]*n[0][3] + m[1][1]*n[1][3] + m[1][2]*n[2][3] + m[1][3]);
  317. srtm_d[2].make(m[2][0]*n[0][0] + m[2][1]*n[1][0] + m[2][2]*n[2][0],
  318. m[2][0]*n[0][1] + m[2][1]*n[1][1] + m[2][2]*n[2][1],
  319. m[2][0]*n[0][2] + m[2][1]*n[1][2] + m[2][2]*n[2][2],
  320. m[2][0]*n[0][3] + m[2][1]*n[1][3] + m[2][2]*n[2][3] + m[2][3]);
  321. srtm_d[3].make(m[3][0]*n[0][0] + m[3][1]*n[1][0] + m[3][2]*n[2][0],
  322. m[3][0]*n[0][1] + m[3][1]*n[1][1] + m[3][2]*n[2][1],
  323. m[3][0]*n[0][2] + m[3][1]*n[1][2] + m[3][2]*n[2][2],
  324. m[3][0]*n[0][3] + m[3][1]*n[1][3] + m[3][2]*n[2][3] + m[3][3]);
  325. }
  326. /**************************************************************************
  327. * Get_Camera_Frustum_Corners -- Returns 8 camera frustum corner points. *
  328. * *
  329. * INPUT: CameraClass * camera - camera. *
  330. * *
  331. * OUTPUT: (parameter) Vector3 points[8] - array of corner points. *
  332. * *
  333. * WARNINGS: points must be an array of length 8 at least, or bad *
  334. * things will happen (this is not checked by the compiler). *
  335. * *
  336. * HISTORY: *
  337. * 01/18/1998 NH : Created. *
  338. * 04/13/1998 NH : Modified for SR 1.3. *
  339. *========================================================================*/
  340. void Get_Camera_Frustum_Corners(const CameraClass * camera, Vector3 points[8])
  341. {
  342. // Generate the camera-space frustum corner points by linearly
  343. // extrapolating the viewplane to the near and far z clipping planes.
  344. // The camera frustum corner points are defined in the following order:
  345. // When looking at the frustum from the position of the camera, the near four points are
  346. // numbered: upper left 0, upper right 1, lower left 2, lower right 3. The far plane's
  347. // points are numbered from 4 to 7 in an analogous fashion.
  348. // (remember: the camera space has x going to the right, y up and z backwards).
  349. Vector2 vpmin, vpmax;
  350. double znear, zfar;
  351. camera->Get_View_Plane(vpmin, vpmax); // Normalized view plane at a depth of 1.0
  352. camera->Get_Clip_Planes(znear, zfar);
  353. // Forward is negative Z in our viewspace coordinate system.
  354. znear = -znear;
  355. zfar = -zfar;
  356. points[0].Set(vpmin.X, vpmax.Y, 1.0);
  357. points[4] = points[0];
  358. points[0] *= znear;
  359. points[4] *= zfar;
  360. points[1].Set(vpmax.X, vpmax.Y, 1.0);
  361. points[5] = points[1];
  362. points[1] *= znear;
  363. points[5] *= zfar;
  364. points[2].Set(vpmin.X, vpmin.Y, 1.0);
  365. points[6] = points[2];
  366. points[2] *= znear;
  367. points[6] *= zfar;
  368. points[3].Set(vpmax.X, vpmin.Y, 1.0);
  369. points[7] = points[3];
  370. points[3] *= znear;
  371. points[7] *= zfar;
  372. // Transform the eight corners of the view frustum from camera space to world space.
  373. Matrix3D cam_mat = camera->Get_Transform();
  374. for (int i = 0; i < 8; i++) {
  375. Matrix3D::Transform_Vector(cam_mat, points[i], &(points[i]));
  376. }
  377. }
  378. /**************************************************************************
  379. * Get_ZClamped_Camera_Frustum_Corners -- Gets zclamped frustum corners. *
  380. * *
  381. * INPUT: CameraClass * camera - camera. *
  382. * float minz, maxz - depth clamps on frustum. *
  383. * *
  384. * OUTPUT: (parameter) Vector3 points[8] - array of corner points. *
  385. * returns false of the intersection between the clamped range *
  386. * and the frustum is empty. *
  387. * *
  388. * WARNINGS: points must be an array of length 8 at least, or bad *
  389. * things will happen (this is not checked by the compiler). *
  390. * *
  391. * HISTORY: *
  392. * 11/18/1998 NH : Re-Created. *
  393. *========================================================================*/
  394. bool Get_ZClamped_Camera_Frustum_Corners(const CameraClass * camera,
  395. Vector3 points[8], float minz, float maxz)
  396. {
  397. int i;
  398. // (remember: the camera space has x going to the right, y up and z backwards).
  399. Vector2 vpmin, vpmax;
  400. double znear, zfar;
  401. camera->Get_View_Plane(vpmin, vpmax); // Normalized view plane at a depth of 1.0
  402. camera->Get_Clip_Planes(znear, zfar);
  403. // Clamp znear, zfar by minz, maxz:
  404. if (minz > zfar || maxz < znear) {
  405. return false;
  406. }
  407. float startz = minz > znear ? minz : znear;
  408. float endz = maxz < zfar ? maxz : zfar;
  409. // Forward is negative Z in our viewspace coordinate system.
  410. znear = -startz;
  411. zfar = -endz;
  412. points[0].Set(vpmin.X, vpmax.Y, 1.0);
  413. points[4] = points[0];
  414. points[0] *= znear;
  415. points[4] *= zfar;
  416. points[1].Set(vpmax.X, vpmax.Y, 1.0);
  417. points[5] = points[1];
  418. points[1] *= znear;
  419. points[5] *= zfar;
  420. points[2].Set(vpmin.X, vpmin.Y, 1.0);
  421. points[6] = points[2];
  422. points[2] *= znear;
  423. points[6] *= zfar;
  424. points[3].Set(vpmax.X, vpmin.Y, 1.0);
  425. points[7] = points[3];
  426. points[3] *= znear;
  427. points[7] *= zfar;
  428. // Transform the eight corners of the view frustum from camera space to world space.
  429. Matrix3D cam_mat = camera->Get_Transform();
  430. for (i = 0; i < 8; i++) {
  431. Matrix3D::Transform_Vector(cam_mat, points[i], &(points[i]));
  432. }
  433. return true;
  434. }
  435. #endif //WW3D_DX8