From f6ef623bb4fa6dd499ac216173abb6b61abc4857 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Wed, 28 Aug 2024 22:03:48 +0100 Subject: [PATCH] Simplify packing by reversing sort and growing in only 1 direction --- project/code/TMV/Mission.cs | 4 +- project/code/TMV/RectPacker.cs | 73 +++++----------------------------- 2 files changed, 10 insertions(+), 67 deletions(-) diff --git a/project/code/TMV/Mission.cs b/project/code/TMV/Mission.cs index 7b1e10e..435e3ec 100644 --- a/project/code/TMV/Mission.cs +++ b/project/code/TMV/Mission.cs @@ -365,10 +365,8 @@ public partial class Mission : Node3D { var bounds = Timing.TimeStage("RectPack", () => { - var bounds = RectPacker.Pack(packingRects); - return bounds; + return RectPacker.Pack(packingRects); }); - bounds = RectPacker.TightBounds(packingRects); GD.Print($"Packed {packingRects.Length} rects in ({bounds.Width}, {bounds.Height})"); var lightmapFormat = Image.Format.Rgba8; diff --git a/project/code/TMV/RectPacker.cs b/project/code/TMV/RectPacker.cs index d7ddef7..250a5c2 100644 --- a/project/code/TMV/RectPacker.cs +++ b/project/code/TMV/RectPacker.cs @@ -13,21 +13,15 @@ public static class RectPacker public ushort Height; } - enum ExpandDir - { - X, - Y, - } - - public static Rect Pack(Rect[] rectangles, ushort minWidth = 512, ushort minHeight = 512) + public static Rect Pack(Rect[] rectangles, ushort width = 1024, ushort minHeight = 512) { ArgumentNullException.ThrowIfNull(rectangles); - ArgumentOutOfRangeException.ThrowIfZero(minWidth); + ArgumentOutOfRangeException.ThrowIfZero(width); ArgumentOutOfRangeException.ThrowIfZero(minHeight); var bounds = new Rect { - Width = minWidth, + Width = width, Height = minHeight }; if (rectangles.Length == 0) @@ -35,51 +29,25 @@ public static class RectPacker return bounds; } - Array.Sort(rectangles, (a, b) => a.Height.CompareTo(b.Height)); + Array.Sort(rectangles, (a, b) => b.Height.CompareTo(a.Height)); // Naively try to pack into the row, wrapping when we reach the end // and expanding the bounds when needed - ushort rowStartX = 0; - ushort rowMaxH = 0; + ushort rowMaxH = rectangles[0].Height; ushort x = 0; ushort y = 0; - var expandDir = ExpandDir.Y; var rectCount = rectangles.Length; for (var i = 0; i < rectCount; i++) { var rect = rectangles[i]; - if (rect.Width == 0 || rect.Height == 0) - { - throw new ArgumentOutOfRangeException(nameof(rectangles), rectangles, $"{nameof(rectangles)} contains rect with width or height 0."); - } - - // uh oh we've hit the edge, wrap to next row if (x + rect.Width > bounds.Width) { - // we just loop to next row - x = rowStartX; + x = 0; y += rowMaxH; - rowMaxH = 0; - } - - // uh oh we've hit the edge, expand - if (y + rect.Height > bounds.Height) - { - if (expandDir == ExpandDir.X) + rowMaxH = rect.Height; + if (y + rowMaxH > bounds.Height) { - // We can expand to the right - x = bounds.Width; - rowStartX = bounds.Width; - y = 0; - rowMaxH = 0; - bounds.Width *= 2; - expandDir = ExpandDir.Y; - } - else if (expandDir == ExpandDir.Y) - { - rowStartX = 0; bounds.Height *= 2; - expandDir = ExpandDir.X; } } @@ -88,32 +56,9 @@ public static class RectPacker rectangles[i] = rect; x += rect.Width; - if (rect.Height > rowMaxH) - { - rowMaxH = rect.Height; - } } - return bounds; - } - - public static Rect TightBounds(Rect[] rectangles) - { - var bounds = new Rect(); - foreach (var rect in rectangles) - { - var w = rect.X + rect.Width; - if (w > bounds.Width) - { - bounds.Width = (ushort)w; - } - - var h = rect.Y + rect.Height; - if (h > bounds.Height) - { - bounds.Height = (ushort)h; - } - } + bounds.Height = (ushort)(y + rowMaxH); return bounds; } }