You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb luc.eygasier #robomerge private-frosty [CL 16737956 by Sebastien Lussier in ue5-main branch]
188 lines
7.0 KiB
C++
188 lines
7.0 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "HLODBuilderMeshApproximate.h"
|
|
|
|
#include "Algo/ForEach.h"
|
|
#include "Algo/Transform.h"
|
|
#include "WorldPartition/HLOD/HLODActor.h"
|
|
#include "WorldPartition/HLOD/HLODLayer.h"
|
|
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Materials/Material.h"
|
|
#include "Materials/MaterialInstance.h"
|
|
#include "MaterialUtilities.h"
|
|
|
|
#include "Modules/ModuleManager.h"
|
|
#include "IGeometryProcessingInterfacesModule.h"
|
|
#include "GeometryProcessingInterfaces/ApproximateActors.h"
|
|
|
|
#include "HLODBuilderInstancing.h"
|
|
|
|
|
|
TArray<UPrimitiveComponent*> FHLODBuilder_MeshApproximate::CreateComponents(AWorldPartitionHLOD* InHLODActor, const UHLODLayer* InHLODLayer, const TArray<UPrimitiveComponent*>& InSubComponents)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FHLODBuilder_MeshApproximate::CreateComponents);
|
|
|
|
TSet<AActor*> Actors;
|
|
TArray<UPrimitiveComponent*> InstancedComponents;
|
|
|
|
// Filter the input components
|
|
for (UPrimitiveComponent* SubComponent : InSubComponents)
|
|
{
|
|
if (!SubComponent)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
switch (SubComponent->HLODBatchingPolicy)
|
|
{
|
|
case EHLODBatchingPolicy::None:
|
|
Actors.Add(SubComponent->GetOwner());
|
|
break;
|
|
case EHLODBatchingPolicy::Instancing:
|
|
InstancedComponents.Add(SubComponent);
|
|
break;
|
|
case EHLODBatchingPolicy::MeshSection:
|
|
InstancedComponents.Add(SubComponent);
|
|
UE_LOG(LogHLODBuilder, Warning, TEXT("EHLODBatchingPolicy::MeshSection is not yet supported by the MeshApproximate builder."));
|
|
break;
|
|
}
|
|
}
|
|
|
|
IGeometryProcessingInterfacesModule& GeomProcInterfaces = FModuleManager::Get().LoadModuleChecked<IGeometryProcessingInterfacesModule>("GeometryProcessingInterfaces");
|
|
IGeometryProcessing_ApproximateActors* ApproxActorsAPI = GeomProcInterfaces.GetApproximateActorsImplementation();
|
|
|
|
//
|
|
// Construct options for ApproximateActors operation
|
|
//
|
|
|
|
const FMeshApproximationSettings& UseSettings = InHLODLayer->GetMeshApproximationSettings();
|
|
|
|
IGeometryProcessing_ApproximateActors::FOptions Options = ApproxActorsAPI->ConstructOptions(UseSettings);
|
|
Options.BasePackagePath = InHLODActor->GetPackage()->GetName();
|
|
Options.bGenerateLightmapUVs = false;
|
|
Options.bCreatePhysicsBody = false;
|
|
|
|
// Material baking settings
|
|
Options.BakeMaterial = GEngine->DefaultHLODFlattenMaterial;
|
|
Options.BaseColorTexParamName = FName("BaseColorTexture");
|
|
Options.NormalTexParamName = FName("NormalTexture");
|
|
Options.MetallicTexParamName = FName("MetallicTexture");
|
|
Options.RoughnessTexParamName = FName("RoughnessTexture");
|
|
Options.SpecularTexParamName = FName("SpecularTexture");
|
|
Options.EmissiveTexParamName = FName("EmissiveHDRTexture");
|
|
Options.bUsePackedMRS = true;
|
|
Options.PackedMRSTexParamName = FName("PackedTexture");
|
|
|
|
// Gather bounds of the input components
|
|
auto GetActorsBounds = [&]() -> FBoxSphereBounds
|
|
{
|
|
FBoxSphereBounds Bounds;
|
|
bool bFirst = true;
|
|
|
|
for (UPrimitiveComponent* Component : InSubComponents)
|
|
{
|
|
FBoxSphereBounds ComponentBounds = Component->Bounds;
|
|
Bounds = bFirst ? ComponentBounds : Bounds + ComponentBounds;
|
|
bFirst = false;
|
|
}
|
|
|
|
return Bounds;
|
|
};
|
|
|
|
// Compute texel density if needed, depending on the TextureSizingType setting
|
|
ETextureSizingType TextureSizingType = UseSettings.MaterialSettings.TextureSizingType;
|
|
float TexelDensityPerMeter = 0.0f;
|
|
|
|
IGeometryProcessing_ApproximateActors::ETextureSizePolicy TextureSizePolicy = IGeometryProcessing_ApproximateActors::ETextureSizePolicy::TextureSize;
|
|
if (TextureSizingType == ETextureSizingType::TextureSizingType_AutomaticFromTexelDensity)
|
|
{
|
|
TexelDensityPerMeter = UseSettings.MaterialSettings.TargetTexelDensityPerMeter;
|
|
TextureSizePolicy = IGeometryProcessing_ApproximateActors::ETextureSizePolicy::TexelDensity;
|
|
}
|
|
else if (TextureSizingType == ETextureSizingType::TextureSizingType_AutomaticFromMeshScreenSize)
|
|
{
|
|
TexelDensityPerMeter = FMaterialUtilities::ComputeRequiredTexelDensityFromScreenSize(UseSettings.MaterialSettings.MeshMaxScreenSizePercent, GetActorsBounds().SphereRadius);
|
|
TextureSizePolicy = IGeometryProcessing_ApproximateActors::ETextureSizePolicy::TexelDensity;
|
|
}
|
|
else if (TextureSizingType == ETextureSizingType::TextureSizingType_AutomaticFromMeshDrawDistance)
|
|
{
|
|
TexelDensityPerMeter = FMaterialUtilities::ComputeRequiredTexelDensityFromDrawDistance(UseSettings.MaterialSettings.MeshMinDrawDistance, GetActorsBounds().SphereRadius);
|
|
TextureSizePolicy = IGeometryProcessing_ApproximateActors::ETextureSizePolicy::TexelDensity;
|
|
}
|
|
|
|
Options.MeshTexelDensity = TexelDensityPerMeter;
|
|
Options.TextureSizePolicy = TextureSizePolicy;
|
|
|
|
// run actor approximation computation
|
|
IGeometryProcessing_ApproximateActors::FResults Results;
|
|
ApproxActorsAPI->ApproximateActors(Actors.Array(), Options, Results);
|
|
|
|
TArray<UPrimitiveComponent*> Components;
|
|
if (Results.ResultCode == IGeometryProcessing_ApproximateActors::EResultCode::Success)
|
|
{
|
|
auto FixupAsset = [&InHLODActor](UObject* Asset)
|
|
{
|
|
Asset->ClearFlags(RF_Public | RF_Standalone);
|
|
Asset->Rename(nullptr, InHLODActor->GetPackage(), REN_NonTransactional | REN_DontCreateRedirectors | REN_ForceNoResetLoaders);
|
|
};
|
|
|
|
Algo::ForEach(Results.NewMeshAssets, FixupAsset);
|
|
Algo::ForEach(Results.NewMaterials, FixupAsset);
|
|
Algo::ForEach(Results.NewTextures, FixupAsset);
|
|
|
|
for (UStaticMesh* StaticMesh : Results.NewMeshAssets)
|
|
{
|
|
UStaticMeshComponent* Component = NewObject<UStaticMeshComponent>(InHLODActor);
|
|
Component->SetStaticMesh(StaticMesh);
|
|
DisableCollisions(Component);
|
|
|
|
Components.Add(Component);
|
|
}
|
|
|
|
for (UMaterialInterface* Material : Results.NewMaterials)
|
|
{
|
|
UMaterialInstance* MaterialInst = CastChecked<UMaterialInstance>(Material);
|
|
|
|
FStaticParameterSet StaticParameterSet;
|
|
|
|
auto SetStaticSwitch = [&StaticParameterSet](FName ParamName, bool bSet)
|
|
{
|
|
if (bSet)
|
|
{
|
|
FStaticSwitchParameter SwitchParameter;
|
|
SwitchParameter.ParameterInfo.Name = ParamName;
|
|
SwitchParameter.Value = true;
|
|
SwitchParameter.bOverride = true;
|
|
StaticParameterSet.StaticSwitchParameters.Add(SwitchParameter);
|
|
}
|
|
};
|
|
|
|
// Set proper switches needed by our base flatten material
|
|
SetStaticSwitch("UseBaseColor", Options.bBakeBaseColor);
|
|
SetStaticSwitch("UseRoughness", Options.bBakeRoughness);
|
|
SetStaticSwitch("UseMetallic", Options.bBakeMetallic);
|
|
SetStaticSwitch("UseSpecular", Options.bBakeSpecular);
|
|
SetStaticSwitch("UseEmissiveHDR", Options.bBakeEmissive);
|
|
SetStaticSwitch("UseNormal", Options.bBakeNormalMap);
|
|
SetStaticSwitch("PackMetallic", Options.bUsePackedMRS);
|
|
SetStaticSwitch("PackSpecular", Options.bUsePackedMRS);
|
|
SetStaticSwitch("PackRoughness", Options.bUsePackedMRS);
|
|
|
|
// Force initializing the static permutations according to the switches we have set
|
|
MaterialInst->UpdateStaticPermutation(StaticParameterSet);
|
|
MaterialInst->InitStaticPermutation();
|
|
MaterialInst->PostEditChange();
|
|
}
|
|
}
|
|
|
|
// Batch instances
|
|
if (InstancedComponents.Num())
|
|
{
|
|
FHLODBuilder_Instancing InstancingHLODBuilder;
|
|
Components.Append(InstancingHLODBuilder.CreateComponents(InHLODActor, nullptr, InstancedComponents));
|
|
}
|
|
|
|
return Components;
|
|
}
|