// Copyright 2020 Phyronnaz #pragma once #include "CoreMinimal.h" #include "VoxelTools/VoxelDataTools.h" #include "VoxelTools/VoxelToolHelpers.h" #include "VoxelUtilities/VoxelDistanceFieldUtilities.h" template void UVoxelDataTools::MergeDistanceFieldImpl( FVoxelData& Data, const FVoxelIntBox& Bounds, T1 GetSDF, T2 MergeSDF, bool bMultiThreaded, bool bSetMaterials, T3 GetMaterial) { VOXEL_TOOL_FUNCTION_COUNTER(Bounds.Count()); const FIntVector Size = Bounds.Size(); const TArray Values = Data.ParallelGet(Bounds.Extend(1) /* See GetSurfacePositionsFromDensities */, !bMultiThreaded); TArray Distances; TArray SurfacePositions; FVoxelDistanceFieldUtilities::GetSurfacePositionsFromDensities(Size, Values, Distances, SurfacePositions); FVoxelDistanceFieldUtilities::JumpFlood(Size, SurfacePositions, EVoxelComputeDevice::GPU); FVoxelDistanceFieldUtilities::GetDistancesFromSurfacePositions(Size, SurfacePositions, Distances); FVoxelDebug::Broadcast("Values", Bounds.Size(), Data.Get(Bounds)); FVoxelDebug::Broadcast("Distances", Bounds.Size(), Distances); const auto Set = [&](int32 X, int32 Y, int32 Z, FVoxelValue& Value, FVoxelMaterial& Material, auto bSetMaterials_Static) { checkVoxelSlow(Bounds.Contains(X, Y, Z)); const float OtherSDF = GetSDF(X, Y, Z); const float OldSDF = FVoxelUtilities::Get3D(Distances, Size, X, Y, Z, Bounds.Min); const float NewSDF = MergeSDF(OldSDF, OtherSDF); Value = FVoxelValue(NewSDF); if (bSetMaterials_Static) { Material = GetMaterial(OldSDF, NewSDF, Material); } }; if (bSetMaterials) { Data.ParallelSet(Bounds, [&](int32 X, int32 Y, int32 Z, FVoxelValue& Value, FVoxelMaterial& Material) { Set(X, Y, Z, Value, Material, FVoxelUtilities::FTrueType()); }, !bMultiThreaded); } else { // TODO optional // TODO check surface position is in bounds Data.ParallelSet(Bounds, [&](int32 X, int32 Y, int32 Z, FVoxelMaterial& Material) { const FVector3f SurfacePosition = FVoxelUtilities::Get3D(SurfacePositions, Size, X, Y, Z, Bounds.Min); const auto Result = FindClosestNonEmptyVoxelImpl(Data, FVoxelVector(Bounds.Min) + FVector(SurfacePosition), true); if (Result.bSuccess) { Material = Result.Material; } }, !bMultiThreaded); Data.ParallelSet(Bounds, [&](int32 X, int32 Y, int32 Z, FVoxelValue& Value) { FVoxelMaterial Material; Set(X, Y, Z, Value, Material, FVoxelUtilities::FFalseType()); }, !bMultiThreaded); } }