306 lines
11 KiB
C++
306 lines
11 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/projectormanager.cpp $*
|
|
* *
|
|
* Original Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Author:: Greg_h $*
|
|
* *
|
|
* $Modtime:: 5/14/01 7:58p $*
|
|
* *
|
|
* $Revision:: 17 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "projectormanager.h"
|
|
#include "colmathaabox.h"
|
|
#include "pscene.h"
|
|
#include "assetmgr.h"
|
|
#include "chunkio.h"
|
|
#include "phystexproject.h"
|
|
#include "phys.h"
|
|
#include "texture.h"
|
|
|
|
|
|
/*
|
|
** load up a texture. also strips off the path since the game has everything
|
|
** on one place
|
|
*/
|
|
TextureClass * create_projector_texture_from_filename( const char * filename )
|
|
{
|
|
StringClass tex_name = filename;
|
|
if (::strchr(tex_name, '\\') != 0) {
|
|
tex_name = ::strrchr(filename, '\\') + 1;
|
|
}
|
|
|
|
TextureClass * texture = WW3DAssetManager::Get_Instance()->Get_Texture(tex_name,TextureClass::MIP_LEVELS_1);
|
|
if (texture == NULL) {
|
|
WWDEBUG_SAY(("Failed to create %s from %s\n", (const char *)tex_name, filename));
|
|
}
|
|
return texture;
|
|
}
|
|
|
|
|
|
/********************************************************************************************
|
|
**
|
|
** ProjectorManagerClass Implementation
|
|
**
|
|
********************************************************************************************/
|
|
|
|
ProjectorManagerClass::ProjectorManagerClass(void) :
|
|
Projector(NULL),
|
|
ProjectorBoneIndex(0)
|
|
{
|
|
}
|
|
|
|
ProjectorManagerClass::~ProjectorManagerClass(void)
|
|
{
|
|
Free();
|
|
}
|
|
|
|
void ProjectorManagerClass::Free(void)
|
|
{
|
|
if (Projector) {
|
|
PhysicsSceneClass::Get_Instance()->Remove_Texture_Projector(Projector);
|
|
Projector->Release_Ref();
|
|
Projector = NULL;
|
|
}
|
|
ProjectorBoneIndex = 0;
|
|
}
|
|
|
|
void ProjectorManagerClass::Init(const ProjectorManagerDefClass & def,RenderObjClass * model)
|
|
{
|
|
Free();
|
|
WWASSERT(Projector == NULL);
|
|
|
|
if (model == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (def.IsEnabled) {
|
|
|
|
/*
|
|
** Create the projector
|
|
*/
|
|
Projector = NEW_REF(PhysTexProjectClass, ());
|
|
Projector->Peek_Material_Pass()->Enable_On_Translucent_Meshes(false);
|
|
|
|
if (Projector != NULL) {
|
|
/*
|
|
** Set up projection parameters
|
|
*/
|
|
if (def.IsPerspective) {
|
|
Projector->Set_Perspective_Projection( def.HorizontalFOV,
|
|
def.VerticalFOV,
|
|
def.NearZ,
|
|
def.FarZ);
|
|
} else {
|
|
Projector->Set_Ortho_Projection( -def.OrthoWidth * 0.5f,def.OrthoWidth * 0.5f,
|
|
-def.OrthoHeight * 0.5f,def.OrthoHeight * 0.5f,
|
|
def.NearZ,def.FarZ);
|
|
}
|
|
|
|
/*
|
|
** Set up the blending
|
|
*/
|
|
if (def.IsAdditive) {
|
|
Projector->Init_Additive();
|
|
} else {
|
|
Projector->Init_Multiplicative();
|
|
}
|
|
Projector->Set_Intensity(def.Intensity);
|
|
|
|
/*
|
|
** Install the texture
|
|
*/
|
|
TextureClass * tex = create_projector_texture_from_filename(def.TextureName);
|
|
|
|
if (tex != NULL) {
|
|
tex->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
|
|
tex->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
|
|
Projector->Set_Texture(tex);
|
|
tex->Release_Ref();
|
|
} else {
|
|
Projector->Release_Ref();
|
|
Projector = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
** If the projector is animated, resolve the bone name into a bone index and install it into the scene
|
|
** If it is not animated, add it as a static projector (for more efficient culling)
|
|
*/
|
|
if (Projector != NULL) {
|
|
|
|
/*
|
|
** Find the bone
|
|
*/
|
|
ProjectorBoneIndex = model->Get_Bone_Index(def.BoneName);
|
|
if (ProjectorBoneIndex == 0xFFFF) {
|
|
ProjectorBoneIndex = 0;
|
|
}
|
|
Projector->Set_Transform(model->Get_Bone_Transform(ProjectorBoneIndex));
|
|
|
|
Set_Flag(IS_ANIMATED,(def.IsAnimated) && (ProjectorBoneIndex != 0));
|
|
|
|
if (Get_Flag(IS_ANIMATED)) {
|
|
PhysicsSceneClass::Get_Instance()->Add_Dynamic_Texture_Projector(Projector);
|
|
} else {
|
|
PhysicsSceneClass::Get_Instance()->Add_Static_Texture_Projector(Projector);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProjectorManagerClass::Update_From_Model(RenderObjClass * model)
|
|
{
|
|
if ((Projector != NULL) && (ProjectorBoneIndex != -1)) {
|
|
const Matrix3D & tm = model->Get_Bone_Transform(ProjectorBoneIndex);
|
|
Projector->Set_Transform(tm);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************************************
|
|
**
|
|
** ProjectorManagerDefClass Implementation
|
|
** Note, ProjectorManagerDef is not a full-fleged definition class. It is meant to be
|
|
** embedded inside another real definition.
|
|
**
|
|
********************************************************************************************/
|
|
|
|
enum
|
|
{
|
|
PROJECTORMANAGERDEF_CHUNK_VARIABLES = 0x01110004,
|
|
|
|
PROJECTORMANAGERDEF_VARIABLE_ISENABLED = 0x00,
|
|
PROJECTORMANAGERDEF_VARIABLE_ISPERSPECTIVE,
|
|
PROJECTORMANAGERDEF_VARIABLE_ISADDITIVE,
|
|
PROJECTORMANAGERDEF_VARIABLE_ISANIMATED,
|
|
PROJECTORMANAGERDEF_VARIABLE_ORTHOWIDTH,
|
|
PROJECTORMANAGERDEF_VARIABLE_ORTHOHEIGHT,
|
|
PROJECTORMANAGERDEF_VARIABLE_HORIZONTALFOV,
|
|
PROJECTORMANAGERDEF_VARIABLE_VERTICALFOV,
|
|
PROJECTORMANAGERDEF_VARIABLE_NEARZ,
|
|
PROJECTORMANAGERDEF_VARIABLE_FARZ,
|
|
PROJECTORMANAGERDEF_VARIABLE_TEXTURENAME,
|
|
PROJECTORMANAGERDEF_VARIABLE_BONENAME,
|
|
|
|
PROJECTORMANAGERDEF_VARIABLE_INTENSITY,
|
|
};
|
|
|
|
|
|
ProjectorManagerDefClass::ProjectorManagerDefClass(void) :
|
|
IsEnabled(false),
|
|
IsPerspective(false),
|
|
IsAdditive(false),
|
|
IsAnimated(false),
|
|
OrthoWidth(10.0f),
|
|
OrthoHeight(10.0f),
|
|
HorizontalFOV(DEG_TO_RADF(10.0f)),
|
|
VerticalFOV(DEG_TO_RADF(10.0f)),
|
|
NearZ(5.0f),
|
|
FarZ(20.0f),
|
|
Intensity(1.0f)
|
|
{
|
|
}
|
|
|
|
ProjectorManagerDefClass::~ProjectorManagerDefClass(void)
|
|
{
|
|
}
|
|
|
|
void ProjectorManagerDefClass::Validate_Parameters(void)
|
|
{
|
|
if (HorizontalFOV <= 0.0f) { HorizontalFOV = DEG_TO_RADF(10.0f); }
|
|
if (VerticalFOV <= 0.0f) { VerticalFOV = DEG_TO_RADF(10.0f); }
|
|
if (OrthoWidth <= 0.0f) { OrthoWidth = 10.0f; }
|
|
if (OrthoHeight <= 0.0f) { OrthoHeight = 10.0f; }
|
|
if (NearZ < 0.0f) { NearZ = 0.0f; }
|
|
if (FarZ < NearZ) { FarZ = NearZ + 10.0f; }
|
|
}
|
|
|
|
bool ProjectorManagerDefClass::Save(ChunkSaveClass &csave)
|
|
{
|
|
Validate_Parameters();
|
|
|
|
csave.Begin_Chunk(PROJECTORMANAGERDEF_CHUNK_VARIABLES);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ISENABLED,IsEnabled);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ISPERSPECTIVE,IsPerspective);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ISADDITIVE,IsAdditive);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ISANIMATED,IsAnimated);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ORTHOWIDTH,OrthoWidth);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_ORTHOHEIGHT,OrthoHeight);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_HORIZONTALFOV,HorizontalFOV);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_VERTICALFOV,VerticalFOV);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_NEARZ,NearZ);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_FARZ,FarZ);
|
|
WRITE_MICRO_CHUNK_WWSTRING(csave,PROJECTORMANAGERDEF_VARIABLE_TEXTURENAME,TextureName);
|
|
WRITE_MICRO_CHUNK_WWSTRING(csave,PROJECTORMANAGERDEF_VARIABLE_BONENAME,BoneName);
|
|
WRITE_MICRO_CHUNK(csave,PROJECTORMANAGERDEF_VARIABLE_INTENSITY,Intensity);
|
|
csave.End_Chunk();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ProjectorManagerDefClass::Load(ChunkLoadClass &cload)
|
|
{
|
|
while (cload.Open_Chunk()) {
|
|
|
|
switch(cload.Cur_Chunk_ID()) {
|
|
|
|
case PROJECTORMANAGERDEF_CHUNK_VARIABLES:
|
|
while (cload.Open_Micro_Chunk()) {
|
|
switch(cload.Cur_Micro_Chunk_ID()) {
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ISENABLED,IsEnabled);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ISPERSPECTIVE,IsPerspective);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ISADDITIVE,IsAdditive);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ISANIMATED,IsAnimated);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ORTHOWIDTH,OrthoWidth);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_ORTHOHEIGHT,OrthoHeight);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_HORIZONTALFOV,HorizontalFOV);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_VERTICALFOV,VerticalFOV);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_NEARZ,NearZ);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_FARZ,FarZ);
|
|
READ_MICRO_CHUNK_WWSTRING(cload,PROJECTORMANAGERDEF_VARIABLE_TEXTURENAME,TextureName);
|
|
READ_MICRO_CHUNK_WWSTRING(cload,PROJECTORMANAGERDEF_VARIABLE_BONENAME,BoneName);
|
|
READ_MICRO_CHUNK(cload,PROJECTORMANAGERDEF_VARIABLE_INTENSITY,Intensity);
|
|
}
|
|
cload.Close_Micro_Chunk();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
|
|
break;
|
|
}
|
|
|
|
cload.Close_Chunk();
|
|
}
|
|
return true;
|
|
}
|