Files
UnrealEngine/Engine/Source/Developer/MeshMergeUtilities/Public/MeshMergeDataTracker.h
2025-05-18 13:04:45 +08:00

224 lines
8.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "StaticMeshResources.h"
#include "Materials/MaterialInstance.h"
#include "MaterialUtilities.h"
#include "StaticMeshAttributes.h"
typedef TPair<uint32, uint32> MeshLODPair;
typedef TPair<uint32, uint32> SectionRemapPair;
typedef TPair<uint32, uint32> MaterialRemapPair;
struct FSectionInfo;
/** Structure representing a mesh and lod index */
struct MESHMERGEUTILITIES_API FMeshLODKey
{
public:
FMeshLODKey(int32 MeshIndex, int32 LODIndex, UStaticMesh* InMesh = nullptr)
{
CombinedKey = ((LODIndex & 0xffff) << 16) | (MeshIndex & 0xffff);
Mesh = InMesh;
VertexColorHash = 0;
}
explicit FMeshLODKey(uint32 InCombinedKey)
{
CombinedKey = InCombinedKey;
Mesh = nullptr;
VertexColorHash = 0;
}
UStaticMesh* GetMesh() const
{
return Mesh;
}
int32 GetMeshIndex() const
{
return (CombinedKey & 0x0000ffff);
}
int32 GetLODIndex() const
{
return (CombinedKey & 0xffff0000) >> 16;
}
uint32 GetVertexColorHash() const
{
return VertexColorHash;
}
void SetVertexColorHash(uint32 InVertexColorHash)
{
VertexColorHash = InVertexColorHash;
}
inline bool operator==(const FMeshLODKey& Other) const
{
return CombinedKey == Other.CombinedKey;
}
inline friend uint32 GetTypeHash(const FMeshLODKey& Item)
{
return Item.CombinedKey;
}
protected:
uint32 CombinedKey;
UStaticMesh* Mesh;
uint32 VertexColorHash;
};
/** This helps identify materials that can be collapsed because of equivalence */
struct MESHMERGEUTILITIES_API FMaterialKey
{
FMaterialKey(const UMaterialInterface* InMaterial)
: Material(InMaterial)
{
}
inline bool operator==(const FMaterialKey& Other) const
{
// Perform an optional custom comparison if we are trying to collapse material instances
const UMaterialInstance* MaterialInstance0 = Cast<UMaterialInstance>(Material);
const UMaterialInstance* MaterialInstance1 = Cast<UMaterialInstance>(Other.Material);
if(MaterialInstance0 && MaterialInstance1)
{
return MaterialInstance0->Equivalent(MaterialInstance1);
}
else
{
return Material == Other.Material;
}
}
const UMaterialInterface* Material;
};
/** Typedefs to allow for some nicer looking loops */
typedef TMap<FMeshLODKey, FMeshDescription>::TConstIterator TConstRawMeshIterator;
typedef TMap<FMeshLODKey, FMeshDescription>::TIterator TRawMeshIterator;
typedef TArray<int32>::TConstIterator TConstLODIndexIterator;
/** Used to keep track of in-flight data while meshes are merged and their corresponding materials baked down */
class MESHMERGEUTILITIES_API FMeshMergeDataTracker
{
public:
FMeshMergeDataTracker();
/** Looks at all available raw mesh data and processes it to populate some flags */
void ProcessRawMeshes();
/** Adding a mapping between the index for an original mesh section index and the mesh section it will be indexed to in the final mesh */
void AddSectionRemapping(int32 MeshIndex, int32 LODIndex, int32 OriginalIndex, int32 UniqueIndex);
/** Retrieves the MeshLOD keys from which the original sections are mapped to the unique section index */
void GetMeshLODsMappedToUniqueSection(int32 UniqueIndex, TArray<FMeshLODKey>& InOutMeshLODs);
/** Retrieves all section mappings for the MeshLOD key*/
void GetMappingsForMeshLOD(FMeshLODKey Key, TArray<SectionRemapPair>& InOutMappings);
/** Adds or retrieves raw mesh data for the mesh and LOD index */
FMeshDescription& AddAndRetrieveRawMesh(int32 MeshIndex, int32 LODIndex, UStaticMesh* InMesh);
/** Removes raw mesh entry for the given mesh and LOD index */
void RemoveRawMesh(int32 MeshIndex, int32 LODIndex);
/** Retrieves Raw Mesh ptr for the given mesh and LOD index */
FMeshDescription* GetRawMeshPtr(int32 MeshIndex, int32 LODIndex);
/** Retrieves Raw Mesh ptr for the given MeshLOD key */
FMeshDescription* GetRawMeshPtr(FMeshLODKey Key);
/** Tries to retrieve a FMeshDescription and returns the LOD index it found an entry for */
FMeshDescription* FindRawMeshAndLODIndex(int32 MeshIndex, int32& OutLODIndex);
/** Tries to retrieve a FMeshDescription for the given mesh and LOD index, if it can't it will try to find an entry for each LOD levle below InOutDesiredLODIndex */
FMeshDescription* TryFindRawMeshForLOD(int32 MeshIndex, int32& InOutDesiredLODIndex);
/** Returns a const key/value iterator for the FMeshDescription entries */
TConstRawMeshIterator GetConstRawMeshIterator() const;
/** Returns a non-const key/value iterator for the FMeshDescription entries */
TRawMeshIterator GetRawMeshIterator();
/** Adds a record of what channel lightmap data is stored at */
void AddLightmapChannelRecord(int32 MeshIndex, int32 LODIndex, int32 LightmapChannelIndex);
/** Adds (unique) section to stored data */
int32 AddSection(const FSectionInfo& SectionInfo);
/** Returns the number of unique sections */
int32 NumberOfUniqueSections() const;
/** Returns the material used by the unique section */
UMaterialInterface* GetMaterialForSectionIndex(int32 SectionIndex);
/** Returns the unique section instance */
const FSectionInfo& GetSection(int32 SectionIndex) const;
/** Clears out unique section to be replaced with the baked material one */
void AddBakedMaterialSection(const FSectionInfo& SectionInfo);
/** Add a material slot name for a unique material instance. */
void AddMaterialSlotName(UMaterialInterface *MaterialInterface, FName MaterialSlotName);
/** Get the material slot name from a unique material instance. */
FName GetMaterialSlotName(UMaterialInterface *MaterialInterface) const;
/** Adds a LOD index which will be part of the final merged mesh */
void AddLODIndex(int32 LODIndex);
/** Retrieves number of LODs part of the final merged mesh */
int32 GetNumLODsForMergedMesh() const;
/** Iterates over LOD indices for mesh */
TConstLODIndexIterator GetLODIndexIterator() const;
/** Add number of lightmap pixels used for one of the Meshes */
void AddLightMapPixels(int32 Pixels);
/** Returns the texture dimension required to distribute all of the lightmap pixels */
int32 GetLightMapDimension() const;
/** Returns whether or not any raw mesh entry contains vertex colors for the specified LOD index */
bool DoesLODContainVertexColors(int32 LODIndex) const;
/** Returns whether or not any raw mesh entry contains vertex colors for any LOD index */
bool DoesAnyLODContainVertexColors() const;
/** Returns whether or not any raw mesh entry contains texture coordinates for the specified UV channel and LOD index */
bool DoesUVChannelContainData(int32 UVChannel, int32 LODIndex) const;
/** Returns whether or not any raw mesh entry contains texture coordinates for the specified UV channel and any LOD index */
bool DoesUVChannelContainData(int32 UVChannel) const;
/** Returns whether or not the raw mesh entry for the given MeshLOD key requires unique UVs for baking out its material(s) */
bool DoesMeshLODRequireUniqueUVs(FMeshLODKey Key);
/** Returns the first available UV channel across all raw mesh entries, which will be a good fit for the lightmap UV index in the final mesh */
int32 GetAvailableLightMapUVChannel() const;
void AddComponentToWedgeMapping(int32 MeshIndex, int32 LODIndex, uint32 WedgeIndex);
uint32 GetComponentToWedgeMappng(int32 MeshIndex, int32 LODIndex) const;
double GetTextureSizeFromTargetTexelDensity(float InTargetTexelDensity) const;
protected:
// Mesh / LOD index, RawMesh
TMap<FMeshLODKey, FMeshDescription> RawMeshLODs;
// Mesh / LOD index, lightmap channel
TMap<FMeshLODKey, int32> LightmapChannelLODs;
// Whether a key requires unique UVs
TArray<FMeshLODKey> RequiresUniqueUVs;
//Use this map to recycle the material slot name
TMap<UMaterialInterface *, FName> MaterialInterfaceToMaterialSlotName;
/** Flags for UV and vertex color usage */
bool bWithVertexColors[MAX_STATIC_MESH_LODS];
bool bOcuppiedUVChannels[MAX_STATIC_MESH_LODS][MAX_MESH_TEXTURE_COORDS_MD];
/** First available UV channel across all RawMesh entries */
int32 AvailableLightMapUVChannel;
int32 SummedLightMapPixels;
/** Remapping pairs for each mesh and LOD index combination */
TMultiMap<FMeshLODKey, SectionRemapPair> UniqueSectionIndexPerLOD;
/** Maps from each unique section index to all the RawMesh entries which contain an original section that's mapped to it */
TMultiMap<uint32, FMeshLODKey> UniqueSectionToMeshLOD;
/** All LOD indices which should be populated in the final merged mesh */
TArray<int32> LODIndices;
/** Unique set of sections in mesh */
TArray<FSectionInfo> UniqueSections;
TMap<FMeshLODKey, uint32> ComponentToWedgeOffsets;
};