/* ** 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/03/01 3:07p $* * * * $Revision:: 38 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifndef _LIGHTSCAPE_H #define _LIGHTSCAPE_H // Includes. #include "Chunk.h" #include "LightMapPacker.h" #include "Triangle.h" #include "arraylistof.h" #include "light.h" #include "lsbasebuilders.h" #include "ltttypes.h" #include "rmap.h" #include "vector.h" #include "vector2.h" #include "vector3.h" #include "vector3i.h" #include "wwmath.h" #include "w3d_file.h" class TextureNameNode; class SolveStatistics { public: enum SolveStatisticEnum { VERTEX_NOT_FOUND, VERTEX_NO_COLOR, FACE_NOT_FOUND, FACE_NO_LIGHTMAP, VERTEX_NOT_SMOOTH, FACE_AMBIGUOUS, FACE_DEGENERATE, FACE_UNDERSIZED, EDGE_MATCH, ALL_FILL_COLOR, NULL_TEXTURE, SOLVE_STATISTIC_COUNT }; SolveStatistics () { VertexCount = 0; FaceCount = 0; for (unsigned s = 0; s < SOLVE_STATISTIC_COUNT; s++) Count [s] = 0; } SolveStatistics (unsigned vertexcount, unsigned facecount) { VertexCount = vertexcount; FaceCount = facecount; for (unsigned s = 0; s < SOLVE_STATISTIC_COUNT; s++) Count [s] = 0; } bool Valid_Vertex_Solve() const { return (((Count [VERTEX_NOT_FOUND] == 0) || (Count [VERTEX_NOT_FOUND] < VertexCount)) && (Count [VERTEX_NO_COLOR] == 0)); } bool Valid_Lightmap_Solve() const { return (((Count [FACE_NOT_FOUND] == 0) || (Count [FACE_NOT_FOUND] < FaceCount)) && (Count [FACE_NO_LIGHTMAP] == 0)); } bool operator == (unsigned c) { unsigned sum; sum = 0; for (unsigned s = 0; s < SOLVE_STATISTIC_COUNT; s++) sum += Count [s]; return (sum == c); } unsigned VertexCount; unsigned FaceCount; unsigned Count [SOLVE_STATISTIC_COUNT]; }; // Class wrapper for floating point color vectors. class ColorVector : public Vector3 { public: ColorVector () : Vector3() {} ColorVector (float r, float g, float b) : Vector3 (r, g, b) {} void Set (float r, float g, float b) { Vector3::Set (r, g, b); } void Set (const LtTRGBColor &irradiance, const RadianceMap &radiancemap) { const double oopi = 1.0 / M_PI; X = irradiance.GetR() * oopi; Y = irradiance.GetG() * oopi; Z = irradiance.GetB() * oopi; radiancemap.ToColor (X, Y, Z); } }; class LightscapeSolve : public LightmapPacker { public: // Member functions. LightscapeSolve (const char *solvedirectoryname, const char *solvefilenamelist, CStatusBar* statusptr, const char *statusbarmessage, bool blendnoise = false); Finish(); ~LightscapeSolve (); // Database ammendment functions. void Set_Is_Solution (bool issolution) {IsSolution = issolution;} void Set_Brightness (float brightness) {Brightness = brightness;} void Set_Contrast (float contrast) {Contrast = contrast;} void Set_Is_Daylight (bool isdaylight) {IsDaylight = isdaylight;} void Set_Is_Exterior (bool isexterior) {IsExterior = isexterior;} void Set_Patch_Cluster_Count (int count) {PatchClusterCount = count;} void Set_Is_M2T_Solve (bool ism2tsolve) {IsM2TSolve = ism2tsolve;} void Add_Material_Texture_Name (const char *materialname, const char *texturename); void Add_Texture_Name (unsigned patchindex, const char *materialname); void Add_Light (LightClass *light); bool Add_Vertex (unsigned vertexindex, const Vector3 &p, const Vector3 &n, unsigned patchindex, const Vector2 &t); bool Add_Vertex (unsigned vertexindex, const Vector3 &p, const Vector3 &n, unsigned patchindex, const ColorVector &c); bool Add_Patch_Face (unsigned patchfaceindex, unsigned patchindex, unsigned vertexindexcount, unsigned *vertexindices); // Database query functions. float Get_Brightness() {return (Brightness);} float Get_Contrast() {return (Contrast);} bool Is_Daylight() {return (IsDaylight);} bool Is_Exterior() {return (IsExterior);} bool Is_M2T_Solve() {return (IsM2TSolve);} float Filter_Sharpness() {return (FilterSharpness);} ProceduralTexture *Procedural_Texture() {return (ProceduralTexture);} unsigned Light_Count() {return (Lights.Count());} LightClass *Get_Light (unsigned l) {return (Lights [l]);} const char *Light_Exclusion_String() {return (LightExclusionString);} void Find_Vertex (const Vector3 &point, const Vector3 *smoothingnormalptr, W3dRGBStruct &vertexcolor, SolveStatistics &solvestatistics); void Find_Triangle (const Vector3 *points, const Vector3 &normal, PackingTriangle &triangle, SolveStatistics &solvestatistics); void Submit_Triangle (PackingTriangle &triangle); const TextureNameNode *Texture_Name (unsigned patchindex); void Pack(); // Update the progress bar. void Step_It() {ProgressBar->StepIt();} // Static functions. static LightscapeSolve *Importer() {return (_ActiveImporter);} static const char *Asset_Directory() {return (LightmapPacker::Asset_Directory());} static const char *Asset_Directory (const char *filename) {return (LightmapPacker::Asset_Directory (filename));} static void Copy_Assets (const char *pathname) {LightmapPacker::Copy_Assets (pathname);} private: // Result of finding a face. enum FaceResultEnum { FACE_NOT_FOUND, FACE_AMBIGUOUS, FACE_FOUND }; // Area of the face. enum FaceSizeEnum { FACE_DEGENERATE, FACE_UNDERSIZED, FACE_NOT_UNDERSIZED }; struct VerticesStruct { // Equality operator. bool operator == (const VerticesStruct &v) { return ((Point == v.Point) && (FaceNormal == v.FaceNormal) && (PatchIndex == v.PatchIndex) && (ValidColor == v.ValidColor) && (Color == v.Color) && (ValidUV == v.ValidUV) && (UV == v.UV)); } // Inequality operator. bool operator != (const VerticesStruct &v) { return (!(*this == v)); } Vector3 Point; Vector3 FaceNormal; unsigned PatchIndex; bool ValidColor; ColorVector Color; bool ValidUV; Vector2 UV; }; struct PatchFaceStruct { enum VerticesPerPatchFace { VERTICES_PER_PATCH_FACE = 4 }; // To indicate whether a patch face vertex index is valid. enum VertexIndexValidity { VERTEX_INDEX_INVALID = -1 }; // Equality operator. bool operator == (const PatchFaceStruct &p) { return ((PatchIndex == p.PatchIndex) && (VertexIndices [0] == p.VertexIndices [0]) && (VertexIndices [1] == p.VertexIndices [1]) && (VertexIndices [2] == p.VertexIndices [2]) && (VertexIndices [3] == p.VertexIndices [3])); } // Inequality operator. bool operator != (const PatchFaceStruct &p) { return (!(*this == p)); } unsigned PatchIndex; unsigned VertexIndices [VERTICES_PER_PATCH_FACE]; }; // Member functions. void Find_Adjacent_Triangles (const PackingTriangle &principaltriangle, DynamicVectorClass &adjtriangles); void Find_Triangle (const Vector3 *points, const Vector3 &facenormal, VerticesStruct *vertices, FaceResultEnum &faceresult); void Find_Triangle (const Vector3 *points, float tolerance, bool centroidtest, const Vector3 *facenormal, VerticesStruct *vertices, FaceResultEnum &faceresult); void Find_Vertices (const Vector3 &point, float tolerance, DynamicVectorClass &vertices); // Miscellaneous convenience functions. FaceSizeEnum Face_Size (const Vector3 *points, unsigned count); unsigned Longest_Edge (const Vector3 *points, unsigned count, bool *usededges); float Manhatten_Distance (const Vector3 &v) { return (WWMath::Fabs (v.X) + WWMath::Fabs (v.Y) + WWMath::Fabs (v.Z)); } // Comparison functions. static int Compare_Material_Texture_Names (const void *materialname0, const void *materialname1); static int Compare_Vertices (const void *vertexindexptr0, const void *vertexindexptr1); static int Compare_Patch_Faces (const void *patchface0, const void *patchface1); // Member data. float SmoothingAngle; float SpatialTolerance; float FilterSharpness; bool IsSolution; // Is the currently imported file a valid solve file? int PatchClusterCount; // Total patch cluster count over all parsed solve files. float Brightness; float Contrast; bool IsDaylight; bool IsExterior; bool IsM2TSolve; ProceduralTexture *ProceduralTexture; CProgressCtrl *ProgressBar; DynamicVectorClass MaterialTextureNames; // pairs for all materials in the solve. DynamicVectorClass TextureNames; // for all patches in the solve. DynamicVectorClass Vertices; // tuples for all vertices in the solve. DynamicVectorClass VertexIndices; // Indices into Vertices. DynamicVectorClass PatchFaces; // pairs for all faces in the solve. DynamicVectorClass Lights; // All active lights in the solve. const char *LightExclusionString; // Do not add lights that contain this string. // Static data. static LightscapeSolve *_ActiveImporter; // Object currently importing (reading a solution file) (otherwise NULL). }; class LsInformationFactory : public LtTBuilderFactory { protected: virtual LtTInfoBuilderApi *OnGetInfoBuilder(); virtual LtTParameterBuilderApi *OnGetParameterBuilder(); }; class LsPreparationFactory : public LtTBuilderFactory { protected: virtual LtTInfoBuilderApi *OnGetInfoBuilder(); virtual LtTParameterBuilderApi *OnGetParameterBuilder(); virtual LtTMaterialBuilderApi *OnGetMaterialBuilder(); virtual LtTLampBuilderApi *OnGetLampBuilder(); virtual LtTMeshBuilderApi *OnGetMeshBuilder(); }; class LsMainFactory : public LtTBuilderFactory { public: LsMainFactory(); unsigned Patch_Face_Count() {return (PatchFaceIndex);} void Patch_Face_Increment() {PatchFaceIndex++;} unsigned Vertex_Count() {return (VertexIndex);} void Vertex_Increment() {VertexIndex++;} unsigned Patch_Count() {return (PatchIndex);} void Patch_Increment() {PatchIndex++; LightscapeSolve::Importer()->Step_It();} protected: virtual LtTInfoBuilderApi *OnGetInfoBuilder(); virtual LtTParameterBuilderApi *OnGetParameterBuilder(); virtual LtTMeshBuilderApi *OnGetMeshBuilder(); private: unsigned PatchFaceIndex; unsigned VertexIndex; unsigned PatchIndex; }; class LsInfoBuilder : public LtTBaseInfoBuilder { protected: LsInfoBuilder (LtTBuilderFactory *factory); LtTBool Finish(); friend class LsInformationFactory; friend class LsPreparationFactory; friend class LsMainFactory; }; class LsParameterBuilder : public LtTBaseParameterBuilder { protected: LsParameterBuilder (LtTBuilderFactory *factory); LtTBool Finish(); friend class LsInformationFactory; friend class LsPreparationFactory; friend class LsMainFactory; }; class LsMaterialBuilder : public LtTBaseMaterialBuilder { protected: LsMaterialBuilder (LtTBuilderFactory *factory); LtTBool Finish(); friend class LsPreparationFactory; }; class LsLampBuilder : public LtTBaseLampBuilder { protected: LsLampBuilder (LtTBuilderFactory *factory); LtTBool Finish(); friend class LsPreparationFactory; }; class LsMeshInquirer : public LtTBaseMeshBuilder { protected: LsMeshInquirer (LtTBuilderFactory *factory); LtTBool Finish(); friend class LsPreparationFactory; }; class LsMeshBuilder : public LtTBaseMeshBuilder { protected: LsMeshBuilder (LtTBuilderFactory *factory); ~LsMeshBuilder(); LtTBool Finish(); void SetFaces (const int facecount, const LtTFace *v); int GetFaceCount() const; const LtTFace *GetFaces() const; LsMainFactory *FactoryPtr; private: struct FaceVertexStruct { // Equality operator. bool operator == (const FaceVertexStruct &fv) { return ((Point == fv.Point) && (Color == fv.Color) && (Weight == fv.Weight)); } // Inequality operator. bool operator != (const FaceVertexStruct &fv) { return (!(*this == fv)); } Vector3 Point; ColorVector Color; float Weight; }; LtTFace *Faces; int FaceCount; int AllocatedCount; friend class LsMainFactory; friend class VertexUser; }; class VertexUser { public: VertexUser (const LsMeshBuilder &meshbuilder); ~VertexUser () {delete [] UsedVertexIndices;} bool Is_Used (unsigned vertexindex) { ASSERT (vertexindex < Count); return (UsedVertexIndices [vertexindex] != UNUSED); } void Set_Index (unsigned vertexindex, unsigned usedvertexindex) { ASSERT (Is_Used (vertexindex)); UsedVertexIndices [vertexindex] = usedvertexindex; } unsigned Get_Index (unsigned vertexindex) { ASSERT (vertexindex < Count); // This vertex must have previously been set. ASSERT (UsedVertexIndices [vertexindex] >= 0); return (UsedVertexIndices [vertexindex]); } private: enum VertexUsage { UNUSED = -2, USED = -1 }; VertexUser() {} unsigned Count; int *UsedVertexIndices; }; class LightscapeMeshSolve { public: LightscapeMeshSolve (LightscapeSolve &solve, ChunkClass &trianglechunk, ChunkClass &vertexchunk); ~LightscapeMeshSolve(); W3dRGBStruct Vertex_Color (unsigned vertexindex) const; unsigned Vertex_Color_Count() const {return (VertexCount);} const char *Lightmap_Pathname (unsigned lightmapindex) const; unsigned Lightmap_Index (unsigned faceindex) const; W3dTexCoordStruct Lightmap_UV (unsigned facevertexindex) const; unsigned Lightmap_Count() const {return (LightmapCount);} const SolveStatistics *Get_Statistics() const {return (&Statistics);} private: unsigned VertexCount; // No. of vertices in mesh. unsigned FaceCount; // No. of faces in mesh. unsigned FaceVertexCount; // No. of face-vertices in mesh. unsigned LightmapCount; // No. of lightmaps used by mesh. W3dRGBStruct *VertexColors; // Array of vertex colors. Vector2 *FaceVertexUVs; // Array to map a face-vertex index to a UV coordinate. unsigned *FaceRemapLightmapIndices; // Array to map a face to a zero-based lightmap index. unsigned *LightmapIndices; // Array to map a zero-based lightmap index to a 'real' lightmap index. SolveStatistics Statistics; // Statistics counters. }; #endif // LIGHTSCAPE_H