| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*
- ** Command & Conquer Generals(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/Tools/max2w3d/meshbuild.h $*
- * *
- * Author:: Greg_h *
- * *
- * $Modtime:: 5/22/00 3:17p $*
- * *
- * $Revision:: 12 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * 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
|