dynamicphys.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. ** Command & Conquer Renegade(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/wwphys/dynamicphys.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 3/29/02 2:49p $*
  31. * *
  32. * $Revision:: 17 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "dynamicphys.h"
  38. #include "chunkio.h"
  39. #include "pscene.h"
  40. #include "wwprofile.h"
  41. #include "physcoltest.h"
  42. #if (UMBRASUPPORT)
  43. #include <umbra.hpp>
  44. #endif
  45. #include "umbrasupport.h"
  46. /***********************************************************************************************
  47. **
  48. ** DynamicPhysClass Implementation
  49. ** Note that this is not a concrete class. It therefore does not have factories defined...
  50. **
  51. ***********************************************************************************************/
  52. const int MIN_VIS_UPDATE_TICK_DELAY = 250; // min number of milliseconds between dynamic vis id updates
  53. bool DynamicPhysClass::_DisableDynamicPhysSimulation = false;
  54. bool DynamicPhysClass::_DisableDynamicPhysRendering = false;
  55. /*
  56. ** Chunk ID's used by DynamicPhysClass
  57. */
  58. enum
  59. {
  60. DYNAMICPHYS_CHUNK_PHYS = 813001100,
  61. };
  62. DynamicPhysClass::DynamicPhysClass(void) :
  63. DirtyVisObjectID(true),
  64. VisNodeID(0),
  65. VisStatusLastUpdated(0)
  66. {
  67. }
  68. DynamicPhysClass::~DynamicPhysClass(void)
  69. {
  70. }
  71. void DynamicPhysClass::Init(const DynamicPhysDefClass & definition)
  72. {
  73. PhysClass::Init(definition);
  74. }
  75. void DynamicPhysClass::Set_Model(RenderObjClass * model)
  76. {
  77. PhysClass::Set_Model(model);
  78. #if (UMBRASUPPORT)
  79. if (model != NULL) {
  80. /*
  81. ** Create a new test-model for the bounding box of this object
  82. */
  83. AABoxClass obj_box;
  84. model->Get_Obj_Space_Bounding_Box(obj_box);
  85. /*
  86. ** Insert it into our Umbra object
  87. */
  88. WWASSERT(UmbraObject);
  89. UmbraObject->setTestModel(UmbraSupport::Create_Box_Model(obj_box));
  90. UmbraObject->setCost(100000,100000,5);
  91. }
  92. #endif
  93. }
  94. void DynamicPhysClass::Update_Visibility_Status(void)
  95. {
  96. /*
  97. ** Invalidate our cached vis object ID
  98. */
  99. DirtyVisObjectID = true;
  100. /*
  101. ** Invalidate the lighting cache. Next time this object is rendered the cache will be updated.
  102. */
  103. Invalidate_Static_Lighting_Cache();
  104. }
  105. int DynamicPhysClass::Get_Vis_Object_ID(void)
  106. {
  107. if (DirtyVisObjectID) {
  108. Internal_Update_Visibility_Status();
  109. }
  110. return VisObjectID;
  111. }
  112. void DynamicPhysClass::Internal_Update_Visibility_Status(void)
  113. {
  114. /*
  115. ** Don't update our VIS-ID more often than 4 times per second
  116. */
  117. unsigned current_time=WW3D::Get_Sync_Time();
  118. unsigned delta = current_time - VisStatusLastUpdated;
  119. if (delta < MIN_VIS_UPDATE_TICK_DELAY) return;
  120. VisStatusLastUpdated=current_time;
  121. /*
  122. ** Update our VIS-ID
  123. */
  124. VisObjectID = PhysicsSceneClass::Get_Instance()->Get_Dynamic_Object_Vis_ID(Model->Get_Bounding_Box(),&VisNodeID);
  125. if ((int)VisObjectID >= PhysicsSceneClass::Get_Instance()->Get_Vis_Table_Size()) {
  126. int size = PhysicsSceneClass::Get_Instance()->Get_Vis_Table_Size();
  127. // int id = PhysicsSceneClass::Get_Instance()->Get_Dynamic_Object_Vis_ID(Model->Get_Bounding_Box(),&VisNodeID);
  128. WWDEBUG_SAY(("Invalid VisObjectID: %d for object: %s (max vis id = %d)\n",VisObjectID,Model->Get_Name(),size));
  129. VisObjectID = 0;
  130. }
  131. /*
  132. ** Clear the dirty bit
  133. */
  134. DirtyVisObjectID = false;
  135. /*
  136. ** Update our Umbra Object
  137. */
  138. #if (UMBRASUPPORT)
  139. UmbraSupport::Update_Umbra_Object(this);
  140. #endif
  141. }
  142. bool DynamicPhysClass::Save(ChunkSaveClass &csave)
  143. {
  144. csave.Begin_Chunk(DYNAMICPHYS_CHUNK_PHYS);
  145. PhysClass::Save(csave);
  146. csave.End_Chunk();
  147. return true;
  148. }
  149. bool DynamicPhysClass::Load(ChunkLoadClass &cload)
  150. {
  151. while (cload.Open_Chunk()) {
  152. switch(cload.Cur_Chunk_ID())
  153. {
  154. case DYNAMICPHYS_CHUNK_PHYS:
  155. PhysClass::Load(cload);
  156. break;
  157. default:
  158. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  159. break;
  160. }
  161. cload.Close_Chunk();
  162. }
  163. SaveLoadSystemClass::Register_Post_Load_Callback(this);
  164. return true;
  165. }
  166. void DynamicPhysClass::On_Post_Load(void)
  167. {
  168. PhysClass::On_Post_Load();
  169. // update cached vis object id, vis node id, and sunlight status...
  170. Update_Cull_Box();
  171. Update_Visibility_Status();
  172. }
  173. /***********************************************************************************************
  174. **
  175. ** DynamicPhysDefClass Implementation
  176. ** This holds the description for a DynamicPhysClass. Again, this class isn't concrete
  177. ** so it doesn't have factories...
  178. **
  179. ***********************************************************************************************/
  180. enum
  181. {
  182. DYNAMICPHYSDEF_CHUNK_PHYSDEF = 813001104, // parent class data.
  183. };
  184. DynamicPhysDefClass::DynamicPhysDefClass(void)
  185. {
  186. }
  187. bool DynamicPhysDefClass::Is_Valid_Config(StringClass &message)
  188. {
  189. return PhysDefClass::Is_Valid_Config(message);
  190. }
  191. bool DynamicPhysDefClass::Is_Type(const char * type_name)
  192. {
  193. if (stricmp(type_name,DynamicPhysDefClass::Get_Type_Name()) == 0) {
  194. return true;
  195. } else {
  196. return PhysDefClass::Is_Type(type_name);
  197. }
  198. }
  199. bool DynamicPhysDefClass::Save(ChunkSaveClass &csave)
  200. {
  201. csave.Begin_Chunk(DYNAMICPHYSDEF_CHUNK_PHYSDEF);
  202. PhysDefClass::Save(csave);
  203. csave.End_Chunk();
  204. return true;
  205. }
  206. bool DynamicPhysDefClass::Load(ChunkLoadClass &cload)
  207. {
  208. while (cload.Open_Chunk()) {
  209. switch(cload.Cur_Chunk_ID()) {
  210. case DYNAMICPHYSDEF_CHUNK_PHYSDEF:
  211. PhysDefClass::Load(cload);
  212. break;
  213. }
  214. cload.Close_Chunk();
  215. }
  216. return true;
  217. }