2019-12-26 15:32:37 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2017-06-30 12:21:06 -04:00
|
|
|
|
|
|
|
|
#include "ProxyGenerationProcessor.h"
|
2022-10-26 16:22:34 -04:00
|
|
|
#include "Components/StaticMeshComponent.h"
|
|
|
|
|
#include "Engine/StaticMesh.h"
|
2017-06-30 12:21:06 -04:00
|
|
|
#include "MaterialUtilities.h"
|
2018-05-23 21:04:31 -04:00
|
|
|
#include "MeshMergeUtilities.h"
|
|
|
|
|
#include "IMeshMergeExtension.h"
|
2017-06-30 12:21:06 -04:00
|
|
|
#include "IMeshReductionInterfaces.h"
|
|
|
|
|
#include "IMeshReductionManagerModule.h"
|
|
|
|
|
#include "Modules/ModuleManager.h"
|
2019-10-01 20:41:42 -04:00
|
|
|
#include "StaticMeshAttributes.h"
|
2022-10-26 16:22:34 -04:00
|
|
|
#include "StaticMeshResources.h"
|
2020-09-01 14:07:48 -04:00
|
|
|
#include "Stats/Stats.h"
|
2021-11-07 23:43:01 -05:00
|
|
|
#include "Algo/ForEach.h"
|
2018-10-03 16:09:08 -04:00
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
#if WITH_EDITOR
|
|
|
|
|
#include "Editor.h"
|
2018-03-06 13:26:20 -05:00
|
|
|
#include "MeshMergeHelpers.h"
|
2021-11-07 23:43:01 -05:00
|
|
|
#include "ObjectCacheEventSink.h"
|
2022-02-14 12:01:24 -05:00
|
|
|
#include "Materials/MaterialInstanceConstant.h"
|
2017-06-30 12:21:06 -04:00
|
|
|
#endif // WITH_EDITOR
|
|
|
|
|
|
2018-05-23 21:04:31 -04:00
|
|
|
FProxyGenerationProcessor::FProxyGenerationProcessor(const FMeshMergeUtilities* InOwner)
|
|
|
|
|
: Owner(InOwner)
|
2017-06-30 12:21:06 -04:00
|
|
|
{
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
FEditorDelegates::MapChange.AddRaw(this, &FProxyGenerationProcessor::OnMapChange);
|
|
|
|
|
FEditorDelegates::NewCurrentLevel.AddRaw(this, &FProxyGenerationProcessor::OnNewCurrentLevel);
|
|
|
|
|
|
|
|
|
|
IMeshReductionManagerModule& Module = FModuleManager::Get().LoadModuleChecked<IMeshReductionManagerModule>("MeshReductionInterface");
|
|
|
|
|
IMeshMerging* MeshMerging = Module.GetMeshMergingInterface();
|
|
|
|
|
if (!MeshMerging)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMeshMerging, Log, TEXT("No automatic mesh merging module available"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MeshMerging->CompleteDelegate.BindRaw(this, &FProxyGenerationProcessor::ProxyGenerationComplete);
|
|
|
|
|
MeshMerging->FailedDelegate.BindRaw(this, &FProxyGenerationProcessor::ProxyGenerationFailed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IMeshMerging* DistributedMeshMerging = Module.GetDistributedMeshMergingInterface();
|
|
|
|
|
if (!DistributedMeshMerging)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMeshMerging, Log, TEXT("No distributed automatic mesh merging module available"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DistributedMeshMerging->CompleteDelegate.BindRaw(this, &FProxyGenerationProcessor::ProxyGenerationComplete);
|
|
|
|
|
DistributedMeshMerging->FailedDelegate.BindRaw(this, &FProxyGenerationProcessor::ProxyGenerationFailed);
|
|
|
|
|
}
|
|
|
|
|
#endif // WITH_EDITOR
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FProxyGenerationProcessor::~FProxyGenerationProcessor()
|
|
|
|
|
{
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
FEditorDelegates::MapChange.RemoveAll(this);
|
|
|
|
|
FEditorDelegates::NewCurrentLevel.RemoveAll(this);
|
|
|
|
|
#endif // WITH_EDITOR
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::AddProxyJob(FGuid InJobGuid, FMergeCompleteData* InCompleteData)
|
|
|
|
|
{
|
|
|
|
|
FScopeLock Lock(&StateLock);
|
|
|
|
|
ProxyMeshJobs.Add(InJobGuid, InCompleteData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FProxyGenerationProcessor::Tick(float DeltaTime)
|
|
|
|
|
{
|
2020-09-01 14:07:48 -04:00
|
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_FProxyGenerationProcessor_Tick);
|
|
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
FScopeLock Lock(&StateLock);
|
|
|
|
|
for (const auto& Entry : ToProcessJobDataMap)
|
|
|
|
|
{
|
|
|
|
|
FGuid JobGuid = Entry.Key;
|
|
|
|
|
FProxyGenerationData* Data = Entry.Value;
|
|
|
|
|
|
|
|
|
|
// Process the job
|
|
|
|
|
ProcessJob(JobGuid, Data);
|
|
|
|
|
|
|
|
|
|
// Data retrieved so can now remove the job from the map
|
|
|
|
|
ProxyMeshJobs.Remove(JobGuid);
|
|
|
|
|
delete Data->MergeData;
|
|
|
|
|
delete Data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ToProcessJobDataMap.Reset();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-03 16:09:08 -04:00
|
|
|
void FProxyGenerationProcessor::ProxyGenerationComplete(FMeshDescription& OutProxyMesh, struct FFlattenMaterial& OutMaterial, const FGuid OutJobGUID)
|
2017-06-30 12:21:06 -04:00
|
|
|
{
|
|
|
|
|
FScopeLock Lock(&StateLock);
|
|
|
|
|
FMergeCompleteData** FindData = ProxyMeshJobs.Find(OutJobGUID);
|
|
|
|
|
if (FindData && *FindData)
|
|
|
|
|
{
|
|
|
|
|
FMergeCompleteData* Data = *FindData;
|
|
|
|
|
|
|
|
|
|
FProxyGenerationData* GenerationData = new FProxyGenerationData();
|
|
|
|
|
GenerationData->Material = OutMaterial;
|
|
|
|
|
GenerationData->RawMesh = OutProxyMesh;
|
|
|
|
|
GenerationData->MergeData = Data;
|
|
|
|
|
|
|
|
|
|
ToProcessJobDataMap.Add(OutJobGUID, GenerationData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::ProxyGenerationFailed(const FGuid OutJobGUID, const FString& ErrorMessage)
|
|
|
|
|
{
|
|
|
|
|
FScopeLock Lock(&StateLock);
|
|
|
|
|
FMergeCompleteData** FindData = ProxyMeshJobs.Find(OutJobGUID);
|
|
|
|
|
if (FindData && *FindData)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogMeshMerging, Log, TEXT("Failed to generate proxy mesh for cluster %s, %s"), *(*FindData)->ProxyBasePackageName, *ErrorMessage);
|
|
|
|
|
ProxyMeshJobs.Remove(OutJobGUID);
|
2019-03-07 11:44:50 -05:00
|
|
|
|
|
|
|
|
TArray<UObject*> OutAssetsToSync;
|
|
|
|
|
(*FindData)->CallbackDelegate.ExecuteIfBound(OutJobGUID, OutAssetsToSync);
|
2017-06-30 12:21:06 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::OnMapChange(uint32 MapFlags)
|
|
|
|
|
{
|
|
|
|
|
ClearProcessingData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::OnNewCurrentLevel()
|
|
|
|
|
{
|
|
|
|
|
ClearProcessingData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::ClearProcessingData()
|
|
|
|
|
{
|
|
|
|
|
FScopeLock Lock(&StateLock);
|
|
|
|
|
ProxyMeshJobs.Empty();
|
|
|
|
|
ToProcessJobDataMap.Empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FProxyGenerationProcessor::ProcessJob(const FGuid& JobGuid, FProxyGenerationData* Data)
|
|
|
|
|
{
|
|
|
|
|
TArray<UObject*> OutAssetsToSync;
|
|
|
|
|
const FString AssetBaseName = FPackageName::GetShortName(Data->MergeData->ProxyBasePackageName);
|
|
|
|
|
const FString AssetBasePath = Data->MergeData->InOuter ? TEXT("") : FPackageName::GetLongPackagePath(Data->MergeData->ProxyBasePackageName) + TEXT("/");
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
UMaterialInstanceConstant* ProxyMaterial = nullptr;
|
2017-06-30 12:21:06 -04:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
if (!Data->RawMesh.IsEmpty())
|
2018-05-23 21:04:31 -04:00
|
|
|
{
|
2022-09-20 01:40:59 -04:00
|
|
|
Data->MergeData->InProxySettings.MaterialSettings.ResolveTextureSize(Data->RawMesh);
|
|
|
|
|
|
2020-11-16 09:42:29 -04:00
|
|
|
// Don't recreate render states with the material update context as we will manually do it through
|
|
|
|
|
// the FStaticMeshComponentRecreateRenderStateContext below
|
|
|
|
|
FMaterialUpdateContext MaterialUpdateContext(FMaterialUpdateContext::EOptions::Default & ~FMaterialUpdateContext::EOptions::RecreateRenderStates);
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// Retrieve flattened material data
|
|
|
|
|
FFlattenMaterial& FlattenMaterial = Data->Material;
|
2018-05-23 21:04:31 -04:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// Resize flattened material
|
|
|
|
|
FMaterialUtilities::ResizeFlattenMaterial(FlattenMaterial, Data->MergeData->InProxySettings);
|
|
|
|
|
|
|
|
|
|
// Optimize flattened material
|
|
|
|
|
FMaterialUtilities::OptimizeFlattenMaterial(FlattenMaterial);
|
|
|
|
|
|
|
|
|
|
// Create a new proxy material instance
|
2022-02-14 12:01:24 -05:00
|
|
|
ProxyMaterial = FMaterialUtilities::CreateFlattenMaterialInstance(Data->MergeData->InOuter, Data->MergeData->InProxySettings.MaterialSettings, Data->MergeData->BaseMaterial, FlattenMaterial, AssetBasePath, AssetBaseName, OutAssetsToSync, &MaterialUpdateContext);
|
2020-09-24 00:43:27 -04:00
|
|
|
|
|
|
|
|
for (IMeshMergeExtension* Extension : Owner->MeshMergeExtensions)
|
|
|
|
|
{
|
|
|
|
|
Extension->OnCreatedProxyMaterial(Data->MergeData->StaticMeshComponents, ProxyMaterial);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set material static lighting usage flag if project has static lighting enabled
|
2023-09-01 12:07:26 -04:00
|
|
|
if (IsStaticLightingAllowed())
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
|
|
|
|
ProxyMaterial->CheckMaterialUsage(MATUSAGE_StaticLighting);
|
|
|
|
|
}
|
2017-06-30 12:21:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Construct proxy static mesh
|
|
|
|
|
UPackage* MeshPackage = Data->MergeData->InOuter;
|
|
|
|
|
FString MeshAssetName = TEXT("SM_") + AssetBaseName;
|
|
|
|
|
if (MeshPackage == nullptr)
|
|
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
MeshPackage = CreatePackage( *(AssetBasePath + MeshAssetName));
|
2017-06-30 12:21:06 -04:00
|
|
|
MeshPackage->FullyLoad();
|
|
|
|
|
MeshPackage->Modify();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
UStaticMesh* OldStaticMesh = FindObject<UStaticMesh>(MeshPackage, *MeshAssetName);
|
|
|
|
|
|
|
|
|
|
FStaticMeshComponentRecreateRenderStateContext RecreateRenderStateContext(OldStaticMesh);
|
2018-05-23 21:04:31 -04:00
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
UStaticMesh* StaticMesh = NewObject<UStaticMesh>(MeshPackage, FName(*MeshAssetName), RF_Public | RF_Standalone);
|
|
|
|
|
StaticMesh->InitResources();
|
|
|
|
|
|
|
|
|
|
FString OutputPath = StaticMesh->GetPathName();
|
|
|
|
|
|
|
|
|
|
// make sure it has a new lighting guid
|
2020-10-22 19:19:16 -04:00
|
|
|
StaticMesh->SetLightingGuid();
|
2017-06-30 12:21:06 -04:00
|
|
|
|
|
|
|
|
// Set it to use textured lightmaps. Note that Build Lighting will do the error-checking (texcoordindex exists for all LODs, etc).
|
2020-10-28 22:08:44 -04:00
|
|
|
StaticMesh->SetLightMapResolution(Data->MergeData->InProxySettings.LightMapResolution);
|
|
|
|
|
StaticMesh->SetLightMapCoordinateIndex(1);
|
2017-06-30 12:21:06 -04:00
|
|
|
|
2022-09-19 21:54:48 -04:00
|
|
|
// Ray tracing support
|
|
|
|
|
StaticMesh->bSupportRayTracing = Data->MergeData->InProxySettings.bSupportRayTracing;
|
2018-03-06 13:26:20 -05:00
|
|
|
|
2018-03-05 10:06:09 -05:00
|
|
|
FStaticMeshSourceModel& SrcModel = StaticMesh->AddSourceModel();
|
2017-06-30 12:21:06 -04:00
|
|
|
/*Don't allow the engine to recalculate normals*/
|
2018-03-05 10:06:09 -05:00
|
|
|
SrcModel.BuildSettings.bRecomputeNormals = false;
|
|
|
|
|
SrcModel.BuildSettings.bRecomputeTangents = false;
|
2019-09-10 11:35:20 -04:00
|
|
|
SrcModel.BuildSettings.bComputeWeightedNormals = true;
|
2018-03-05 10:06:09 -05:00
|
|
|
SrcModel.BuildSettings.bRemoveDegenerates = true;
|
|
|
|
|
SrcModel.BuildSettings.bUseHighPrecisionTangentBasis = false;
|
|
|
|
|
SrcModel.BuildSettings.bUseFullPrecisionUVs = false;
|
2018-03-06 13:26:20 -05:00
|
|
|
SrcModel.BuildSettings.bGenerateLightmapUVs = Data->MergeData->InProxySettings.bGenerateLightmapUVs;
|
|
|
|
|
SrcModel.BuildSettings.bBuildReversedIndexBuffer = false;
|
|
|
|
|
if (!Data->MergeData->InProxySettings.bAllowDistanceField)
|
|
|
|
|
{
|
|
|
|
|
SrcModel.BuildSettings.DistanceFieldResolutionScale = 0.0f;
|
|
|
|
|
}
|
2017-06-30 12:21:06 -04:00
|
|
|
|
2018-03-06 13:26:20 -05:00
|
|
|
const bool bContainsImposters = Data->MergeData->ImposterComponents.Num() > 0;
|
2018-05-23 21:04:31 -04:00
|
|
|
FBox ImposterBounds(EForceInit::ForceInit);
|
2018-10-03 16:09:08 -04:00
|
|
|
|
2020-07-16 08:23:15 -04:00
|
|
|
TPolygonGroupAttributesConstRef<FName> PolygonGroupMaterialSlotName = FStaticMeshAttributes(Data->RawMesh).GetPolygonGroupMaterialSlotNames();
|
2019-04-19 19:00:45 -04:00
|
|
|
|
|
|
|
|
auto RemoveVertexColorAndCommitMeshDescription = [&StaticMesh, &Data, &ProxyMaterial, &PolygonGroupMaterialSlotName]()
|
2018-10-03 16:09:08 -04:00
|
|
|
{
|
|
|
|
|
if (!Data->MergeData->InProxySettings.bAllowVertexColors)
|
|
|
|
|
{
|
|
|
|
|
//We cannot remove the vertex color with the mesh description so we assign a white value to all color
|
2021-09-22 10:01:48 -04:00
|
|
|
TVertexInstanceAttributesRef<FVector4f> VertexInstanceColors = FStaticMeshAttributes(Data->RawMesh).GetVertexInstanceColors();
|
2018-10-03 16:09:08 -04:00
|
|
|
//set all value to white
|
2020-08-11 01:36:57 -04:00
|
|
|
for (const FVertexInstanceID VertexInstanceID : Data->RawMesh.VertexInstances().GetElementIDs())
|
2018-10-03 16:09:08 -04:00
|
|
|
{
|
2021-09-22 10:01:48 -04:00
|
|
|
VertexInstanceColors[VertexInstanceID] = FVector4f(1.0f, 1.0f, 1.0f);
|
2018-10-03 16:09:08 -04:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-10 17:26:53 -05:00
|
|
|
|
|
|
|
|
//Commit the FMeshDescription to the source model we just created
|
2019-07-31 03:40:45 -04:00
|
|
|
int32 SourceModelIndex = StaticMesh->GetNumSourceModels() - 1;
|
2019-10-01 20:41:42 -04:00
|
|
|
FMeshDescription* MeshDescription = StaticMesh->CreateMeshDescription(SourceModelIndex, Data->RawMesh);
|
2019-01-10 17:26:53 -05:00
|
|
|
if (ensure(MeshDescription))
|
|
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
if (ProxyMaterial)
|
2019-03-12 06:52:45 -04:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
// Make sure the Proxy material have a valid ImportedMaterialSlotName
|
|
|
|
|
//The proxy material must be add only once and is always the first slot of the HLOD mesh
|
|
|
|
|
FStaticMaterial NewMaterial(ProxyMaterial);
|
|
|
|
|
if (MeshDescription->PolygonGroups().Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
NewMaterial.ImportedMaterialSlotName = PolygonGroupMaterialSlotName[MeshDescription->PolygonGroups().GetFirstValidID()];
|
|
|
|
|
}
|
2020-10-22 19:19:16 -04:00
|
|
|
StaticMesh->GetStaticMaterials().Add(NewMaterial);
|
2019-03-12 06:52:45 -04:00
|
|
|
}
|
|
|
|
|
|
2021-03-20 20:01:33 -04:00
|
|
|
UStaticMesh::FCommitMeshDescriptionParams CommitParams;
|
|
|
|
|
CommitParams.bUseHashAsGuid = true;
|
|
|
|
|
StaticMesh->CommitMeshDescription(SourceModelIndex, CommitParams);
|
2019-01-10 17:26:53 -05:00
|
|
|
}
|
2018-10-03 16:09:08 -04:00
|
|
|
};
|
|
|
|
|
|
2018-03-06 13:26:20 -05:00
|
|
|
if (bContainsImposters)
|
|
|
|
|
{
|
|
|
|
|
TArray<UMaterialInterface*> ImposterMaterials;
|
|
|
|
|
|
|
|
|
|
// Merge imposter meshes to rawmesh
|
|
|
|
|
// The base material index is always one here as we assume we only have one HLOD material
|
2020-09-02 07:14:07 -04:00
|
|
|
FMeshMergeHelpers::MergeImpostersToMesh(Data->MergeData->ImposterComponents, Data->RawMesh, FVector::ZeroVector, 1, ImposterMaterials);
|
2018-03-06 13:26:20 -05:00
|
|
|
|
2018-05-23 21:04:31 -04:00
|
|
|
for (const UStaticMeshComponent* Component : Data->MergeData->ImposterComponents)
|
|
|
|
|
{
|
|
|
|
|
if (Component->GetStaticMesh())
|
|
|
|
|
{
|
|
|
|
|
ImposterBounds += Component->GetStaticMesh()->GetBoundingBox().TransformBy(Component->GetComponentToWorld());
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-03 16:09:08 -04:00
|
|
|
RemoveVertexColorAndCommitMeshDescription();
|
2018-05-23 21:04:31 -04:00
|
|
|
|
2018-03-06 13:26:20 -05:00
|
|
|
for (UMaterialInterface* Material : ImposterMaterials)
|
|
|
|
|
{
|
2019-04-19 19:00:45 -04:00
|
|
|
//Set the ImportedMaterialSlotName in each imposter material
|
|
|
|
|
FStaticMaterial NewMaterial(Material);
|
|
|
|
|
if (Data->RawMesh.PolygonGroups().Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
NewMaterial.ImportedMaterialSlotName = PolygonGroupMaterialSlotName[Data->RawMesh.PolygonGroups().GetFirstValidID()];
|
|
|
|
|
}
|
2020-10-22 19:19:16 -04:00
|
|
|
StaticMesh->GetStaticMaterials().Add(NewMaterial);
|
2018-03-06 13:26:20 -05:00
|
|
|
}
|
2022-08-26 16:20:09 -04:00
|
|
|
|
|
|
|
|
// Ensure the new mesh is not referencing non standalone materials
|
|
|
|
|
FMeshMergeHelpers::FixupNonStandaloneMaterialReferences(StaticMesh);
|
2018-03-06 13:26:20 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-10-03 16:09:08 -04:00
|
|
|
RemoveVertexColorAndCommitMeshDescription();
|
2019-03-12 06:52:45 -04:00
|
|
|
}
|
2017-06-30 12:21:06 -04:00
|
|
|
|
2021-02-26 12:32:53 -04:00
|
|
|
// Nanite settings
|
2022-09-19 21:54:48 -04:00
|
|
|
StaticMesh->NaniteSettings = Data->MergeData->InProxySettings.NaniteSettings;
|
2021-02-26 12:32:53 -04:00
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
//Set the Imported version before calling the build
|
|
|
|
|
StaticMesh->ImportVersion = EImportStaticMeshVersion::LastVersion;
|
|
|
|
|
|
2018-03-06 13:26:20 -05:00
|
|
|
// setup section info map
|
2018-10-03 16:09:08 -04:00
|
|
|
TPolygonGroupAttributesConstRef<FName> PolygonGroupImportedMaterialSlotNames = Data->RawMesh.PolygonGroupAttributes().GetAttributesRef<FName>(MeshAttribute::PolygonGroup::ImportedMaterialSlotName);
|
2018-03-06 13:26:20 -05:00
|
|
|
TArray<int32> UniqueMaterialIndices;
|
2020-08-11 01:36:57 -04:00
|
|
|
for (const FPolygonGroupID PolygonGroupID : Data->RawMesh.PolygonGroups().GetElementIDs())
|
2018-03-06 13:26:20 -05:00
|
|
|
{
|
2018-10-03 16:09:08 -04:00
|
|
|
int32 PolygonGroupMaterialIndex = PolygonGroupID.GetValue();
|
|
|
|
|
FName PolygonGroupName = PolygonGroupImportedMaterialSlotNames[PolygonGroupID];
|
|
|
|
|
if (PolygonGroupName != NAME_None)
|
|
|
|
|
{
|
2020-10-22 19:19:16 -04:00
|
|
|
for (int32 MaterialIndex = 0; MaterialIndex < StaticMesh->GetStaticMaterials().Num(); ++MaterialIndex)
|
2018-10-03 16:09:08 -04:00
|
|
|
{
|
2020-10-22 19:19:16 -04:00
|
|
|
if (StaticMesh->GetStaticMaterials()[MaterialIndex].ImportedMaterialSlotName == PolygonGroupName)
|
2018-10-03 16:09:08 -04:00
|
|
|
{
|
|
|
|
|
PolygonGroupMaterialIndex = MaterialIndex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-22 19:19:16 -04:00
|
|
|
if (!StaticMesh->GetStaticMaterials().IsValidIndex(PolygonGroupMaterialIndex))
|
2018-10-03 16:09:08 -04:00
|
|
|
{
|
|
|
|
|
PolygonGroupMaterialIndex = 0;
|
|
|
|
|
}
|
|
|
|
|
UniqueMaterialIndices.AddUnique(PolygonGroupMaterialIndex);
|
2018-03-06 13:26:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 SectionIndex = 0;
|
|
|
|
|
for (int32 UniqueMaterialIndex : UniqueMaterialIndices)
|
|
|
|
|
{
|
|
|
|
|
FMeshSectionInfo MeshSectionInfo(UniqueMaterialIndex);
|
|
|
|
|
|
|
|
|
|
// enable/disable section collision according to settings
|
|
|
|
|
MeshSectionInfo.bEnableCollision = Data->MergeData->InProxySettings.bCreateCollision;
|
|
|
|
|
|
2019-07-31 03:40:45 -04:00
|
|
|
StaticMesh->GetSectionInfoMap().Set(0, SectionIndex, MeshSectionInfo);
|
2018-03-06 13:26:20 -05:00
|
|
|
SectionIndex++;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
StaticMesh->Build();
|
2018-05-23 21:04:31 -04:00
|
|
|
|
|
|
|
|
if (ImposterBounds.IsValid)
|
|
|
|
|
{
|
|
|
|
|
const FBox StaticMeshBox = StaticMesh->GetBoundingBox();
|
|
|
|
|
const FBox CombinedBox = StaticMeshBox + ImposterBounds;
|
2020-10-28 22:08:44 -04:00
|
|
|
StaticMesh->SetPositiveBoundsExtension((CombinedBox.Max - StaticMeshBox.Max));
|
|
|
|
|
StaticMesh->SetNegativeBoundsExtension((StaticMeshBox.Min - CombinedBox.Min));
|
2018-05-23 21:04:31 -04:00
|
|
|
StaticMesh->CalculateExtendedBounds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StaticMesh->PostEditChange();
|
2017-06-30 12:21:06 -04:00
|
|
|
|
|
|
|
|
OutAssetsToSync.Add(StaticMesh);
|
|
|
|
|
|
2021-11-07 23:43:01 -05:00
|
|
|
if (OldStaticMesh != nullptr)
|
|
|
|
|
{
|
|
|
|
|
Algo::ForEach(RecreateRenderStateContext.GetComponentsUsingMesh(OldStaticMesh), [](UStaticMeshComponent* Component)
|
|
|
|
|
{
|
This changelist contains various changes to allow the creation of FPrimitiveSceneProxy & FPrimtiveSceneInfos for meshes not associated with an AActor/UPrimitiveComponent pair. In other words, it's now possible to add primitives to FScene that aren't associated with AActors & UPrimitiveComponents. These are additional entry points, all existing code should continue to build & execute as is.
*Added FPrimitiveSceneDesc, a structure you can initialize with a description of the primitive you're trying to Add/Remove/Update in the FScene
-Added entry points in FSceneInterface to do those operations, legacy entry points using UPrimitiveComponent are untouched.
-The code that executes those operations in FScene has been refactored to be shared between the two entry points as much as possible to lessen the additional maintenance burden.
*Added FPrimitiveSceneProxyDesc/FStaticMeshSceneProxyDesc/FInstancedStaticMeshSceneProxyDesc, structures that hold all the necessary information to create a FPrimitiveSceneProxy/FStaticMeshSceneProxy/FInstancedStaticMeshSceneProxy without depending on AActors or UPrimitiveComponent.
-Those structures can be initialized by constructing them with the corresponding UPrimitiveComponents, or by constructing their default versions and initializing the desired fields.
-Creation code for FPrimitiveSceneProxy/FStaticMeshSceneProxy/FInstancedStaticMeshSceneProxy now takes all its info from those desc structures. They are created on demand during scene proxy creation for UPrimitiveComponents. This means no additional memory, and all serialized assets & blueprints are unaffected.
*Added IPrimitiveComponent/IStaticMeshComponent interfaces
-These allow for some editor-only interactions occurring during proxy creation, and serve as a common interface for some code that expected to manipulate UPrimitiveComponent/UStaticMeshComponents. For example FObjectCacheEventSink / FObjectCacheContext now uses those interfaces to associate the resources between various users and interactions like proxy recreation on shader/mesh changes occur through those interfaces.
* Misc
-Moved scene primitive related member variables into a new structure (FPrimitiveSceneInfoData) to facilitate code sharing and implementations of various related functionality (like SetLastRenderTime).
-Changed ObjectCacheContext to store associations between resources and components using component interfaces so that other systems creating proxies have the proper behaviors when resource changes require proxy recreation.
-Added natvis support so that component interfaces to UPrimitiveComponent/UStaticMeshComponent display the component ptr for easier debugging.
-Changed FMotionVectorSimulation to use UObject* instead of UPrimitiveComponent*, it was already using this internally
-Templatized some nanite helpers like ShouldCreateNaniteProxy & AuditMaterials since we need to use them from both UPrimitiveComponent & FPrimitiveSceneProxyDesc and it'll help make sure we keep them in sync.
#jira UE-191990
#rb Zach.Bethel, Ola.Olsson, Jason.Nadro, Krzysztof.Narkowicz
[CL 27200716 by dominic couture in ue5-main branch]
2023-08-18 09:26:39 -04:00
|
|
|
FObjectCacheEventSink::NotifyStaticMeshChanged_Concurrent(Component->GetStaticMeshComponentInterface());
|
2021-11-07 23:43:01 -05:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-30 12:21:06 -04:00
|
|
|
// Execute the delegate received from the user
|
|
|
|
|
Data->MergeData->CallbackDelegate.ExecuteIfBound(JobGuid, OutAssetsToSync);
|
|
|
|
|
}
|