VisMgr.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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 : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/VisMgr.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 3/26/01 2:46p $*
  29. * *
  30. * $Revision:: 8 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "vismgr.h"
  37. #include "sceneeditor.h"
  38. #include "matrix3d.h"
  39. #include "w3d_file.h"
  40. #include "chunkio.h"
  41. #include "utils.h"
  42. #include "staticphys.h"
  43. #include "node.h"
  44. #include "nodemgr.h"
  45. #include "cameramgr.h"
  46. #include "camera.h"
  47. #include "vispointnode.h"
  48. #include "groupmgr.h"
  49. ///////////////////////////////////////////////////////////////////////
  50. // Local constants
  51. ///////////////////////////////////////////////////////////////////////
  52. enum
  53. {
  54. CHUNKID_VIS_OBJECT = 0x06150222,
  55. CHUNKID_VIS_DATA
  56. };
  57. ///////////////////////////////////////////////////////////////////////
  58. // Local structures
  59. ///////////////////////////////////////////////////////////////////////
  60. typedef struct
  61. {
  62. char mesh_name[W3D_NAME_LEN * 2];
  63. Matrix3D transform;
  64. int vis_id;
  65. }
  66. VIS_OBJECT_INFO;
  67. ///////////////////////////////////////////////////////////////////////
  68. //
  69. // Export_Remap_Data
  70. //
  71. ///////////////////////////////////////////////////////////////////////
  72. void
  73. VisMgrClass::Export_Remap_Data (ChunkSaveClass &csave)
  74. {
  75. //
  76. // Get the list of all static objects from the physics scene
  77. //
  78. RefPhysListIterator iterator = ::Get_Scene_Editor ()->Get_Static_Object_Iterator ();
  79. for (iterator.First (); !iterator.Is_Done (); iterator.Next ()) {
  80. //
  81. // Double-check to make sure this object is static
  82. //
  83. PhysClass *phys_obj = iterator.Peek_Obj ();
  84. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  85. if (static_phys_obj != NULL && static_phys_obj->Peek_Model () != NULL) {
  86. //
  87. // Build a structure of information about this static object
  88. //
  89. VIS_OBJECT_INFO obj_info;
  90. ::lstrcpy (obj_info.mesh_name, static_phys_obj->Peek_Model ()->Get_Name ());
  91. obj_info.transform = static_phys_obj->Get_Transform ();
  92. obj_info.vis_id = static_phys_obj->Get_Vis_Object_ID ();
  93. //
  94. // Save the object info to its own chunk
  95. //
  96. csave.Begin_Chunk (CHUNKID_VIS_OBJECT);
  97. csave.Write (&obj_info, sizeof (obj_info));
  98. csave.End_Chunk ();
  99. }
  100. }
  101. //
  102. // Now export all the vis data
  103. //
  104. csave.Begin_Chunk (CHUNKID_VIS_DATA);
  105. ::Get_Scene_Editor ()->Export_Vis_Data (csave);
  106. csave.End_Chunk ();
  107. return ;
  108. }
  109. ///////////////////////////////////////////////////////////////////////
  110. //
  111. // Import_Remap_Data
  112. //
  113. ///////////////////////////////////////////////////////////////////////
  114. void
  115. VisMgrClass::Import_Remap_Data (ChunkLoadClass &cload)
  116. {
  117. bool is_valid = true;
  118. //
  119. // Start with a clean slate
  120. //
  121. ::Get_Scene_Editor ()->Discard_Vis ();
  122. //
  123. // Process all the chunks in this file
  124. //
  125. while (is_valid && cload.Open_Chunk ()) {
  126. switch (cload.Cur_Chunk_ID ())
  127. {
  128. //
  129. // Try to remap the vis-id of this object with the
  130. // vis-id of the object in the level where vis was generated.
  131. //
  132. case CHUNKID_VIS_OBJECT:
  133. {
  134. VIS_OBJECT_INFO info;
  135. cload.Read (&info, sizeof (info));
  136. //
  137. // Attempt to find this physics object in the scene
  138. //
  139. StaticPhysClass *vis_object = Find_Static_Phys_Object (info.mesh_name, info.transform);
  140. if (vis_object != NULL) {
  141. vis_object->Set_Vis_Object_ID (info.vis_id);
  142. } else {
  143. is_valid = false;
  144. }
  145. }
  146. break;
  147. //
  148. // Import the actual vis data. If we successfully
  149. // remapped the vis-id's of all the objects, then this
  150. // should work seamlessly
  151. //
  152. case CHUNKID_VIS_DATA:
  153. {
  154. ::Get_Scene_Editor ()->Import_Vis_Data (cload);
  155. }
  156. break;
  157. }
  158. cload.Close_Chunk ();
  159. }
  160. //
  161. // Warn the user if we failed
  162. //
  163. if (is_valid == false) {
  164. ::MessageBox ( NULL,
  165. "The static geometry in this level does not match the geometry of the level in which vis was generated. Unable to import vis data into this level.",
  166. "Import Error",
  167. MB_ICONERROR | MB_OK);
  168. }
  169. return ;
  170. }
  171. ///////////////////////////////////////////////////////////////////////
  172. //
  173. // Find_Static_Phys_Object
  174. //
  175. ///////////////////////////////////////////////////////////////////////
  176. StaticPhysClass *
  177. VisMgrClass::Find_Static_Phys_Object (LPCTSTR mesh_name, const Matrix3D &tm)
  178. {
  179. StaticPhysClass *retval = NULL;
  180. //
  181. // Get the list of all static objects from the physics scene
  182. //
  183. RefPhysListIterator iterator = ::Get_Scene_Editor ()->Get_Static_Object_Iterator ();
  184. for (iterator.First (); retval == NULL && !iterator.Is_Done (); iterator.Next ()) {
  185. //
  186. // Double-check to make sure this object is static
  187. //
  188. PhysClass *phys_obj = iterator.Peek_Obj ();
  189. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  190. if (static_phys_obj != NULL && static_phys_obj->Peek_Model () != NULL) {
  191. //
  192. // Is this the object we are looking for?
  193. //
  194. LPCTSTR curr_name = static_phys_obj->Peek_Model ()->Get_Name ();
  195. Matrix3D curr_tm = static_phys_obj->Get_Transform ();
  196. if ((::lstrcmpi (curr_name, mesh_name) == 0) && (curr_tm == tm)) {
  197. retval = static_phys_obj;
  198. }
  199. }
  200. }
  201. return retval;
  202. }
  203. ///////////////////////////////////////////////////////////////////////
  204. //
  205. // Build_Node_List
  206. //
  207. ///////////////////////////////////////////////////////////////////////
  208. void
  209. VisMgrClass::Build_Node_List (DynamicVectorClass<NodeClass *> &node_list, bool selection_only)
  210. {
  211. if (selection_only) {
  212. SelectionMgrClass &sel_mgr = ::Get_Scene_Editor ()->Get_Selection_Mgr ();
  213. //
  214. // Build a list of the selected nodes that should be used to calculate
  215. // vis renders
  216. //
  217. for (int index = 0; index < sel_mgr.Get_Count (); index ++) {
  218. NodeClass *node = sel_mgr.Get_At (index);
  219. if (node != NULL && node->Is_Static ()) {
  220. Add_Nodes_To_List (node_list, node);
  221. }
  222. }
  223. } else {
  224. //
  225. // Build a list of nodes that should be used to calculate
  226. // vis renders
  227. //
  228. for (NodeClass *node = ::Get_Node_Mgr ().Get_First ();
  229. node != NULL;
  230. node = ::Get_Node_Mgr ().Get_Next (node))
  231. {
  232. if (node->Is_Static ()) {
  233. Add_Nodes_To_List (node_list, node);
  234. }
  235. }
  236. }
  237. return ;
  238. }
  239. ///////////////////////////////////////////////////////////////////////
  240. //
  241. // Add_Nodes_To_List
  242. //
  243. ///////////////////////////////////////////////////////////////////////
  244. void
  245. VisMgrClass::Add_Nodes_To_List
  246. (
  247. DynamicVectorClass<NodeClass *> &node_list,
  248. NodeClass *node
  249. )
  250. {
  251. //
  252. // If the node is an aggregate (like a terrain), we are adding the
  253. // sub-nodes directly into the list
  254. //
  255. int sub_count = node->Get_Sub_Node_Count ();
  256. if (sub_count > 0) {
  257. for (int index = 0; index < sub_count; index ++) {
  258. NodeClass *sub_node = node->Get_Sub_Node (index);
  259. //
  260. // Recurse into this node
  261. //
  262. Add_Nodes_To_List (node_list, sub_node);
  263. }
  264. } else {
  265. if (node->Has_Vis_Sectors ()) {
  266. node_list.Add (node);
  267. }
  268. }
  269. return ;
  270. }
  271. //////////////////////////////////////////////////////////////////////////////
  272. //
  273. // Render_Manual_Vis_Points
  274. //
  275. //////////////////////////////////////////////////////////////////////////////
  276. void
  277. VisMgrClass::Render_Manual_Vis_Points
  278. (
  279. bool farm_mode,
  280. int processor_index,
  281. int total_processors,
  282. VIS_POINT_RENDERED_CALLBACK callback,
  283. DWORD param
  284. )
  285. {
  286. SceneEditorClass *scene_editor = ::Get_Scene_Editor ();
  287. VisLogClass &vis_log = scene_editor->Get_Vis_Log ();
  288. CameraClass *camera = new CameraClass (*::Get_Camera_Mgr ()->Get_Camera ());
  289. bool keep_going = true;
  290. //
  291. // Bulid a list of vis points
  292. //
  293. DynamicVectorClass<VisPointNodeClass *> point_list;
  294. VisPointNodeClass *vis_point = NULL;
  295. for ( vis_point = (VisPointNodeClass *)NodeMgrClass::Get_First (NODE_TYPE_VIS_POINT);
  296. vis_point != NULL && keep_going;
  297. vis_point = (VisPointNodeClass *)NodeMgrClass::Get_Next (vis_point, NODE_TYPE_VIS_POINT))
  298. {
  299. point_list.Add (vis_point);
  300. }
  301. //
  302. // Determine which nodes to process if we
  303. // are in farm mode.
  304. //
  305. if (farm_mode) {
  306. int points = point_list.Count ();
  307. float points_per_processor = ((float)points) / ((float)total_processors);
  308. int starting_point = (int)::floor (points_per_processor* (float)processor_index);
  309. int ending_point = (int)::ceil (points_per_processor * (float)(processor_index + 1));
  310. ending_point = min (ending_point, points);
  311. //
  312. // Copy the points from the total list into a temporary list
  313. //
  314. DynamicVectorClass<VisPointNodeClass *> temp_list;
  315. for (int index = starting_point; index < ending_point; index ++) {
  316. temp_list.Add (point_list[index]);
  317. }
  318. point_list.Delete_All ();
  319. point_list = temp_list;
  320. }
  321. //
  322. // Loop over all manual vis points in the level
  323. //
  324. for (int index = 0; index < point_list.Count (); index ++)
  325. {
  326. DWORD before = ::GetTickCount ();
  327. VisPointNodeClass *vis_point = point_list[index];
  328. // Set the camera up to use the same settings we used when
  329. // we generated this manual vis point
  330. //
  331. vis_point->Setup_Camera (*camera);
  332. //
  333. // Get the camera's clip plane settings
  334. //
  335. float znear = 0;
  336. float zfar = 0;
  337. camera->Get_Clip_Planes (znear, zfar);
  338. //
  339. // Convert the object transform to a camera transform
  340. //
  341. Matrix3D transform = vis_point->Get_Transform ();
  342. Matrix3D cam_transform (Vector3 (0, -1, 0), Vector3 (0, 0, 1), Vector3 (-1, 0, 0), Vector3 (0, 0, 0));
  343. Matrix3D new_transform = transform * cam_transform;
  344. Vector3 sample_location = (new_transform * Vector3 (0, 0, -znear));
  345. //
  346. //
  347. // Render vis for this point
  348. //
  349. VisSampleClass vis_sample = scene_editor->Update_Vis (sample_location,
  350. new_transform,
  351. VisDirBitsType(VIS_FORWARD_BIT | VIS_DONT_RECENTER),
  352. camera);
  353. vis_log.Log_Sample (vis_sample);
  354. scene_editor->Create_Vis_Point (transform);
  355. //
  356. // Notify the callback that we've renedered a point
  357. //
  358. if (callback != NULL) {
  359. DWORD after = ::GetTickCount ();
  360. keep_going = (*callback) (after - before, param);
  361. }
  362. }
  363. MEMBER_RELEASE (camera);
  364. return ;
  365. }