decalsys.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/decalsys.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 8 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * DecalSystemClass::DecalSystemClass -- Constructor *
  38. * DecalSystemClass::~DecalSystemClass -- Destructor *
  39. * DecalSystemClass::Lock_Decal_Generator -- returns a DecalGenerator *
  40. * DecalSystemClass::Unlock_Decal_Generator -- Destroys the decal generator *
  41. * DecalSystemClass::Generate_Unique_Global_Decal_Id -- Generates a unique id for a decal *
  42. * DecalGeneratorClass::DecalGeneratorClass -- Constructor *
  43. * DecalGeneratorClass::~DecalGeneratorClass -- Destructor *
  44. * DecalGeneratorClass::Add_Mesh -- Meshes that generate a decal should add themselves *
  45. * DecalGeneratorClass::Get_Mesh_List -- returns the list of meshes *
  46. * DecalGeneratorClass::Set_Mesh_Transform -- sets the current mesh coordinate system *
  47. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  48. #include "decalsys.h"
  49. #include "rendobj.h"
  50. #include "mesh.h"
  51. #include "decalmsh.h"
  52. #include "matrixmapper.h"
  53. #include "texture.h"
  54. uint32 DecalSystemClass::DecalIDGenerator = 0;
  55. /*
  56. ** DecalSystemClass Implementation
  57. */
  58. /***********************************************************************************************
  59. * DecalSystemClass::DecalSystemClass -- Constructor *
  60. * *
  61. * INPUT: *
  62. * *
  63. * OUTPUT: *
  64. * *
  65. * WARNINGS: *
  66. * *
  67. * HISTORY: *
  68. *=============================================================================================*/
  69. DecalSystemClass::DecalSystemClass(void)
  70. {
  71. }
  72. /***********************************************************************************************
  73. * DecalSystemClass::~DecalSystemClass -- Destructor *
  74. * *
  75. * INPUT: *
  76. * *
  77. * OUTPUT: *
  78. * *
  79. * WARNINGS: *
  80. * *
  81. * HISTORY: *
  82. *=============================================================================================*/
  83. DecalSystemClass::~DecalSystemClass(void)
  84. {
  85. }
  86. /***********************************************************************************************
  87. * DecalSystemClass::Lock_Decal_Generator -- returns a DecalGenerator *
  88. * *
  89. * INPUT: *
  90. * *
  91. * OUTPUT: *
  92. * *
  93. * WARNINGS: *
  94. * *
  95. * HISTORY: *
  96. * 1/26/00 gth : Created. *
  97. *=============================================================================================*/
  98. DecalGeneratorClass * DecalSystemClass::Lock_Decal_Generator(void)
  99. {
  100. DecalGeneratorClass * gen = W3DNEW DecalGeneratorClass(Generate_Decal_Id(), this);
  101. return gen;
  102. }
  103. /***********************************************************************************************
  104. * DecalSystemClass::Unlock_Decal_Generator -- Destroys the decal generator *
  105. * *
  106. * Derived classes may take a record of the results of the generator here. Then they can *
  107. * put a cap on the total number of decals in the system or whatever... *
  108. * *
  109. * INPUT: *
  110. * *
  111. * OUTPUT: *
  112. * *
  113. * WARNINGS: *
  114. * *
  115. * HISTORY: *
  116. * 1/26/00 gth : Created. *
  117. *=============================================================================================*/
  118. void DecalSystemClass::Unlock_Decal_Generator(DecalGeneratorClass * generator)
  119. {
  120. delete generator;
  121. }
  122. /***********************************************************************************************
  123. * DecalSystemClass::Generate_Unique_Global_Decal_Id -- Generates a unique id for a decal *
  124. * *
  125. * INPUT: *
  126. * *
  127. * OUTPUT: *
  128. * *
  129. * WARNINGS: *
  130. * Hopefully you won't use more than 4 billion decals at one time... *
  131. * *
  132. * HISTORY: *
  133. * 1/26/00 gth : Created. *
  134. *=============================================================================================*/
  135. uint32 DecalSystemClass::Generate_Unique_Global_Decal_Id(void)
  136. {
  137. return DecalIDGenerator++;
  138. }
  139. /*
  140. ** DecalGeneratorClass Implementation
  141. */
  142. /***********************************************************************************************
  143. * DecalGeneratorClass::DecalGeneratorClass -- Constructor *
  144. * *
  145. * INPUT: *
  146. * *
  147. * OUTPUT: *
  148. * *
  149. * WARNINGS: *
  150. * *
  151. * HISTORY: *
  152. * 1/26/00 gth : Created. *
  153. *=============================================================================================*/
  154. DecalGeneratorClass::DecalGeneratorClass(uint32 id,DecalSystemClass * system) :
  155. DecalID(id),
  156. System(system),
  157. BackfaceVal(0.0f),
  158. ApplyToTranslucentMeshes(false),
  159. Material(NULL)
  160. {
  161. Material = NEW_REF(MaterialPassClass,());
  162. WWASSERT(System != NULL);
  163. WWASSERT(Material != NULL);
  164. }
  165. /***********************************************************************************************
  166. * DecalGeneratorClass::~DecalGeneratorClass -- Destructor *
  167. * *
  168. * INPUT: *
  169. * *
  170. * OUTPUT: *
  171. * *
  172. * WARNINGS: *
  173. * *
  174. * HISTORY: *
  175. * 1/26/00 gth : Created. *
  176. *=============================================================================================*/
  177. DecalGeneratorClass::~DecalGeneratorClass(void)
  178. {
  179. REF_PTR_RELEASE(Material);
  180. }
  181. /***********************************************************************************************
  182. * DecalGeneratorClass::Add_Mesh -- Meshes that generate a decal should add themselves *
  183. * *
  184. * This adds a mesh to the internal list. All meshes that actually add a decal should add *
  185. * themselves to this list so that the DecalSystem can keep track of them. *
  186. * *
  187. * INPUT: *
  188. * *
  189. * OUTPUT: *
  190. * *
  191. * WARNINGS: *
  192. * *
  193. * HISTORY: *
  194. * 1/26/00 gth : Created. *
  195. *=============================================================================================*/
  196. void DecalGeneratorClass::Add_Mesh(RenderObjClass * mesh)
  197. {
  198. WWASSERT(mesh->Class_ID() == RenderObjClass::CLASSID_MESH);
  199. MeshList.Add(mesh);
  200. }
  201. /***********************************************************************************************
  202. * DecalGeneratorClass::Get_Mesh_List -- returns the list of meshes *
  203. * *
  204. * This is the list of meshes which generated decals for this "logical decal" *
  205. * *
  206. * INPUT: *
  207. * *
  208. * OUTPUT: *
  209. * *
  210. * WARNINGS: *
  211. * *
  212. * HISTORY: *
  213. * 1/26/00 gth : Created. *
  214. *=============================================================================================*/
  215. NonRefRenderObjListClass & DecalGeneratorClass::Get_Mesh_List(void)
  216. {
  217. return MeshList;
  218. }
  219. /***********************************************************************************************
  220. * DecalGeneratorClass::Set_Mesh_Transform -- sets the current mesh coordinate system *
  221. * *
  222. * The coordinate system of the mesh is needed in order to compute texture coordinates for *
  223. * the decal polygons. *
  224. * *
  225. * INPUT: *
  226. * *
  227. * OUTPUT: *
  228. * *
  229. * WARNINGS: *
  230. * *
  231. * HISTORY: *
  232. * 1/26/00 gth : Created. *
  233. *=============================================================================================*/
  234. void DecalGeneratorClass::Set_Mesh_Transform(const Matrix3D & mesh_transform)
  235. {
  236. /*
  237. ** Mobj-texture = Projection * Mwrld-texture * Mobj-wrld
  238. */
  239. Matrix3D world_to_texture;
  240. Matrix3D tmp;
  241. Matrix4x4 mesh_to_texture;
  242. Transform.Get_Orthogonal_Inverse(world_to_texture);
  243. Matrix3D::Multiply(world_to_texture,mesh_transform,&tmp);
  244. Matrix4x4::Multiply(Projection,tmp,&mesh_to_texture);
  245. /*
  246. ** Plug the matrix and texture size into the mapper
  247. */
  248. if (WW3D::Is_Texturing_Enabled()) {
  249. float texsize = 64.0f;
  250. TextureClass * tex = Material->Peek_Texture();
  251. WWASSERT(tex != NULL);
  252. if (tex) {
  253. // SurfaceClass::SurfaceDescription surface_desc;
  254. // tex->Get_Level_Description(surface_desc);
  255. // texsize = surface_desc.Width;
  256. texsize = tex->Get_Width();
  257. }
  258. Mapper->Set_Texture_Transform(mesh_to_texture,texsize);
  259. }
  260. }
  261. /*
  262. ** MultiFixedPoolDecalSystemClass implementation
  263. */
  264. MultiFixedPoolDecalSystemClass::MultiFixedPoolDecalSystemClass(uint32 num_pools, const uint32 *pool_sizes) :
  265. Pools(0),
  266. PoolCount(num_pools),
  267. Generator_PoolID(0),
  268. Generator_SlotID(0)
  269. {
  270. if (PoolCount)
  271. {
  272. WWASSERT(pool_sizes);
  273. Pools = W3DNEWARRAY LogicalDecalPoolClass [PoolCount];
  274. }
  275. for (uint32 i = 0; i < PoolCount; i++) {
  276. assert(pool_sizes[i]);
  277. Pools[i].Initialize(pool_sizes[i]);
  278. }
  279. }
  280. MultiFixedPoolDecalSystemClass::MultiFixedPoolDecalSystemClass(const MultiFixedPoolDecalSystemClass & that) :
  281. Pools(0),
  282. PoolCount(that.PoolCount),
  283. Generator_PoolID(that.Generator_PoolID),
  284. Generator_SlotID(that.Generator_SlotID)
  285. {
  286. uint32 i;
  287. // Allocate arrays (we dont' copy array contents because those are mesh-specific and will be
  288. // filled when the state is set anyway)
  289. if (PoolCount) Pools = W3DNEWARRAY LogicalDecalPoolClass [PoolCount];
  290. for (i = 0; i < PoolCount; i++) {
  291. Pools[i].Initialize(that.Pools[i].Size);
  292. }
  293. }
  294. MultiFixedPoolDecalSystemClass::~MultiFixedPoolDecalSystemClass(void)
  295. {
  296. if (Pools) {
  297. delete [] Pools;
  298. Pools = 0;
  299. }
  300. }
  301. // This clears the slot in addition to locking the generator, thus preventing any decal id
  302. // collisions (since any decal previously in that slot will have the same id as the new one).
  303. DecalGeneratorClass * MultiFixedPoolDecalSystemClass::Lock_Decal_Generator(void)
  304. {
  305. Clear_Decal_Slot(Generator_PoolID, Generator_SlotID);
  306. return DecalSystemClass::Lock_Decal_Generator();
  307. }
  308. // This will register the decal in the system in the appropriate pool and slot (determined by
  309. // the generator's pool and slot ids), removing any decal which may have been there before.
  310. void MultiFixedPoolDecalSystemClass::Unlock_Decal_Generator(DecalGeneratorClass * generator)
  311. {
  312. find_logical_decal(generator->Get_Decal_ID()).Set(generator);
  313. DecalSystemClass::Unlock_Decal_Generator(generator);
  314. }
  315. // This notifies the system that a mesh which has decals on it was destroyed - therefore we
  316. // need to remove the mesh from our list to avoid dangling pointers.
  317. void MultiFixedPoolDecalSystemClass::Decal_Mesh_Destroyed(uint32 decal_id,DecalMeshClass * mesh)
  318. {
  319. // We must remove this mesh from all lists where it is present. The method is: for each
  320. // decal id present in the decal mesh, find the logical decal and remove the decal mesh from
  321. // its list.
  322. assert(mesh);
  323. MeshClass *parent = mesh->Peek_Parent();
  324. find_logical_decal(decal_id).MeshList.Remove(parent);
  325. }
  326. // Not part of the DecalSystemClass interface - this function removes any decal currently in
  327. // the given slot in the given pool.
  328. void MultiFixedPoolDecalSystemClass::Clear_Decal_Slot(uint32 pool_id, uint32 slot_id)
  329. {
  330. find_logical_decal(pool_id, slot_id).Clear(encode_decal_id(pool_id, slot_id));
  331. }
  332. // This one removes all decals in a given pool.
  333. void MultiFixedPoolDecalSystemClass::Clear_Pool(uint32 pool_id)
  334. {
  335. LogicalDecalPoolClass & pool = Pools[pool_id];
  336. uint32 pool_size = pool.Size;
  337. for (uint32 slot_id = 0; slot_id < pool_size; slot_id++) {
  338. pool.Array[slot_id].Clear(encode_decal_id(pool_id, slot_id));
  339. }
  340. }
  341. // And this one removes all decals in the system.
  342. void MultiFixedPoolDecalSystemClass::Clear_All_Decals(void)
  343. {
  344. for (uint32 pool_id = 0; pool_id < PoolCount; pool_id++) {
  345. LogicalDecalPoolClass & pool = Pools[pool_id];
  346. uint32 pool_size = pool.Size;
  347. for (uint32 slot_id = 0; slot_id < pool_size; slot_id++) {
  348. pool.Array[slot_id].Clear(encode_decal_id(pool_id, slot_id));
  349. }
  350. }
  351. }
  352. // Get a reference to the logical decal at the given pool and slot id (performs range checking)
  353. MultiFixedPoolDecalSystemClass::LogicalDecalClass & MultiFixedPoolDecalSystemClass::find_logical_decal(uint32 pool_id, uint32 slot_id)
  354. {
  355. assert(pool_id < PoolCount);
  356. pool_id = MIN(pool_id, PoolCount);
  357. LogicalDecalPoolClass & pool = Pools[pool_id];
  358. assert(slot_id < pool.Size);
  359. slot_id = MIN(slot_id, pool.Size);
  360. return pool.Array[slot_id];
  361. }
  362. // Get a reference to the logical decal with the given decal id
  363. MultiFixedPoolDecalSystemClass::LogicalDecalClass & MultiFixedPoolDecalSystemClass::find_logical_decal(uint32 decal_id)
  364. {
  365. uint32 pool_id, slot_id;
  366. decode_decal_id(decal_id, pool_id, slot_id);
  367. return find_logical_decal(pool_id, slot_id);
  368. }
  369. /*
  370. ** MultiFixedPoolDecalSystemClass::LogicalDecalClass implementation
  371. */
  372. MultiFixedPoolDecalSystemClass::LogicalDecalClass::LogicalDecalClass(void)
  373. {
  374. }
  375. MultiFixedPoolDecalSystemClass::LogicalDecalClass::~LogicalDecalClass(void)
  376. {
  377. // We don't need to do anything here since the mesh list will get removed automatically and
  378. // the decals themselves don't neccessarily need to be removed because the logical decal is.
  379. // (we don't hold references to the meshes in the mesh list)
  380. }
  381. // Sets the logical decal to the one specified by the given generator (clearing any existing
  382. // decal information)
  383. void MultiFixedPoolDecalSystemClass::LogicalDecalClass::Set(DecalGeneratorClass * generator)
  384. {
  385. Clear(generator->Get_Decal_ID());
  386. /*
  387. ** Copy the generators' mesh list into our mesh list
  388. */
  389. NonRefRenderObjListIterator gen_mesh_it(&(generator->Get_Mesh_List()));
  390. for (gen_mesh_it.First(); !gen_mesh_it.Is_Done(); gen_mesh_it.Next()) {
  391. MeshList.Add(gen_mesh_it.Get_Obj());
  392. }
  393. }
  394. // Just clears any existing logical decal information, leaving the decal empty.
  395. void MultiFixedPoolDecalSystemClass::LogicalDecalClass::Clear(uint32 decal_id)
  396. {
  397. // Remove the decal with this ID from all meshes where it appears
  398. NonRefRenderObjListIterator it(&MeshList);
  399. for (it.First(); !it.Is_Done(); it.Next()) {
  400. it.Get_Obj()->Delete_Decal(decal_id);
  401. }
  402. // Delete list
  403. while (!MeshList.Is_Empty()) {
  404. MeshList.Remove_Head();
  405. }
  406. }
  407. /*
  408. ** MultiFixedPoolDecalSystemClass::LogicalDecalPoolClass implementation
  409. */
  410. MultiFixedPoolDecalSystemClass::LogicalDecalPoolClass::LogicalDecalPoolClass(void) :
  411. Array(0),
  412. Size(0)
  413. {
  414. }
  415. MultiFixedPoolDecalSystemClass::LogicalDecalPoolClass::~LogicalDecalPoolClass(void)
  416. {
  417. if (Array) {
  418. delete [] Array;
  419. Array = 0;
  420. }
  421. }
  422. void MultiFixedPoolDecalSystemClass::LogicalDecalPoolClass::Initialize(uint32 size)
  423. {
  424. if (Array) {
  425. delete [] Array;
  426. Array = 0;
  427. }
  428. Size = size;
  429. assert(Size);
  430. Array = W3DNEWARRAY LogicalDecalClass[Size];
  431. }