| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- /*
- ** 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 : Commando *
- * *
- * $Archive:: /Commando/Code/ww3d2/dynamesh.h $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 12/03/01 4:20p $*
- * *
- * $Revision:: 15 $*
- * *
- *-------------------------------------------------------------------------*/
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #ifndef DYNAMESH_H
- #define DYNAMESH_H
- #include "meshgeometry.h"
- #include "meshmatdesc.h"
- #include "matinfo.h"
- #include "rendobj.h"
- #include "polyinfo.h"
- #include "dx8wrapper.h"
- class ShaderClass;
- class IntersectionClass;
- class IntersectionResultClass;
- /*
- ** DynamicMeshModel: used for low-level rendering of DynamicMeshClass.
- ** It is composed of the same two classes (one base, one embedded as
- ** MeshModelClass, so many of its features are similar (see meshmdl.h)
- */
- class DynamicMeshModel : public MeshGeometryClass
- {
- public:
- DynamicMeshModel(unsigned int max_polys, unsigned int max_verts);
- DynamicMeshModel(unsigned int max_polys, unsigned int max_verts, MaterialInfoClass *mat_info);
- DynamicMeshModel(const DynamicMeshModel &src);
- ~DynamicMeshModel(void);
- // Inherited from MeshGeometryClass
- virtual void Compute_Plane_Equations(void);
- virtual void Compute_Vertex_Normals(void);
- virtual void Compute_Bounds(Vector3 * verts);
- // Reset mesh (with existing max polygon and max vertex counts)
- void Reset(void);
- // Render mesh
- void Render(RenderInfoClass & rinfo);
- // Set current polygon and vertex counts
- void Set_Counts(int pnum, int vnum) { DynamicMeshPNum = pnum; DynamicMeshVNum = vnum; }
- // Access to material stuff:
- unsigned * Get_Color_Array(int color_array_index) { return MatDesc->Get_Color_Array(color_array_index); }
- Vector2 * Get_UV_Array(int uv_array_index) { return MatDesc->Get_UV_Array_By_Index(uv_array_index); }
- void Set_Single_Material(VertexMaterialClass * vmat, int pass=0) { MatDesc->Set_Single_Material(vmat, pass); }
- void Set_Single_Texture(TextureClass * tex, int pass=0, int stage=0) { MatDesc->Set_Single_Texture(tex, pass, stage); }
- void Set_Single_Shader(ShaderClass shader, int pass=0) { MatDesc->Set_Single_Shader(shader, pass); }
-
- void Set_Material(int vidx, VertexMaterialClass * vmat, int pass=0) { MatDesc->Set_Material(vidx, vmat, pass); }
- void Set_Shader(int pidx, ShaderClass shader, int pass=0) { MatDesc->Set_Shader(pidx, shader, pass); }
- void Set_Texture(int pidx, TextureClass * tex, int pass=0, int stage=0) { MatDesc->Set_Texture(pidx, tex, pass, stage); }
- void Set_Pass_Count(int passes) { MatDesc->Set_Pass_Count(passes); }
- int Get_Pass_Count(void) const { return MatDesc->Get_Pass_Count(); }
- // Create the array (if it doesn't exist), fill it with the supplied value.
- void Initialize_Texture_Array(int pass, int stage, TextureClass *texture = NULL);
- void Initialize_Material_Array(int pass, VertexMaterialClass *vmat = NULL);
- // Accessors to material info:
- MaterialInfoClass *Peek_Material_Info(void) { return MatInfo; }
- MaterialInfoClass *Get_Material_Info(void) { if (MatInfo) MatInfo->Add_Ref(); return MatInfo;}
- void Set_Material_Info(MaterialInfoClass *mat_info)
- {
- if (MatInfo)
- MatInfo->Release_Ref();
- WWASSERT(MatInfo != 0);
- MatInfo = mat_info;
- MatInfo->Add_Ref();
- }
- // New geometry accessors (non-const)
- TriIndex * Get_Non_Const_Polygon_Array(void);
- Vector3 * Get_Non_Const_Vertex_Normal_Array(void);
- private:
- // These are current counts, as opposed to those in the mesh geometry and
- // material description which are actually maximum counts.
- int DynamicMeshPNum;
- int DynamicMeshVNum;
- // All non-geometry properties (uvs, colors, textures, shaders, etc)
- MeshMatDescClass * MatDesc;
- // Lists of textures and vertex materials for ease of processing
- MaterialInfoClass * MatInfo;
- };
- /*
- ** Dynamic Meshes
- */
- class DynamicMeshClass : public RenderObjClass {
- public:
- // constructor and destructor
- DynamicMeshClass( int max_poly, int max_vert);
- DynamicMeshClass( int max_poly, int max_vert, MaterialInfoClass *mat_info);
- DynamicMeshClass( const DynamicMeshClass & src);
- virtual ~DynamicMeshClass( void);
- // Inherited from RenderObjClass:
- virtual RenderObjClass * Clone(void) const;
- virtual int Class_ID(void) const { return CLASSID_DYNAMESH; }
- virtual void Render(RenderInfoClass & rinfo);
- virtual MaterialInfoClass *Peek_Material_Info(void) { return Model->Peek_Material_Info(); }
- virtual MaterialInfoClass *Get_Material_Info(void) { return Model->Get_Material_Info(); }
- virtual void Set_Material_Info(MaterialInfoClass *mat_info) { Model->Set_Material_Info(mat_info); }
- // all render objects should be able to tell you how many polygons were
- // used in the making of the render object.
- virtual int Get_Num_Polys(void) const { return PolyCount; }
- // return the number of vertices used by this renderobject
- virtual int Get_Num_Vertices(void) const { return VertCount; }
- // Get and set static sort level
- virtual int Get_Sort_Level(void) const { return SortLevel; }
- virtual void Set_Sort_Level(int level) { SortLevel = level; if(level != SORT_LEVEL_NONE) Disable_Sort();}
- // object space bounding volumes
- virtual inline void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const;
- virtual inline void Get_Obj_Space_Bounding_Box(AABoxClass & box) const;
- // Set the vertex material for the current triangle
- int Set_Vertex_Material( int idx, int pass = 0);
- int Set_Vertex_Material( VertexMaterialClass *material, bool dont_search = false, int pass = 0);
- // Set the number of passes for the mesh
- void Set_Pass_Count(int passes) { assert(PolyCount == 0); Model->Set_Pass_Count(passes); }
- int Get_Pass_Count() { return Model->Get_Pass_Count(); }
- // Set the texture for the current triangle
- int Set_Texture( int idx, int pass = 0);
- int Set_Texture( TextureClass *texture, bool dont_search = false, int pass = 0);
- // Set the shader for the current triangle
- int Set_Shader( const ShaderClass & shader, int pass = 0) { Model->Set_Single_Shader(shader, pass); return 0; }
-
- // set the shader, texture, and vertex material as found in the polygon info object
- void Set_Polygon_Info(const PolygonInfoClass &polyInfo, bool dont_search_texture = false, bool dont_search_vertex_material = false, int pass = 0)
- {
- // there must be a shader..
- assert(polyInfo.Peek_Shader() != 0);
- Set_Shader(* (polyInfo.Peek_Shader()), pass);
- assert(polyInfo.Peek_Vertex_Material() != 0);
- Set_Vertex_Material(polyInfo.Peek_Vertex_Material(), dont_search_vertex_material, pass);
- if (polyInfo.Peek_Texture())
- Set_Texture(polyInfo.Peek_Texture(), dont_search_texture, pass);
- }
- // Set vertex Color
- inline int Set_Vertex_Color(const Vector4 & color, int color_array_index = 0);
- inline int Set_Vertex_Color(const Vector3 & color, int color_array_index = 0);
- // reset the mesh flags
- void Reset_Flags() { Set_Dirty(); }
- // Flush the mesh
- void Reset_Native_Mesh() { Model->Reset(); }
- // reset our poly and vertex counts
- void Reset_Mesh_Counters()
- {
- Model->Set_Counts(0, 0);
- Disable_Sort();
- PolyCount = 0;
- VertCount = 0;
- }
- // Reset all polys and verts. Call the other reset functions directly if you do not want all
- // characteristics to be reset.
- virtual void Reset( void )
- {
- // Note that the active poly count has changed since the last render call by setting the dirty flag
- Reset_Flags();
- Reset_Native_Mesh();
- Reset_Mesh_Counters();
- // reset all the texture & vertex material indices
- int pass = MAX_PASSES;
- while (pass--) {
- TextureIdx[pass] = -1;
- VertexMaterialIdx[pass] = -1;
- MultiVertexMaterial[pass] = false;
- }
- }
- // Deletes mesh and recreates it with new max_polys and verts.
- void Resize(int max_polys, int max_verts);
- // Triangle creation routines
- void Begin_Tri_Strip( void ) { TriVertexCount = 0; TriMode = TRI_MODE_STRIPS; }
- void Begin_Tri_Fan( void ) { TriVertexCount = 0; TriMode = TRI_MODE_FANS; FanVertex = VertCount; }
- // vertex creation routines
- void Begin_Vertex( void) {}
- virtual void Location( float x, float y, float z);
- // version for speedier use in certain cases
- void Location_Inline( float x, float y, float z )
- {
- Vector3 * loc = Model->Get_Vertex_Array();
- assert(loc);
- loc[VertCount].X = x;
- loc[VertCount].Y = y;
- loc[VertCount].Z = z;
- }
- void Location_Inline(Vector3 &v) { Location_Inline(v.X,v.Y,v.Z); }
- // retrieve a reference to the vertex in the object
- // WARNING: does not validate index
- Vector3 & Get_Location(int index) {
- return Model->Get_Vertex_Array()[index];
- }
- void Normal( float x, float y, float z)
- {
- Vector3 * norms = Model->Get_Non_Const_Vertex_Normal_Array();
- assert(norms);
- norms[VertCount].X = x;
- norms[VertCount].Y = y;
- norms[VertCount].Z = z;
- }
- void Normal(Vector3 &v) { Normal(v.X,v.Y,v.Z); }
- // retrieve a reference to the normal vector3 in the object
- // WARNING: does not validate index
- Vector3 & Get_Normal(int index) { return Model->Get_Non_Const_Vertex_Normal_Array()[index]; }
- void Color(float r, float g, float b, float a, int color_array_index = 0)
- {
- // Vector4 * color = Model->Get_Color_Array(color_array_index);
- unsigned * color = Model->Get_Color_Array(color_array_index);
- assert(color);
- color[VertCount]=DX8Wrapper::Convert_Color_Clamp(Vector4(r,g,b,a));
- // color[VertCount].X = r;
- // color[VertCount].Y = g;
- // color[VertCount].Z = b;
- // color[VertCount].W = a;
- }
- void Color(const Vector4 &v, int color_array_index = 0) { Color(v.X, v.Y, v.Z, v.W, color_array_index); }
- void Color(unsigned v, int color_array_index=0)
- {
- unsigned * color = Model->Get_Color_Array(color_array_index);
- assert(color);
- color[VertCount]=v;
- }
- // retrieve a reference to a color entry in the object
- // WARNING: does not validate index
- // Vector4 & Get_Color(int index, int color_array_index = 0) { return Model->Get_Color_Array(color_array_index)[index]; }
- unsigned Get_Color(int index, int color_array_index = 0) { return Model->Get_Color_Array(color_array_index)[index]; }
- void UV(float u, float v, int uv_array_index = 0)
- {
- Vector2 * uv = Model->Get_UV_Array(uv_array_index);
- assert(uv);
- uv[VertCount].U = u;
- uv[VertCount].V = v;
- }
- void UV( Vector2 &v, int uv_array_index = 0) { UV(v.U, v.V, uv_array_index); }
- // retrieve a reference to a UV entry in the object
- // WARNING: does not validate index
- Vector2 & Get_UV(int index, int uv_array_index = 0 )
- {
- return Model->Get_UV_Array(uv_array_index)[index];
- }
- bool End_Vertex( void);
- // vertex creation shortcut, performs a begin, projected, rotated, and end
- bool Vertex(float x, float y, float z, float u, float v)
- {
- Begin_Vertex();
- Location(x, y, z);
- UV(u, v);
- return End_Vertex();
- }
- bool Vertex(Vector2 v)
- {
- Begin_Vertex();
- Location(v.X, v.Y, 0);
- return End_Vertex();
- }
- void End_Tri_Strip( void )
- {
- TriVertexCount = 0;
- }
- void End_Tri_Fan( void )
- {
- TriVertexCount = 0;
- }
- // For moving a vertex after the DynaMesh has already been created.
- virtual void Move_Vertex(int index, float x, float y, float z);
- virtual void Get_Vertex(int index, float &x, float &y, float &z);
- // For moving all vertices in the mesh by a fixed amount
- void Translate_Vertices(const Vector3 & offset);
- // For changing the color of a vertex after DynaMesh has been created.
- virtual void Change_Vertex_Color(int index, const Vector4 &color, int color_array_index)
- {
- // check if switching to multivertexcolor
- if (!MultiVertexColor[color_array_index]) {
- Switch_To_Multi_Vertex_Color(color_array_index);
- }
- CurVertexColor[color_array_index].X = color.X;
- CurVertexColor[color_array_index].Y = color.Y;
- CurVertexColor[color_array_index].Z = color.Z;
- CurVertexColor[color_array_index].W = color.W;
- // Vector4 * color_list = Model->Get_Color_Array(color_array_index);
- unsigned * color_list = Model->Get_Color_Array(color_array_index);
- color_list[index] = DX8Wrapper::Convert_Color_Clamp(color);
- }
- /*
- ** The following are a bunch of inlined functions for setting & clearing the mesh model's various flags
- */
- // dirty flags
- void Set_Dirty_Bounds(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_BOUNDS, true); }
- void Clear_Dirty_Bounds(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_BOUNDS, false); }
- void Set_Dirty_Planes(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_PLANES, true); }
- void Clear_Dirty_Planes(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_PLANES, false); }
- void Set_Dirty_Vertex_Normals(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_VNORMALS, true); }
- void Clear_Dirty_Vertex_Normals(void) { Model->Set_Flag(MeshGeometryClass::DIRTY_VNORMALS, false); }
- // control flags
- void Disable_Sort(void) { Model->Set_Flag(MeshGeometryClass::SORT, false); }
- void Enable_Sort(void) { Model->Set_Flag(MeshGeometryClass::SORT, true); }
- bool Sort_Enabled(void) { return (Model->Get_Flag(MeshGeometryClass::SORT) != 0); }
- void Disable_Bounding_Box(void) { Model->Set_Flag(MeshGeometryClass::DISABLE_BOUNDING_BOX, true); }
- void Enable_Bounding_Box(void) { Model->Set_Flag(MeshGeometryClass::DISABLE_BOUNDING_BOX, false); }
- bool Test_Bounding_Box(void) { return (Model->Get_Flag(MeshGeometryClass::DISABLE_BOUNDING_BOX) == 0); }
- void Disable_Bounding_Sphere(void) { Model->Set_Flag(MeshGeometryClass::DISABLE_BOUNDING_SPHERE, true); }
- void Enable_Bounding_Sphere(void) { Model->Set_Flag(MeshGeometryClass::DISABLE_BOUNDING_SPHERE, false); }
- bool Test_Bounding_Sphere(void) { return (Model->Get_Flag(MeshGeometryClass::DISABLE_BOUNDING_SPHERE) == 0); }
- // this is called by the Reset function
- void Set_Dirty( void) { Set_Dirty_Bounds(); Set_Dirty_Planes(); Set_Dirty_Vertex_Normals(); }
- enum {
- MAX_COLOR_ARRAYS = MeshMatDescClass::MAX_COLOR_ARRAYS,
- MAX_PASSES = MeshMatDescClass::MAX_PASSES
- };
- // USER BE WARNED: This hack is only here because DynamicMeshClass does not expose all of the
- // features that DynamicMeshModel provides. It may be dangerous to modify the model behind the
- // DynamicMeshClass's back so use at your own risk!
- DynamicMeshModel * Peek_Model(void) { return Model; }
-
- protected:
-
- inline void Switch_To_Multi_Vertex_Color(int color_array_index = 0);
- // tells when the triangle needs to be back flipped
- virtual bool Flip_Face( void) { return (!(TriVertexCount & 1)); }
- // Low-level mesh object
- DynamicMeshModel * Model;
- int VertexMaterialIdx[MAX_PASSES];
- bool MultiVertexMaterial[MAX_PASSES];
- int TextureIdx[MAX_PASSES];
- bool MultiTexture[MAX_PASSES];
- Vector4 CurVertexColor[MAX_COLOR_ARRAYS];
- bool MultiVertexColor[MAX_COLOR_ARRAYS];
- // number of polygons in the mesh
- int PolyCount;
- // number of vertices in the mesh
- int VertCount;
- // triangle vertex number
- int TriVertexCount;
-
- // base vertex when submitting fans
- int FanVertex;
- // is user currently submitting strips or fans
- enum { TRI_MODE_STRIPS = 0, TRI_MODE_FANS = 1 };
- int TriMode;
- // The static sort level
- char SortLevel;
- };
- inline Vector3 * DynamicMeshModel::Get_Non_Const_Vertex_Normal_Array(void)
- {
- if (Get_Flag(DIRTY_VNORMALS)) {
- Compute_Vertex_Normals();
- }
- return get_vert_normals();
- }
- inline TriIndex * DynamicMeshModel::Get_Non_Const_Polygon_Array(void)
- {
- return get_polys();
- }
- inline void DynamicMeshClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
- {
- if (!Bounding_Volumes_Valid()) {
- Model->Compute_Bounds(NULL);
- }
- Model->Get_Bounding_Sphere(&sphere);
- }
- inline void DynamicMeshClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
- {
- if (!Bounding_Volumes_Valid()) {
- Model->Compute_Bounds(NULL);
- }
- Model->Get_Bounding_Box(&box);
- }
- /*
- **
- */
- void DynamicMeshClass::Switch_To_Multi_Vertex_Color(int color_array_index)
- {
- /* Vector4 * color_list = Model->Get_Color_Array(color_array_index);
- // set the proper color for all the existing vertices
- for (int lp = 0; lp < VertCount; lp++) {
- color_list[lp].X = CurVertexColor[color_array_index].X;
- color_list[lp].Y = CurVertexColor[color_array_index].Y;
- color_list[lp].Z = CurVertexColor[color_array_index].Z;
- color_list[lp].W = CurVertexColor[color_array_index].W;
- }
- */
- unsigned * color_list = Model->Get_Color_Array(color_array_index);
- // set the proper color for all the existing vertices
- unsigned vertex_color=DX8Wrapper::Convert_Color_Clamp(CurVertexColor[color_array_index]);
- for (int lp = 0; lp < VertCount; lp++) {
- color_list[lp]=vertex_color;
- }
- MultiVertexColor[color_array_index] = true;
- }
- /*
- ** Set the color of all vertices in the mesh for one color_array_index
- */
- int DynamicMeshClass::Set_Vertex_Color(const Vector4 & color, int color_array_index)
- {
- // check if switching to multivertexcolor
- if (!MultiVertexColor[color_array_index]) {
- Switch_To_Multi_Vertex_Color(color_array_index);
- }
- CurVertexColor[color_array_index] = color;
- return 0;
- }
- int DynamicMeshClass::Set_Vertex_Color(const Vector3 & color, int color_array_index)
- {
- Set_Vertex_Color(Vector4(color.X,color.Y,color.Z,1),color_array_index);
- return 0;
- }
- /*
- ** Dynamic Screen Meshes
- **
- ** Same as DynamicMesh, but mapped in Screen Coordinates
- **
- ** Screen -> 0,0 1,0
- ** +---+
- ** | |
- ** +---+
- ** 0,1 1,1
- **
- **
- ** View -> -1,1 1,1
- ** +---+
- ** | |
- ** +---+
- ** -1,-1 1,-1
- **
- ** Note: since y is inverted, it switches from right handed to left handed
- ** (from counter-clockwise to clockwise), so Flip Face accounts for this
- */
- class DynamicScreenMeshClass : public DynamicMeshClass {
- public:
- // constructor and destructor
- DynamicScreenMeshClass( int max_poly, int max_vert, float aspect = 1.0f ) : DynamicMeshClass( max_poly, max_vert), Aspect( aspect ) {}
- DynamicScreenMeshClass( const DynamicScreenMeshClass & src) : DynamicMeshClass(src), Aspect(src.Aspect) {}
- virtual ~DynamicScreenMeshClass( void) {}
- // function to clone a dynamic screen mesh class
- virtual RenderObjClass * Clone(void) const { return NEW_REF( DynamicScreenMeshClass, (*this)); }
- // class id of this render object
- virtual int Class_ID(void) const { return CLASSID_DYNASCREENMESH; }
- // Remap locations to match a screen
- virtual void Location( float x, float y, float z = 0.0f);
- // For moving a vertex after the DynaMesh has already been created.
- virtual void Move_Vertex(int index, float x, float y, float z = 0.0f);
- // Set position
- virtual void Set_Position(const Vector3 &v);
- virtual void Reset( void);
- virtual void Set_Aspect(float aspect) { Aspect=aspect; };
- protected:
- // Aspect Ratio of the virtual screen.
- // 1.0 gives a -1,-1 to 1,1 display
- // 3/4 givs a -1,-3/4 to 1,3/4 display
- float Aspect;
- // tells when the triangle needs to be back flipped
- virtual bool Flip_Face( void) { return !DynamicMeshClass::Flip_Face(); }
- };
- #endif // DYNAMESH
|