umbrasupport.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 : wwphys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/umbrasupport.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 11/29/00 4:46p $*
  31. * *
  32. * $Revision:: 1 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "umbrasupport.h"
  38. #if (UMBRASUPPORT)
  39. #include <umbra.hpp>
  40. #include "mesh.h"
  41. #include "meshmdl.h"
  42. #include "camera.h"
  43. #include "phys.h"
  44. class UmbraCommanderClass;
  45. /*
  46. ** Static Variables
  47. */
  48. static Umbra::Model * _DummySphere = NULL;
  49. static Umbra::Cell * _TheCell = NULL;
  50. static Umbra::Camera * _TheCamera = NULL;
  51. static UmbraCommanderClass * _TheCommander = NULL;
  52. static bool _UmbraEnabled = true;
  53. static Umbra::Vector3 _umbra_box_verts[8];
  54. static Umbra::Vector3i _umbra_box_faces[12];
  55. static int _umbra_box_vert_count = 8;
  56. static int _umbra_box_face_count = 12;
  57. /*
  58. **
  59. ** Local utility functions
  60. **
  61. */
  62. static void _convert_matrix_westwood_to_umbra(const Matrix3D & in,Umbra::Matrix4x4 & out)
  63. {
  64. #if 0
  65. for (int j=0;j<3;j++) {
  66. for (int i=0;i<4;i++) {
  67. out.m[j][i] = in[j][i];
  68. }
  69. }
  70. out.m[3][0] = 0.0;
  71. out.m[3][1] = 0.0;
  72. out.m[3][2] = 0.0;
  73. out.m[3][3] = 1.0;
  74. #endif
  75. #if 0
  76. for (int j=0;j<3;j++) {
  77. for (int i=0; i<3; i++) {
  78. out.m[i][j] = in[j][i];
  79. }
  80. }
  81. out.m[0][3] = in[0][3];
  82. out.m[1][3] = in[1][3];
  83. out.m[2][3] = in[2][3];
  84. out.m[3][0] = 0.0;
  85. out.m[3][1] = 0.0;
  86. out.m[3][2] = 0.0;
  87. out.m[3][3] = 1.0;
  88. #endif
  89. #if 1
  90. for (int j=0;j<3;j++) {
  91. for (int i=0;i<4;i++) {
  92. out.m[i][j] = in[j][i];
  93. }
  94. }
  95. out.m[0][3] = 0.0;
  96. out.m[1][3] = 0.0;
  97. out.m[2][3] = 0.0;
  98. out.m[3][3] = 1.0;
  99. #endif
  100. }
  101. static void _convert_frustum_westwood_to_umbra(const CameraClass & camera,Umbra::Frustum & out)
  102. {
  103. camera.Get_Clip_Planes(out.zNear,out.zFar);
  104. Vector2 vmin,vmax;
  105. camera.Get_View_Plane(vmin,vmax);
  106. out.left = vmin.X;
  107. out.right = vmax.X;
  108. out.top = vmax.Y;
  109. out.bottom = vmin.Y;
  110. // out.zFar = 1500.0;
  111. }
  112. static void _init_umbra_box(const AABoxClass & obj_bound_box)
  113. {
  114. _umbra_box_verts[0].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
  115. _umbra_box_verts[0].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
  116. _umbra_box_verts[0].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
  117. _umbra_box_verts[1].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
  118. _umbra_box_verts[1].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
  119. _umbra_box_verts[1].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
  120. _umbra_box_verts[2].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
  121. _umbra_box_verts[2].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
  122. _umbra_box_verts[2].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
  123. _umbra_box_verts[3].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
  124. _umbra_box_verts[3].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
  125. _umbra_box_verts[3].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
  126. _umbra_box_verts[4].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
  127. _umbra_box_verts[4].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
  128. _umbra_box_verts[4].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
  129. _umbra_box_verts[5].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
  130. _umbra_box_verts[5].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
  131. _umbra_box_verts[5].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
  132. _umbra_box_verts[6].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
  133. _umbra_box_verts[6].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
  134. _umbra_box_verts[6].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
  135. _umbra_box_verts[7].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
  136. _umbra_box_verts[7].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
  137. _umbra_box_verts[7].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
  138. // -z face
  139. _umbra_box_faces[0].i = 2; _umbra_box_faces[0].j = 0; _umbra_box_faces[0].k = 3;
  140. _umbra_box_faces[1].i = 2; _umbra_box_faces[1].j = 1; _umbra_box_faces[1].k = 0;
  141. // +z face
  142. _umbra_box_faces[2].i = 6; _umbra_box_faces[2].j = 7; _umbra_box_faces[2].k = 4;
  143. _umbra_box_faces[3].i = 6; _umbra_box_faces[3].j = 4; _umbra_box_faces[3].k = 5;
  144. // +x face
  145. _umbra_box_faces[4].i = 7; _umbra_box_faces[4].j = 0; _umbra_box_faces[4].k = 4;
  146. _umbra_box_faces[5].i = 7; _umbra_box_faces[5].j = 3; _umbra_box_faces[5].k = 0;
  147. // -x face
  148. _umbra_box_faces[6].i = 6; _umbra_box_faces[6].j = 5; _umbra_box_faces[6].k = 1;
  149. _umbra_box_faces[7].i = 6; _umbra_box_faces[7].j = 1; _umbra_box_faces[7].k = 2;
  150. // +y face
  151. _umbra_box_faces[8].i = 5; _umbra_box_faces[8].j = 4; _umbra_box_faces[8].k = 0;
  152. _umbra_box_faces[9].i = 5; _umbra_box_faces[9].j = 0; _umbra_box_faces[9].k = 1;
  153. // -y face
  154. _umbra_box_faces[10].i = 2; _umbra_box_faces[10].j = 7; _umbra_box_faces[10].k = 6;
  155. _umbra_box_faces[11].i = 2; _umbra_box_faces[11].j = 3; _umbra_box_faces[11].k = 7;
  156. }
  157. /**
  158. ** UmbraCommanderClass
  159. ** This is our commander for recording the results of a visibility query to Umbra
  160. */
  161. class UmbraCommanderClass : public Umbra::Commander
  162. {
  163. public:
  164. UmbraCommanderClass(void) : VisObjList(NULL)
  165. {
  166. }
  167. void Set_List(RefPhysListClass & visible_obj_list)
  168. {
  169. VisObjList = &visible_obj_list;
  170. }
  171. virtual void command(Command cmd)
  172. {
  173. WWASSERT(VisObjList != NULL);
  174. if (cmd == Umbra::Commander::INSTANCE_VISIBLE)
  175. {
  176. const Umbra::Object * obj = getInstance()->getObject();
  177. if (obj != NULL) {
  178. VisObjList->Add((PhysClass *)(obj->getUserPointer()));
  179. }
  180. }
  181. }
  182. protected:
  183. RefPhysListClass * VisObjList;
  184. };
  185. /*
  186. ** UmbraSupport implementation
  187. */
  188. void UmbraSupport::Init(void)
  189. {
  190. /*
  191. ** Initialize UMBRA
  192. */
  193. Umbra::Library::init(Umbra::LibraryDefs::COLUMN_MAJOR);
  194. /*
  195. ** Create the dummy sphere model
  196. */
  197. Umbra::Vector3 center;
  198. center.v[0] = 0.0; center.v[1] = 0.0; center.v[2] = 0.0;
  199. _DummySphere = new Umbra::SphereModel(center,1.0);
  200. /*
  201. ** Create a Cell to put everything (we don't have portals so everything is in one cell)
  202. */
  203. _TheCell = new Umbra::Cell;
  204. /*
  205. ** Create the camera
  206. */
  207. _TheCamera = new Umbra::Camera;
  208. _TheCamera->setCell(_TheCell);
  209. // _TheCamera->setParameters( 640,480,0);
  210. // _TheCamera->setParameters( 640,480,Umbra::Camera::VIEWFRUSTUM_CULLING);
  211. _TheCamera->setParameters( 640,480,Umbra::Camera::VIEWFRUSTUM_CULLING | Umbra::Camera::OCCLUSION_CULLING);
  212. /*
  213. ** Create the commander
  214. */
  215. _TheCommander = new UmbraCommanderClass;
  216. }
  217. void UmbraSupport::Shutdown(void)
  218. {
  219. /*
  220. ** Release everything
  221. */
  222. delete _TheCommander;
  223. _TheCommander = NULL;
  224. _TheCamera->release();
  225. _TheCamera = NULL;
  226. _TheCell->release();
  227. _TheCell = NULL;
  228. _DummySphere->release();
  229. _DummySphere = NULL;
  230. /*
  231. ** UMBRA shutdown
  232. */
  233. Umbra::Library::exit();
  234. }
  235. void UmbraSupport::Enable_Umbra(bool onoff)
  236. {
  237. _UmbraEnabled = onoff;
  238. }
  239. bool UmbraSupport::Is_Umbra_Enabled(void)
  240. {
  241. return _UmbraEnabled;
  242. }
  243. float UmbraSupport::Get_Umbra_Memory_Consumption(void)
  244. {
  245. return Umbra::Library::getStatistic(Umbra::Library::STAT_MEMORYUSED);
  246. }
  247. Umbra::Model * UmbraSupport::Peek_Dummy_Sphere(void)
  248. {
  249. return _DummySphere;
  250. }
  251. Umbra::Cell * UmbraSupport::Peek_Umbra_Cell(void)
  252. {
  253. return _TheCell;
  254. }
  255. Umbra::Camera * UmbraSupport::Peek_Umbra_Camera(void)
  256. {
  257. return _TheCamera;
  258. }
  259. Umbra::Model * UmbraSupport::Create_Box_Model(const AABoxClass & inputbox)
  260. {
  261. AABoxClass objbox(inputbox);
  262. if (objbox.Extent.Length2() < 0.001f) {
  263. objbox.Extent.Set(1,1,1);
  264. }
  265. _init_umbra_box(objbox);
  266. Umbra::Model * test_model = new Umbra::MeshModel(_umbra_box_verts,_umbra_box_faces,_umbra_box_vert_count,_umbra_box_face_count);
  267. test_model->autoRelease();
  268. return test_model;
  269. }
  270. Umbra::Model * UmbraSupport::Create_Mesh_Model(MeshClass & mesh)
  271. {
  272. MeshModelClass * mdl = mesh.Get_Model();
  273. Umbra::Model * new_model = NULL;
  274. if (mdl != NULL) {
  275. int vcount = mdl->Get_Vertex_Count();
  276. int fcount = mdl->Get_Polygon_Count();
  277. if ((vcount > 0) && (fcount > 0)) {
  278. Umbra::Vector3 * uverts = new Umbra::Vector3[vcount];
  279. Umbra::Vector3i * ufaces = new Umbra::Vector3i[fcount];
  280. const Vector3 * wverts = mdl->Get_Vertex_Array();
  281. const Vector3i * wfaces = mdl->Get_Polygon_Array();
  282. for (int vi = 0; vi<vcount; vi++) {
  283. uverts[vi].v[0] = wverts[vi].X;
  284. uverts[vi].v[1] = wverts[vi].Y;
  285. uverts[vi].v[2] = wverts[vi].Z;
  286. }
  287. for (int fi = 0; fi<fcount; fi++) {
  288. ufaces[fi].i = wfaces[fi].I;
  289. ufaces[fi].j = wfaces[fi].J;
  290. ufaces[fi].k = wfaces[fi].K;
  291. }
  292. new_model = new Umbra::MeshModel(uverts,ufaces,vcount,fcount);
  293. new_model->autoRelease();
  294. }
  295. REF_PTR_RELEASE(mdl);
  296. }
  297. if (new_model != NULL) {
  298. return new_model;
  299. } else {
  300. return Peek_Dummy_Sphere();
  301. }
  302. }
  303. void UmbraSupport::Collect_Visible_Objects(const CameraClass & camera,RefPhysListClass & visible_obj_list)
  304. {
  305. Umbra::Matrix4x4 camtocell;
  306. Matrix3D camtm;
  307. camtm = camera.Get_Transform();
  308. camtm.Rotate_X(DEG_TO_RAD(180.0f));
  309. _convert_matrix_westwood_to_umbra(camtm,camtocell);
  310. // _convert_matrix_westwood_to_umbra(camera.Get_Transform(),camtocell);
  311. _TheCamera->setCameraToCellMatrix(camtocell);
  312. Umbra::Frustum frustum;
  313. _convert_frustum_westwood_to_umbra(camera,frustum);
  314. _TheCamera->setFrustum(frustum);
  315. _TheCommander->Set_List(visible_obj_list);
  316. _TheCamera->resolveVisibility(_TheCommander,1,0.0);
  317. }
  318. void UmbraSupport::Update_Umbra_Object(PhysClass * obj)
  319. {
  320. Umbra::Matrix4x4 objtm;
  321. _convert_matrix_westwood_to_umbra(obj->Get_Transform(),objtm);
  322. obj->Peek_Umbra_Object()->setObjectToCellMatrix(objtm);
  323. }
  324. void UmbraSupport::Install_Umbra_Object(PhysClass * obj)
  325. {
  326. obj->Peek_Umbra_Object()->setCell(_TheCell);
  327. }
  328. void UmbraSupport::Remove_Umbra_Object(PhysClass * obj)
  329. {
  330. obj->Peek_Umbra_Object()->setCell(NULL);
  331. }
  332. #endif //UMBRASUPPORT