385 lines
17 KiB
C++
385 lines
17 KiB
C++
/*
|
|
** 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/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** 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 <W3dVertexMaterialStruct> *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 <MeshStatusStruct> MeshStatus; // Mesh information database.
|
|
DynamicVectorClass <LightClass*> 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
|