// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelRange.h" #include "VoxelIntBox.h" #include namespace FVoxelRangeUtilities { template inline TVoxelRange Min(const TVoxelRange& A, const TVoxelRange& B) { return { FMath::Min(A.Min, B.Min), FMath::Min(A.Max, B.Max) }; } template inline TVoxelRange Max(const TVoxelRange& A, const TVoxelRange& B) { return { FMath::Max(A.Min, B.Min), FMath::Max(A.Max, B.Max) }; } template inline TVoxelRange Clamp(const TVoxelRange& Value, const TVoxelRange& Min, const TVoxelRange& Max) { if (Min.IsSingleValue() && Max.IsSingleValue()) { return { FMath::Clamp(Value.Min, Min.GetSingleValue(), Max.GetSingleValue()), FMath::Clamp(Value.Max, Min.GetSingleValue(), Max.GetSingleValue()) }; } if (Min.Max <= Value.Min && Value.Max <= Max.Min) // If already clamped { return Value; } else if (Max.Max <= Value.Min) { return Max.Max; } else if (Value.Max <= Min.Min) { return Min.Min; } else { return { Min.Min, Max.Max }; } } template inline TVoxelRange Abs(const TVoxelRange& A) { return { A.Contains(0) ? 0 : FMath::Min(FMath::Abs(A.Min), FMath::Abs(A.Max)), FMath::Max(FMath::Abs(A.Min), FMath::Abs(A.Max)) }; } template inline TVoxelRange Sign(const TVoxelRange& A) { if (0 < A.Min) { return { 1, 1 }; } else if (A.Max < 0) { return { -1, -1 }; } else if (A.Min == 0 && A.Max == 0) { return { 0, 0 }; } else { return { -1, 1 }; } } inline v_flt Sqrt(v_flt F) { if (F <= 0) { return 0; } else { return std::sqrt(F); } } inline TVoxelRange Sqrt(const TVoxelRange& F) { return { Sqrt(FMath::Max(0., F.Min)), Sqrt(FMath::Max(0., F.Max)) }; } inline TVoxelRange Lerp(const TVoxelRange& A, const TVoxelRange& B, const TVoxelRange& Alpha) { if (Alpha.IsSingleValue() && 0 <= Alpha.GetSingleValue() && Alpha.GetSingleValue() <= 1) { return { FMath::Lerp(A.Min, B.Min, Alpha.GetSingleValue()), FMath::Lerp(A.Max, B.Max, Alpha.GetSingleValue()) }; } else { return A + Alpha * (B - A); } } inline FVoxelIntBox BoundsFromRanges(TVoxelRange X, TVoxelRange Y, TVoxelRange Z) { return FVoxelIntBox( FIntVector( FMath::FloorToInt(X.Min), FMath::FloorToInt(Y.Min), FMath::FloorToInt(Z.Min)), FIntVector( FMath::CeilToInt(X.Max) + 1, FMath::CeilToInt(Y.Max) + 1, FMath::CeilToInt(Z.Max) + 1)); } }