Files
UnrealEngine/Engine/Plugins/Runtime/MassGameplay/Source/MassLOD/Public/MassLODLogic.h
2025-05-18 13:04:45 +08:00

203 lines
7.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "MassLODSubsystem.h"
#include "Containers/StaticArray.h"
#include "ConvexVolume.h"
#include "MassLODTypes.h"
#define UE_API MASSLOD_API
#define DECLARE_CONDITIONAL_MEMBER_ACCESSORS( Condition, MemberType, MemberName ) \
template <bool Condition, typename TemplateClass> static FORCEINLINE typename TEnableIf< Condition, MemberType>::Type Get##MemberName(TemplateClass& Obj, MemberType DefaultValue) { return Obj.MemberName; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE typename TEnableIf<!Condition, MemberType>::Type Get##MemberName(TemplateClass& Obj, MemberType DefaultValue) { return DefaultValue; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName(TemplateClass& Obj, typename TEnableIf< Condition, MemberType>::Type Value) { Obj.MemberName = Value; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName(TemplateClass& Obj, typename TEnableIf<!Condition, MemberType>::Type Value) {}
#define DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS( Condition, MemberType, MemberName ) \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName##Num(TemplateClass& Obj, typename TEnableIf< Condition, int32>::Type Num) { Obj.MemberName.SetNum(Num); } \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName##Num(TemplateClass& Obj, typename TEnableIf<!Condition, int32>::Type Num) {} \
template <bool Condition, typename TemplateClass> static FORCEINLINE typename TEnableIf< Condition, MemberType>::Type Get##MemberName(TemplateClass& Obj, int32 Index, MemberType DefaultValue) { return Obj.MemberName[Index]; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE typename TEnableIf<!Condition, MemberType>::Type Get##MemberName(TemplateClass& Obj, int32 Index, MemberType DefaultValue) { return DefaultValue; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName(TemplateClass& Obj, int32 Index, typename TEnableIf< Condition, MemberType>::Type Value) { Obj.MemberName[Index] = Value; } \
template <bool Condition, typename TemplateClass> static FORCEINLINE void Set##MemberName(TemplateClass& Obj, int32 Index, typename TEnableIf<!Condition, MemberType>::Type Value) {}
/**
* Traits for LOD logic calculation behaviors
*/
struct FLODDefaultLogic
{
enum
{
bStoreInfoPerViewer = false, // Enable to store all calculated information per viewer
bCalculateLODPerViewer = false, // Enable to calculate and store the result LOD per viewer in the FMassLODResultInfo::LODPerViewer and FMassLODResultInfo::PrevLODPerViewer, requires bStoreInfoPerViewer to be true as well.
bMaximizeCountPerViewer = false, // Enable to maximize count per viewer, requires a valid InLODMaxCountPerViewer parameter during initialization of TMassLODCalculator.
bDoVisibilityLogic = false, // Enable to calculate visibility and apply its own LOD distances. Requires a valid InVisibleLODDistance parameter during initialization of TMassLODCalculator.
bCalculateLODSignificance = false, // Enable to calculate and set the a more precise LOD floating point significance in member FMassLODResultInfo::LODSignificance.
bLocalViewersOnly = false, // Enable to calculate LOD from LocalViewersOnly, otherwise will be done on all viewers.
};
};
struct FMassSimulationLODLogic : public FLODDefaultLogic
{
};
struct FMassRepresentationLODLogic : public FLODDefaultLogic
{
enum
{
bDoVisibilityLogic = true,
bCalculateLODSignificance = true,
bLocalViewersOnly = true,
};
};
struct FMassCombinedLODLogic : public FLODDefaultLogic
{
enum
{
bDoVisibilityLogic = true,
bCalculateLODSignificance = true,
bLocalViewersOnly = true,
};
};
/** Simplest version of RepresentationLODLogic strictly based on Distance to Viewer
* Compared to FMassRepresentationLODLogic, we:
* * Do not care about doing the Visibility Logic
* * For now we will keep the Significance computation as it could allow for finer grained control later on
*/
struct FMassDistanceLODLogic : public FLODDefaultLogic
{
enum
{
bCalculateLODSignificance = true,
bLocalViewersOnly = true,
};
};
/**
* TMassLODCollector outputs
*
struct FMassViewerInfoFragment
{
// Closest viewer distance (Always needed)
float ClosestViewerDistanceSq;
// Square distances to each valid viewers (Required when FLODLogic::bStoreInfoPerViewer is enabled)
TArray<float> DistanceToViewerSq;
};
struct FMassInfoPerViewerFragment
{
// Square distances to each valid viewers (Required when FLODLogic::bStoreInfoPerViewer is enabled)
TArray<float> DistanceToViewerSq;
// Distances to each valid viewers frustums (Required when FLODLogic::bDoVisibilityLogic and FLODLogic::bStoreInfoPerViewer are enabled)
TArray<float> DistanceToFrustum;
};
*/
/**
* TMassLODCalculator outputs
*
struct FMassLODFragment
{
// LOD information
TEnumAsByte<EMassLOD::Type> LOD;
TEnumAsByte<EMassLOD::Type> PrevLOD;
// Visibility information (Required when FLODLogic::bDoVisibilityLogic is enabled)
EMassVisibility Visibility;
EMassVisibility PrevVisibility
// Floating point LOD value, scaling from 0 to 3, 0 highest LOD and 3 being completely off LOD
// (Required only when FLODLogic::bCalculateLODSignificance is enabled)
float LODSignificance = 0.0f; //
// Per viewer LOD information (Required when FLODLogic::bCalculateLODPerViewer is enabled)
TArray<EMassLOD::Type> LODPerViewer;
TArray<EMassLOD::Type> PrevLODPerViewer;
// Visibility information per viewer (Required when FLODLogic::bDoVisibilityLogic and FLODLogicbStoreInfoPerViewer are enabled)
TArray<EMassVisibility> VisibilityPerViewer;
TArray<EMassVisibility> PrevVisibilityPerViewer;
}
*/
/**
* TMassLODTickRateController outputs
*
struct FMassVariableTickFragment
{
// Accumulated DeltaTime
float DeltaTime = 0.0f;
float LastTickedTime = 0.0f;
};
*/
struct FViewerLODInfo
{
/* Boolean indicating the viewer is local or not */
bool bLocal = false;
/* Boolean indicating the viewer data needs to be cleared */
bool bClearData = false;
/** The handle to the viewer */
FMassViewerHandle Handle;
/** Viewer location and looking direction */
FVector Location;
FVector Direction;
/** Viewer frustum (will not include near and far planes) */
FConvexVolume Frustum;
};
/**
* Base struct for the LOD calculation helpers
*/
struct FMassLODBaseLogic
{
FMassLODBaseLogic(bool bShouldBuildFrustumData)
: bBuildFrustumData(bShouldBuildFrustumData)
{}
protected:
UE_API void CacheViewerInformation(TConstArrayView<FViewerInfo> ViewerInfos);
/** Per viewer LOD information conditional fragment accessors */
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, EMassLOD::Type, LODPerViewer);
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, EMassLOD::Type, PrevLODPerViewer);
/** LOD Significance conditional fragment accessors */
DECLARE_CONDITIONAL_MEMBER_ACCESSORS(Condition, float, LODSignificance);
/** Visibility conditional fragment accessors */
DECLARE_CONDITIONAL_MEMBER_ACCESSORS(Condition, float, ClosestDistanceToFrustum);
DECLARE_CONDITIONAL_MEMBER_ACCESSORS(Condition, EMassVisibility, Visibility);
DECLARE_CONDITIONAL_MEMBER_ACCESSORS(Condition, EMassVisibility, PrevVisibility);
/** Per viewer distance conditional fragment accessors */
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, float, DistanceToViewerSq);
/** Per viewer visibility conditional fragment accessors */
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, float, DistanceToFrustum);
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, EMassVisibility, VisibilityPerViewer);
DECLARE_CONDITIONAL_MEMBER_ARRAY_ACCESSORS(Condition, EMassVisibility, PrevVisibilityPerViewer);
TArray<FViewerLODInfo> Viewers;
private:
/**
* Setting to false will prevent costly FViewerLODInfo.Frustum creation. Makes sense only if that data is not required.
* Note that this property is not expected to be changed at runtime.
*/
bool bBuildFrustumData = true;
};
#undef UE_API