// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelIntBox.h" #include "VoxelValue.h" #include "VoxelMaterial.h" class FVoxelData; class FVoxelDataOctreeLeaf; class FVoxelDataOctreeBase; namespace FVoxelDataAcceleratorParameters { VOXEL_API int32 GetDefaultCacheSize(); VOXEL_API bool GetUseAcceleratorMap(); VOXEL_API bool GetShowStats(); } template class TVoxelDataAccelerator { public: TData& Data; const FVoxelIntBox Bounds; const int32 CacheSize; const bool bUseAcceleratorMap; static constexpr bool bIsConst = TIsConst::Value; // Will not build an accelerator map. Access can be done anywhere explicit TVoxelDataAccelerator(TData& Data, int32 CacheSize = FVoxelDataAcceleratorParameters::GetDefaultCacheSize()); // Will build an accelerator map. Access can only be done in Bounds // Map source can't be used when TData is not const TVoxelDataAccelerator(TData& Data, const FVoxelIntBox& Bounds, const TVoxelDataAccelerator* MapSource = nullptr, int32 CacheSize = FVoxelDataAcceleratorParameters::GetDefaultCacheSize()); ~TVoxelDataAccelerator(); // Copying can mess up the cache UE_NONCOPYABLE(TVoxelDataAccelerator); public: template T GetCustomOutput(T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD) const; public: v_flt GetFloatValue(v_flt X, v_flt Y, v_flt Z, int32 LOD, bool* bIsGeneratorValue = nullptr) const; FORCEINLINE v_flt GetFloatValue(const FVoxelVector& P, int32 LOD, bool* bIsGeneratorValue = nullptr) const { return GetFloatValue(P.X, P.Y, P.Z, LOD, bIsGeneratorValue); } public: template T Get(int32 X, int32 Y, int32 Z, int32 LOD) const; template FORCEINLINE T Get(const FIntVector& P, int32 LOD) const { return Get(P.X, P.Y, P.Z, LOD); } FORCEINLINE FVoxelValue GetValue(int32 X, int32 Y, int32 Z, int32 LOD) const { return Get(X, Y, Z, LOD); } FORCEINLINE FVoxelValue GetValue(const FIntVector& P, int32 LOD) const { return Get(P, LOD); } FORCEINLINE FVoxelMaterial GetMaterial(int32 X, int32 Y, int32 Z, int32 LOD) const { return Get(X, Y, Z, LOD); } FORCEINLINE FVoxelMaterial GetMaterial(const FIntVector& P, int32 LOD) const { return Get(P, LOD); } public: // Returns if value was set, or if it was out of the world template FORCEINLINE bool Set(int32 X, int32 Y, int32 Z, const T& Value) { return SetImpl(X, Y, Z, [&](auto& InValue) { InValue = Value; }); } template FORCEINLINE bool Set(const FIntVector& P, const T& Value) { return Set(P.X, P.Y, P.Z, Value); } template FORCEINLINE bool SetValue(int32 X, int32 Y, int32 Z, FVoxelValue Value) { return Set(X, Y, Z, Value); } template FORCEINLINE bool SetValue(const FIntVector& P, FVoxelValue Value) { return Set(P, Value); } template FORCEINLINE bool SetMaterial(int32 X, int32 Y, int32 Z, FVoxelMaterial Material) { return Set(X, Y, Z, Material); } template FORCEINLINE bool SetMaterial(const FIntVector& P, FVoxelMaterial Material) { return Set(P, Material); } public: template FORCEINLINE bool Edit(int32 X, int32 Y, int32 Z, TLambda Lambda) { return SetImpl(X, Y, Z, Lambda); } template FORCEINLINE bool Edit(const FIntVector& P, TLambda Lambda) { return Edit(P.X, P.Y, P.Z, Lambda); } template FORCEINLINE bool EditValue(int32 X, int32 Y, int32 Z, TLambda Lambda) { return Edit(X, Y, Z, Lambda); } template FORCEINLINE bool EditValue(const FIntVector& P, TLambda Lambda) { return Edit(P, Lambda); } template FORCEINLINE bool EditMaterial(int32 X, int32 Y, int32 Z, TLambda Lambda) { return Edit(X, Y, Z, Lambda); } template FORCEINLINE bool EditMaterial(const FIntVector& P, TLambda Lambda) { return Edit(P, Lambda); } private: struct FCacheEntry { FVoxelDataOctreeBase* Octree; uint64 LastAccessTime; }; mutable TNoGrowArray CacheEntries; mutable uint64 GlobalTime = 0; #if VOXEL_DATA_ACCELERATOR_STATS mutable uint32 NumGet = 0; mutable uint32 NumSet = 0; mutable uint32 NumCacheTopAccess = 0; mutable uint32 NumCacheTopMiss = 0; mutable uint32 NumCacheAllAccess = 0; mutable uint32 NumCacheAllMiss = 0; mutable uint32 NumMapAccess = 0; mutable uint32 NumMapMiss = 0; mutable uint32 NumOutOfWorld = 0; #endif using FAcceleratorMap = TMap; using FConstAcceleratorMap = typename TChooseClass::Result; // Map from Leaf.GetMin() to &Leaf const TVoxelSharedPtr AcceleratorMap; template auto GetImpl(int32 X, int32 Y, int32 Z, T UseOctree) const; template bool SetImpl(int32 X, int32 Y, int32 Z, TLambda EditValue) const; FVoxelDataOctreeBase* GetOctreeFromCache_CheckTopOnly(int32 X, int32 Y, int32 Z) const; FVoxelDataOctreeBase* GetOctreeFromCache_CheckAll(int32 X, int32 Y, int32 Z) const; FVoxelDataOctreeBase* GetOctreeFromMap(int32 X, int32 Y, int32 Z) const; void StoreOctreeInCache(FVoxelDataOctreeBase& Octree) const; static TVoxelSharedRef GetAcceleratorMap(const FVoxelData& Data, const FVoxelIntBox& Bounds); }; class FVoxelMutableDataAccelerator : public TVoxelDataAccelerator { public: using TVoxelDataAccelerator::TVoxelDataAccelerator; }; class FVoxelConstDataAccelerator : public TVoxelDataAccelerator { public: using TVoxelDataAccelerator::TVoxelDataAccelerator; };