Files
UnrealEngine/Engine/Plugins/Runtime/MassGameplay/Source/MassRepresentation/Private/MassDistanceLODProcessor.cpp
2025-05-18 13:04:45 +08:00

113 lines
5.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MassDistanceLODProcessor.h"
#include "MassRepresentationDebug.h"
#include "MassExecutionContext.h"
#include "MassCommonFragments.h"
#include "MassLODFragments.h"
#include "MassLODTypes.h"
#include "MassRepresentationFragments.h"
UMassDistanceLODProcessor::UMassDistanceLODProcessor()
{
bAutoRegisterWithProcessingPhases = true;
ExecutionFlags = (int32)(EProcessorExecutionFlags::AllNetModes);
ExecutionOrder.ExecuteInGroup = UE::Mass::ProcessorGroupNames::LOD;
ExecutionOrder.ExecuteAfter.Add(UE::Mass::ProcessorGroupNames::LODCollector);
}
void UMassDistanceLODProcessor::ConfigureQueries(const TSharedRef<FMassEntityManager>& EntityManager)
{
FMassEntityQuery BaseQuery(EntityManager);
BaseQuery.AddTagRequirement<FMassDistanceLODProcessorTag>(EMassFragmentPresence::All);
BaseQuery.AddRequirement<FMassViewerInfoFragment>(EMassFragmentAccess::ReadOnly);
BaseQuery.AddRequirement<FMassRepresentationLODFragment>(EMassFragmentAccess::ReadWrite);
BaseQuery.AddRequirement<FTransformFragment>(EMassFragmentAccess::ReadOnly);
BaseQuery.AddConstSharedRequirement<FMassDistanceLODParameters>();
BaseQuery.AddSharedRequirement<FMassDistanceLODSharedFragment>(EMassFragmentAccess::ReadWrite);
CloseEntityQuery = BaseQuery;
CloseEntityQuery.AddTagRequirement<FMassVisibilityCulledByDistanceTag>(EMassFragmentPresence::None);
CloseEntityQuery.RegisterWithProcessor(*this);
FarEntityQuery = BaseQuery;
FarEntityQuery.AddTagRequirement<FMassVisibilityCulledByDistanceTag>(EMassFragmentPresence::All);
FarEntityQuery.AddChunkRequirement<FMassVisualizationChunkFragment>(EMassFragmentAccess::ReadOnly);
FarEntityQuery.SetChunkFilter(&FMassVisualizationChunkFragment::ShouldUpdateVisualizationForChunk);
FarEntityQuery.RegisterWithProcessor(*this);
DebugEntityQuery = BaseQuery;
DebugEntityQuery.RegisterWithProcessor(*this);
ProcessorRequirements.AddSubsystemRequirement<UMassLODSubsystem>(EMassFragmentAccess::ReadOnly);
}
void UMassDistanceLODProcessor::Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context)
{
if (bForceOFFLOD)
{
CloseEntityQuery.ForEachEntityChunk(Context, [this](FMassExecutionContext& Context)
{
FMassDistanceLODSharedFragment& LODSharedFragment = Context.GetMutableSharedFragment<FMassDistanceLODSharedFragment>();
TArrayView<FMassRepresentationLODFragment> RepresentationLODList = Context.GetMutableFragmentView<FMassRepresentationLODFragment>();
LODSharedFragment.LODCalculator.ForceOffLOD(Context, RepresentationLODList);
});
return;
}
{
TRACE_CPUPROFILER_EVENT_SCOPE(PrepareExecution)
const UMassLODSubsystem& LODSubsystem = Context.GetSubsystemChecked<UMassLODSubsystem>();
const TArray<FViewerInfo>& Viewers = LODSubsystem.GetViewers();
EntityManager.ForEachSharedFragment<FMassDistanceLODSharedFragment>([this, &Viewers](FMassDistanceLODSharedFragment& LODSharedFragment)
{
if (FilterTag == LODSharedFragment.FilterTag)
{
LODSharedFragment.LODCalculator.PrepareExecution(Viewers);
}
});
}
{
TRACE_CPUPROFILER_EVENT_SCOPE(CalculateLOD)
auto CalculateLOD = [this](FMassExecutionContext& Context)
{
FMassDistanceLODSharedFragment& LODSharedFragment = Context.GetMutableSharedFragment<FMassDistanceLODSharedFragment>();
TArrayView<FMassRepresentationLODFragment> RepresentationLODList = Context.GetMutableFragmentView<FMassRepresentationLODFragment>();
TConstArrayView<FMassViewerInfoFragment> ViewerInfoList = Context.GetFragmentView<FMassViewerInfoFragment>();
LODSharedFragment.LODCalculator.CalculateLOD(Context, ViewerInfoList, RepresentationLODList);
};
CloseEntityQuery.ForEachEntityChunk(Context, CalculateLOD);
FarEntityQuery.ForEachEntityChunk(Context, CalculateLOD);
}
#if WITH_MASSGAMEPLAY_DEBUG
// Optional debug display
if (UE::Mass::Representation::Debug::DebugRepresentationLOD == 1 || UE::Mass::Representation::Debug::DebugRepresentationLOD >= 3)
{
TRACE_CPUPROFILER_EVENT_SCOPE(DebugDisplayLOD)
UWorld* World = EntityManager.GetWorld();
DebugEntityQuery.ForEachEntityChunk(Context, [World](FMassExecutionContext& Context)
{
FMassDistanceLODSharedFragment& LODSharedFragment = Context.GetMutableSharedFragment<FMassDistanceLODSharedFragment>();
TConstArrayView<FMassRepresentationLODFragment> RepresentationLODList = Context.GetFragmentView<FMassRepresentationLODFragment>();
TConstArrayView<FTransformFragment> TransformList = Context.GetFragmentView<FTransformFragment>();
LODSharedFragment.LODCalculator.DebugDisplaySignificantLOD(Context, RepresentationLODList, TransformList, World, UE::Mass::Representation::Debug::DebugRepresentationLODMaxSignificance);
});
}
// Optional vislog
if (UE::Mass::Representation::Debug::DebugRepresentationLOD >= 2)
{
TRACE_CPUPROFILER_EVENT_SCOPE(VisLogLOD)
DebugEntityQuery.ForEachEntityChunk(Context, [this](FMassExecutionContext& Context)
{
FMassDistanceLODSharedFragment& LODSharedFragment = Context.GetMutableSharedFragment<FMassDistanceLODSharedFragment>();
TConstArrayView<FMassRepresentationLODFragment> RepresentationLODList = Context.GetFragmentView<FMassRepresentationLODFragment>();
TConstArrayView<FTransformFragment> TransformList = Context.GetFragmentView<FTransformFragment>();
LODSharedFragment.LODCalculator.VisLogSignificantLOD(Context, RepresentationLODList, TransformList, this, UE::Mass::Representation::Debug::DebugRepresentationLODMaxSignificance);
});
}
#endif // WITH_MASSGAMEPLAY_DEBUG
}