This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/ww3d2/decalsys.h

308 lines
12 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 : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/decalsys.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 6/29/01 11:30a $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef DECALSYS_H
#define DECALSYS_H
#include "always.h"
#include "matrix3d.h"
#include "matrix4.h"
#include "obbox.h"
#include "robjlist.h"
#include "matpass.h"
#include "projector.h"
class DecalGeneratorClass;
class DecalMeshClass;
/**
** DecalSystemClass
** This is a class that manages creation and destruction of decals in the system. It is
** meant to be over-ridden for game-specific behaviors.
**
** Sample Code:
** 1 - Create the generator. The system gives it a unique id and gives you a clean decal generator
**
** DecalGeneratorClass * gen = DecalSystem->Lock_Decal_Generator();
** gen->Set_Transform(tm);
** gen->Set_Projection(proj_tm);
** gen->Set_Bounds(OBBox);
**
** 2 - Apply the generator to any objects that you want it to affect. It wont do anything if it
** does not overlap any polygons in those objects
**
** Scene->Collect_Objects(gen->Get_Bounding_Box(),objectlist);
** for (iterator.First(objectlist); !iterator.Is_Done(); iterator.Next()) {
** iterator.Peek_Object()->Create_Decal(gen);
** }
**
** 3 - Release the generator back to the system. At this point, the system may record which meshes
** actually generated extra decal polygons for future removal. All of this information will be
** tied together with the unique 'decal ID' that was assigned to the generator.
**
** DecalSystem->Unlock_Decal_Generator(gen);
**
*/
class DecalSystemClass
{
public:
DecalSystemClass(void);
virtual ~DecalSystemClass(void);
/*
** Create and release DecalGenerators. Note that this is the point at which the
** decal system can track "logical" decals. The generator will keep an internal list
** of all of the render objects which generated decals which you should copy if you
** want to track them (e.g. if you want to cap the maximum number of active decals and
** kill the old ones...)
*/
virtual DecalGeneratorClass * Lock_Decal_Generator(void);
virtual void Unlock_Decal_Generator(DecalGeneratorClass * generator);
/*
** When a decal-mesh is destroyed, it must inform the DecalSystem. Otherwise, systems
** which track decals can get dangling pointers.
*/
virtual void Decal_Mesh_Destroyed(uint32 decal_id,DecalMeshClass * mesh) { }
protected:
/*
** This generates the decal ID when a generator is created. This decal system reroutes this
** to Generate_Unique_Global_Decal_Id(), but other decal systems may use a different method.
*/
virtual uint32 Generate_Decal_Id(void) { return Generate_Unique_Global_Decal_Id(); }
/*
** Unique ID generation for decals. Not all decal systems have to use
** this method of generating ids. Some may wish to assign the id as the
** array index of the logical id or use some other aritrary method.
*/
static uint32 Generate_Unique_Global_Decal_Id(void);
static uint32 DecalIDGenerator;
};
/**
** DecalGeneratorClass
** This class encapsulates the information needed to generate a decal. It also tracks
** what meshes actually used it to generate new decal polygons.
*/
class DecalGeneratorClass : public ProjectorClass
{
public:
/*
** All meshes that actually generate decal polygons should register themselves in the
** list. Then when the decal generation is finished, this list can be copied so that
** we can come back to those meshes and remove the decals if we want to.
*/
void Add_Mesh(RenderObjClass * mesh);
NonRefRenderObjListClass & Get_Mesh_List(void);
/*
** Decal generator parameters.
** see ProjectorClass for control over the coordinate system, projection, etc
*/
uint32 Get_Decal_ID(void) { return DecalID; }
DecalSystemClass * Peek_Decal_System(void) { return System; }
/*
** Backface rejection thresh-hold. The dot-product between the projection vector and
** the normal of each polygon is taken, if the result is greater than this value the polygon
** is accepted into the decal. Set it to -1 if you want to accept all polygons.
*/
void Set_Backface_Threshhold(float val) { BackfaceVal = val; }
float Get_Backface_Threshhold(void) { return BackfaceVal; }
/*
** Normally, decals are not generated on translucent meshes. This is due to the "floating
** decals" that you can get on things like trees. The user can override this behavior
** through the following interface.
*/
void Apply_To_Translucent_Meshes(bool onoff) { ApplyToTranslucentMeshes = onoff; }
bool Is_Applied_To_Translucent_Meshes(void) { return ApplyToTranslucentMeshes; }
/*
** Material parameters: just grab a pointer the material pass and modify it.
** Remember to release your ref to it when you are done.
*/
MaterialPassClass * Get_Material(void) { WWASSERT(Material != NULL); Material->Add_Ref(); return Material; }
/*
** Decal generation support. Call Set_Mesh_Transform for the mesh you want to add
** a decal to. Then for each vertex, you can call 'Compute_Texture_Coordinate'
*/
void Set_Mesh_Transform(const Matrix3D & tm);
protected:
DecalGeneratorClass(uint32 id,DecalSystemClass * system);
~DecalGeneratorClass(void);
/*
** Logical Decal ID, DecalSystem that this generator is tied to
*/
DecalSystemClass * System;
uint32 DecalID; // unique ID generated by the DecalSystem
/*
** Backface Threshhold, Translucent mesh decal enable
*/
float BackfaceVal;
bool ApplyToTranslucentMeshes;
/*
** Material settings
*/
MaterialPassClass * Material; // material settings for the decal
/*
** Results, list of the meshes which actually generated decal polygons for this logical decal.
*/
NonRefRenderObjListClass MeshList;
friend class DecalSystemClass;
};
/**
** MultiFixedPoolDecalSystemClass: This is for decal systems which use several fixed-size decal
** pools (If more than one pool is used, it is usually to have separate pools for several
** different classes of decals). Note that here the decal IDs are a combination of the pool and
** slot ids. (decal ids only have to be unique within a given decal system)
*/
class MultiFixedPoolDecalSystemClass : public DecalSystemClass
{
public:
MultiFixedPoolDecalSystemClass(uint32 num_pools, const uint32 *pool_sizes);
MultiFixedPoolDecalSystemClass(const MultiFixedPoolDecalSystemClass & that);
virtual ~MultiFixedPoolDecalSystemClass(void);
// This clears the slot in addition to locking the generator, thus preventing any decal id
// collisions (since any decal previously in that slot will have the same id as the new one).
virtual DecalGeneratorClass * Lock_Decal_Generator(void);
// This will register the decal in the system in the appropriate pool and slot (determined by
// the generator's pool and slot ids), removing any decal which may have been there before.
virtual void Unlock_Decal_Generator(DecalGeneratorClass * generator);
// This notifies the system that a mesh which has decals on it was destroyed - therefore we
// need to remove the mesh from our list to avoid dangling pointers.
virtual void Decal_Mesh_Destroyed(uint32 id,DecalMeshClass * mesh);
// Not part of the DecalSystemClass interface - this function removes any decal currently in
// the given slot in the given pool.
void Clear_Decal_Slot(uint32 pool_id, uint32 slot_id);
// This one removes all decals in a given pool.
void Clear_Pool(uint32 pool_id);
// And this one removes all decals in the system.
void Clear_All_Decals(void);
protected:
/*
** This generates the decal ID when a generator is created. This decal system generates the
** decal ID from a pool ID and slot ID which are part of the state of the system so someone
** can set them before calling Lock_Decal_Generator() (which is where this function is called).
** We do it this way to avoid needing to override Lock_Decal_Generator().
*/
virtual uint32 Generate_Decal_Id(void) { return encode_decal_id(Generator_PoolID, Generator_SlotID); }
uint32 Generator_PoolID; // These should be set before calling Lock_Decal_Generator()
uint32 Generator_SlotID; // These should be set before calling Lock_Decal_Generator()
class LogicalDecalClass;
// Get a reference to the logical decal at the given pool and slot id (performs range chacking)
LogicalDecalClass & find_logical_decal(uint32 pool_id, uint32 slot_id);
// Get a reference to the logical decal with the given decal id
LogicalDecalClass & find_logical_decal(uint32 decal_id);
// The decal ids are formed so that the upper 16 bits are equal to the pool id and the lower
// 16 bits are equal to the slot id.
static uint32 encode_decal_id(uint32 pool_id, uint32 slot_id) { return (slot_id & 0xFFFF) | (pool_id << 16); }
static void decode_decal_id(uint32 decal_id, uint32 & pool_id, uint32 & slot_id) { slot_id = decal_id & 0xFFFF; pool_id = decal_id >> 16; }
// A class to store the meshes to which the decal has been applied (so that they can be removed when needed)
class LogicalDecalClass
{
public:
LogicalDecalClass(void);
~LogicalDecalClass(void);
void Set(DecalGeneratorClass * generator);
// Just clears any existing logical decal information, leaving the decal empty.
void Clear(uint32 decal_id);
NonRefRenderObjListClass MeshList;
};
class LogicalDecalPoolClass
{
public:
LogicalDecalPoolClass(void);
~LogicalDecalPoolClass(void);
void Initialize(uint32 size);
LogicalDecalClass * Array;
uint32 Size;
};
LogicalDecalPoolClass * Pools;
uint32 PoolCount;
};
#endif //DECALSYS_H