/* ** 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 . */ /*********************************************************************************************** *** 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/meshmdl.h $* * * * Author:: Greg Hjelstrom * * * * $Modtime:: 3/14/02 1:30p $* * * * $Revision:: 41 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if defined(_MSC_VER) #pragma once #endif #ifndef MESHMDL_H #define MESHMDL_H #include "vector2.h" #include "vector3.h" #include "vector4.h" #include "vector3i.h" #include "sharebuf.h" #include "shader.h" #include "wwdebug.h" #include "vertmaterial.h" #include "bittype.h" #include "colmath.h" #include "simplevec.h" #include "wwstring.h" #include "rinfo.h" #include "meshgeometry.h" #include "meshmatdesc.h" #include "dx8list.h" class TextureClass; class RenderInfoClass; class SpecialRenderInfoClass; class MatBufferClass; class TexBufferClass; class AABoxClass; class OBBoxClass; class FrustumClass; class SphereClass; class AABTreeClass; class MaterialInfoClass; class MeshLoadContextClass; class MeshSaveContextClass; class ChunkLoadClass; class ChunkSaveClass; class MeshClass; class HTreeClass; class DecalGeneratorClass; class LightEnvironmentClass; class DX8MeshRendererClass; class DX8PolygonRendererAttachClass; class DX8SkinFVFCategoryContainer; class GapFillerClass; struct VertexFormatXYZNDUV2; /** ** MeshModelClass ** This class is a repository for all of the geometry information that defines the mesh. ** Its purpose is to allow separate instances of a mesh to share as much data as possible. ** ** There are some tricky aspects to this class that may not be immediately obvious. The ** arrays of pointers to textures and vertex materials must be handled in a special way ** due to the fact that they are also ref-counted objects which should only be released ** when the last reference to the array is released (i.e. when no one is using the array ** any more...) ** ** Copy/Add_Ref Rules: ** The purpose of this model was to share data between models whenever possible. To this ** end, some of the arrays of data are handled differently: ** ** ALWAYS SHARED: These are *ALWAYS* Add_Ref'd and thus all point to the same array ** Poly - Connectivity of a mesh are always shared (cannot be changed at runtime) ** VertexShadeIdx - Shade indices of a mesh are always shared (cannot be changed at runtime) ** VertexInfluences - Vertex bone attachments are always shared (cannot be changed at runtime) ** ** SHARED UNTIL SCALED, SKIN DEFORMED, or DAMAGED: ** Vertex - vertex positions must be copied if any are moved... ** VertexNorm - vertex normals cannot be shared if a vertex is moved ** PlaneEq - plane equations cannot be shared if a vertex is moved ** CullTree - culling tree becomes instance specific if a vertex moves (shouldn't even use this with skins...) ** ** ALWAYS UNIQUE, BUT SHARE ARRAYS BETWEEN ALTERNATE MATERIAL REPRESENTATIONS (should we share some of these?) ** UV, DIG, DCG, SCG ** Texture, Shader, Material, ** TextureArray, MaterialArray, ShaderArray */ class MeshModelClass : public MeshGeometryClass { public: MeshModelClass(void); MeshModelClass(const MeshModelClass & that); ~MeshModelClass(void); MeshModelClass & operator = (const MeshModelClass & that); void Reset(int polycount,int vertcount,int passcount); void Register_For_Rendering(); void Shadow_Render(SpecialRenderInfoClass & rinfo,const Matrix3D & tm,const HTreeClass * htree); ///////////////////////////////////////////////////////////////////////////////////// // Material interface, All of these functions call through to the current // material decription. ///////////////////////////////////////////////////////////////////////////////////// void Set_Pass_Count(int passes) { CurMatDesc->Set_Pass_Count(passes); } int Get_Pass_Count(void) const { return CurMatDesc->Get_Pass_Count(); } const Vector2 * Get_UV_Array(int pass = 0, int stage = 0) { return CurMatDesc->Get_UV_Array(pass,stage); } int Get_UV_Array_Count(void) { return CurMatDesc->Get_UV_Array_Count(); } const Vector2 * Get_UV_Array_By_Index(int index) { return CurMatDesc->Get_UV_Array_By_Index(index, false); } unsigned * Get_DCG_Array(int pass) { return CurMatDesc->Get_DCG_Array(pass); } unsigned * Get_DIG_Array(int pass) { return CurMatDesc->Get_DIG_Array(pass); } VertexMaterialClass::ColorSourceType Get_DCG_Source(int pass) { return CurMatDesc->Get_DCG_Source(pass); } VertexMaterialClass::ColorSourceType Get_DIG_Source(int pass) { return CurMatDesc->Get_DIG_Source(pass); } unsigned * Get_Color_Array(int array_index,bool create = true) { return CurMatDesc->Get_Color_Array(array_index,create); } void Set_Single_Material(VertexMaterialClass * vmat,int pass=0) { CurMatDesc->Set_Single_Material(vmat,pass); } void Set_Single_Texture(TextureClass * tex,int pass=0,int stage=0) { CurMatDesc->Set_Single_Texture(tex,pass,stage); } void Set_Single_Shader(ShaderClass shader,int pass=0) { CurMatDesc->Set_Single_Shader(shader,pass); } // the "Get" functions add a reference before returning the pointer (if appropriate) VertexMaterialClass * Get_Single_Material(int pass=0) const { return CurMatDesc->Get_Single_Material(pass); } TextureClass * Get_Single_Texture(int pass=0,int stage=0) const { return CurMatDesc->Get_Single_Texture(pass,stage); } ShaderClass Get_Single_Shader(int pass=0) const { return CurMatDesc->Get_Single_Shader(pass); } // 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 { return CurMatDesc->Peek_Single_Material(pass); } TextureClass * Peek_Single_Texture(int pass=0,int stage=0) const { return CurMatDesc->Peek_Single_Texture(pass,stage); } void Set_Material(int vidx,VertexMaterialClass * vmat,int pass=0) { CurMatDesc->Set_Material(vidx,vmat,pass); } void Set_Shader(int pidx,ShaderClass shader,int pass=0) { CurMatDesc->Set_Shader(pidx,shader,pass); } void Set_Texture(int pidx,TextureClass * tex,int pass=0,int stage=0) { CurMatDesc->Set_Texture(pidx,tex,pass,stage); } // Queries for determining whether this model has per-polygon arrays of Materials, Shaders, or Textures bool Has_Material_Array(int pass) const { return CurMatDesc->Has_Material_Array(pass); } bool Has_Shader_Array(int pass) const { return CurMatDesc->Has_Shader_Array(pass); } bool Has_Texture_Array(int pass,int stage) const { return CurMatDesc->Has_Texture_Array(pass,stage); } // "Get" functions for Materials, Textures, and Shaders when there are more than one (per-polygon/per-vertex) VertexMaterialClass * Get_Material(int vidx,int pass=0) const { return CurMatDesc->Get_Material(vidx,pass); } TextureClass * Get_Texture(int pidx,int pass=0,int stage=0) const { return CurMatDesc->Get_Texture(pidx,pass,stage); } ShaderClass Get_Shader(int pidx,int pass=0) const { return CurMatDesc->Get_Shader(pidx,pass); } // "Peek" functions for Materials and Textures when there are more than one (per-polygon/per-vertex) VertexMaterialClass * Peek_Material(int vidx,int pass=0) const { return CurMatDesc->Peek_Material(vidx,pass); } TextureClass * Peek_Texture(int pidx,int pass=0,int stage=0) const { return CurMatDesc->Peek_Texture(pidx,pass,stage); } void Replace_Texture(TextureClass* texture,TextureClass* new_texture); void Replace_VertexMaterial(VertexMaterialClass* vmat,VertexMaterialClass* new_vmat); ///////////////////////////////////////////////////////////////////////////////////// // Modification interface. Call these functions to cause the model to ensure // that the specified array is unique to this instance. (I.e. if the specified // data is being shared, break the link!) ///////////////////////////////////////////////////////////////////////////////////// void Make_Geometry_Unique(); void Make_UV_Array_Unique(int pass=0,int stage=0); void Make_Color_Array_Unique(int array_index=0); // Load the w3d file format WW3DErrorType Load_W3D(ChunkLoadClass & cload); ///////////////////////////////////////////////////////////////////////////////////// // Decal interface ///////////////////////////////////////////////////////////////////////////////////// void Create_Decal(DecalGeneratorClass * generator, MeshClass * parent); void Delete_Decal(uint32 decal_id); ///////////////////////////////////////////////////////////////////////////////////// // Alternate Material Description Interface // Some models will allow you to alternate between multiple material descriptions ///////////////////////////////////////////////////////////////////////////////////// void Enable_Alternate_Material_Description(bool onoff); bool Is_Alternate_Material_Description_Enabled(void); // Determine whether any rendering feature used by this mesh requires vertex normals bool Needs_Vertex_Normals(void); void Init_For_NPatch_Rendering(); const GapFillerClass* Get_Gap_Filler() const { return GapFiller; } protected: // MeshClass will set this for skins so that they can get the bone transforms void Set_HTree(const HTreeClass * htree); public: // Jani: I need to have an access to these for now... TexBufferClass * Get_Texture_Array(int pass,int stage,bool create = true) { return CurMatDesc->Get_Texture_Array(pass,stage,create); } MatBufferClass * Get_Material_Array(int pass,bool create = true) { return CurMatDesc->Get_Material_Array(pass,create); } ShaderClass * Get_Shader_Array(int pass,bool create = true) { return CurMatDesc->Get_Shader_Array(pass,create); } protected: int Register_Type(); // functions to compute the deformed vertices of skins. // Destination pointers MUST point to arrays large enough to hold all vertices void get_deformed_vertices(Vector3 *dst_vert, Vector3 *dst_norm, const HTreeClass * htree); void get_deformed_vertices(Vector3 *dst_vert, const HTreeClass * htree); void get_deformed_screenspace_vertices(Vector4 *dst_vert,const RenderInfoClass & rinfo,const Matrix3D & mesh_tm,const HTreeClass * htree); void compose_deformed_vertex_buffer( VertexFormatXYZNDUV2* verts, const Vector2* uv0, const Vector2* uv1, const unsigned* diffuse, const HTreeClass * htree); // loading WW3DErrorType read_chunks(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_texcoords(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_materials(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_v2_materials(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_v3_materials(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_per_tri_materials(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_vertex_colors(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_material_info(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_shaders(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_vertex_materials(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_textures(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_material_pass(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_vertex_material_ids(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_shader_ids(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_scg(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_dig(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_dcg(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_texture_stage(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_texture_ids(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_stage_texcoords(ChunkLoadClass & cload,MeshLoadContextClass * context); WW3DErrorType read_per_face_texcoord_ids (ChunkLoadClass &cload, MeshLoadContextClass *context); WW3DErrorType read_prelit_material (ChunkLoadClass &cload, MeshLoadContextClass *context); // post-processing void post_process(void); void post_process_fog(void); unsigned int get_sort_flags(int pass) const; unsigned int get_sort_flags(void) const; void compute_static_sort_levels(void); // mat info support void install_materials(MeshLoadContextClass * loadinfo); void clone_materials(const MeshModelClass & srcmesh); void install_alternate_material_desc(MeshLoadContextClass * context); // Material Descriptions // DefMatDesc - the default material description, allocated in constructor, always present. // AlternateMatDes - an optional alternate material description, allocated at load time if needed // CurMatDesc - pointer to the currently active material description. MeshMatDescClass * DefMatDesc; MeshMatDescClass * AlternateMatDesc; MeshMatDescClass * CurMatDesc; // Collection of the unique materials in the mesh MaterialInfoClass * MatInfo; // Jani: Adding this here temporarily... must fine better place GapFillerClass * GapFiller; bool HasBeenInUse; // For debugging purposes! friend class MeshClass; friend class MeshDeformSetClass; friend class MeshDeformClass; friend class MeshLoadContextClass; friend class DX8SkinFVFCategoryContainer; friend class DX8MeshRendererClass; friend class DX8PolygonRendererClass; }; /** ** GapFillerClass ** This class is used to generate gap-filling polygons for "N-Patched" meshes */ class GapFillerClass { TriIndex* PolygonArray; unsigned PolygonCount; unsigned ArraySize; TextureClass** TextureArray[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES]; VertexMaterialClass** MaterialArray[MeshMatDescClass::MAX_PASSES]; ShaderClass* ShaderArray[MeshMatDescClass::MAX_PASSES]; MeshModelClass* mmc; GapFillerClass& operator = (const GapFillerClass & that) {} public: GapFillerClass(MeshModelClass* mmc); GapFillerClass(const GapFillerClass& that); ~GapFillerClass(); WWINLINE const TriIndex* Get_Polygon_Array() const { return PolygonArray; } WWINLINE unsigned Get_Polygon_Count() const { return PolygonCount; } WWINLINE TextureClass** Get_Texture_Array(int pass, int stage) const { return TextureArray[pass][stage]; } WWINLINE VertexMaterialClass** Get_Material_Array(int pass) const { return MaterialArray[pass]; } WWINLINE ShaderClass* Get_Shader_Array(int pass) const { return ShaderArray[pass]; } void Add_Polygon(unsigned polygon_index,unsigned vidx1,unsigned vidx2, unsigned vidx3); void Shrink_Buffers(); }; #endif