Compare commits

..

4 Commits

3 changed files with 74 additions and 10 deletions

View File

@ -1,8 +1,8 @@
<Project Sdk="Godot.NET.Sdk/4.3.0"> <Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework> <!-- <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework> <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework> -->
<EnableDynamicLoading>true</EnableDynamicLoading> <EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>ThiefMissionViewer</RootNamespace> <RootNamespace>ThiefMissionViewer</RootNamespace>
</PropertyGroup> </PropertyGroup>

View File

@ -3,7 +3,6 @@ using KeepersCompound.LGS;
using KeepersCompound.LGS.Database; using KeepersCompound.LGS.Database;
using KeepersCompound.LGS.Database.Chunks; using KeepersCompound.LGS.Database.Chunks;
using KeepersCompound.TMV.UI; using KeepersCompound.TMV.UI;
using RectpackSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -261,7 +260,7 @@ public partial class Mission : Node3D
var lmHdr = worldRep.DataHeader.LightmapFormat == 2; var lmHdr = worldRep.DataHeader.LightmapFormat == 2;
GD.Print($"HDR Lightmap: {lmHdr}"); GD.Print($"HDR Lightmap: {lmHdr}");
var packingRects = new List<PackingRectangle>(); var packingRects = new List<RectPacker.Rect>();
var surfaceDataMap = new Dictionary<int, MeshSurfaceData>(); var surfaceDataMap = new Dictionary<int, MeshSurfaceData>();
var rectDataMap = new Dictionary<int, LightmapRectData>(); var rectDataMap = new Dictionary<int, LightmapRectData>();
@ -288,7 +287,12 @@ public partial class Mission : Node3D
rectDataMap.Add(packingRects.Count, lightmapRectData); rectDataMap.Add(packingRects.Count, lightmapRectData);
var light = cell.LightList[polyIdx]; var light = cell.LightList[polyIdx];
var rect = new PackingRectangle(0, 0, light.Width, light.Height, packingRects.Count); var rect = new RectPacker.Rect
{
Width = light.Width,
Height = light.Height,
Id = packingRects.Count,
};
packingRects.Add(rect); packingRects.Add(rect);
cellIdxOffset += cell.Polys[polyIdx].VertexCount; cellIdxOffset += cell.Polys[polyIdx].VertexCount;
@ -355,16 +359,15 @@ public partial class Mission : Node3D
private static Texture2DArray BuildLightmapTexture( private static Texture2DArray BuildLightmapTexture(
WorldRep.Cell[] cells, WorldRep.Cell[] cells,
PackingRectangle[] packingRects, RectPacker.Rect[] packingRects,
Dictionary<int, LightmapRectData> rectDataMap, Dictionary<int, LightmapRectData> rectDataMap,
Dictionary<int, MeshSurfaceData> surfaceDataMap) Dictionary<int, MeshSurfaceData> surfaceDataMap)
{ {
var bounds = Timing.TimeStage("RectPack", () => var bounds = Timing.TimeStage("RectPack", () =>
{ {
RectanglePacker.Pack(packingRects, out var bounds, PackingHints.FindBest, 0); return RectPacker.Pack(packingRects);
return bounds;
}); });
GD.Print($"Creating lightmap with bounds: ({bounds.Width}, {bounds.Height})"); GD.Print($"Packed {packingRects.Length} rects in ({bounds.Width}, {bounds.Height})");
var lightmapFormat = Image.Format.Rgba8; var lightmapFormat = Image.Format.Rgba8;
var lmLayerCount = 33; // TODO: Use LightmapLayers var lmLayerCount = 33; // TODO: Use LightmapLayers
@ -413,6 +416,7 @@ public partial class Mission : Node3D
return new Vector2(u, v); return new Vector2(u, v);
}); });
} }
lmImages[0].SavePng("user://lm.png");
var lightmapTexture = new Texture2DArray(); var lightmapTexture = new Texture2DArray();
lightmapTexture.CreateFromImages(lmImages); lightmapTexture.CreateFromImages(lmImages);

View File

@ -0,0 +1,60 @@
using System;
namespace KeepersCompound.TMV;
public static class RectPacker
{
public struct Rect
{
public int Id;
public ushort X;
public ushort Y;
public ushort Width;
public ushort Height;
}
public static Rect Pack(Rect[] rectangles, ushort width = 2048, ushort minHeight = 512)
{
ArgumentNullException.ThrowIfNull(rectangles);
ArgumentOutOfRangeException.ThrowIfZero(width);
ArgumentOutOfRangeException.ThrowIfZero(minHeight);
var bounds = new Rect
{
Width = width,
Height = minHeight
};
if (rectangles.Length == 0)
{
return bounds;
}
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 rowMaxH = rectangles[0].Height;
ushort x = 0;
ushort y = 0;
var rectCount = rectangles.Length;
for (var i = 0; i < rectCount; i++)
{
var rect = rectangles[i];
if (x + rect.Width > width)
{
x = 0;
y += rowMaxH;
rowMaxH = rect.Height;
}
rect.X = x;
rect.Y = y;
rectangles[i] = rect;
x += rect.Width;
}
bounds.Height = (ushort)(y + rowMaxH);
return bounds;
}
}