matrixmapper.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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 : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/matrixmapper.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 11 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * MatrixMapperClass::MatrixMapperClass -- Constructor *
  38. * MatrixMapperClass::Set_Texture_Transform -- Sets the viewspace-to-texturespace transform *
  39. * MatrixMapperClass::Update_View_To_Pixel_Transform -- recomputes ViewToPixel *
  40. * MatrixMapperClass::Compute_Texture_Coordinate -- compute a single texture coord *
  41. * MatrixMapperClass::Apply -- Apply texture mapper to render states and texture stage states*
  42. * MatrixMapperClass::Calculate_Texture_Matrix -- Calculate texture matrix *
  43. * CompositeMatrixMapperClass::CompositeMatrixMapperClass -- Constructor *
  44. * CompositeMatrixMapperClass::CompositeMatrixMapperClass -- Copy Constructor *
  45. * CompositeMatrixMapperClass::~CompositeMatrixMapperClass -- Destructor *
  46. * CompositeMatrixMapperClass::~CompositeMatrixMapperClass -- Destructor *
  47. * CompositeMatrixMapperClass::Apply -- Apply texture mapper to render states and ts states *
  48. * CompositeMatrixMapperClass::Calculate_Texture_Matrix -- Calculate texture matrix *
  49. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  50. #include "matrixmapper.h"
  51. #include "dx8wrapper.h"
  52. /***********************************************************************************************
  53. * MatrixMapperClass::MatrixMapperClass -- Constructor *
  54. * *
  55. * Initializes the member variables to defaults *
  56. * *
  57. * INPUT: *
  58. * *
  59. * OUTPUT: *
  60. * *
  61. * WARNINGS: *
  62. * *
  63. * HISTORY: *
  64. * 11/13/99 gth : created *
  65. *=============================================================================================*/
  66. MatrixMapperClass::MatrixMapperClass(int stage) :
  67. TextureMapperClass(stage),
  68. Flags(0),
  69. Type(ORTHO_PROJECTION),
  70. ViewToTexture(true),
  71. ViewToPixel(true),
  72. ViewSpaceProjectionNormal(0.0f, 0.0f, 0.0f),
  73. GradientUCoord(0.5f)
  74. {
  75. }
  76. /***********************************************************************************************
  77. * MatrixMapperClass::Set_Texture_Transform -- Sets the viewspace-to-texturespace transform *
  78. * *
  79. * INPUT: *
  80. * *
  81. * OUTPUT: *
  82. * *
  83. * WARNINGS: *
  84. * *
  85. * HISTORY: *
  86. * 6/20/2001 gth : created *
  87. *=============================================================================================*/
  88. void MatrixMapperClass::Set_Texture_Transform(const Matrix3D & view_to_texture,float texsize)
  89. {
  90. ViewToTexture = Matrix4x4(view_to_texture);
  91. Update_View_To_Pixel_Transform(texsize);
  92. }
  93. /***********************************************************************************************
  94. * MatrixMapperClass::Set_Texture_Transform -- Sets the viewspace-to-texturespace transform *
  95. * *
  96. * INPUT: *
  97. * *
  98. * OUTPUT: *
  99. * *
  100. * WARNINGS: *
  101. * *
  102. * HISTORY: *
  103. * 11/13/99 gth : Created. *
  104. *=============================================================================================*/
  105. void MatrixMapperClass::Set_Texture_Transform(const Matrix4x4 & view_to_texture,float texsize)
  106. {
  107. ViewToTexture=view_to_texture;
  108. Update_View_To_Pixel_Transform(texsize);
  109. }
  110. /***********************************************************************************************
  111. * MatrixMapperClass::Update_View_To_Pixel_Transform -- recomputes ViewToPixel *
  112. * *
  113. * INPUT: *
  114. * *
  115. * OUTPUT: *
  116. * *
  117. * WARNINGS: *
  118. * *
  119. * HISTORY: *
  120. * 1/4/00 gth : Created. *
  121. *=============================================================================================*/
  122. void MatrixMapperClass::Update_View_To_Pixel_Transform(float tex_size)
  123. {
  124. /*
  125. ** Create a ViewToPixel matrix which also does all of the offseting and flipping that has
  126. ** to take place to get the actual texture coordinates.
  127. **
  128. ** Here is a description of the math:
  129. ** If you transform eye-space points with the ViewToTexture matrix, you then need to compute:
  130. ** s = ((x/w) + 1.0f) * 0.5f * ((texwid-2)/texwid)
  131. ** t = (1.0f - (y/w)) * 0.5f * ((texwid-2)/texwid)
  132. **
  133. ** Let K = 0.5 * ((texwid-2)/texwid), Then:
  134. ** ((x/w) + 1.0f) * K = (K*x + K*w) / w
  135. ** (1.0f - (y/w)) * K = (-K*y + K*w) / w
  136. **
  137. ** This leads to the following matrix (The KOOK matrix!)
  138. ** | K 0 0 K |
  139. ** | 0 -K 0 K |
  140. ** | 0 0 1 0 |
  141. ** | 0 0 0 1 |
  142. **
  143. ** The code below manually "optimally" pre-multiplies this matrix with the ViewToTexture matrix
  144. **
  145. ** In addition, the z-coordinate is modified so that it goes from 0 to 1 rather than -1 to +1.
  146. ** It can also be flipped if the INVERT_DEPTH_GRADIENT flag is on.
  147. */
  148. float k = 0.5 * (tex_size - 2.0f) / tex_size;
  149. ViewToPixel[0][0] = k * ViewToTexture[0][0] + k * ViewToTexture[3][0];
  150. ViewToPixel[0][1] = k * ViewToTexture[0][1] + k * ViewToTexture[3][1];
  151. ViewToPixel[0][2] = k * ViewToTexture[0][2] + k * ViewToTexture[3][2];
  152. ViewToPixel[0][3] = k * ViewToTexture[0][3] + k * ViewToTexture[3][3];
  153. ViewToPixel[1][0] = -k * ViewToTexture[1][0] + k * ViewToTexture[3][0];
  154. ViewToPixel[1][1] = -k * ViewToTexture[1][1] + k * ViewToTexture[3][1];
  155. ViewToPixel[1][2] = -k * ViewToTexture[1][2] + k * ViewToTexture[3][2];
  156. ViewToPixel[1][3] = -k * ViewToTexture[1][3] + k * ViewToTexture[3][3];
  157. if (Get_Flag(INVERT_DEPTH_GRADIENT)) {
  158. ViewToPixel[2][0] = -0.5f * ViewToTexture[2][0] + 0.5f * ViewToTexture[3][0];
  159. ViewToPixel[2][1] = -0.5f * ViewToTexture[2][1] + 0.5f * ViewToTexture[3][1];
  160. ViewToPixel[2][2] = -0.5f * ViewToTexture[2][2] + 0.5f * ViewToTexture[3][2];
  161. ViewToPixel[2][3] = -0.5f * ViewToTexture[2][3] + 0.5f * ViewToTexture[3][3];
  162. } else {
  163. ViewToPixel[2][0] = 0.5f * ViewToTexture[2][0] + 0.5f * ViewToTexture[3][0];
  164. ViewToPixel[2][1] = 0.5f * ViewToTexture[2][1] + 0.5f * ViewToTexture[3][1];
  165. ViewToPixel[2][2] = 0.5f * ViewToTexture[2][2] + 0.5f * ViewToTexture[3][2];
  166. ViewToPixel[2][3] = 0.5f * ViewToTexture[2][3] + 0.5f * ViewToTexture[3][3];
  167. }
  168. ViewToPixel[3] = ViewToTexture[3];
  169. /*
  170. ** Store the view space negative z vector for lighting effects
  171. */
  172. ViewSpaceProjectionNormal.X = -ViewToTexture[2][0];
  173. ViewSpaceProjectionNormal.Y = -ViewToTexture[2][1];
  174. ViewSpaceProjectionNormal.Z = -ViewToTexture[2][2];
  175. ViewSpaceProjectionNormal.Normalize();
  176. }
  177. /***********************************************************************************************
  178. * MatrixMapperClass::Compute_Texture_Coordinate -- compute a single texture coord *
  179. * *
  180. * INPUT: *
  181. * point - 3D point to calculate the texture coordinate for *
  182. * set_stq - pointer to texture coordinate, s,t will be stored in X,Y. q will be stored in Z *
  183. * *
  184. * OUTPUT: *
  185. * *
  186. * WARNINGS: *
  187. * *
  188. * HISTORY: *
  189. * 1/25/00 gth : Created. *
  190. *=============================================================================================*/
  191. void MatrixMapperClass::Compute_Texture_Coordinate(const Vector3 & point,Vector3 * set_stq)
  192. {
  193. set_stq->X = ViewToPixel[0][0]*point.X + ViewToPixel[0][1]*point.Y + ViewToPixel[0][2]*point.Z + ViewToPixel[0][3];
  194. set_stq->Y = ViewToPixel[1][0]*point.X + ViewToPixel[1][1]*point.Y + ViewToPixel[1][2]*point.Z + ViewToPixel[1][3];
  195. set_stq->Z = ViewToPixel[3][0]*point.X + ViewToPixel[3][1]*point.Y + ViewToPixel[3][2]*point.Z + ViewToPixel[3][3];
  196. }
  197. /***********************************************************************************************
  198. * MatrixMapperClass::Apply -- Apply texture mapper to render states and texture stage states *
  199. * *
  200. * INPUT: *
  201. * *
  202. * OUTPUT: *
  203. * *
  204. * WARNINGS: *
  205. * *
  206. * HISTORY: *
  207. * 11/05/01 NH : Created comment block. *
  208. *=============================================================================================*/
  209. void MatrixMapperClass::Apply(int uv_array_index)
  210. {
  211. Matrix4x4 m;
  212. switch (Type)
  213. {
  214. case ORTHO_PROJECTION:
  215. /*
  216. ** Orthographic projection
  217. */
  218. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + Stage),ViewToPixel);
  219. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
  220. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  221. break;
  222. case PERSPECTIVE_PROJECTION:
  223. /*
  224. ** Perspective projection
  225. */
  226. m[0]=ViewToPixel[0];
  227. m[1]=ViewToPixel[1];
  228. m[2]=ViewToPixel[3];
  229. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + Stage),m);
  230. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
  231. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_PROJECTED|D3DTTFF_COUNT3);
  232. break;
  233. case DEPTH_GRADIENT:
  234. /*
  235. ** Depth gradient, Set up second stage texture coordinates to
  236. ** apply a depth gradient to the projection. Note that the
  237. ** depth values have been set up to vary from 0 to 1 in the
  238. ** Update_View_To_Pixel_Transform function.
  239. */
  240. m[0].Set(0,0,0,GradientUCoord);
  241. m[1]=ViewToPixel[2];
  242. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + Stage),m);
  243. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
  244. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  245. break;
  246. case NORMAL_GRADIENT:
  247. /*
  248. ** Normal Gradient, Set up the second stage texture coordinates to
  249. ** apply a gradient based on the dot product of the vertex normal
  250. ** and the projection direction. (NOTE: this is basically texture-
  251. ** based diffuse lighting!)
  252. */
  253. m[0].Set(0,0,0,GradientUCoord);
  254. m[1].Set(ViewSpaceProjectionNormal.X,ViewSpaceProjectionNormal.Y,ViewSpaceProjectionNormal.Z, 0);
  255. DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + Stage),m);
  256. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
  257. DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
  258. break;
  259. }
  260. }
  261. /***********************************************************************************************
  262. * MatrixMapperClass::Calculate_Texture_Matrix -- Calculate texture matrix *
  263. * *
  264. * INPUT: *
  265. * *
  266. * OUTPUT: *
  267. * *
  268. * WARNINGS: *
  269. * *
  270. * HISTORY: *
  271. * 11/06/01 NH : Created comment block. *
  272. *=============================================================================================*/
  273. void MatrixMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  274. {
  275. // We return ViewToPixel. This is not, strictly speaking, always correct, but it is close
  276. // and it is OK not to be 100% correct since this function is not called by the Apply()
  277. // function.
  278. tex_matrix = ViewToPixel;
  279. }
  280. /***********************************************************************************************
  281. * CompositeMatrixMapperClass::CompositeMatrixMapperClass -- Constructor *
  282. * *
  283. * INPUT: *
  284. * *
  285. * OUTPUT: *
  286. * *
  287. * WARNINGS: *
  288. * *
  289. * HISTORY: *
  290. * 11/05/01 NH : Created. *
  291. *=============================================================================================*/
  292. CompositeMatrixMapperClass::CompositeMatrixMapperClass(TextureMapperClass *internal_mapper, unsigned int stage) :
  293. MatrixMapperClass(stage),
  294. InternalMapper(internal_mapper)
  295. {
  296. if (InternalMapper) {
  297. InternalMapper->Add_Ref();
  298. }
  299. }
  300. /***********************************************************************************************
  301. * CompositeMatrixMapperClass::CompositeMatrixMapperClass -- Copy Constructor *
  302. * *
  303. * INPUT: *
  304. * *
  305. * OUTPUT: *
  306. * *
  307. * WARNINGS: *
  308. * *
  309. * HISTORY: *
  310. * 11/05/01 NH : Created. *
  311. *=============================================================================================*/
  312. CompositeMatrixMapperClass::CompositeMatrixMapperClass(const CompositeMatrixMapperClass & src) :
  313. MatrixMapperClass(src),
  314. InternalMapper(src.InternalMapper ? src.InternalMapper->Clone() : NULL)
  315. {
  316. if (InternalMapper) {
  317. InternalMapper->Add_Ref();
  318. }
  319. }
  320. /***********************************************************************************************
  321. * CompositeMatrixMapperClass::~CompositeMatrixMapperClass -- Destructor *
  322. * *
  323. * INPUT: *
  324. * *
  325. * OUTPUT: *
  326. * *
  327. * WARNINGS: *
  328. * *
  329. * HISTORY: *
  330. * 11/05/01 NH : Created. *
  331. *=============================================================================================*/
  332. CompositeMatrixMapperClass::~CompositeMatrixMapperClass(void)
  333. {
  334. if (InternalMapper) {
  335. InternalMapper->Release_Ref();
  336. InternalMapper = NULL;
  337. }
  338. }
  339. /***********************************************************************************************
  340. * CompositeMatrixMapperClass::Apply -- Apply texture mapper to render states and ts states *
  341. * *
  342. * INPUT: *
  343. * *
  344. * OUTPUT: *
  345. * *
  346. * WARNINGS: *
  347. * *
  348. * HISTORY: *
  349. * 11/05/01 NH : Created. *
  350. *=============================================================================================*/
  351. void CompositeMatrixMapperClass::Apply(int uv_array_index)
  352. {
  353. if (InternalMapper) {
  354. // Get the texture matrix from the internal mapper, composite it into ViewToPixel (save off
  355. // the previous value of ViewToPixel first), call the base class Apply() function (which will
  356. // use the modifiedViewToPixel) and then restore ViewToPixel to its previous state.
  357. Matrix4x4 int_mat;
  358. InternalMapper->Calculate_Texture_Matrix(int_mat);
  359. Matrix4x4 view_to_pixel_copy(ViewToPixel);
  360. // We need to modify the view-to-pixel matrix to produce q (third texture coordinate values)
  361. // equal to one. This is the input which the internal mappers' matrix was designed for (it
  362. // is what you get when you use 2D vertex coordinates from the vertex buffer).
  363. // For this we need to multiply the matrix by the following matrix:
  364. // [1 0 0 0]
  365. // [0 1 0 0] This is equivalent to overwriting the third row with the fourth one.
  366. // [0 0 0 1]
  367. // [0 0 0 1]
  368. Matrix4x4 tmp;
  369. tmp[0] = ViewToPixel[0];
  370. tmp[1] = ViewToPixel[1];
  371. tmp[2] = ViewToPixel[3];
  372. tmp[3] = ViewToPixel[3];
  373. // We multiply the matrices in this order so the camera position, transformed by ViewToPixel
  374. // is used as the 'input texture coordinates' to be affected by the internal mapper matrix.
  375. Matrix4x4::Multiply(int_mat, tmp, &ViewToPixel);
  376. MatrixMapperClass::Apply(uv_array_index);
  377. ViewToPixel = view_to_pixel_copy;
  378. } else {
  379. MatrixMapperClass::Apply(uv_array_index);
  380. }
  381. }
  382. /***********************************************************************************************
  383. * MatrixMapperClass::Calculate_Texture_Matrix -- Calculate texture matrix *
  384. * *
  385. * INPUT: *
  386. * *
  387. * OUTPUT: *
  388. * *
  389. * WARNINGS: *
  390. * *
  391. * HISTORY: *
  392. * 11/06/01 NH : Created comment block. *
  393. *=============================================================================================*/
  394. void CompositeMatrixMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
  395. {
  396. if (InternalMapper) {
  397. // We return the internal mapper's matrix times ViewToPixel, adjusted to produce the correct
  398. // z-value of 1. This is only correct if the mapper is in ORTHO_PROJECTION or
  399. // PERSPECTIVE_PROJECTION mode, which should be the case for most uses of this mapper. It is
  400. // OK for this function not be be 100% correct in all cases, since it is not used in the
  401. // Apply() function.
  402. Matrix4x4 int_mat;
  403. InternalMapper->Calculate_Texture_Matrix(int_mat);
  404. // We need to modify the view-to-pixel matrix to produce q (third texture coordinate values)
  405. // equal to one. This is the input which the internal mappers' matrix was designed for (it
  406. // is what you get when you use 2D vertex coordinates from the vertex buffer).
  407. // For this we need to multiply the matrix by the following matrix:
  408. // [1 0 0 0]
  409. // [0 1 0 0] This is equivalent to overwriting the third row with the fourth one.
  410. // [0 0 0 1]
  411. // [0 0 0 1]
  412. Matrix4x4 tmp;
  413. tmp[0] = ViewToPixel[0];
  414. tmp[1] = ViewToPixel[1];
  415. tmp[2] = ViewToPixel[3];
  416. tmp[3] = ViewToPixel[3];
  417. // We multiply the matrices in this order so the camera position, transformed by ViewToPixel
  418. // is used as the 'input texture coordinates' to be affected by the internal mapper matrix.
  419. Matrix4x4::Multiply(int_mat, tmp, &tex_matrix);
  420. } else {
  421. MatrixMapperClass::Calculate_Texture_Matrix(tex_matrix);
  422. }
  423. }