// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelMinimal.h" #include "BodySetupEnums.h" #include "VoxelEnums.h" #include "VoxelIntBox.h" #include "VoxelRender/VoxelMeshConfig.h" #include "VoxelContainers/VoxelStaticArray.h" struct FVoxelMaterialIndices; class FInvokerPositionsArray; class IVoxelPool; class FVoxelData; class FVoxelDebugManager; class FVoxelToolRenderingManager; class UMaterialInterface; class UMaterialInstanceDynamic; class UVoxelMaterialCollectionBase; class UVoxelProceduralMeshComponent; class AVoxelWorld; class AActor; struct FVoxelChunkUpdate; DECLARE_MULTICAST_DELEGATE(FVoxelRendererOnWorldLoaded); // Fired once per chunk DECLARE_MULTICAST_DELEGATE_OneParam(FVoxelOnChunkUpdateFinished, FVoxelIntBox); DECLARE_MULTICAST_DELEGATE_ThreeParams(FVoxelOnMaterialInstanceCreated, int32 /*ChunkLOD*/, const FVoxelIntBox& /*ChunkBounds*/, UMaterialInstanceDynamic* /*Instance*/); struct FVoxelRendererDynamicSettings { struct FLODData { TWeakObjectPtr Material; TWeakObjectPtr MaterialCollection; FThreadSafeCounter MaxMaterialIndices = 1; }; TVoxelStaticArray LODData{ ForceInit }; }; struct FVoxelRendererSettingsBase { const float VoxelSize; const TVoxelSharedRef WorldOffset; // Always valid UClass* const ProcMeshClass; const bool bCastFarShadow; const EVoxelPlayType PlayType; const TWeakObjectPtr World; const TWeakObjectPtr RootComponent; const EVoxelUVConfig UVConfig; const float UVScale; const EVoxelNormalConfig NormalConfig; const EVoxelMaterialConfig MaterialConfig; const bool bHardColorTransitions; const float BoundsExtension; const ECollisionTraceFlag CollisionTraceFlag; const int32 NumConvexHullsPerAxis; const bool bCleanCollisionMeshes; const EVoxelRenderType RenderType; const uint32 RenderSharpness; const bool bCreateMaterialInstances; const bool bDitherChunks; const float ChunksDitheringDuration; const bool bOptimizeIndices; const int32 MaxDistanceFieldLOD; const int32 DistanceFieldBoundsExtension; const int32 DistanceFieldResolutionDivisor; const float DistanceFieldSelfShadowBias; const bool bOneMaterialPerCubeSide; const bool bHalfPrecisionCoordinates; const bool bInterpolateColors; const bool bInterpolateUVs; const bool bSRGBColors; const bool bRenderWorld; const float MeshUpdatesBudget; const TArray HolesMaterials; const TMap MaterialsMeshConfigs; const bool bMergeChunks; const int32 ChunksClustersSize; const bool bDoNotMergeCollisionsAndNavmesh; const bool bStaticWorld; const float PriorityDuration; const TVoxelSharedRef DynamicSettings; // If Data isn't null, it's Depth and WorldBounds will be used, and WorldOffset will be set to 0 FVoxelRendererSettingsBase( const AVoxelWorld* World, EVoxelPlayType PlayType, UPrimitiveComponent* RootComponent, const FVoxelData* Data = nullptr); public: inline FVector GetChunkRelativePosition(const FIntVector& Position) const { return FVector(Position + *WorldOffset) * VoxelSize; } UMaterialInterface* GetVoxelMaterial(int32 LOD, const FVoxelMaterialIndices& MaterialIndices) const; UMaterialInterface* GetVoxelMaterial(int32 LOD) const; inline void OnMaterialsChanged() const { // Needed to have errors display again UniqueId = UniqueIdCounter++; } private: mutable uint64 UniqueId = UniqueIdCounter++; static uint64 UniqueIdCounter; }; struct FVoxelRendererSettings : FVoxelRendererSettingsBase { const TVoxelSharedRef Data; const TVoxelSharedRef Pool; const TVoxelSharedPtr ToolRenderingManager; // No tools in asset actors const TVoxelSharedRef DebugManager; FVoxelRendererSettings( const AVoxelWorld* World, EVoxelPlayType PlayType, UPrimitiveComponent* RootComponent, const TVoxelSharedRef& Data, const TVoxelSharedRef& Pool, const TVoxelSharedPtr& ToolRenderingManager, const TVoxelSharedRef& DebugManager, bool bUseDataSettings); }; class VOXEL_API IVoxelRenderer { public: const FVoxelRendererSettings Settings; FVoxelRendererOnWorldLoaded OnWorldLoaded; FVoxelOnMaterialInstanceCreated OnMaterialInstanceCreated; explicit IVoxelRenderer(const FVoxelRendererSettings& Settings); virtual ~IVoxelRenderer() = default; //~ Begin IVoxelRenderer Interface virtual void Destroy() = 0; virtual int32 UpdateChunks( const FVoxelIntBox& Bounds, const TArray& ChunksToUpdate, const FVoxelOnChunkUpdateFinished& FinishDelegate) = 0; virtual void UpdateLODs(uint64 InUpdateIndex, const TArray& ChunkUpdates) = 0; virtual int32 GetTaskCount() const = 0; virtual void RecomputeMeshPositions() = 0; virtual void ApplyNewMaterials() = 0; virtual void ApplyToAllMeshes(TFunctionRef Lambda) = 0; virtual void CreateGeometry_AnyThread(int32 LOD, const FIntVector& ChunkPosition, TArray& OutIndices, TArray& OutVertices) const = 0; //~ End IVoxelRenderer Interface // Called by LOD manager void SetInvokersPositionsForPriorities(const TArray& NewInvokersPositionsForPriorities); // Used by render chunks to compute the priorities inline const TVoxelSharedRef& GetInvokersPositionsForPriorities() const { return InvokersPositionsForPriorities; } private: TVoxelSharedRef InvokersPositionsForPriorities; };