491 lines
16 KiB
C++
491 lines
16 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/meshmatdesc.h $*
|
|
* *
|
|
* Original Author:: Greg Hjelstrom *
|
|
* *
|
|
* $Author:: Greg_h $*
|
|
* *
|
|
* $Modtime:: 1/18/02 3:08p $*
|
|
* *
|
|
* $Revision:: 14 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#ifndef MESHMATDESC_H
|
|
#define MESHMATDESC_H
|
|
|
|
#include "always.h"
|
|
#include "vector2.h"
|
|
#include "vector3.h"
|
|
#include "vector3i.h"
|
|
#include "vector4.h"
|
|
#include "sharebuf.h"
|
|
#include "shader.h"
|
|
#include "vertmaterial.h"
|
|
|
|
class MatBufferClass;
|
|
class TexBufferClass;
|
|
class UVBufferClass;
|
|
class TextureClass;
|
|
class MeshModelClass;
|
|
|
|
/**
|
|
** MeshMatDescClass - This class encapsulates all of the material description data for a mesh.
|
|
** WARNING: The vertex count and polygon count *MUST* be kept in sync with the mesh
|
|
*/
|
|
class MeshMatDescClass
|
|
{
|
|
public:
|
|
|
|
enum
|
|
{
|
|
MAX_PASSES = 4,
|
|
MAX_TEX_STAGES = 2,
|
|
MAX_COLOR_ARRAYS = 2,
|
|
MAX_UV_ARRAYS = MAX_PASSES * MAX_TEX_STAGES
|
|
};
|
|
|
|
MeshMatDescClass(void);
|
|
MeshMatDescClass(const MeshMatDescClass & that);
|
|
~MeshMatDescClass(void);
|
|
void Reset(int polycount,int vertcount,int passcount);
|
|
MeshMatDescClass & operator = (const MeshMatDescClass & that);
|
|
|
|
/*
|
|
** Initialize the alternate material description by copying the default materials
|
|
** and overriding the entries that exist in the alternate_desc
|
|
*/
|
|
void Init_Alternate(MeshMatDescClass & def_mat_desc,MeshMatDescClass & alternate_desc);
|
|
bool Is_Empty(void);
|
|
|
|
/*
|
|
** Counts, make sure the vertex and polygon counts match the parent mesh.
|
|
*/
|
|
void Set_Pass_Count(int passes) { PassCount = passes; }
|
|
int Get_Pass_Count(void) const { return PassCount; }
|
|
void Set_Vertex_Count(int vertcount) { VertexCount = vertcount; }
|
|
int Get_Vertex_Count(void) const { return VertexCount; }
|
|
void Set_Polygon_Count(int polycount) { PolyCount = polycount; }
|
|
int Get_Polygon_Count(void) const { return PolyCount; }
|
|
|
|
/*
|
|
** Material Interface
|
|
*/
|
|
Vector2 * Get_UV_Array(int pass,int stage);
|
|
void Install_UV_Array(int pass,int stage,Vector2 * uvs,int count);
|
|
void Set_UV_Source(int pass,int stage,int sourceindex);
|
|
int Get_UV_Source(int pass,int stage);
|
|
|
|
int Get_UV_Array_Count(void);
|
|
Vector2 * Get_UV_Array_By_Index(int index, bool create = true);
|
|
|
|
unsigned* Get_DCG_Array(int pass);
|
|
unsigned* Get_DIG_Array(int pass);
|
|
void Set_DCG_Source(int pass,VertexMaterialClass::ColorSourceType source);
|
|
void Set_DIG_Source(int pass,VertexMaterialClass::ColorSourceType source);
|
|
VertexMaterialClass::ColorSourceType Get_DCG_Source(int pass);
|
|
VertexMaterialClass::ColorSourceType Get_DIG_Source(int pass);
|
|
unsigned * Get_Color_Array(int array,bool create = true);
|
|
|
|
void Set_Single_Material(VertexMaterialClass * vmat,int pass=0);
|
|
void Set_Single_Texture(TextureClass * tex,int pass=0,int stage=0);
|
|
void Set_Single_Shader(ShaderClass shader,int pass=0);
|
|
|
|
/*
|
|
** the "Get" functions add a reference before returning the pointer (if appropriate)
|
|
*/
|
|
VertexMaterialClass * Get_Single_Material(int pass=0) const;
|
|
TextureClass * Get_Single_Texture(int pass=0,int stage=0) const;
|
|
ShaderClass Get_Single_Shader(int pass=0) const;
|
|
|
|
/*
|
|
** the "Peek" functions just return the pointer and it's the caller's responsibility to
|
|
** maintain a reference to an object with a reference to the data
|
|
*/
|
|
VertexMaterialClass * Peek_Single_Material(int pass=0) const;
|
|
TextureClass * Peek_Single_Texture(int pass=0,int stage=0) const;
|
|
|
|
void Set_Material(int vidx,VertexMaterialClass * vmat,int pass=0);
|
|
void Set_Shader(int pidx,ShaderClass shader,int pass=0);
|
|
void Set_Texture(int pidx,TextureClass * tex,int pass=0,int stage=0);
|
|
|
|
/*
|
|
** Queries for determining whether this model has per-polygon arrays of Materials, Shaders, or Textures
|
|
*/
|
|
bool Has_Material_Array(int pass) const;
|
|
bool Has_Shader_Array(int pass) const;
|
|
bool Has_Texture_Array(int pass,int stage) const;
|
|
|
|
/*
|
|
** Determine whether this material description contains data for the specified category
|
|
*/
|
|
bool Has_UV(int pass,int stage) { return UVSource[pass][stage] != -1; }
|
|
bool Has_Color_Array(int array) { return ColorArray[array] != NULL; }
|
|
|
|
bool Has_Texture_Data(int pass,int stage) { return (Texture[pass][stage] != NULL) || (TextureArray[pass][stage] != NULL); }
|
|
bool Has_Shader_Data(int pass) { return (Shader[pass] != NullShader) || (ShaderArray[pass] != NULL); }
|
|
bool Has_Material_Data(int pass) { return (Material[pass] != NULL) || (MaterialArray[pass] != NULL); }
|
|
|
|
/*
|
|
** "Get" functions for Materials, Textures, and Shaders when there are more than one (per-polygon or per-vertex)
|
|
*/
|
|
VertexMaterialClass * Get_Material(int vidx,int pass=0) const;
|
|
TextureClass * Get_Texture(int pidx,int pass=0,int stage=0) const;
|
|
ShaderClass Get_Shader(int pidx,int pass=0) const;
|
|
|
|
/*
|
|
** "Peek" functions for Materials and Textures when there are more than one (per-polygon or per-vertex)
|
|
*/
|
|
VertexMaterialClass * Peek_Material(int vidx,int pass=0) const;
|
|
TextureClass * Peek_Texture(int pidx,int pass=0,int stage=0) const;
|
|
|
|
/*
|
|
** Access to the arrays
|
|
*/
|
|
TexBufferClass * Get_Texture_Array(int pass,int stage,bool create = true);
|
|
MatBufferClass * Get_Material_Array(int pass,bool create = true);
|
|
ShaderClass * Get_Shader_Array(int pass,bool create = true);
|
|
|
|
void Make_UV_Array_Unique(int pass,int stage);
|
|
void Make_Color_Array_Unique(int index);
|
|
|
|
/*
|
|
** Post-Load processing, configures all materials to use the correct passes and
|
|
** material color sources, etc.
|
|
*/
|
|
void Post_Load_Process(bool enable_lighting = true,MeshModelClass * parent = NULL);
|
|
void Disable_Lighting(void);
|
|
|
|
/*
|
|
** Do any of the vertex materials require vertex normals?
|
|
*/
|
|
bool Do_Mappers_Need_Normals(void);
|
|
|
|
static ShaderClass NullShader; // Used to mark no shader data
|
|
|
|
protected:
|
|
|
|
void Configure_Material(VertexMaterialClass * mtl,int pass,bool lighting_enabled);
|
|
void Disable_Backface_Culling(void);
|
|
void Delete_Pass(int pass);
|
|
|
|
int PassCount;
|
|
int VertexCount;
|
|
int PolyCount;
|
|
|
|
// u-v coordinates
|
|
UVBufferClass * UV[MAX_UV_ARRAYS];
|
|
int UVSource[MAX_PASSES][MAX_TEX_STAGES];
|
|
|
|
// vertex color arrays, we support two arrays: each can only be used on the
|
|
// first pass.
|
|
ShareBufferClass<unsigned> * ColorArray[2];
|
|
VertexMaterialClass::ColorSourceType DCGSource[MAX_PASSES];
|
|
VertexMaterialClass::ColorSourceType DIGSource[MAX_PASSES];
|
|
|
|
// default textures, shader, vmat
|
|
TextureClass * Texture[MAX_PASSES][MAX_TEX_STAGES];
|
|
ShaderClass Shader[MAX_PASSES];
|
|
VertexMaterialClass * Material[MAX_PASSES];
|
|
|
|
// array textures, shaders, vmats
|
|
TexBufferClass * TextureArray[MAX_PASSES][MAX_TEX_STAGES];
|
|
MatBufferClass * MaterialArray[MAX_PASSES];
|
|
ShareBufferClass<ShaderClass> * ShaderArray[MAX_PASSES];
|
|
|
|
friend class MeshModelClass;
|
|
};
|
|
|
|
|
|
/**
|
|
** MatBufferClass
|
|
** This is a ShareBufferClass of pointers to vertex materials. Should be written as a template...
|
|
** Get and Peek work like normal, and all non-NULL pointers will be released when the buffer
|
|
** is destroyed.
|
|
*/
|
|
class MatBufferClass : public ShareBufferClass < VertexMaterialClass * >
|
|
{
|
|
public:
|
|
MatBufferClass(int count) : ShareBufferClass<VertexMaterialClass *>(count) { Clear(); }
|
|
MatBufferClass(const MatBufferClass & that);
|
|
~MatBufferClass(void);
|
|
|
|
void Set_Element(int index,VertexMaterialClass * mat);
|
|
VertexMaterialClass * Get_Element(int index);
|
|
VertexMaterialClass * Peek_Element(int index);
|
|
|
|
private:
|
|
// not implemented
|
|
MatBufferClass & operator = (const MatBufferClass & that);
|
|
};
|
|
|
|
/**
|
|
** TexBufferClass
|
|
** This is a ShareBufferClass of pointers to textures. Works just like MatBufferClass but with
|
|
** TextureClass's...
|
|
*/
|
|
class TexBufferClass : public ShareBufferClass < TextureClass * >
|
|
{
|
|
public:
|
|
TexBufferClass(int count) : ShareBufferClass<TextureClass *>(count) { Clear(); }
|
|
TexBufferClass(const TexBufferClass & that);
|
|
~TexBufferClass(void);
|
|
|
|
void Set_Element(int index,TextureClass * mat);
|
|
TextureClass * Get_Element(int index);
|
|
TextureClass * Peek_Element(int index);
|
|
|
|
private:
|
|
// not implemented
|
|
TexBufferClass & operator = (const TexBufferClass & that);
|
|
};
|
|
|
|
/**
|
|
** UVBufferClass
|
|
** This is a ShareBufferClass of uv coordinates. At load time, we are detecting redundant UV arrays
|
|
** so this class stores a CRC for quick checking.
|
|
*/
|
|
class UVBufferClass : public ShareBufferClass < Vector2 >
|
|
{
|
|
public:
|
|
UVBufferClass(int count) : ShareBufferClass<Vector2>(count), CRC(0xFFFFFFFF) { }
|
|
UVBufferClass(const UVBufferClass & that);
|
|
|
|
bool operator == (const UVBufferClass & that);
|
|
bool Is_Equal_To(const UVBufferClass & that);
|
|
|
|
void Update_CRC(void);
|
|
unsigned int Get_CRC(void) { return CRC; }
|
|
|
|
private:
|
|
unsigned int CRC;
|
|
|
|
// not implemented
|
|
UVBufferClass & operator = (const UVBufferClass & that);
|
|
};
|
|
|
|
/*********************************************************************************************************
|
|
**
|
|
** MeshMatDescClass Inline Functions
|
|
** These functions manage the data associated with the material description for the mesh. Since there
|
|
** can be an alternate material description, these functions are encapsulated into MatDescClass.
|
|
**
|
|
*********************************************************************************************************/
|
|
|
|
inline Vector2 * MeshMatDescClass::Get_UV_Array(int pass,int stage)
|
|
{
|
|
if (UVSource[pass][stage] == -1) {
|
|
return NULL;
|
|
}
|
|
if (UV[UVSource[pass][stage]] != NULL) {
|
|
return UV[UVSource[pass][stage]]->Get_Array();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
inline void MeshMatDescClass::Set_UV_Source(int pass,int stage,int sourceindex)
|
|
{
|
|
WWASSERT(pass >= 0);
|
|
WWASSERT(pass < MAX_PASSES);
|
|
WWASSERT(stage >= 0);
|
|
WWASSERT(stage < MAX_TEX_STAGES);
|
|
UVSource[pass][stage] = sourceindex;
|
|
}
|
|
|
|
inline int MeshMatDescClass::Get_UV_Source(int pass,int stage)
|
|
{
|
|
WWASSERT(pass >= 0);
|
|
WWASSERT(pass < MAX_PASSES);
|
|
WWASSERT(stage >= 0);
|
|
WWASSERT(stage < MAX_TEX_STAGES);
|
|
return UVSource[pass][stage];
|
|
}
|
|
|
|
inline int MeshMatDescClass::Get_UV_Array_Count(void)
|
|
{
|
|
int count = 0;
|
|
while ((UV[count] != NULL) && (count < MAX_UV_ARRAYS)) {
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
inline Vector2 * MeshMatDescClass::Get_UV_Array_By_Index(int index, bool create)
|
|
{
|
|
WWASSERT((index >= 0)&&(index < MAX_UV_ARRAYS));
|
|
|
|
if (create && !UV[index]) {
|
|
UV[index] = NEW_REF(UVBufferClass,(VertexCount));
|
|
}
|
|
if (UV[index] != NULL) {
|
|
return UV[index]->Get_Array();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
inline unsigned* MeshMatDescClass::Get_DCG_Array(int pass)
|
|
{
|
|
WWASSERT(pass >= 0);
|
|
WWASSERT(pass < MAX_PASSES);
|
|
switch (DCGSource[pass]) {
|
|
case VertexMaterialClass::MATERIAL:
|
|
return NULL;
|
|
break;
|
|
case VertexMaterialClass::COLOR1:
|
|
if (ColorArray[0]) {
|
|
return ColorArray[0]->Get_Array();
|
|
} else {
|
|
return NULL;
|
|
}
|
|
break;
|
|
case VertexMaterialClass::COLOR2:
|
|
if (ColorArray[1]) {
|
|
return ColorArray[1]->Get_Array();
|
|
} else {
|
|
return NULL;
|
|
}
|
|
break;
|
|
default:
|
|
WWASSERT(0);
|
|
return(NULL);
|
|
break;
|
|
};
|
|
}
|
|
|
|
inline unsigned * MeshMatDescClass::Get_DIG_Array(int pass)
|
|
{
|
|
WWASSERT(pass >= 0);
|
|
WWASSERT(pass < MAX_PASSES);
|
|
switch (DIGSource[pass]) {
|
|
case VertexMaterialClass::MATERIAL:
|
|
return NULL;
|
|
break;
|
|
case VertexMaterialClass::COLOR1:
|
|
if (ColorArray[0]) {
|
|
return ColorArray[0]->Get_Array();
|
|
} else {
|
|
return NULL;
|
|
}
|
|
break;
|
|
case VertexMaterialClass::COLOR2:
|
|
if (ColorArray[1]) {
|
|
return ColorArray[1]->Get_Array();
|
|
} else {
|
|
return NULL;
|
|
}
|
|
break;
|
|
default:
|
|
WWASSERT(0);
|
|
return(NULL);
|
|
break;
|
|
};
|
|
}
|
|
|
|
inline void MeshMatDescClass::Set_DCG_Source(int pass,VertexMaterialClass::ColorSourceType source)
|
|
{
|
|
DCGSource[pass] = source;
|
|
}
|
|
|
|
inline void MeshMatDescClass::Set_DIG_Source(int pass,VertexMaterialClass::ColorSourceType source)
|
|
{
|
|
DIGSource[pass] = source;
|
|
}
|
|
|
|
inline VertexMaterialClass::ColorSourceType MeshMatDescClass::Get_DCG_Source(int pass)
|
|
{
|
|
return DCGSource[pass];
|
|
}
|
|
|
|
inline VertexMaterialClass::ColorSourceType MeshMatDescClass::Get_DIG_Source(int pass)
|
|
{
|
|
return DIGSource[pass];
|
|
}
|
|
|
|
inline unsigned * MeshMatDescClass::Get_Color_Array(int index,bool create)
|
|
{
|
|
if (create && !ColorArray[index]) {
|
|
ColorArray[index] = NEW_REF(ShareBufferClass<unsigned>,(VertexCount));
|
|
}
|
|
if (ColorArray[index]) {
|
|
return ColorArray[index]->Get_Array();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
inline VertexMaterialClass * MeshMatDescClass::Get_Single_Material(int pass) const
|
|
{
|
|
if (Material[pass]) {
|
|
Material[pass]->Add_Ref();
|
|
}
|
|
return Material[pass];
|
|
}
|
|
|
|
inline VertexMaterialClass * MeshMatDescClass::Peek_Single_Material(int pass) const
|
|
{
|
|
return Material[pass];
|
|
}
|
|
|
|
inline TextureClass * MeshMatDescClass::Peek_Single_Texture(int pass,int stage) const
|
|
{
|
|
return Texture[pass][stage];
|
|
}
|
|
|
|
inline ShaderClass MeshMatDescClass::Get_Single_Shader(int pass) const
|
|
{
|
|
return Shader[pass];
|
|
}
|
|
|
|
inline bool MeshMatDescClass::Has_Material_Array(int pass) const
|
|
{
|
|
return (MaterialArray[pass] != NULL);
|
|
}
|
|
|
|
inline bool MeshMatDescClass::Has_Shader_Array(int pass) const
|
|
{
|
|
return (ShaderArray[pass] != NULL);
|
|
}
|
|
|
|
inline bool MeshMatDescClass::Has_Texture_Array(int pass,int stage) const
|
|
{
|
|
return (TextureArray[pass][stage] != NULL);
|
|
}
|
|
|
|
inline void MeshMatDescClass::Disable_Backface_Culling(void)
|
|
{
|
|
for (int pass = 0; pass < PassCount; pass++) {
|
|
Shader[pass].Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
|
|
if (ShaderArray[pass]) {
|
|
for (int tri = 0; tri < ShaderArray[pass]->Get_Count(); tri++) {
|
|
ShaderArray[pass]->Get_Element(tri).Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif //MESHMATDESC_H
|
|
|