decalsys.cpp 24 KB

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