272 lines
7.5 KiB
C++
272 lines
7.5 KiB
C++
|
/*
|
||
|
** 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/dynamicphys.cpp $*
|
||
|
* *
|
||
|
* Original Author:: Greg Hjelstrom *
|
||
|
* *
|
||
|
* $Author:: Greg_h $*
|
||
|
* *
|
||
|
* $Modtime:: 3/29/02 2:49p $*
|
||
|
* *
|
||
|
* $Revision:: 17 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
|
||
|
#include "dynamicphys.h"
|
||
|
#include "chunkio.h"
|
||
|
#include "pscene.h"
|
||
|
#include "wwprofile.h"
|
||
|
#include "physcoltest.h"
|
||
|
|
||
|
#if (UMBRASUPPORT)
|
||
|
#include <umbra.hpp>
|
||
|
#endif
|
||
|
|
||
|
#include "umbrasupport.h"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
**
|
||
|
** DynamicPhysClass Implementation
|
||
|
** Note that this is not a concrete class. It therefore does not have factories defined...
|
||
|
**
|
||
|
***********************************************************************************************/
|
||
|
|
||
|
const int MIN_VIS_UPDATE_TICK_DELAY = 250; // min number of milliseconds between dynamic vis id updates
|
||
|
|
||
|
bool DynamicPhysClass::_DisableDynamicPhysSimulation = false;
|
||
|
bool DynamicPhysClass::_DisableDynamicPhysRendering = false;
|
||
|
|
||
|
|
||
|
/*
|
||
|
** Chunk ID's used by DynamicPhysClass
|
||
|
*/
|
||
|
enum
|
||
|
{
|
||
|
DYNAMICPHYS_CHUNK_PHYS = 813001100,
|
||
|
};
|
||
|
|
||
|
|
||
|
DynamicPhysClass::DynamicPhysClass(void) :
|
||
|
DirtyVisObjectID(true),
|
||
|
VisNodeID(0),
|
||
|
VisStatusLastUpdated(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
DynamicPhysClass::~DynamicPhysClass(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void DynamicPhysClass::Init(const DynamicPhysDefClass & definition)
|
||
|
{
|
||
|
PhysClass::Init(definition);
|
||
|
}
|
||
|
|
||
|
void DynamicPhysClass::Set_Model(RenderObjClass * model)
|
||
|
{
|
||
|
PhysClass::Set_Model(model);
|
||
|
|
||
|
#if (UMBRASUPPORT)
|
||
|
if (model != NULL) {
|
||
|
/*
|
||
|
** Create a new test-model for the bounding box of this object
|
||
|
*/
|
||
|
AABoxClass obj_box;
|
||
|
model->Get_Obj_Space_Bounding_Box(obj_box);
|
||
|
|
||
|
/*
|
||
|
** Insert it into our Umbra object
|
||
|
*/
|
||
|
WWASSERT(UmbraObject);
|
||
|
UmbraObject->setTestModel(UmbraSupport::Create_Box_Model(obj_box));
|
||
|
UmbraObject->setCost(100000,100000,5);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void DynamicPhysClass::Update_Visibility_Status(void)
|
||
|
{
|
||
|
/*
|
||
|
** Invalidate our cached vis object ID
|
||
|
*/
|
||
|
DirtyVisObjectID = true;
|
||
|
|
||
|
/*
|
||
|
** Invalidate the lighting cache. Next time this object is rendered the cache will be updated.
|
||
|
*/
|
||
|
Invalidate_Static_Lighting_Cache();
|
||
|
}
|
||
|
|
||
|
int DynamicPhysClass::Get_Vis_Object_ID(void)
|
||
|
{
|
||
|
if (DirtyVisObjectID) {
|
||
|
Internal_Update_Visibility_Status();
|
||
|
}
|
||
|
return VisObjectID;
|
||
|
}
|
||
|
|
||
|
void DynamicPhysClass::Internal_Update_Visibility_Status(void)
|
||
|
{
|
||
|
/*
|
||
|
** Don't update our VIS-ID more often than 4 times per second
|
||
|
*/
|
||
|
unsigned current_time=WW3D::Get_Sync_Time();
|
||
|
unsigned delta = current_time - VisStatusLastUpdated;
|
||
|
|
||
|
if (delta < MIN_VIS_UPDATE_TICK_DELAY) return;
|
||
|
VisStatusLastUpdated=current_time;
|
||
|
|
||
|
/*
|
||
|
** Update our VIS-ID
|
||
|
*/
|
||
|
VisObjectID = PhysicsSceneClass::Get_Instance()->Get_Dynamic_Object_Vis_ID(Model->Get_Bounding_Box(),&VisNodeID);
|
||
|
if ((int)VisObjectID >= PhysicsSceneClass::Get_Instance()->Get_Vis_Table_Size()) {
|
||
|
|
||
|
int size = PhysicsSceneClass::Get_Instance()->Get_Vis_Table_Size();
|
||
|
// int id = PhysicsSceneClass::Get_Instance()->Get_Dynamic_Object_Vis_ID(Model->Get_Bounding_Box(),&VisNodeID);
|
||
|
|
||
|
WWDEBUG_SAY(("Invalid VisObjectID: %d for object: %s (max vis id = %d)\n",VisObjectID,Model->Get_Name(),size));
|
||
|
VisObjectID = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Clear the dirty bit
|
||
|
*/
|
||
|
DirtyVisObjectID = false;
|
||
|
|
||
|
/*
|
||
|
** Update our Umbra Object
|
||
|
*/
|
||
|
#if (UMBRASUPPORT)
|
||
|
UmbraSupport::Update_Umbra_Object(this);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
bool DynamicPhysClass::Save(ChunkSaveClass &csave)
|
||
|
{
|
||
|
csave.Begin_Chunk(DYNAMICPHYS_CHUNK_PHYS);
|
||
|
PhysClass::Save(csave);
|
||
|
csave.End_Chunk();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool DynamicPhysClass::Load(ChunkLoadClass &cload)
|
||
|
{
|
||
|
while (cload.Open_Chunk()) {
|
||
|
|
||
|
switch(cload.Cur_Chunk_ID())
|
||
|
{
|
||
|
case DYNAMICPHYS_CHUNK_PHYS:
|
||
|
PhysClass::Load(cload);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
cload.Close_Chunk();
|
||
|
}
|
||
|
SaveLoadSystemClass::Register_Post_Load_Callback(this);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void DynamicPhysClass::On_Post_Load(void)
|
||
|
{
|
||
|
PhysClass::On_Post_Load();
|
||
|
|
||
|
// update cached vis object id, vis node id, and sunlight status...
|
||
|
Update_Cull_Box();
|
||
|
Update_Visibility_Status();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
**
|
||
|
** DynamicPhysDefClass Implementation
|
||
|
** This holds the description for a DynamicPhysClass. Again, this class isn't concrete
|
||
|
** so it doesn't have factories...
|
||
|
**
|
||
|
***********************************************************************************************/
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
DYNAMICPHYSDEF_CHUNK_PHYSDEF = 813001104, // parent class data.
|
||
|
};
|
||
|
|
||
|
|
||
|
DynamicPhysDefClass::DynamicPhysDefClass(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool DynamicPhysDefClass::Is_Valid_Config(StringClass &message)
|
||
|
{
|
||
|
return PhysDefClass::Is_Valid_Config(message);
|
||
|
}
|
||
|
|
||
|
bool DynamicPhysDefClass::Is_Type(const char * type_name)
|
||
|
{
|
||
|
if (stricmp(type_name,DynamicPhysDefClass::Get_Type_Name()) == 0) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return PhysDefClass::Is_Type(type_name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool DynamicPhysDefClass::Save(ChunkSaveClass &csave)
|
||
|
{
|
||
|
csave.Begin_Chunk(DYNAMICPHYSDEF_CHUNK_PHYSDEF);
|
||
|
PhysDefClass::Save(csave);
|
||
|
csave.End_Chunk();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool DynamicPhysDefClass::Load(ChunkLoadClass &cload)
|
||
|
{
|
||
|
while (cload.Open_Chunk()) {
|
||
|
|
||
|
switch(cload.Cur_Chunk_ID()) {
|
||
|
|
||
|
case DYNAMICPHYSDEF_CHUNK_PHYSDEF:
|
||
|
PhysDefClass::Load(cload);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
cload.Close_Chunk();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|