composite.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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/composite.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 5/30/01 2:10p $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * CompositeRenderObjClass::CompositeRenderObjClass -- Constructor *
  35. * CompositeRenderObjClass::CompositeRenderObjClass -- copy constructor *
  36. * CompositeRenderObjClass::~CompositeRenderObjClass -- Destructor *
  37. * CompositeRenderObjClass::operator -- assignment operator *
  38. * CompositeRenderObjClass::Restart -- Recursively call Restart on all sub-objects *
  39. * CompositeRenderObjClass::Get_Name -- returns the name of this render object *
  40. * CompositeRenderObjClass::Set_Name -- sets the name of this render object *
  41. * CompositeRenderObjClass::Set_Base_Model_Name -- sets the "base-model-name" *
  42. * CompositeRenderObjClass::Get_Num_Polys -- returns the number of polys *
  43. * CompositeRenderObjClass::Notify_Added -- notify all sub-objects that they were added *
  44. * CompositeRenderObjClass::Notify_Removed -- notifies all subobjs they were removed from th *
  45. * CompositeRenderObjClass::Cast_Ray -- cast a ray against this object *
  46. * CompositeRenderObjClass::Cast_AABox -- cast a swept AABox against this object *
  47. * CompositeRenderObjClass::Cast_OBBox -- cast a swept OBBox against this object *
  48. * CompositeRenderObjClass::Intersect_AABox -- intersect this object with an AABox *
  49. * CompositeRenderObjClass::Intersect_OBBox -- intersect this object with an OBBox *
  50. * CompositeRenderObjClass::Create_Decal -- create a decal on this object *
  51. * CompositeRenderObjClass::Delete_Decal -- remove a logical decal from this object *
  52. * CompositeRenderObjClass::Update_Obj_Space_Bounding_Volumes -- updates the object-space BV *
  53. * CompositeRenderObjClass::Set_User_Data -- set the userdata pointer *
  54. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  55. #include "composite.h"
  56. #include "wwdebug.h"
  57. #include <stdlib.h>
  58. #include <string.h>
  59. /***********************************************************************************************
  60. * CompositeRenderObjClass::CompositeRenderObjClass -- Constructor *
  61. * *
  62. * INPUT: *
  63. * *
  64. * OUTPUT: *
  65. * *
  66. * WARNINGS: *
  67. * *
  68. * HISTORY: *
  69. *=============================================================================================*/
  70. CompositeRenderObjClass::CompositeRenderObjClass(void) :
  71. Name(NULL),
  72. BaseModelName(NULL)
  73. {
  74. }
  75. /***********************************************************************************************
  76. * CompositeRenderObjClass::CompositeRenderObjClass -- copy constructor *
  77. * *
  78. * INPUT: *
  79. * *
  80. * OUTPUT: *
  81. * *
  82. * WARNINGS: *
  83. * *
  84. * HISTORY: *
  85. * 1/26/00 gth : Created. *
  86. *=============================================================================================*/
  87. CompositeRenderObjClass::CompositeRenderObjClass(const CompositeRenderObjClass & that) :
  88. Name(NULL),
  89. BaseModelName(NULL)
  90. {
  91. Set_Name(that.Get_Name());
  92. Set_Base_Model_Name(that.Get_Base_Model_Name());
  93. }
  94. /***********************************************************************************************
  95. * CompositeRenderObjClass::~CompositeRenderObjClass -- Destructor *
  96. * *
  97. * INPUT: *
  98. * *
  99. * OUTPUT: *
  100. * *
  101. * WARNINGS: *
  102. * *
  103. * HISTORY: *
  104. * 1/26/00 gth : Created. *
  105. *=============================================================================================*/
  106. CompositeRenderObjClass::~CompositeRenderObjClass(void)
  107. {
  108. if (Name) free(Name);
  109. if (BaseModelName) free(BaseModelName);
  110. }
  111. /***********************************************************************************************
  112. * CompositeRenderObjClass::operator -- assignment operator *
  113. * *
  114. * INPUT: *
  115. * *
  116. * OUTPUT: *
  117. * *
  118. * WARNINGS: *
  119. * *
  120. * HISTORY: *
  121. * 1/26/00 gth : Created. *
  122. *=============================================================================================*/
  123. CompositeRenderObjClass & CompositeRenderObjClass::operator = (const CompositeRenderObjClass & that)
  124. {
  125. Set_Name(that.Get_Name());
  126. Set_Base_Model_Name(that.Get_Base_Model_Name());
  127. return *this;
  128. }
  129. /***********************************************************************************************
  130. * CompositeRenderObjClass::Restart -- Recursively call Restart on all sub-objects *
  131. * *
  132. * INPUT: *
  133. * *
  134. * OUTPUT: *
  135. * *
  136. * WARNINGS: *
  137. * *
  138. * HISTORY: *
  139. * 5/30/2001 gth : Created. *
  140. *=============================================================================================*/
  141. void CompositeRenderObjClass::Restart(void)
  142. {
  143. for (int ni = 0; ni < Get_Num_Sub_Objects(); ni++) {
  144. RenderObjClass * robj = Get_Sub_Object(ni);
  145. WWASSERT(robj);
  146. robj->Restart();
  147. robj->Release_Ref();
  148. }
  149. }
  150. /***********************************************************************************************
  151. * CompositeRenderObjClass::Get_Name -- returns the name of this render object *
  152. * *
  153. * INPUT: *
  154. * *
  155. * OUTPUT: *
  156. * *
  157. * WARNINGS: *
  158. * *
  159. * HISTORY: *
  160. * 1/26/00 gth : Created. *
  161. *=============================================================================================*/
  162. const char * CompositeRenderObjClass::Get_Name(void) const
  163. {
  164. return Name;
  165. }
  166. /***********************************************************************************************
  167. * CompositeRenderObjClass::Set_Name -- sets the name of this render object *
  168. * *
  169. * INPUT: *
  170. * *
  171. * OUTPUT: *
  172. * *
  173. * WARNINGS: *
  174. * *
  175. * HISTORY: *
  176. * 1/26/00 gth : Created. *
  177. *=============================================================================================*/
  178. void CompositeRenderObjClass::Set_Name(const char * name)
  179. {
  180. if (Name) {
  181. free(Name);
  182. Name = NULL;
  183. }
  184. if (name) {
  185. Name = strdup(name);
  186. }
  187. }
  188. /***********************************************************************************************
  189. * CompositeRenderObjClass::Set_Base_Model_Name -- sets the "base-model-name" *
  190. * *
  191. * The base-model-name was needed by the aggregate code. Ask Patrick Smith about it :-) *
  192. * *
  193. * INPUT: *
  194. * *
  195. * OUTPUT: *
  196. * *
  197. * WARNINGS: *
  198. * *
  199. * HISTORY: *
  200. * 1/26/00 gth : Created. *
  201. *=============================================================================================*/
  202. void CompositeRenderObjClass::Set_Base_Model_Name(const char *name)
  203. {
  204. if (BaseModelName) {
  205. free(BaseModelName);
  206. BaseModelName = NULL;
  207. }
  208. if (name) {
  209. BaseModelName = ::strdup(name);
  210. }
  211. return ;
  212. }
  213. /***********************************************************************************************
  214. * CompositeRenderObjClass::Get_Num_Polys -- returns the number of polys *
  215. * *
  216. * INPUT: *
  217. * *
  218. * OUTPUT: *
  219. * *
  220. * WARNINGS: *
  221. * *
  222. * HISTORY: *
  223. * 1/26/00 gth : Created. *
  224. *=============================================================================================*/
  225. int CompositeRenderObjClass::Get_Num_Polys(void) const
  226. {
  227. int count = 0;
  228. for (int ni = 0; ni < Get_Num_Sub_Objects(); ni++) {
  229. RenderObjClass * robj = Get_Sub_Object(ni);
  230. WWASSERT(robj);
  231. count += robj->Get_Num_Polys();
  232. robj->Release_Ref();
  233. }
  234. return count;
  235. }
  236. /***********************************************************************************************
  237. * CompositeRenderObjClass::Notify_Added -- notify all sub-objects that they were added *
  238. * *
  239. * INPUT: *
  240. * *
  241. * OUTPUT: *
  242. * *
  243. * WARNINGS: *
  244. * *
  245. * HISTORY: *
  246. * 1/26/00 gth : Created. *
  247. *=============================================================================================*/
  248. void CompositeRenderObjClass::Notify_Added(SceneClass * scene)
  249. {
  250. RenderObjClass::Notify_Added(scene);
  251. for (int ni = 0; ni < Get_Num_Sub_Objects(); ni++) {
  252. RenderObjClass * robj = Get_Sub_Object(ni);
  253. WWASSERT(robj);
  254. robj->Notify_Added(scene);
  255. robj->Release_Ref();
  256. }
  257. }
  258. /***********************************************************************************************
  259. * CompositeRenderObjClass::Notify_Removed -- notifies all subobjs they were removed from the *
  260. * *
  261. * INPUT: *
  262. * *
  263. * OUTPUT: *
  264. * *
  265. * WARNINGS: *
  266. * *
  267. * HISTORY: *
  268. * 1/26/00 gth : Created. *
  269. *=============================================================================================*/
  270. void CompositeRenderObjClass::Notify_Removed(SceneClass * scene)
  271. {
  272. for (int ni = 0; ni < Get_Num_Sub_Objects(); ni++) {
  273. RenderObjClass * robj = Get_Sub_Object(ni);
  274. WWASSERT(robj);
  275. robj->Notify_Removed(scene);
  276. robj->Release_Ref();
  277. }
  278. RenderObjClass::Notify_Removed(scene);
  279. }
  280. /***********************************************************************************************
  281. * CompositeRenderObjClass::Cast_Ray -- cast a ray against this object *
  282. * *
  283. * INPUT: *
  284. * *
  285. * OUTPUT: *
  286. * *
  287. * WARNINGS: *
  288. * *
  289. * HISTORY: *
  290. * 1/26/00 gth : Created. *
  291. *=============================================================================================*/
  292. bool CompositeRenderObjClass::Cast_Ray(RayCollisionTestClass & raytest)
  293. {
  294. bool res = false;
  295. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  296. RenderObjClass * robj = Get_Sub_Object(i);
  297. WWASSERT(robj);
  298. res |= robj->Cast_Ray(raytest);
  299. robj->Release_Ref();
  300. }
  301. return res;
  302. }
  303. /***********************************************************************************************
  304. * CompositeRenderObjClass::Cast_AABox -- cast a swept AABox against this object *
  305. * *
  306. * INPUT: *
  307. * *
  308. * OUTPUT: *
  309. * *
  310. * WARNINGS: *
  311. * *
  312. * HISTORY: *
  313. * 1/26/00 gth : Created. *
  314. *=============================================================================================*/
  315. bool CompositeRenderObjClass::Cast_AABox(AABoxCollisionTestClass & boxtest)
  316. {
  317. bool res = false;
  318. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  319. RenderObjClass * robj = Get_Sub_Object(i);
  320. WWASSERT(robj);
  321. res |= robj->Cast_AABox(boxtest);
  322. robj->Release_Ref();
  323. }
  324. return res;
  325. }
  326. /***********************************************************************************************
  327. * CompositeRenderObjClass::Cast_OBBox -- cast a swept OBBox against this object *
  328. * *
  329. * INPUT: *
  330. * *
  331. * OUTPUT: *
  332. * *
  333. * WARNINGS: *
  334. * *
  335. * HISTORY: *
  336. * 1/26/00 gth : Created. *
  337. *=============================================================================================*/
  338. bool CompositeRenderObjClass::Cast_OBBox(OBBoxCollisionTestClass & boxtest)
  339. {
  340. bool res = false;
  341. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  342. RenderObjClass * robj = Get_Sub_Object(i);
  343. WWASSERT(robj);
  344. res |= robj->Cast_OBBox(boxtest);
  345. robj->Release_Ref();
  346. }
  347. return res;
  348. }
  349. /***********************************************************************************************
  350. * CompositeRenderObjClass::Intersect_AABox -- intersect this object with an AABox *
  351. * *
  352. * INPUT: *
  353. * *
  354. * OUTPUT: *
  355. * *
  356. * WARNINGS: *
  357. * *
  358. * HISTORY: *
  359. * 1/26/00 gth : Created. *
  360. *=============================================================================================*/
  361. bool CompositeRenderObjClass::Intersect_AABox(AABoxIntersectionTestClass & boxtest)
  362. {
  363. bool res = false;
  364. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  365. RenderObjClass * robj = Get_Sub_Object(i);
  366. WWASSERT(robj);
  367. res |= robj->Intersect_AABox(boxtest);
  368. robj->Release_Ref();
  369. }
  370. return res;
  371. }
  372. /***********************************************************************************************
  373. * CompositeRenderObjClass::Intersect_OBBox -- intersect this object with an OBBox *
  374. * *
  375. * INPUT: *
  376. * *
  377. * OUTPUT: *
  378. * *
  379. * WARNINGS: *
  380. * *
  381. * HISTORY: *
  382. * 1/26/00 gth : Created. *
  383. *=============================================================================================*/
  384. bool CompositeRenderObjClass::Intersect_OBBox(OBBoxIntersectionTestClass & boxtest)
  385. {
  386. bool res = false;
  387. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  388. RenderObjClass * robj = Get_Sub_Object(i);
  389. WWASSERT(robj);
  390. res |= robj->Intersect_OBBox(boxtest);
  391. robj->Release_Ref();
  392. }
  393. return res;
  394. }
  395. /***********************************************************************************************
  396. * CompositeRenderObjClass::Create_Decal -- create a decal on this object *
  397. * *
  398. * INPUT: *
  399. * *
  400. * OUTPUT: *
  401. * *
  402. * WARNINGS: *
  403. * *
  404. * HISTORY: *
  405. * 1/26/00 gth : Created. *
  406. *=============================================================================================*/
  407. void CompositeRenderObjClass::Create_Decal(DecalGeneratorClass * generator)
  408. {
  409. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  410. RenderObjClass * robj = Get_Sub_Object(i);
  411. WWASSERT(robj);
  412. robj->Create_Decal(generator);
  413. robj->Release_Ref();
  414. }
  415. }
  416. /***********************************************************************************************
  417. * CompositeRenderObjClass::Delete_Decal -- remove a logical decal from this object *
  418. * *
  419. * This internally removes all decals with the given ID. The ID comes from the generator *
  420. * which was used to create the decals. *
  421. * *
  422. * INPUT: *
  423. * *
  424. * OUTPUT: *
  425. * *
  426. * WARNINGS: *
  427. * *
  428. * HISTORY: *
  429. * 1/26/00 gth : Created. *
  430. *=============================================================================================*/
  431. void CompositeRenderObjClass::Delete_Decal(uint32 decal_id)
  432. {
  433. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  434. RenderObjClass * robj = Get_Sub_Object(i);
  435. WWASSERT(robj);
  436. robj->Delete_Decal(decal_id);
  437. robj->Release_Ref();
  438. }
  439. }
  440. /***********************************************************************************************
  441. * CompositeRenderObjClass::Update_Obj_Space_Bounding_Volumes -- updates the object-space BVs *
  442. * *
  443. * INPUT: *
  444. * *
  445. * OUTPUT: *
  446. * *
  447. * WARNINGS: *
  448. * *
  449. * HISTORY: *
  450. * 1/26/00 gth : Created. *
  451. *=============================================================================================*/
  452. void CompositeRenderObjClass::Update_Obj_Space_Bounding_Volumes(void)
  453. {
  454. int i;
  455. RenderObjClass * robj = NULL;
  456. // if we don't have any sub objects, just set default bounds
  457. if (Get_Num_Sub_Objects() <= 0) {
  458. ObjSphere.Init(Vector3(0,0,0),0);
  459. ObjBox.Center.Set(0,0,0);
  460. ObjBox.Extent.Set(0,0,0);
  461. return;
  462. }
  463. AABoxClass obj_aabox;
  464. MinMaxAABoxClass box;
  465. SphereClass sphere;
  466. // loop through all sub-objects, combining their object-space bounding spheres and boxes.
  467. robj = Get_Sub_Object(0);
  468. WWASSERT(robj);
  469. robj->Get_Obj_Space_Bounding_Sphere(ObjSphere);
  470. robj->Get_Obj_Space_Bounding_Box(obj_aabox);
  471. robj->Release_Ref();
  472. box.Init(obj_aabox);
  473. for (i=1; i<Get_Num_Sub_Objects(); i++) {
  474. robj = Get_Sub_Object(i);
  475. WWASSERT(robj);
  476. robj->Get_Obj_Space_Bounding_Sphere(sphere);
  477. robj->Get_Obj_Space_Bounding_Box(obj_aabox);
  478. ObjSphere.Add_Sphere(sphere);
  479. box.Add_Box(obj_aabox);
  480. robj->Release_Ref();
  481. }
  482. ObjBox.Init(box);
  483. Invalidate_Cached_Bounding_Volumes();
  484. // Now update the object space bounding volumes of this object's container:
  485. RenderObjClass *container = Get_Container();
  486. if (container) container->Update_Obj_Space_Bounding_Volumes();
  487. }
  488. /***********************************************************************************************
  489. * CompositeRenderObjClass::Set_User_Data -- set the userdata *
  490. * *
  491. * INPUT: *
  492. * *
  493. * OUTPUT: *
  494. * *
  495. * WARNINGS: *
  496. * *
  497. * HISTORY: *
  498. * 1/26/00 gth : Created. *
  499. *=============================================================================================*/
  500. void CompositeRenderObjClass::Set_User_Data(void *value, bool recursive)
  501. {
  502. RenderObjClass::Set_User_Data(value);
  503. if (recursive) {
  504. for (int i=0; i<Get_Num_Sub_Objects(); i++) {
  505. RenderObjClass * robj = Get_Sub_Object(i);
  506. WWASSERT(robj);
  507. robj->Set_User_Data(value,recursive);
  508. robj->Release_Ref();
  509. }
  510. }
  511. }