// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelRange.h" #include "VoxelQueryZone.h" #include "VoxelItemStack.h" #include "VoxelPlaceableItems/VoxelPlaceableItem.h" #include "VoxelGenerators/VoxelGeneratorInit.h" #include "VoxelGenerators/VoxelGeneratorInstance.h" template FORCEINLINE FVector FVoxelGeneratorInstance::GetUpVector(const TVector& P) const { return GetUpVector(P.X, P.Y, P.Z); } /////////////////////////////////////////////////////////////////////////////// template FORCEINLINE T FVoxelGeneratorInstance::GetCustomOutput(T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { if (const auto Ptr = GetOutputsPtrMap().FindRef(Name)) { return (this->*Ptr)(X, Y, Z, LOD, Items); } else { return DefaultValue; } } template FORCEINLINE T FVoxelGeneratorInstance::GetCustomOutput(T DefaultValue, FName Name, const TVector& P, int32 LOD, const FVoxelItemStack& Items) const { return GetCustomOutput(DefaultValue, Name, P.X, P.Y, P.Z, LOD, Items); } template FORCEINLINE TVoxelRange FVoxelGeneratorInstance::GetCustomOutputRange(TVoxelRange DefaultValue, FName Name, const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const { if (const auto Ptr = GetOutputsRangesPtrMap().FindRef(Name)) { return (this->*Ptr)(Bounds, LOD, Items); } else { return DefaultValue; } } /////////////////////////////////////////////////////////////////////////////// template FORCEINLINE T FVoxelTransformableGeneratorInstance::GetCustomOutput_Transform(const FTransform& LocalToWorld, T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { if (const auto Ptr = GetOutputsPtrMap_Transform().FindRef(Name)) { return (this->*Ptr)(LocalToWorld, X, Y, Z, LOD, Items); } else { return DefaultValue; } } template FORCEINLINE TVoxelRange FVoxelTransformableGeneratorInstance::GetCustomOutputRange_Transform(const FTransform& LocalToWorld, TVoxelRange DefaultValue, FName Name, const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const { if (const auto Ptr = GetOutputsRangesPtrMap_Transform().FindRef(Name)) { return (this->*Ptr)(LocalToWorld, Bounds, LOD, Items); } else { return DefaultValue; } } /////////////////////////////////////////////////////////////////////////////// FORCEINLINE v_flt FVoxelGeneratorInstance::GetValue(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs.Value)(X, Y, Z, LOD, Items); } FORCEINLINE FVoxelMaterial FVoxelGeneratorInstance::GetMaterial(v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs.Material)(X, Y, Z, LOD, Items); } FORCEINLINE TVoxelRange FVoxelGeneratorInstance::GetValueRange(const FVoxelIntBox& Bounds, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs.ValueRange)(Bounds, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// FORCEINLINE v_flt FVoxelTransformableGeneratorInstance::GetValue_Transform(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs_Transform.Value)(LocalToWorld, X, Y, Z, LOD, Items); } FORCEINLINE FVoxelMaterial FVoxelTransformableGeneratorInstance::GetMaterial_Transform(const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs_Transform.Material)(LocalToWorld, X, Y, Z, LOD, Items); } FORCEINLINE TVoxelRange FVoxelTransformableGeneratorInstance::GetValueRange_Transform(const FTransform& LocalToWorld, const FVoxelIntBox& WorldBounds, int32 LOD, const FVoxelItemStack& Items) const { return (this->*BasePtrs_Transform.ValueRange)(LocalToWorld, WorldBounds, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// template FORCEINLINE T FVoxelGeneratorInstance::Get(const FIntVector& P, int32 LOD, const FVoxelItemStack& Items) const { return Get(P.X, P.Y, P.Z, LOD, Items); } template<> FORCEINLINE FVoxelValue FVoxelGeneratorInstance::Get( v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return FVoxelValue(GetValue(X, Y, Z, LOD, Items)); } template<> FORCEINLINE v_flt FVoxelGeneratorInstance::Get( v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return GetValue(X, Y, Z, LOD, Items); } template<> FORCEINLINE FVoxelMaterial FVoxelGeneratorInstance::Get( v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return GetMaterial(X, Y, Z, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// template<> FORCEINLINE void FVoxelGeneratorInstance::Get(TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const { GetValues(QueryZone, LOD, Items); } template<> FORCEINLINE void FVoxelGeneratorInstance::Get(TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const { GetMaterials(QueryZone, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// template FORCEINLINE T FVoxelTransformableGeneratorInstance::Get_Transform(const FTransform& LocalToWorld, const FIntVector& P, int32 LOD, const FVoxelItemStack& Items) const { return Get_Transform(LocalToWorld, P.X, P.Y, P.Z, LOD, Items); } template<> FORCEINLINE FVoxelValue FVoxelTransformableGeneratorInstance::Get_Transform( const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return FVoxelValue(GetValue_Transform(LocalToWorld, X, Y, Z, LOD, Items)); } template<> FORCEINLINE v_flt FVoxelTransformableGeneratorInstance::Get_Transform( const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return GetValue_Transform(LocalToWorld, X, Y, Z, LOD, Items); } template<> FORCEINLINE FVoxelMaterial FVoxelTransformableGeneratorInstance::Get_Transform( const FTransform& LocalToWorld, v_flt X, v_flt Y, v_flt Z, int32 LOD, const FVoxelItemStack& Items) const { return GetMaterial_Transform(LocalToWorld, X, Y, Z, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// template<> FORCEINLINE void FVoxelTransformableGeneratorInstance::Get_Transform( const FTransform& LocalToWorld, TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const { GetValues_Transform(LocalToWorld, QueryZone, LOD, Items); } template<> FORCEINLINE void FVoxelTransformableGeneratorInstance::Get_Transform( const FTransform& LocalToWorld, TVoxelQueryZone& QueryZone, int32 LOD, const FVoxelItemStack& Items) const { GetMaterials_Transform(LocalToWorld, QueryZone, LOD, Items); } /////////////////////////////////////////////////////////////////////////////// template<> FORCEINLINE const TMap>& FVoxelGeneratorInstance::GetOutputsPtrMap() const { return CustomPtrs.Float; } template<> FORCEINLINE const TMap>& FVoxelGeneratorInstance::GetOutputsPtrMap() const { return CustomPtrs.Int; } template<> FORCEINLINE const TMap>& FVoxelGeneratorInstance::GetOutputsPtrMap() const { return CustomPtrs.Color; } template<> FORCEINLINE const TMap>& FVoxelGeneratorInstance::GetOutputsRangesPtrMap() const { return CustomPtrs.FloatRange; } /////////////////////////////////////////////////////////////////////////////// template<> FORCEINLINE const TMap>& FVoxelTransformableGeneratorInstance::GetOutputsPtrMap_Transform() const { return CustomPtrs_Transform.Float; } template<> FORCEINLINE const TMap>& FVoxelTransformableGeneratorInstance::GetOutputsPtrMap_Transform() const { return CustomPtrs_Transform.Int; } template<> FORCEINLINE const TMap>& FVoxelTransformableGeneratorInstance::GetOutputsPtrMap_Transform() const { return CustomPtrs_Transform.Color; } template<> FORCEINLINE const TMap>& FVoxelTransformableGeneratorInstance::GetOutputsRangesPtrMap_Transform() const { return CustomPtrs_Transform.FloatRange; } /////////////////////////////////////////////////////////////////////////////// template FORCEINLINE T FVoxelItemStack::Get(v_flt X, v_flt Y, v_flt Z, int32 LOD) const { check(IsValid()); if (Depth == -1) { return Generator->Get(X, Y, Z, LOD, *this); } else { auto& Asset = *ItemHolder.GetAssetItems()[Depth]; return Asset.Generator->Get_Transform(Asset.LocalToWorld, X, Y, Z, LOD, *this); } } FORCEINLINE TVoxelRange FVoxelItemStack::GetValueRange(const FVoxelIntBox& Bounds, int32 LOD) const { check(IsValid()); if (Depth == -1) { return Generator->GetValueRange(Bounds, LOD, *this); } else { TOptional> Range; auto& Asset = *ItemHolder.GetAssetItems()[Depth]; if (Asset.Bounds.Intersect(Bounds)) { Range = Asset.Generator->GetValueRange_Transform( Asset.LocalToWorld, Asset.Bounds.Overlap(Bounds), LOD, *this); } const auto NextStack = FVoxelItemStack(ItemHolder, *Generator, Depth - 1, CustomData); for (auto& SubBounds : Bounds.Difference(Asset.Bounds)) { const auto NextRange = NextStack.GetValueRange(SubBounds, LOD); Range = Range.IsSet() ? TVoxelRange::Union(Range.GetValue(), NextRange) : NextRange; } if (!ensure(Range.IsSet())) { Range = TVoxelRange::Infinite(); } return Range.GetValue(); } } template FORCEINLINE T FVoxelItemStack::GetCustomOutput(T DefaultValue, FName Name, v_flt X, v_flt Y, v_flt Z, int32 LOD) const { check(IsValid()); if (Depth == -1) { return Generator->GetCustomOutput(DefaultValue, Name, X, Y, Z, LOD, *this); } else { auto& Asset = *ItemHolder.GetAssetItems()[Depth]; return Asset.Generator->GetCustomOutput_Transform(Asset.LocalToWorld, DefaultValue, Name, X, Y, Z, LOD, *this); } } template FORCEINLINE TVoxelRange FVoxelItemStack::GetCustomOutputRange(TVoxelRange DefaultValue, FName Name, const FVoxelIntBox& Bounds, int32 LOD) const { check(IsValid()); if (Depth == -1) { return Generator->GetCustomOutputRange(DefaultValue, Name, Bounds, LOD, *this); } else { auto& Asset = *ItemHolder.GetAssetItems()[Depth]; return Asset.Generator->GetCustomOutputRange_Transform(Asset.LocalToWorld, DefaultValue, Name, Bounds, LOD, *this); } } template int32 FVoxelItemStack::GetNextDepth(TArgs... Args) const { for (int32 Index = Depth - 1; Index >= 0; Index--) { auto& Item = *ItemHolder.GetAssetItems()[Index]; if (Item.Bounds.ContainsTemplate(Args...)) { return Index; } else if (Item.Bounds.Intersect(Args...)) { // Invalid, must abort as multiple assets are possible return -2; } } return -1; }