| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : wwphys *
- * *
- * $Archive:: /Commando/Code/wwphys/umbrasupport.cpp $*
- * *
- * Original Author:: Greg Hjelstrom *
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 11/29/00 4:46p $*
- * *
- * $Revision:: 1 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "umbrasupport.h"
- #if (UMBRASUPPORT)
- #include <umbra.hpp>
- #include "mesh.h"
- #include "meshmdl.h"
- #include "camera.h"
- #include "phys.h"
- class UmbraCommanderClass;
- /*
- ** Static Variables
- */
- static Umbra::Model * _DummySphere = NULL;
- static Umbra::Cell * _TheCell = NULL;
- static Umbra::Camera * _TheCamera = NULL;
- static UmbraCommanderClass * _TheCommander = NULL;
- static bool _UmbraEnabled = true;
- static Umbra::Vector3 _umbra_box_verts[8];
- static Umbra::Vector3i _umbra_box_faces[12];
- static int _umbra_box_vert_count = 8;
- static int _umbra_box_face_count = 12;
- /*
- **
- ** Local utility functions
- **
- */
- static void _convert_matrix_westwood_to_umbra(const Matrix3D & in,Umbra::Matrix4x4 & out)
- {
- #if 0
- for (int j=0;j<3;j++) {
- for (int i=0;i<4;i++) {
- out.m[j][i] = in[j][i];
- }
- }
- out.m[3][0] = 0.0;
- out.m[3][1] = 0.0;
- out.m[3][2] = 0.0;
- out.m[3][3] = 1.0;
- #endif
- #if 0
- for (int j=0;j<3;j++) {
- for (int i=0; i<3; i++) {
- out.m[i][j] = in[j][i];
- }
- }
-
- out.m[0][3] = in[0][3];
- out.m[1][3] = in[1][3];
- out.m[2][3] = in[2][3];
- out.m[3][0] = 0.0;
- out.m[3][1] = 0.0;
- out.m[3][2] = 0.0;
- out.m[3][3] = 1.0;
- #endif
- #if 1
- for (int j=0;j<3;j++) {
- for (int i=0;i<4;i++) {
- out.m[i][j] = in[j][i];
- }
- }
- out.m[0][3] = 0.0;
- out.m[1][3] = 0.0;
- out.m[2][3] = 0.0;
- out.m[3][3] = 1.0;
- #endif
- }
- static void _convert_frustum_westwood_to_umbra(const CameraClass & camera,Umbra::Frustum & out)
- {
- camera.Get_Clip_Planes(out.zNear,out.zFar);
- Vector2 vmin,vmax;
- camera.Get_View_Plane(vmin,vmax);
- out.left = vmin.X;
- out.right = vmax.X;
- out.top = vmax.Y;
- out.bottom = vmin.Y;
- // out.zFar = 1500.0;
- }
- static void _init_umbra_box(const AABoxClass & obj_bound_box)
- {
- _umbra_box_verts[0].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
- _umbra_box_verts[0].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
- _umbra_box_verts[0].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
- _umbra_box_verts[1].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
- _umbra_box_verts[1].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
- _umbra_box_verts[1].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
- _umbra_box_verts[2].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
- _umbra_box_verts[2].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
- _umbra_box_verts[2].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
- _umbra_box_verts[3].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
- _umbra_box_verts[3].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
- _umbra_box_verts[3].v[2] = obj_bound_box.Center.Z - obj_bound_box.Extent.Z;
- _umbra_box_verts[4].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
- _umbra_box_verts[4].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
- _umbra_box_verts[4].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
- _umbra_box_verts[5].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
- _umbra_box_verts[5].v[1] = obj_bound_box.Center.Y + obj_bound_box.Extent.Y;
- _umbra_box_verts[5].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
- _umbra_box_verts[6].v[0] = obj_bound_box.Center.X - obj_bound_box.Extent.X;
- _umbra_box_verts[6].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
- _umbra_box_verts[6].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
- _umbra_box_verts[7].v[0] = obj_bound_box.Center.X + obj_bound_box.Extent.X;
- _umbra_box_verts[7].v[1] = obj_bound_box.Center.Y - obj_bound_box.Extent.Y;
- _umbra_box_verts[7].v[2] = obj_bound_box.Center.Z + obj_bound_box.Extent.Z;
- // -z face
- _umbra_box_faces[0].i = 2; _umbra_box_faces[0].j = 0; _umbra_box_faces[0].k = 3;
- _umbra_box_faces[1].i = 2; _umbra_box_faces[1].j = 1; _umbra_box_faces[1].k = 0;
- // +z face
- _umbra_box_faces[2].i = 6; _umbra_box_faces[2].j = 7; _umbra_box_faces[2].k = 4;
- _umbra_box_faces[3].i = 6; _umbra_box_faces[3].j = 4; _umbra_box_faces[3].k = 5;
- // +x face
- _umbra_box_faces[4].i = 7; _umbra_box_faces[4].j = 0; _umbra_box_faces[4].k = 4;
- _umbra_box_faces[5].i = 7; _umbra_box_faces[5].j = 3; _umbra_box_faces[5].k = 0;
- // -x face
- _umbra_box_faces[6].i = 6; _umbra_box_faces[6].j = 5; _umbra_box_faces[6].k = 1;
- _umbra_box_faces[7].i = 6; _umbra_box_faces[7].j = 1; _umbra_box_faces[7].k = 2;
- // +y face
- _umbra_box_faces[8].i = 5; _umbra_box_faces[8].j = 4; _umbra_box_faces[8].k = 0;
- _umbra_box_faces[9].i = 5; _umbra_box_faces[9].j = 0; _umbra_box_faces[9].k = 1;
- // -y face
- _umbra_box_faces[10].i = 2; _umbra_box_faces[10].j = 7; _umbra_box_faces[10].k = 6;
- _umbra_box_faces[11].i = 2; _umbra_box_faces[11].j = 3; _umbra_box_faces[11].k = 7;
- }
- /**
- ** UmbraCommanderClass
- ** This is our commander for recording the results of a visibility query to Umbra
- */
- class UmbraCommanderClass : public Umbra::Commander
- {
- public:
- UmbraCommanderClass(void) : VisObjList(NULL)
- {
- }
- void Set_List(RefPhysListClass & visible_obj_list)
- {
- VisObjList = &visible_obj_list;
- }
-
- virtual void command(Command cmd)
- {
- WWASSERT(VisObjList != NULL);
- if (cmd == Umbra::Commander::INSTANCE_VISIBLE)
- {
- const Umbra::Object * obj = getInstance()->getObject();
- if (obj != NULL) {
- VisObjList->Add((PhysClass *)(obj->getUserPointer()));
- }
- }
- }
- protected:
- RefPhysListClass * VisObjList;
- };
- /*
- ** UmbraSupport implementation
- */
- void UmbraSupport::Init(void)
- {
- /*
- ** Initialize UMBRA
- */
- Umbra::Library::init(Umbra::LibraryDefs::COLUMN_MAJOR);
- /*
- ** Create the dummy sphere model
- */
- Umbra::Vector3 center;
- center.v[0] = 0.0; center.v[1] = 0.0; center.v[2] = 0.0;
- _DummySphere = new Umbra::SphereModel(center,1.0);
-
- /*
- ** Create a Cell to put everything (we don't have portals so everything is in one cell)
- */
- _TheCell = new Umbra::Cell;
- /*
- ** Create the camera
- */
- _TheCamera = new Umbra::Camera;
- _TheCamera->setCell(_TheCell);
- // _TheCamera->setParameters( 640,480,0);
- // _TheCamera->setParameters( 640,480,Umbra::Camera::VIEWFRUSTUM_CULLING);
- _TheCamera->setParameters( 640,480,Umbra::Camera::VIEWFRUSTUM_CULLING | Umbra::Camera::OCCLUSION_CULLING);
- /*
- ** Create the commander
- */
- _TheCommander = new UmbraCommanderClass;
- }
- void UmbraSupport::Shutdown(void)
- {
- /*
- ** Release everything
- */
- delete _TheCommander;
- _TheCommander = NULL;
- _TheCamera->release();
- _TheCamera = NULL;
- _TheCell->release();
- _TheCell = NULL;
- _DummySphere->release();
- _DummySphere = NULL;
- /*
- ** UMBRA shutdown
- */
- Umbra::Library::exit();
- }
- void UmbraSupport::Enable_Umbra(bool onoff)
- {
- _UmbraEnabled = onoff;
- }
- bool UmbraSupport::Is_Umbra_Enabled(void)
- {
- return _UmbraEnabled;
- }
- float UmbraSupport::Get_Umbra_Memory_Consumption(void)
- {
- return Umbra::Library::getStatistic(Umbra::Library::STAT_MEMORYUSED);
- }
- Umbra::Model * UmbraSupport::Peek_Dummy_Sphere(void)
- {
- return _DummySphere;
- }
- Umbra::Cell * UmbraSupport::Peek_Umbra_Cell(void)
- {
- return _TheCell;
- }
- Umbra::Camera * UmbraSupport::Peek_Umbra_Camera(void)
- {
- return _TheCamera;
- }
- Umbra::Model * UmbraSupport::Create_Box_Model(const AABoxClass & inputbox)
- {
- AABoxClass objbox(inputbox);
- if (objbox.Extent.Length2() < 0.001f) {
- objbox.Extent.Set(1,1,1);
- }
- _init_umbra_box(objbox);
- Umbra::Model * test_model = new Umbra::MeshModel(_umbra_box_verts,_umbra_box_faces,_umbra_box_vert_count,_umbra_box_face_count);
- test_model->autoRelease();
- return test_model;
- }
- Umbra::Model * UmbraSupport::Create_Mesh_Model(MeshClass & mesh)
- {
- MeshModelClass * mdl = mesh.Get_Model();
- Umbra::Model * new_model = NULL;
-
- if (mdl != NULL) {
- int vcount = mdl->Get_Vertex_Count();
- int fcount = mdl->Get_Polygon_Count();
- if ((vcount > 0) && (fcount > 0)) {
- Umbra::Vector3 * uverts = new Umbra::Vector3[vcount];
- Umbra::Vector3i * ufaces = new Umbra::Vector3i[fcount];
- const Vector3 * wverts = mdl->Get_Vertex_Array();
- const Vector3i * wfaces = mdl->Get_Polygon_Array();
- for (int vi = 0; vi<vcount; vi++) {
- uverts[vi].v[0] = wverts[vi].X;
- uverts[vi].v[1] = wverts[vi].Y;
- uverts[vi].v[2] = wverts[vi].Z;
- }
- for (int fi = 0; fi<fcount; fi++) {
- ufaces[fi].i = wfaces[fi].I;
- ufaces[fi].j = wfaces[fi].J;
- ufaces[fi].k = wfaces[fi].K;
- }
- new_model = new Umbra::MeshModel(uverts,ufaces,vcount,fcount);
- new_model->autoRelease();
- }
-
- REF_PTR_RELEASE(mdl);
- }
-
- if (new_model != NULL) {
- return new_model;
- } else {
- return Peek_Dummy_Sphere();
- }
- }
- void UmbraSupport::Collect_Visible_Objects(const CameraClass & camera,RefPhysListClass & visible_obj_list)
- {
- Umbra::Matrix4x4 camtocell;
- Matrix3D camtm;
- camtm = camera.Get_Transform();
- camtm.Rotate_X(DEG_TO_RAD(180.0f));
- _convert_matrix_westwood_to_umbra(camtm,camtocell);
- // _convert_matrix_westwood_to_umbra(camera.Get_Transform(),camtocell);
- _TheCamera->setCameraToCellMatrix(camtocell);
- Umbra::Frustum frustum;
- _convert_frustum_westwood_to_umbra(camera,frustum);
- _TheCamera->setFrustum(frustum);
- _TheCommander->Set_List(visible_obj_list);
- _TheCamera->resolveVisibility(_TheCommander,1,0.0);
- }
- void UmbraSupport::Update_Umbra_Object(PhysClass * obj)
- {
- Umbra::Matrix4x4 objtm;
- _convert_matrix_westwood_to_umbra(obj->Get_Transform(),objtm);
- obj->Peek_Umbra_Object()->setObjectToCellMatrix(objtm);
- }
- void UmbraSupport::Install_Umbra_Object(PhysClass * obj)
- {
- obj->Peek_Umbra_Object()->setCell(_TheCell);
- }
- void UmbraSupport::Remove_Umbra_Object(PhysClass * obj)
- {
- obj->Peek_Umbra_Object()->setCell(NULL);
- }
- #endif //UMBRASUPPORT
|