/* ** 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 . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : LightMap * * * * $Archive:: /Commando/Code/Tool $* * * * $Author:: Ian_l $* * * * $Modtime:: 7/24/01 4:53p $* * * * $Revision:: 39 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifndef LIGHTMAPDOC_H #define LIGHTMAPDOC_H // Includes. #include "Rawfile.h" #include "w3d_file.h" #include "Chunk.h" #include "Lightscape.h" #include "meshmdl.h" // Defines. #define MAX_SOLVE_COUNT 2 #define TEMPORARY_SOLVE_FILENAME_COUNT 2 class LightMapDoc : public CDocument { public: enum PrelitModeEnum { UNLIT, VERTEX, MULTI_PASS, MULTI_TEXTURE, COUNT }; // Flags for anomalies in a W3D model. // WARNING: Do not exceed no. of bits in unsigned long. enum MeshFlagsEnum { // Unconditional errors. MESH_HIDDEN, MESH_PRELIT, MESH_NO_VERTEX_MATERIALS, MESH_NO_SHADERS, MESH_HAS_HIERARCHY, MESH_NOT_MODULATED_PRIMARY, MESH_HAS_SPECULAR, MESH_SPECULAR_TO_DIFFUSE, MESH_W3D_CHUNK_DEFORM, MESH_TWO_SIDED, MESH_HAS_EMISSIVE, MESH_HAS_SCG, // Vertex specific errors. MESH_HAS_DIG, // Lightmap multi-pass specific errors. MESH_TOO_MANY_PASSES, MESH_ALPHATEST, MESH_PASS_ZERO_DESTBLEND, // Lightmap multi-texture specific errors. MESH_TOO_MANY_STAGES, // General warnings. MESH_VERTEX_COLORING, MESH_FLAG_COUNT, // Unconditional errors. MESH_ERROR_MASK = (1 << MESH_HIDDEN) | (1 << MESH_PRELIT) | (1 << MESH_NO_VERTEX_MATERIALS) | (1 << MESH_NO_SHADERS) | (1 << MESH_HAS_HIERARCHY) | (1 << MESH_NOT_MODULATED_PRIMARY) | (1 << MESH_HAS_SPECULAR) | (1 << MESH_SPECULAR_TO_DIFFUSE) | (1 << MESH_W3D_CHUNK_DEFORM) | (1 << MESH_TWO_SIDED) | (1 << MESH_HAS_EMISSIVE) | (1 << MESH_HAS_SCG), // Anomalies that will prevent a vertex solve from being inserted. MESH_VERTEX_ERROR_MASK = MESH_ERROR_MASK | (1 << MESH_HAS_DIG), // Anomalies that will prevent a multi-pass lightmap solve from being inserted. MESH_MULTI_PASS_ERROR_MASK = MESH_ERROR_MASK | (1 << MESH_TOO_MANY_PASSES) | (1 << MESH_ALPHATEST) | (1 << MESH_PASS_ZERO_DESTBLEND), // Anomalies that will prevent a multi-texture lightmap solve from being inserted. MESH_MULTI_TEXTURE_ERROR_MASK = MESH_ERROR_MASK | (1 << MESH_TOO_MANY_STAGES) }; // Functions. bool Is_Open() {return (W3dFile != NULL);} bool Can_Insert_Solve() {return (CanInsertSolve && SolveCount < MAX_SOLVE_COUNT);} void Insert_Solve (const char *solvedirectoryname, const char *solvefilenamelist, const char *inclusionstring, bool invertselection, bool blendnoise); bool Solve_Inserted() {return (SolveCount > 0);} unsigned Mesh_Count() {return (MeshStatus.Count());} const char *Mesh_Name (unsigned index) {return (MeshStatus [index].Name);} const char *Mesh_Anomalies_String (unsigned meshindex, bool verbose, StringBuilder &string); const char *Solve_Anomalies_String (unsigned meshindex, bool verbose, StringBuilder &string); const char *Vertex_Solve_Status_String (unsigned meshindex, StringBuilder &string); const char *Lightmap_Solve_Status_String (unsigned meshindex, StringBuilder &string); private: struct MeshInfoStruct { public: MeshInfoStruct (FileClass &meshfile); ~MeshInfoStruct (); unsigned Lightmap_Vertex_Material_Count() const {return (1);} unsigned Lightmap_Shader_Count() const {return (1);} W3dMeshHeader3Struct Header; W3dMaterialInfoStruct MaterialInfo [PrelitModeEnum::COUNT]; ChunkClass *TriangleChunk; ChunkClass *VertexChunk; DynamicVectorClass *VertexMaterials [PrelitModeEnum::COUNT]; ChunkClass *ShaderChunk [PrelitModeEnum::COUNT]; ChunkClass *ShaderIdChunk [PrelitModeEnum::COUNT][MeshMatDescClass::MAX_PASSES]; ChunkClass *SCGChunk [PrelitModeEnum::COUNT][MeshMatDescClass::MAX_PASSES]; bool SCGsExist; bool DIGsExist; bool DeformExists; bool IsMultiStage; bool VertexColorsExist; private: void Parse_Vertex_Materials (ChunkLoadClass &w3dchunk, unsigned prelitmode); void Parse_Material_Pass (ChunkLoadClass &w3dchunk, unsigned prelitmode, unsigned materialpass); void Parse_Prelit_Chunk (ChunkLoadClass &w3dchunk, unsigned prelitmode); }; struct MeshAnomalyStruct { public: MeshAnomalyStruct (const MeshInfoStruct &meshinfo); unsigned long MeshAnomalies; }; struct MeshStatusStruct { // Equality operator. bool operator == (const MeshStatusStruct &m) { return (strcmp (Name, m.Name) == 0); } // Inequality operator. bool operator != (const MeshStatusStruct &m) { return (!(*this == m)); } MeshStatusStruct() {} MeshStatusStruct (const char *name, unsigned trianglecount, unsigned long meshanomalies) { strcpy (Name, name); TriangleCount = trianglecount; MeshAnomalies = meshanomalies; InsertedFlags = 0; } bool Can_Insert_Vertex_Solve() { return (((MeshAnomalies & MESH_VERTEX_ERROR_MASK) == 0) && SolveStatistics.Valid_Vertex_Solve()); } bool Can_Insert_Multi_Pass_Solve() { return (((MeshAnomalies & MESH_MULTI_PASS_ERROR_MASK) == 0) && SolveStatistics.Valid_Lightmap_Solve()); } bool Can_Insert_Multi_Texture_Solve() { return (((MeshAnomalies & MESH_MULTI_TEXTURE_ERROR_MASK) == 0) && SolveStatistics.Valid_Lightmap_Solve()); } bool Inserted_Vertex_Solve() {return ((InsertedFlags & W3D_MESH_FLAG_PRELIT_VERTEX) != 0);} bool Inserted_Multi_Pass_Solve() {return ((InsertedFlags & W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_PASS) != 0);} bool Inserted_Multi_Texture_Solve() {return ((InsertedFlags & W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_TEXTURE) != 0);} unsigned long Prelit_Flags() { unsigned long prelitflags; // If a vertex solve cannot be inserted substitute an unlit solve. if (Can_Insert_Vertex_Solve()) { prelitflags = W3D_MESH_FLAG_PRELIT_VERTEX; } else { prelitflags = W3D_MESH_FLAG_PRELIT_UNLIT; } if (Can_Insert_Multi_Pass_Solve()) prelitflags |= W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_PASS; if (Can_Insert_Multi_Texture_Solve()) prelitflags |= W3D_MESH_FLAG_PRELIT_LIGHTMAP_MULTI_TEXTURE; return (prelitflags); } char Name [W3D_NAME_LEN]; unsigned TriangleCount; unsigned long MeshAnomalies; unsigned long InsertedFlags; // Which prelit mode types were inserted with the most recent solve? SolveStatistics SolveStatistics; }; struct SplitVertexInfoStruct { public: SplitVertexInfoStruct (const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve); ~SplitVertexInfoStruct(); unsigned Vertex_Count() const {return (VertexCount);} uint32 Remap (unsigned v) const {ASSERT (v < Vertex_Count()); return (RemapTable [v]);} uint32 Index (unsigned v) const {ASSERT (v < FaceVertexCount); return (IndexTable [v]);} W3dTexCoordStruct *UV (unsigned v) const {ASSERT (v < Vertex_Count()); return (UVPtrTable [v]);} private: SplitVertexInfoStruct() {ASSERT (false);} unsigned VertexCount; unsigned FaceVertexCount; uint32 *RemapTable; uint32 *IndexTable; W3dTexCoordStruct *UVTable; W3dTexCoordStruct **UVPtrTable; }; struct MeshReorderStruct { // Equality operator. bool operator == (const MeshReorderStruct &m) { return ((Chunk == m.Chunk) && (Position == m.Position)); } // Inequality operator. bool operator != (const MeshReorderStruct &m) { return (!(*this == m)); } public: ChunkClass *Chunk; Vector3 Position; }; // Functions. bool Check_Document(); void Reorder(); void Optimize(); void Optimize_Prelit_Vertex_Material_Pass (ChunkLoadClass &w3dchunk, ChunkSaveClass &optimizechunk); void Rename_Mesh (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *filename, const char *lightmapdirectory); void Rename_Mesh_Header (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *filename); void Rename_Prelit_Chunks (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *lightmapdirectory); void Rename_Lightmaps (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *lightmapdirectory); void Rename_Collection (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *filename); void Rename_HLOD (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *filename); void Rename_Dazzle (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk, const char *filename); void Save_Lights (const char *pathname); void Translate_Mesh_Header3 (ChunkLoadClass &w3dchunk, unsigned long prelitflags, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Vertices (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Vertex_Normals (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Vertex_Influences (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Triangles (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Vertex_Shade_Indices (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Insert_Solve (PrelitModeEnum inputmode, FileClass &meshfile, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Insert_Solve (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Material_Info (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve); void Translate_Vertex_Materials (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo); void Translate_Shaders (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo); void Translate_Textures (ChunkLoadClass &w3dchunk, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const LightscapeMeshSolve &meshsolve); void Add_Lightmap_Textures (ChunkSaveClass &solvechunk, const LightscapeMeshSolve &meshsolve); void Translate_Material_Pass (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, unsigned materialpass, PrelitModeEnum outputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Translate_DCGs (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_DIGs (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, unsigned materialpass, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Add_DIGs (PrelitModeEnum inputmode, unsigned materialpass, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Vertex_Material_IDs (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Texture_Stage (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Stage_Texcoords (ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const SplitVertexInfoStruct &splitvertexinfo); void Add_Lightmap_Material_Pass (PrelitModeEnum inputmode, unsigned materialpass, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Add_Lightmap_Stage (PrelitModeEnum inputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Translate_Lightmap_Stage (PrelitModeEnum inputmode, ChunkLoadClass &w3dchunk, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Add_Lightmap_Stage_Chunks (PrelitModeEnum inputmode, ChunkSaveClass &solvechunk, const MeshInfoStruct &meshinfo, const LightscapeMeshSolve &meshsolve, const SplitVertexInfoStruct &splitvertexinfo); void Copy_Chunk (ChunkLoadClass &loadchunk, ChunkSaveClass &savechunk); // Member data. char DocumentName [_MAX_FNAME]; // Name of this document. RawFileClass *W3dFile; // Ptr to current open w3d document. unsigned MeshCount; // Total no. of meshes in this w3d document. unsigned TriangleCount; // Total no. of triangles in this w3d document. bool CanInsertSolve; // Can a solve be inserted? unsigned SolveCount; // No. of solves inserted so far. DynamicVectorClass MeshStatus; // Mesh information database. DynamicVectorClass Lights [MAX_SOLVE_COUNT]; // All active lights in the solves. // Static data. static const char *_TemporarySolveFilename [TEMPORARY_SOLVE_FILENAME_COUNT]; static const char *_TemporaryOptimizeFilename; static const char *_TemporaryReorderFilename; // The following is maintained by MFC tools. protected: // create from serialization only LightMapDoc(); DECLARE_DYNCREATE(LightMapDoc) // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(LightMapDoc) public: virtual BOOL OnNewDocument(); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual void Serialize(CArchive& ar); virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); virtual void DeleteContents(); //}}AFX_VIRTUAL // Implementation public: virtual ~LightMapDoc(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif // Generated message map functions protected: //{{AFX_MSG(LightMapDoc) afx_msg void OnFileSave(); afx_msg void OnFileSaveAs(); afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI); afx_msg void OnUpdateFileSaveAs(CCmdUI* pCmdUI); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #endif // LIGHTMAPDOC_H