diff --git a/SDFMapCreator.sln.DotSettings.user b/SDFMapCreator.sln.DotSettings.user new file mode 100644 index 0000000..4b0a35a --- /dev/null +++ b/SDFMapCreator.sln.DotSettings.user @@ -0,0 +1,2 @@ + + ForceIncluded \ No newline at end of file diff --git a/SDFMapCreator/Program.cs b/SDFMapCreator/Program.cs index 416a2c9..e7f4b72 100644 --- a/SDFMapCreator/Program.cs +++ b/SDFMapCreator/Program.cs @@ -88,8 +88,13 @@ public class Program { var imagesPath = "images"; + /* for (int i = 0; i < 8; i++) LoadImage($"./{imagesPath}{Path.DirectorySeparatorChar}{i+1:00}.png"); + */ + + LoadImage("spherecut.png"); + LoadImage("spherefull.png"); //LoadImage("1.png"); //LoadImage("2.png"); @@ -132,14 +137,16 @@ public class Program { Console.WriteLine("Creating gradients..."); for (var i = 0; i < Masks.Count - 1; i++) { - var gradientData = Gradient(Masks[i], SDFs[i], SDFs[i + 1]); + var gradientData = Gradient(Masks[i+1], SDFs[i], SDFs[i + 1]); Gradients.Add(gradientData); if(!outputGradients) continue; - var gradient = new MagickImage(MagickColors.Black, (uint)Masks[i].Mask.GetLength(0), (uint)Masks[i].Mask.GetLength(1)); + var gradient = new MagickImage(MagickColors.Black, (uint)Masks[i+1].Mask.GetLength(0), (uint)Masks[i+1].Mask.GetLength(1)); gradient.GetPixels().SetPixels(gradientData.ToFloatArray()); gradient.Write($"gradient{i}.png", MagickFormat.Png24); } + return; + Console.WriteLine("Preparing transitions..."); //for each gradient read the corresponding mask //for each pixel in the mask, lerp the pixel value with the gradient value @@ -150,14 +157,35 @@ public class Program { var mask = Masks[i + 1]; var gradient = Gradients[i]; var transition = new float3[width, height]; + var absMax = MIN; + var absMin = MAX; for (var x = 0; x < mask.Mask.GetLength(0); x++) { for (var y = 0; y < mask.Mask.GetLength(1); y++) { - if (mask.Mask[x, y].X == 0) continue; - transition[x, y] = new(Lerp(Images[i].Pixels[x,y].X, MAX, gradient[x,y].X)); + if (mask.Mask[x, y].X == 0 || mask.Mask[x, y].Y > 0) continue; + transition[x, y] = new(Lerp(Images[i].Pixels[x, y].X, MAX, gradient[x, y].X)); + if (transition[x, y].X > absMax) absMax = transition[x, y].X; + if (transition[x, y].X < absMin) absMin = transition[x, y].X; } } + + absMax = MathF.Min(absMax, MAX); + absMin = MathF.Max(absMin, MIN); + + //normalize + Parallel.For(0, width * height, parallelOptions, (j) => { + var x = (int)(j % width); + var y = (int)(j / width); + //Console.WriteLine($"Transition {i} | Min: {absMin} | Max: {absMax}, {transition[x, y].X}"); + transition[x, y] = new(Remap(transition[x, y].X, absMin, absMax, MIN, MAX)); + }); + + Console.WriteLine($"Transition {i} | Min: {absMin} | Max: {absMax}"); + Console.WriteLine($"Transition {i} | Min: {transition.Cast().Min(x => x.X)} | Max: {transition.Cast().Max(x => x.X)}"); + var transitionImage = new MagickImage(MagickColors.Black, (uint)mask.Mask.GetLength(0), (uint)mask.Mask.GetLength(1)); transitionImage.GetPixels().SetPixels(transition.ToFloatArray()); + + transitionImage.Write($"transition{i}.png", MagickFormat.Png24); } @@ -196,21 +224,28 @@ public class Program { var sw = new Stopwatch(); sw.Start(); float3[,] temp = new float3[width, height]; - Console.WriteLine("Running edge detection..."); + + var min = MAX; + var max = MIN; + + Console.WriteLine("Running gradient generation..."); Parallel.For(0, width * height, parallelOptions, (i) => { int x = (int)(i % width); int y = (int)(i / width); - var a = (sdfA.SDF[x,y].X + sdfB.SDF[x,y].Y + sdfB.SDF[x,y].Z )/ 3; - var b = (sdfB.SDF[x,y].X + sdfB.SDF[x,y].Y + sdfB.SDF[x,y].Z )/ 3; + if(mask.Mask[x,y].X == 0 || mask.Mask[x,y].Y > 0) return; + + var a = sdfA.SDF[x, y].X; + var b = sdfB.SDF[x, y].X; var gradient = a / (a + b); temp[x, y] = new(Remap(gradient, 0, 1, MIN, MAX)); + + if (gradient < min) min = gradient; + if (gradient > max) max = gradient; }); Console.WriteLine($"Gradient Time: {sw.Elapsed.TotalSeconds:N4}s ({iterCount/(float)sw.Elapsed.TotalSeconds:N0} pixels/s)"); - var min = temp.Cast().Min(x => x.X); - var max = temp.Cast().Max(x => x.X); Console.WriteLine($"Min: {min} | Max: {max}"); return temp; } @@ -253,6 +288,8 @@ public class Program { var y = (int)(i / width); temp[x, y] = new(Remap(temp[x, y].X, 0, AbsMax, MIN, MAX)); }); + sw.Stop(); + Console.WriteLine($"SDF Normalization Time: {sw.Elapsed.TotalSeconds:N4}s ({iterCount/sw.Elapsed.TotalSeconds:N0} pixels/s)"); Console.WriteLine("AbsMax: " + AbsMax); return new(temp); @@ -262,7 +299,6 @@ public class Program { private static float EuclideanDistance(float2 a, float2 b) => MathF.Sqrt(MathF.Pow(a.X - b.X, 2) + MathF.Pow(a.Y - b.Y, 2)); - private static void ImageData(MagickImage image1, IPixelCollection pixels1) { Console.WriteLine( $""" diff --git a/SDFMapCreator/SDFMapCreator.csproj b/SDFMapCreator/SDFMapCreator.csproj index 2d047f2..63e0f22 100644 --- a/SDFMapCreator/SDFMapCreator.csproj +++ b/SDFMapCreator/SDFMapCreator.csproj @@ -46,6 +46,12 @@ Always + + Always + + + Always + diff --git a/SDFMapCreator/spherecut.png b/SDFMapCreator/spherecut.png new file mode 100644 index 0000000..cad0b78 Binary files /dev/null and b/SDFMapCreator/spherecut.png differ diff --git a/SDFMapCreator/spherefull.png b/SDFMapCreator/spherefull.png new file mode 100644 index 0000000..6cb948e Binary files /dev/null and b/SDFMapCreator/spherefull.png differ