mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
379
Code/ww3d2/meshbuild.h
Normal file
379
Code/ww3d2/meshbuild.h
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
** 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/meshbuild.h $*
|
||||
* *
|
||||
* Author:: Greg_h *
|
||||
* *
|
||||
* $Modtime:: 1/08/01 10:04a $*
|
||||
* *
|
||||
* $Revision:: 1 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef MESHBUILD_H
|
||||
#define MESHBUILD_H
|
||||
|
||||
#include "always.h"
|
||||
#include "vector2.h"
|
||||
#include "vector3.h"
|
||||
#include "bittype.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
** WorldInfoClass
|
||||
** Abstract base class that defines an interface for 'world information'.
|
||||
** This class provides the mesh builder with information about the world
|
||||
** outside of its mesh.
|
||||
*/
|
||||
class WorldInfoClass
|
||||
{
|
||||
public:
|
||||
WorldInfoClass(void) { }
|
||||
virtual ~WorldInfoClass(void) { }
|
||||
|
||||
// Public methods
|
||||
virtual Vector3 Get_Shared_Vertex_Normal (Vector3 pos, int smgroup) = 0;
|
||||
virtual bool Are_Meshes_Smoothed (void) const { return true; }
|
||||
};
|
||||
|
||||
/*
|
||||
** MeshBuilderClass
|
||||
** This class will process meshes for you, splitting all vertices which do not
|
||||
** share all parameters (such as texture coordinates), sort the polygons by
|
||||
** material, and put them into strip order.
|
||||
**
|
||||
** To "build" a mesh:
|
||||
** 1. Reset the builder with the number of polys you're going to sumbit
|
||||
** 2. Enable the vertex channels that you want
|
||||
** 3. Submit each face in the form of a FaceClass
|
||||
** 4. Call Build_Mesh
|
||||
**
|
||||
** To use the results:
|
||||
** 1. Call Get_Vertex_Count and Get_Face_Count to get the counts
|
||||
** 2. Loop through the verts, looking at each one using Get_Vertex
|
||||
** 3. Loop through the faces, looking at each one using Get_Face
|
||||
**
|
||||
** *NOTE* This class is meant to be relatively self-sufficient. It is used in a
|
||||
** variety of different applications which are built on completely different
|
||||
** code-bases. Do not introduce dependencies into this module lightly! :-)
|
||||
*/
|
||||
class MeshBuilderClass
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
STATE_ACCEPTING_INPUT = 0, // mesh builder is accepting input triangles
|
||||
STATE_MESH_PROCESSED, // mesh builder has processed the mesh
|
||||
|
||||
MAX_PASSES = 4, // maximum number of material passes supported
|
||||
MAX_STAGES = 2, // maximum number of texture stages supported in a single pass
|
||||
};
|
||||
|
||||
/*
|
||||
** Constructor, Destructor
|
||||
*/
|
||||
MeshBuilderClass(int pass_count=1,int face_count_guess=255,int face_count_growth_rate=64);
|
||||
~MeshBuilderClass(void);
|
||||
|
||||
/*
|
||||
** VertClass. The MeshBuilder deals with vertices in this format.
|
||||
*/
|
||||
class VertClass
|
||||
{
|
||||
public:
|
||||
VertClass(void) { Reset(); }
|
||||
void Reset(void);
|
||||
|
||||
public:
|
||||
|
||||
Vector3 Position; // position of the vertex
|
||||
Vector3 Normal; // vertex normal (can be calculated by mesh builder)
|
||||
int SmGroup; // smoothing group of the face this vertex was submitted with
|
||||
int Id; // id of the vertex, must match for vert to be welded, ok at zero if you don't care
|
||||
int BoneIndex; // bone influence if the mesh is a skin
|
||||
|
||||
int MaxVertColIndex; // Index into the Max mesh.vertCol array of this vertex.
|
||||
|
||||
Vector2 TexCoord[MAX_PASSES][MAX_STAGES];
|
||||
Vector3 DiffuseColor[MAX_PASSES]; // diffuse color
|
||||
Vector3 SpecularColor[MAX_PASSES]; // specular color
|
||||
Vector3 DiffuseIllumination[MAX_PASSES]; // pre-calced diffuse illum
|
||||
float Alpha[MAX_PASSES]; // alpha
|
||||
int VertexMaterialIndex[MAX_PASSES]; // vertex material index
|
||||
|
||||
int Attribute0; // user-set attributes (passed on through...)
|
||||
int Attribute1; // user-set attributes
|
||||
|
||||
// These values are set up by the mesh builder:
|
||||
|
||||
int SharedSmGroup; // smooth bits that were on in all faces that contributed to this final vertex
|
||||
int UniqueIndex; // used internally!
|
||||
int ShadeIndex; // used internally!
|
||||
VertClass * NextHash; // used internally!
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
** FaceClass. The MeshBuilder deals faces in this format. When inputing faces, set the
|
||||
** top half of the struct and the builder will fill in the bottom (vertex indices, normal,
|
||||
** and distance).
|
||||
*/
|
||||
class FaceClass
|
||||
{
|
||||
public:
|
||||
FaceClass(void) { Reset(); }
|
||||
void Reset(void); // reset this face
|
||||
|
||||
public:
|
||||
VertClass Verts[3]; // array of 3 verts
|
||||
int SmGroup; // smoothing group
|
||||
int Index; // user-set index of the face
|
||||
int Attributes; // user-set attributes
|
||||
int TextureIndex[MAX_PASSES][MAX_STAGES]; // texture to use for each pass
|
||||
int ShaderIndex[MAX_PASSES]; // shader for each pass
|
||||
uint32 SurfaceType; // surface type identifier
|
||||
|
||||
int AddIndex; // set by builder: index of addition
|
||||
int VertIdx[3]; // set by builder: "optimized" vertex indices
|
||||
Vector3 Normal; // set by builder: Face normal
|
||||
float32 Dist; // set by builder: Plane distance
|
||||
|
||||
void Compute_Plane(void);
|
||||
bool operator != (const FaceClass & that) { return !(*this == that); }
|
||||
bool operator == (const FaceClass & /*that*/) { return false; }
|
||||
bool Is_Degenerate(void);
|
||||
|
||||
friend class MeshBuilderClass;
|
||||
};
|
||||
|
||||
/*
|
||||
** To "build" a mesh:
|
||||
** 1. Reset the builder with the approximate number of polys you're going to sumbit, etc.
|
||||
** 3. Submit each face in the form of a FaceClass, set only the fields you need (leave others at default)
|
||||
** 4. Call Build_Mesh
|
||||
*/
|
||||
void Reset(int pass_count,int face_count_guess,int face_count_growth_rate);
|
||||
int Add_Face(const FaceClass & face);
|
||||
void Build_Mesh(bool compute_normals);
|
||||
|
||||
/*
|
||||
** Optional controls:
|
||||
** If one of your passes has more textures than another, you may wish to do the
|
||||
** stripping and sorting based on that channel. By default, everything will
|
||||
** be stripped and sorted based on pass 0, stage 0
|
||||
** Sort_Vertices can be used to order the vertices arbitrarily. I use it to
|
||||
** sort them according to the bone they are attached for skin meshes.
|
||||
*/
|
||||
void Set_Polygon_Ordering_Channel(int pass,int texstage);
|
||||
|
||||
/*
|
||||
** To use the results:
|
||||
** 1. Call Get_Vertex_Count and Get_Face_Count to get the counts
|
||||
** 2. Loop through the verts, looking at each one using Get_Vertex
|
||||
** 3. Loop through the faces, looking at each one using Get_Face
|
||||
*/
|
||||
int Get_Pass_Count(void) const;
|
||||
int Get_Vertex_Count(void) const;
|
||||
int Get_Face_Count(void) const;
|
||||
const VertClass & Get_Vertex(int index) const;
|
||||
const FaceClass & Get_Face(int index) const;
|
||||
|
||||
/*
|
||||
** Access to the Vertices and Faces for modifications. This is used by
|
||||
** the max plugin when generating a skin mesh for example. Be careful
|
||||
** what you do to them. (I haven't thought through all of the
|
||||
** possible things you might do to mess up my nice clean mesh...).
|
||||
*/
|
||||
VertClass & Get_Vertex(int index);
|
||||
FaceClass & Get_Face(int index);
|
||||
|
||||
/*
|
||||
** Bounding volume information about the mesh. These functions can compute
|
||||
** various types of bounding volumes for the mesh you just processed...
|
||||
*/
|
||||
void Compute_Bounding_Box(Vector3 * set_min,Vector3 * set_max);
|
||||
void Compute_Bounding_Sphere(Vector3 * set_center,float * set_radius);
|
||||
|
||||
/*
|
||||
** World information managment. Used to give the mesh builder information
|
||||
** about the world outside of its mesh.
|
||||
*/
|
||||
WorldInfoClass * Peek_World_Info(void) const { return WorldInfo; }
|
||||
void Set_World_Info(WorldInfoClass *world_info) { WorldInfo = world_info; }
|
||||
|
||||
/*
|
||||
** Mesh Stats, mainly lots of flags for whether this mesh has various
|
||||
** channels of information.
|
||||
*/
|
||||
struct MeshStatsStruct
|
||||
{
|
||||
void Reset(void);
|
||||
|
||||
bool HasTexture[MAX_PASSES][MAX_STAGES]; // has at least one texture in given pass/stage
|
||||
bool HasShader[MAX_PASSES]; // has at least one shader in given pass
|
||||
bool HasVertexMaterial[MAX_PASSES]; // has at least one vert material in given pass
|
||||
|
||||
bool HasPerPolyTexture[MAX_PASSES][MAX_STAGES]; // has 2+ textures in given pass/stage
|
||||
bool HasPerPolyShader[MAX_PASSES]; // has 2+ shaders in given pass
|
||||
bool HasPerVertexMaterial[MAX_PASSES]; // has 2+ vertex materials in given pass
|
||||
|
||||
bool HasDiffuseColor[MAX_PASSES]; // has diffuse colors in given pass
|
||||
bool HasSpecularColor[MAX_PASSES]; // has specular colors in given pass
|
||||
bool HasDiffuseIllumination[MAX_PASSES]; // has diffuse illum in given pass
|
||||
|
||||
bool HasTexCoords[MAX_PASSES][MAX_STAGES]; // has texture coords in given pass
|
||||
|
||||
int UVSplitCount; // how many vertices were split due solely to UV discontinuities
|
||||
int StripCount; // number of strips that were created
|
||||
int MaxStripLength; // longest strip created
|
||||
float AvgStripLength; // average strip length
|
||||
};
|
||||
|
||||
const MeshStatsStruct & Get_Mesh_Stats(void) const;
|
||||
|
||||
private:
|
||||
|
||||
void Free(void);
|
||||
void Compute_Mesh_Stats(void);
|
||||
void Optimize_Mesh(bool compute_normals);
|
||||
void Strip_Optimize_Mesh(void);
|
||||
void Remove_Degenerate_Faces(void);
|
||||
void Compute_Face_Normals(void);
|
||||
bool Verify_Face_Normals(void);
|
||||
void Compute_Vertex_Normals(void);
|
||||
void Grow_Face_Array(void);
|
||||
void Sort_Vertices(void);
|
||||
|
||||
/*
|
||||
** Winged edge stuff is used by the strip optimize function
|
||||
*/
|
||||
struct WingedEdgeStruct
|
||||
{
|
||||
int MaterialIdx;
|
||||
WingedEdgeStruct * Next;
|
||||
int Vertex[2];
|
||||
int Poly[2];
|
||||
};
|
||||
|
||||
struct WingedEdgePolyStruct
|
||||
{
|
||||
WingedEdgeStruct * Edge[3];
|
||||
};
|
||||
|
||||
|
||||
int State; // is the builder accepting input or already processed the mesh.
|
||||
int PassCount; // number of render passes for this mesh
|
||||
int FaceCount; // number of faces
|
||||
FaceClass * Faces; // array of faces
|
||||
int InputVertCount; // number of input verts;
|
||||
int VertCount; // number of verts;
|
||||
VertClass * Verts; // array of verts;
|
||||
int CurFace; // current face being added
|
||||
|
||||
WorldInfoClass * WorldInfo; // obj containing info about other meshes in the world
|
||||
|
||||
MeshStatsStruct Stats; // internally useful junk about the mesh being processed.
|
||||
int PolyOrderPass; // order the polys using the texture indices in this pass
|
||||
int PolyOrderStage; // order the polys using the texture indices in this stage
|
||||
|
||||
int AllocFaceCount; // number of faces allocated
|
||||
int AllocFaceGrowth; // growth rate of face array
|
||||
};
|
||||
|
||||
inline void MeshBuilderClass::Set_Polygon_Ordering_Channel(int pass,int texstage)
|
||||
{
|
||||
assert(pass >= 0);
|
||||
assert(pass < MAX_PASSES);
|
||||
assert(texstage >= 0);
|
||||
assert(texstage < MAX_STAGES);
|
||||
|
||||
PolyOrderPass = pass;
|
||||
PolyOrderStage = texstage;
|
||||
}
|
||||
|
||||
inline int MeshBuilderClass::Get_Pass_Count(void) const
|
||||
{
|
||||
return PassCount;
|
||||
}
|
||||
|
||||
inline int MeshBuilderClass::Get_Vertex_Count(void) const
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
return VertCount;
|
||||
}
|
||||
|
||||
inline int MeshBuilderClass::Get_Face_Count(void) const
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
return FaceCount;
|
||||
}
|
||||
|
||||
inline const MeshBuilderClass::VertClass & MeshBuilderClass::Get_Vertex(int index) const
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
assert(index >= 0);
|
||||
assert(index < VertCount);
|
||||
return Verts[index];
|
||||
}
|
||||
|
||||
inline const MeshBuilderClass::FaceClass & MeshBuilderClass::Get_Face(int index) const
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
assert(index >= 0);
|
||||
assert(index < FaceCount);
|
||||
return Faces[index];
|
||||
}
|
||||
|
||||
inline MeshBuilderClass::VertClass & MeshBuilderClass::Get_Vertex(int index)
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
assert(index >= 0);
|
||||
assert(index < VertCount);
|
||||
return Verts[index];
|
||||
}
|
||||
|
||||
inline MeshBuilderClass::FaceClass & MeshBuilderClass::Get_Face(int index)
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
assert(index >= 0);
|
||||
assert(index < FaceCount);
|
||||
return Faces[index];
|
||||
}
|
||||
|
||||
inline const MeshBuilderClass::MeshStatsStruct & MeshBuilderClass::Get_Mesh_Stats(void) const
|
||||
{
|
||||
assert(State == STATE_MESH_PROCESSED);
|
||||
return Stats;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user