You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
162 lines
7.1 KiB
C++
162 lines
7.1 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MeshDescriptionHelper.h"
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "CoreTypes.h"
|
|
#include "UObject/UObjectGlobals.h"
|
|
#include "UObject/Package.h"
|
|
#include "Engine/EngineTypes.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "MeshDescription.h"
|
|
#include "MeshAttributes.h"
|
|
#include "Serialization/MemoryWriter.h"
|
|
#include "Serialization/MemoryReader.h"
|
|
#include "RenderUtils.h"
|
|
#include "IMeshReductionInterfaces.h"
|
|
#include "IMeshReductionManagerModule.h"
|
|
#include "Materials/Material.h"
|
|
#include "RawMesh.h"
|
|
#include "BuildStatisticManager.h"
|
|
#include "MeshDescriptionOperations.h"
|
|
#include "Modules/ModuleManager.h"
|
|
|
|
//Enable all check
|
|
//#define ENABLE_NTB_CHECK
|
|
|
|
DEFINE_LOG_CATEGORY(LogMeshDescriptionBuildStatistic);
|
|
|
|
FMeshDescriptionHelper::FMeshDescriptionHelper(FMeshBuildSettings* InBuildSettings)
|
|
: BuildSettings(InBuildSettings)
|
|
{
|
|
}
|
|
|
|
void FMeshDescriptionHelper::GetRenderMeshDescription(UObject* Owner, const FMeshDescription& InOriginalMeshDescription, FMeshDescription& OutRenderMeshDescription)
|
|
{
|
|
UStaticMesh* StaticMesh = Cast<UStaticMesh>(Owner);
|
|
check(StaticMesh);
|
|
|
|
//Copy the Original Mesh Description in the render mesh description
|
|
OutRenderMeshDescription = InOriginalMeshDescription;
|
|
float ComparisonThreshold = BuildSettings->bRemoveDegenerates ? THRESH_POINTS_ARE_SAME : 0.0f;
|
|
|
|
//This function make sure the Polygon NTB are compute and also remove degenerated triangle from the render mesh description.
|
|
FMeshDescriptionOperations::CreatePolygonNTB(OutRenderMeshDescription, ComparisonThreshold);
|
|
//OutRenderMeshDescription->ComputePolygonTangentsAndNormals(BuildSettings->bRemoveDegenerates ? SMALL_NUMBER : 0.0f);
|
|
|
|
FVertexInstanceArray& VertexInstanceArray = OutRenderMeshDescription.VertexInstances();
|
|
TVertexInstanceAttributesRef<FVector> Normals = OutRenderMeshDescription.VertexInstanceAttributes().GetAttributesRef<FVector>( MeshAttribute::VertexInstance::Normal );
|
|
TVertexInstanceAttributesRef<FVector> Tangents = OutRenderMeshDescription.VertexInstanceAttributes().GetAttributesRef<FVector>( MeshAttribute::VertexInstance::Tangent );
|
|
TVertexInstanceAttributesRef<float> BinormalSigns = OutRenderMeshDescription.VertexInstanceAttributes().GetAttributesRef<float>( MeshAttribute::VertexInstance::BinormalSign );
|
|
|
|
// Find overlapping corners to accelerate adjacency.
|
|
FMeshDescriptionOperations::FindOverlappingCorners(OverlappingCorners, OutRenderMeshDescription, ComparisonThreshold);
|
|
|
|
// Compute any missing normals or tangents.
|
|
{
|
|
// Static meshes always blend normals of overlapping corners.
|
|
uint32 TangentOptions = FMeshDescriptionOperations::ETangentOptions::BlendOverlappingNormals;
|
|
if (BuildSettings->bRemoveDegenerates)
|
|
{
|
|
// If removing degenerate triangles, ignore them when computing tangents.
|
|
TangentOptions |= FMeshDescriptionOperations::ETangentOptions::IgnoreDegenerateTriangles;
|
|
}
|
|
|
|
//Keep the original mesh description NTBs if we do not rebuild the normals or tangents.
|
|
bool bComputeTangentLegacy = !BuildSettings->bUseMikkTSpace && (BuildSettings->bRecomputeNormals || BuildSettings->bRecomputeTangents);
|
|
bool bHasAllNormals = true;
|
|
bool bHasAllTangents = true;
|
|
for (const FVertexInstanceID VertexInstanceID : VertexInstanceArray.GetElementIDs())
|
|
{
|
|
// Dump normals and tangents if we are recomputing them.
|
|
if (BuildSettings->bRecomputeTangents)
|
|
{
|
|
//Dump the tangents
|
|
BinormalSigns[VertexInstanceID] = 0.0f;
|
|
Tangents[VertexInstanceID] = FVector(0.0f);
|
|
}
|
|
if (BuildSettings->bRecomputeNormals)
|
|
{
|
|
//Dump the normals
|
|
Normals[VertexInstanceID] = FVector(0.0f);
|
|
}
|
|
bHasAllNormals &= !Normals[VertexInstanceID].IsNearlyZero();
|
|
bHasAllTangents &= !Tangents[VertexInstanceID].IsNearlyZero();
|
|
}
|
|
|
|
|
|
//MikkTSpace should be use only when the user want to recompute the normals or tangents otherwise should always fallback on builtin
|
|
//We cannot use mikkt space with degenerated normals fallback on buitin.
|
|
if (BuildSettings->bUseMikkTSpace && (BuildSettings->bRecomputeNormals || BuildSettings->bRecomputeTangents))
|
|
{
|
|
if (!bHasAllNormals)
|
|
{
|
|
FMeshDescriptionOperations::CreateNormals(OutRenderMeshDescription, (FMeshDescriptionOperations::ETangentOptions)TangentOptions, false);
|
|
|
|
//EComputeNTBsOptions ComputeNTBsOptions = EComputeNTBsOptions::Normals;
|
|
//OutRenderMeshDescription.ComputeTangentsAndNormals(ComputeNTBsOptions);
|
|
}
|
|
FMeshDescriptionOperations::CreateMikktTangents(OutRenderMeshDescription, (FMeshDescriptionOperations::ETangentOptions)TangentOptions);
|
|
}
|
|
else
|
|
{
|
|
FMeshDescriptionOperations::CreateNormals(OutRenderMeshDescription, (FMeshDescriptionOperations::ETangentOptions)TangentOptions, true);
|
|
//EComputeNTBsOptions ComputeNTBsOptions = (bHasAllNormals ? EComputeNTBsOptions::None : EComputeNTBsOptions::Normals) | (bHasAllTangents ? EComputeNTBsOptions::None : EComputeNTBsOptions::Tangents);
|
|
//OutRenderMeshDescription.ComputeTangentsAndNormals(ComputeNTBsOptions);
|
|
}
|
|
}
|
|
|
|
if (BuildSettings->bGenerateLightmapUVs && VertexInstanceArray.Num() > 0)
|
|
{
|
|
TVertexInstanceAttributesRef<FVector2D> VertexInstanceUVs = OutRenderMeshDescription.VertexInstanceAttributes().GetAttributesRef<FVector2D>(MeshAttribute::VertexInstance::TextureCoordinate);
|
|
int32 NumIndices = VertexInstanceUVs.GetNumIndices();
|
|
//Verify the src light map channel
|
|
if (BuildSettings->SrcLightmapIndex >= NumIndices)
|
|
{
|
|
BuildSettings->SrcLightmapIndex = 0;
|
|
}
|
|
//Verify the destination light map channel
|
|
if (BuildSettings->DstLightmapIndex >= NumIndices)
|
|
{
|
|
//Make sure we do not add illegal UV Channel index
|
|
if (BuildSettings->DstLightmapIndex >= MAX_MESH_TEXTURE_COORDS_MD)
|
|
{
|
|
BuildSettings->DstLightmapIndex = MAX_MESH_TEXTURE_COORDS_MD - 1;
|
|
}
|
|
|
|
//Add some unused UVChannel to the mesh description for the lightmapUVs
|
|
VertexInstanceUVs.SetNumIndices(BuildSettings->DstLightmapIndex + 1);
|
|
BuildSettings->DstLightmapIndex = NumIndices;
|
|
}
|
|
FMeshDescriptionOperations::CreateLightMapUVLayout(OutRenderMeshDescription,
|
|
BuildSettings->SrcLightmapIndex,
|
|
BuildSettings->DstLightmapIndex,
|
|
BuildSettings->MinLightmapResolution,
|
|
(ELightmapUVVersion)(StaticMesh->LightmapUVVersion),
|
|
OverlappingCorners);
|
|
}
|
|
}
|
|
|
|
void FMeshDescriptionHelper::ReduceLOD(const FMeshDescription& BaseMesh, FMeshDescription& DestMesh, const FMeshReductionSettings& ReductionSettings, const FOverlappingCorners& InOverlappingCorners, float &OutMaxDeviation)
|
|
{
|
|
IMeshReductionManagerModule& MeshReductionModule = FModuleManager::Get().LoadModuleChecked<IMeshReductionManagerModule>("MeshReductionInterface");
|
|
IMeshReduction* MeshReduction = MeshReductionModule.GetStaticMeshReductionInterface();
|
|
|
|
|
|
if (!MeshReduction)
|
|
{
|
|
// no reduction possible
|
|
OutMaxDeviation = 0.f;
|
|
return;
|
|
}
|
|
|
|
OutMaxDeviation = ReductionSettings.MaxDeviation;
|
|
MeshReduction->ReduceMeshDescription(DestMesh, OutMaxDeviation, BaseMesh, InOverlappingCorners, ReductionSettings);
|
|
}
|
|
|
|
void FMeshDescriptionHelper::FindOverlappingCorners(const FMeshDescription& MeshDescription, float ComparisonThreshold)
|
|
{
|
|
FMeshDescriptionOperations::FindOverlappingCorners(OverlappingCorners, MeshDescription, ComparisonThreshold);
|
|
}
|
|
|