From 4cf8a0ccd4bcc50174066b4a63b794f7fafc8bfa Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:05:06 +0100 Subject: [PATCH 01/15] Move colour classes, simplify ToString --- TRLevelControl/Model/{Base => Common}/TRColour.cs | 15 +++------------ .../Model/{Base => Common}/TRColour4.cs | 15 ++------------- 2 files changed, 5 insertions(+), 25 deletions(-) rename TRLevelControl/Model/{Base => Common}/TRColour.cs (62%) rename TRLevelControl/Model/{Base => Common}/TRColour4.cs (67%) diff --git a/TRLevelControl/Model/Base/TRColour.cs b/TRLevelControl/Model/Common/TRColour.cs similarity index 62% rename from TRLevelControl/Model/Base/TRColour.cs rename to TRLevelControl/Model/Common/TRColour.cs index 322f1e1b5..8039d0527 100644 --- a/TRLevelControl/Model/Base/TRColour.cs +++ b/TRLevelControl/Model/Common/TRColour.cs @@ -1,25 +1,16 @@ -using System.Text; -using TRLevelControl.Serialization; +using TRLevelControl.Serialization; namespace TRLevelControl.Model; public class TRColour : ISerializableCompact { public byte Red { get; set; } - - public byte Green { get; set; } - + public byte Green { get; set; } public byte Blue { get; set; } public override string ToString() { - StringBuilder sb = new(base.ToString()); - - sb.Append(" Red: " + Red); - sb.Append(" Green: " + Green); - sb.Append(" Blue: " + Blue); - - return sb.ToString(); + return $"{base.ToString()} R: {Red} G: {Green} B: {Blue}"; } public byte[] Serialize() diff --git a/TRLevelControl/Model/Base/TRColour4.cs b/TRLevelControl/Model/Common/TRColour4.cs similarity index 67% rename from TRLevelControl/Model/Base/TRColour4.cs rename to TRLevelControl/Model/Common/TRColour4.cs index 1df532a4a..e730909ac 100644 --- a/TRLevelControl/Model/Base/TRColour4.cs +++ b/TRLevelControl/Model/Common/TRColour4.cs @@ -1,28 +1,17 @@ -using System.Text; -using TRLevelControl.Serialization; +using TRLevelControl.Serialization; namespace TRLevelControl.Model; public class TRColour4 : ISerializableCompact { public byte Red { get; set; } - public byte Green { get; set; } - public byte Blue { get; set; } - public byte Unused { get; set; } public override string ToString() { - StringBuilder sb = new(base.ToString()); - - sb.Append(" Red: " + Red); - sb.Append(" Green: " + Green); - sb.Append(" Blue: " + Blue); - sb.Append(" Unused: " + Unused); - - return sb.ToString(); + return $"{base.ToString()} R: {Red} G: {Green} B: {Blue} Unused: {Unused}"; } public byte[] Serialize() From 1b369ac558ed3e8d279e824fc6385877a9450052 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:19:31 +0100 Subject: [PATCH 02/15] Common colour conversions --- .../Types/Textures/EMImportTextureFunction.cs | 2 +- TRLevelControl/Helpers/TRConsts.cs | 2 ++ .../Helpers/ColourExtensions.cs | 19 +++++++++++++++++++ .../Helpers/TR1PaletteManager.cs | 9 ++------- TRTexture16Importer/TextureUtilities.cs | 7 ++++--- .../Mapping/AbstractTextureMapping.cs | 10 ++-------- TextureExport/Types/HtmlExporter.cs | 18 ++++++------------ 7 files changed, 36 insertions(+), 31 deletions(-) diff --git a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs index ccf098739..52b55bf94 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs @@ -15,7 +15,7 @@ public class EMImportTextureFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { using BitmapGraphics bg = new(new Bitmap(Bitmap)); - List palette = level.Palette.Select(c => Color.FromArgb(c.Red * 4, c.Green * 4, c.Blue * 4)).ToList(); + List palette = level.Palette.Select(c => c.ToColor()).ToList(); Rectangle size = new(0, 0, bg.Bitmap.Width, bg.Bitmap.Height); bg.Scan(size, (c, x, y) => { diff --git a/TRLevelControl/Helpers/TRConsts.cs b/TRLevelControl/Helpers/TRConsts.cs index 18f6813c3..b7666a042 100644 --- a/TRLevelControl/Helpers/TRConsts.cs +++ b/TRLevelControl/Helpers/TRConsts.cs @@ -5,4 +5,6 @@ public static class TRConsts public const int TPageWidth = 256; public const int TPageHeight = 256; public const int TPageSize = TPageWidth * TPageHeight; + + public const int Palette8Multiplier = 4; } diff --git a/TRTexture16Importer/Helpers/ColourExtensions.cs b/TRTexture16Importer/Helpers/ColourExtensions.cs index cb7c98f9a..97b09ebbf 100644 --- a/TRTexture16Importer/Helpers/ColourExtensions.cs +++ b/TRTexture16Importer/Helpers/ColourExtensions.cs @@ -1,4 +1,6 @@ using System.Drawing; +using TRLevelControl; +using TRLevelControl.Model; namespace TRTexture16Importer.Helpers; @@ -146,4 +148,21 @@ public static ushort ToRGB555(this Color c) return (ushort)(a | r | g | b); } + + public static Color ToColor(this TRColour c) + { + int multiplier = TRConsts.Palette8Multiplier; + return Color.FromArgb(c.Red * multiplier, c.Green * multiplier, c.Blue * multiplier); + } + + public static TRColour ToTRColour(this Color c) + { + int divisor = TRConsts.Palette8Multiplier; + return new() + { + Red = (byte)(c.R / divisor), + Green = (byte)(c.G / divisor), + Blue = (byte)(c.B / divisor) + }; + } } diff --git a/TRTexture16Importer/Helpers/TR1PaletteManager.cs b/TRTexture16Importer/Helpers/TR1PaletteManager.cs index ced5369c0..e0646dfe1 100644 --- a/TRTexture16Importer/Helpers/TR1PaletteManager.cs +++ b/TRTexture16Importer/Helpers/TR1PaletteManager.cs @@ -135,12 +135,7 @@ public void WritePalletteToLevel() for (int i = 0; i < Level.Palette.Length; i++) { Color c = _palette[i]; - Level.Palette[i] = new TRColour - { - Red = (byte)(c.R / 4), - Green = (byte)(c.G / 4), - Blue = (byte)(c.B / 4) - }; + Level.Palette[i] = c.ToTRColour(); } } @@ -194,7 +189,7 @@ public void MergePredefinedColours() public int GetOrAddPaletteIndex(TRColour c) { - return GetOrAddPaletteIndex(Color.FromArgb(c.Red * 4, c.Green * 4, c.Blue * 4)); + return GetOrAddPaletteIndex(c.ToColor()); } public int GetOrAddPaletteIndex(Color c) diff --git a/TRTexture16Importer/TextureUtilities.cs b/TRTexture16Importer/TextureUtilities.cs index 64d6fa116..9f239b0c9 100644 --- a/TRTexture16Importer/TextureUtilities.cs +++ b/TRTexture16Importer/TextureUtilities.cs @@ -2,6 +2,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; +using TRLevelControl; using TRLevelControl.Model; using TRTexture16Importer.Helpers; @@ -45,9 +46,9 @@ public static Bitmap ToBitmap(this TRTexImage8 tex, TRColour[] palette) foreach (byte colourIndex in tex.Pixels) { TRColour c = palette[colourIndex]; - pixelCollection.Add((byte)(4 * c.Blue)); - pixelCollection.Add((byte)(4 * c.Green)); - pixelCollection.Add((byte)(4 * c.Red)); + pixelCollection.Add((byte)(TRConsts.Palette8Multiplier * c.Blue)); + pixelCollection.Add((byte)(TRConsts.Palette8Multiplier * c.Green)); + pixelCollection.Add((byte)(TRConsts.Palette8Multiplier * c.Red)); pixelCollection.Add((byte)(colourIndex == 0 ? 0 : 0xFF)); // The first entry in the palette is used for transparency } diff --git a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs index 8f2ce0185..e4e515deb 100644 --- a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs @@ -224,8 +224,7 @@ private void RecolourDynamicTargets(List meshes, HSBOperation operation) continue; } TRColour col = palette[colourIndex]; - Color c = Color.FromArgb(col.Red * 4, col.Green * 4, col.Blue * 4); - HSB hsb = c.ToHSB(); + HSB hsb = col.ToColor().ToHSB(); hsb.H = operation.ModifyHue(hsb.H); hsb.S = operation.ModifySaturation(hsb.S); hsb.B = operation.ModifyBrightness(hsb.B); @@ -379,12 +378,7 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D TRColour[] palette = GetPalette8(); foreach (Color targetColour in source.EntityColourMap8[entity].Keys) { - TRColour col = new() - { - Red = (byte)(targetColour.R / 4), - Green = (byte)(targetColour.G / 4), - Blue = (byte)(targetColour.B / 4) - }; + TRColour col = targetColour.ToTRColour(); int matchedIndex = Array.FindIndex(palette, c => c.Red == col.Red && c.Green == col.Green && c.Blue == col.Blue); if (matchedIndex == -1) { diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index add5f6c8a..8c0e14639 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -6,6 +6,7 @@ using TRLevelControl.Model.Enums; using TRModelTransporter.Model.Textures; using TRModelTransporter.Packing; +using TRTexture16Importer.Helpers; namespace TextureExport.Types; @@ -25,12 +26,10 @@ public static void Export(TR1Level level, string lvlName) BuildSkyBox(skyboxInfo, skyColours); StringBuilder palette = new(); - ISet colors = new HashSet(); - foreach (TRColour c in level.Palette) - { - colors.Add(Color.FromArgb(c.Red, c.Green, c.Blue)); - } - palette.Append(colors.Count).Append(" unique colours"); + IEnumerable colors = level.Palette + .Select(c => c.ToColor()) + .Distinct(); + palette.Append(colors.Count()).Append(" unique colours"); Write("TR1", lvlName, tiles, levelSel, skyboxInfo, palette); } @@ -97,12 +96,7 @@ private static void BuildTiles(StringBuilder html, IReadOnlyList t Color c = segment.Bitmap.GetPixel(x, y); if (c.A != 0) { - TRColour col = new() - { - Red = (byte)(c.R / 4), - Green = (byte)(c.G / 4), - Blue = (byte)(c.B / 4) - }; + TRColour col = c.ToTRColour(); int index = Array.FindIndex(palette, p => p.Red == col.Red && p.Green == col.Green && p.Blue == col.Blue); if (index != -1) { From e2e4f01eb1a30283e066801209cc74cb5c8c42d2 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:31:36 +0100 Subject: [PATCH 03/15] Create colour IO utilities --- TRLevelControl/IO/TRLevelReader.cs | 31 ++++++++++++++++++++++++++++++ TRLevelControl/IO/TRLevelWriter.cs | 26 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/TRLevelControl/IO/TRLevelReader.cs b/TRLevelControl/IO/TRLevelReader.cs index f5862165e..145bc2b67 100644 --- a/TRLevelControl/IO/TRLevelReader.cs +++ b/TRLevelControl/IO/TRLevelReader.cs @@ -89,4 +89,35 @@ public List ReadImage32s(long numImages) } return images; } + + public List ReadColours(long numColours) + { + List colours = new((int)numColours); + for (long i = 0; i < numColours; i++) + { + colours.Add(new() + { + Red = ReadByte(), + Green = ReadByte(), + Blue = ReadByte() + }); + } + return colours; + } + + public List ReadColour4s(long numColours) + { + List colours = new((int)numColours); + for (long i = 0; i < numColours; i++) + { + colours.Add(new() + { + Red = ReadByte(), + Green = ReadByte(), + Blue = ReadByte(), + Unused = ReadByte() + }); + } + return colours; + } } diff --git a/TRLevelControl/IO/TRLevelWriter.cs b/TRLevelControl/IO/TRLevelWriter.cs index 7c36c327b..6c2c77c36 100644 --- a/TRLevelControl/IO/TRLevelWriter.cs +++ b/TRLevelControl/IO/TRLevelWriter.cs @@ -76,4 +76,30 @@ public void Write(IEnumerable images) Write(image.Pixels); } } + + public void Write(IEnumerable colours) + { + foreach (TRColour colour in colours) + { + Write(colour); + } + } + + public void Write(TRColour colour) + { + Write(colour.Red); + Write(colour.Green); + Write(colour.Blue); + } + + public void Write(IEnumerable colours) + { + foreach (TRColour4 colour in colours) + { + Write(colour.Red); + Write(colour.Green); + Write(colour.Blue); + Write(colour.Unused); + } + } } From 8d3d9846dd6b0ab4097847791dbed5f3419611ee Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:50:40 +0100 Subject: [PATCH 04/15] Convert TR1 palette array to list --- TRLevelControl/Control/TR1LevelControl.cs | 33 ++----------------- TRLevelControl/Helpers/TRConsts.cs | 1 + TRLevelControl/Model/Base/TR1Level.cs | 6 +--- .../DataControls/TR/TRPaletteControl.cs | 2 +- .../Handlers/ColourTransportHandler.cs | 2 +- .../Helpers/TR1PaletteManager.cs | 11 +++---- TRTexture16Importer/TextureUtilities.cs | 2 +- .../Textures/Mapping/TR1TextureMapping.cs | 2 +- TextureExport/Types/HtmlExporter.cs | 4 +-- TextureExport/Types/PngExporter.cs | 2 +- 10 files changed, 16 insertions(+), 49 deletions(-) diff --git a/TRLevelControl/Control/TR1LevelControl.cs b/TRLevelControl/Control/TR1LevelControl.cs index d1b751b5b..82fdb7b2e 100644 --- a/TRLevelControl/Control/TR1LevelControl.cs +++ b/TRLevelControl/Control/TR1LevelControl.cs @@ -6,8 +6,6 @@ namespace TRLevelControl; public class TR1LevelControl : TRLevelControlBase { - private const uint MAX_PALETTE_SIZE = 256; - protected override TR1Level CreateLevel(TRFileVersion version) { TR1Level level = new() @@ -294,7 +292,7 @@ protected override void Read(TRLevelReader reader) _level.LightMap[i] = reader.ReadByte(); } - _level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3)); + _level.Palette = reader.ReadColours(TRConsts.PaletteSize); //Cinematic Frames _level.NumCinematicFrames = reader.ReadUInt16(); @@ -410,8 +408,9 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumEntities); foreach (TREntity entity in _level.Entities) { writer.Write(entity.Serialize()); } + Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize); writer.Write(_level.LightMap); - foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); } + writer.Write(_level.Palette); writer.Write(_level.NumCinematicFrames); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } @@ -428,32 +427,6 @@ protected override void Write(TRLevelWriter writer) foreach (uint index in _level.SampleIndices) { writer.Write(index); } } - private static TRColour[] PopulateColourPalette(byte[] palette) - { - TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE]; - - int ci = 0; - - for (int i = 0; i < MAX_PALETTE_SIZE; i++) - { - TRColour col = new() - { - Red = palette[ci] - }; - ci++; - - col.Green = palette[ci]; - ci++; - - col.Blue = palette[ci]; - ci++; - - colourPalette[i] = col; - } - - return colourPalette; - } - private static TRRoomData ConvertToRoomData(TRRoom room) { int RoomDataOffset = 0; diff --git a/TRLevelControl/Helpers/TRConsts.cs b/TRLevelControl/Helpers/TRConsts.cs index b7666a042..a9684f9cd 100644 --- a/TRLevelControl/Helpers/TRConsts.cs +++ b/TRLevelControl/Helpers/TRConsts.cs @@ -6,5 +6,6 @@ public static class TRConsts public const int TPageHeight = 256; public const int TPageSize = TPageWidth * TPageHeight; + public const int PaletteSize = 256; public const int Palette8Multiplier = 4; } diff --git a/TRLevelControl/Model/Base/TR1Level.cs b/TRLevelControl/Model/Base/TR1Level.cs index 88041c690..5395c3cbc 100644 --- a/TRLevelControl/Model/Base/TR1Level.cs +++ b/TRLevelControl/Model/Base/TR1Level.cs @@ -230,11 +230,7 @@ public class TR1Level : TRLevelBase /// (32 * 256 entries) of 1 byte = 8192 bytes /// public byte[] LightMap { get; set; } - - /// - /// 256 entries * 3 components = 768 Bytes - /// - public TRColour[] Palette { get; set; } + public List Palette { get; set; } /// /// 2 bytes diff --git a/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs index abdca8790..4ba1e0311 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs @@ -11,7 +11,7 @@ public void Draw() if (ImGui.TreeNodeEx("Palette Data", ImGuiTreeNodeFlags.OpenOnArrow)) { ImGui.Text("Light map Count: " + IOManager.CurrentLevelAsTR1?.LightMap.Length); - ImGui.Text("Palette Count: " + IOManager.CurrentLevelAsTR1?.Palette.Length); + ImGui.Text("Palette Count: " + IOManager.CurrentLevelAsTR1?.Palette.Count); ImGui.TreePop(); } } diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index 9c488b04d..894f34f6a 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -9,7 +9,7 @@ public class ColourTransportHandler { public static void Export(TR1Level level, TR1ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette); + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette.ToArray()); // Temporary until TR2/3 converted } public static void Export(TR2Level level, TR2ModelDefinition definition) diff --git a/TRTexture16Importer/Helpers/TR1PaletteManager.cs b/TRTexture16Importer/Helpers/TR1PaletteManager.cs index e0646dfe1..8ea390342 100644 --- a/TRTexture16Importer/Helpers/TR1PaletteManager.cs +++ b/TRTexture16Importer/Helpers/TR1PaletteManager.cs @@ -1,4 +1,5 @@ using System.Drawing; +using TRLevelControl; using TRLevelControl.Helpers; using TRLevelControl.Model; using TRLevelControl.Model.Enums; @@ -7,7 +8,7 @@ namespace TRTexture16Importer.Helpers; public class TR1PaletteManager : IDisposable { - private const int _paletteLimit = byte.MaxValue; + private const int _paletteLimit = TRConsts.PaletteSize - 1; private const double _weightR = 1; private const double _weightG = 1; private const double _weightB = 1; @@ -131,12 +132,8 @@ public void WritePalletteToLevel() _palette.Add(Color.Black); } - Level.Palette = new TRColour[_paletteLimit + 1]; - for (int i = 0; i < Level.Palette.Length; i++) - { - Color c = _palette[i]; - Level.Palette[i] = c.ToTRColour(); - } + Level.Palette.Clear(); + Level.Palette.AddRange(_palette.Select(c => c.ToTRColour())); } public int AddPredefinedColour(Color c) diff --git a/TRTexture16Importer/TextureUtilities.cs b/TRTexture16Importer/TextureUtilities.cs index 9f239b0c9..232fd3e1c 100644 --- a/TRTexture16Importer/TextureUtilities.cs +++ b/TRTexture16Importer/TextureUtilities.cs @@ -37,7 +37,7 @@ public static ushort[] ImportFromBitmap(Bitmap texture) return convertedPixels; } - public static Bitmap ToBitmap(this TRTexImage8 tex, TRColour[] palette) + public static Bitmap ToBitmap(this TRTexImage8 tex, List palette) { Bitmap bmp = new(_tileSize, _tileSize, PixelFormat.Format32bppArgb); BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); diff --git a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs index f38609382..09711c8af 100644 --- a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs @@ -29,7 +29,7 @@ public static TR1TextureMapping Get(TR1Level level, string mappingFilePrefix, TR protected override TRColour[] GetPalette8() { - return _level.Palette; + return _level.Palette.ToArray(); // Temporary until TR2/3 converted } protected override TRColour4[] GetPalette16() diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index 8c0e14639..23c34b054 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -66,7 +66,7 @@ public static void Export(TR3Level level, string lvlName) Write("TR3", lvlName, tiles, levelSel, skyboxInfo); } - private static void BuildTiles(StringBuilder html, IReadOnlyList tiles, TRColour[] palette = null) + private static void BuildTiles(StringBuilder html, IReadOnlyList tiles, List palette = null) { foreach (TexturedTile tile in tiles) { @@ -97,7 +97,7 @@ private static void BuildTiles(StringBuilder html, IReadOnlyList t if (c.A != 0) { TRColour col = c.ToTRColour(); - int index = Array.FindIndex(palette, p => p.Red == col.Red && p.Green == col.Green && p.Blue == col.Blue); + int index = palette.FindIndex(p => p.Red == col.Red && p.Green == col.Green && p.Blue == col.Blue); if (index != -1) { paletteIndices.Add(index); diff --git a/TextureExport/Types/PngExporter.cs b/TextureExport/Types/PngExporter.cs index 594d95d6a..2bde72fb2 100644 --- a/TextureExport/Types/PngExporter.cs +++ b/TextureExport/Types/PngExporter.cs @@ -21,7 +21,7 @@ public static void Export(TR3Level level, string lvl) Export(@"TR3\PNG", lvl, level.Images16); } - public static void Export(string topDir, string lvl, IEnumerable images, TRColour[] palette) + public static void Export(string topDir, string lvl, IEnumerable images, List palette) { string dir = MakeDir(topDir, lvl); int index = 0; From 41ab5871f9217b9423ca4af159f2ca3003878b5d Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:56:23 +0100 Subject: [PATCH 05/15] Convert TR2 palette arrays to lists --- TRLevelControl/Control/TR2LevelControl.cs | 70 ++----------------- TRLevelControl/Model/TR2/TR2Level.cs | 11 +-- .../Handlers/ColourTransportHandler.cs | 2 +- TRTexture16Importer/PaletteUtilities.cs | 2 +- .../Textures/Mapping/TR2TextureMapping.cs | 4 +- TextureExport/Types/HtmlExporter.cs | 2 +- 6 files changed, 14 insertions(+), 77 deletions(-) diff --git a/TRLevelControl/Control/TR2LevelControl.cs b/TRLevelControl/Control/TR2LevelControl.cs index f9532efe8..bc59b8305 100644 --- a/TRLevelControl/Control/TR2LevelControl.cs +++ b/TRLevelControl/Control/TR2LevelControl.cs @@ -6,8 +6,6 @@ namespace TRLevelControl; public class TR2LevelControl : TRLevelControlBase { - private const uint MAX_PALETTE_SIZE = 256; - protected override TR2Level CreateLevel(TRFileVersion version) { TR2Level level = new() @@ -25,10 +23,9 @@ protected override TR2Level CreateLevel(TRFileVersion version) protected override void Read(TRLevelReader reader) { - //Colour palettes and textures - _level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3)); - - _level.Palette16 = PopulateColourPalette16(reader.ReadBytes((int)MAX_PALETTE_SIZE * 4)); + // Colour palettes and textures + _level.Palette = reader.ReadColours(TRConsts.PaletteSize); + _level.Palette16 = reader.ReadColour4s(TRConsts.PaletteSize); uint numImages = reader.ReadUInt32(); _level.Images8 = reader.ReadImage8s(numImages); @@ -352,8 +349,10 @@ protected override void Read(TRLevelReader reader) protected override void Write(TRLevelWriter writer) { - foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); } - foreach (TRColour4 col in _level.Palette16) { writer.Write(col.Serialize()); } + Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize); + Debug.Assert(_level.Palette16.Count == TRConsts.PaletteSize); + writer.Write(_level.Palette); + writer.Write(_level.Palette16); Debug.Assert(_level.Images8.Count == _level.Images16.Count); writer.Write((uint)_level.Images8.Count); @@ -430,61 +429,6 @@ protected override void Write(TRLevelWriter writer) foreach (uint index in _level.SampleIndices) { writer.Write(index); } } - private static TRColour[] PopulateColourPalette(byte[] palette) - { - TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE]; - - int ci = 0; - - for (int i = 0; i < MAX_PALETTE_SIZE; i++) - { - TRColour col = new() - { - Red = palette[ci] - }; - ci++; - - col.Green = palette[ci]; - ci++; - - col.Blue = palette[ci]; - ci++; - - colourPalette[i] = col; - } - - return colourPalette; - } - - private static TRColour4[] PopulateColourPalette16(byte[] palette) - { - TRColour4[] colourPalette = new TRColour4[MAX_PALETTE_SIZE]; - - int ci = 0; - - for (int i = 0; i < MAX_PALETTE_SIZE; i++) - { - TRColour4 col = new() - { - Red = palette[ci] - }; - ci++; - - col.Green = palette[ci]; - ci++; - - col.Blue = palette[ci]; - ci++; - - col.Unused = palette[ci]; - ci++; - - colourPalette[i] = col; - } - - return colourPalette; - } - private static TR2RoomData ConvertToRoomData(TR2Room room) { int RoomDataOffset = 0; diff --git a/TRLevelControl/Model/TR2/TR2Level.cs b/TRLevelControl/Model/TR2/TR2Level.cs index 156e9b0b3..8f49846a2 100644 --- a/TRLevelControl/Model/TR2/TR2Level.cs +++ b/TRLevelControl/Model/TR2/TR2Level.cs @@ -2,15 +2,8 @@ public class TR2Level : TRLevelBase { - /// - /// 256 entries * 3 components = 768 Bytes - /// - public TRColour[] Palette { get; set; } - - /// - /// 256 entries * 4 components = 1024 bytes - /// - public TRColour4[] Palette16 { get; set; } + public List Palette { get; set; } + public List Palette16 { get; set; } public List Images8 { get; set; } public List Images16 { get; set; } diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index 894f34f6a..8eb9aa508 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -14,7 +14,7 @@ public static void Export(TR1Level level, TR1ModelDefinition definition) public static void Export(TR2Level level, TR2ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16); + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16.ToArray()); // Temporary until TR3 converted } public static void Export(TR3Level level, TR3ModelDefinition definition) diff --git a/TRTexture16Importer/PaletteUtilities.cs b/TRTexture16Importer/PaletteUtilities.cs index e41b0f6ee..df4389edd 100644 --- a/TRTexture16Importer/PaletteUtilities.cs +++ b/TRTexture16Importer/PaletteUtilities.cs @@ -27,7 +27,7 @@ private static TRColour4 FromRGB(Color c) public static int Import(TR2Level lvl, TRColour4 c) { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); + int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16.ToArray()); // Temporary until TR3 converted if (nextAvailableIndex != -1) { lvl.Palette16[nextAvailableIndex] = c; diff --git a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs index c3f6d6770..a0e072871 100644 --- a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs @@ -25,12 +25,12 @@ public static TR2TextureMapping Get(TR2Level level, string mappingFilePrefix, TR protected override TRColour[] GetPalette8() { - return _level.Palette; + return _level.Palette.ToArray(); // Temporary until TR3 converted } protected override TRColour4[] GetPalette16() { - return _level.Palette16; + return _level.Palette16.ToArray(); // Temporary until TR3 converted } protected override int ImportColour(Color colour) diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index 23c34b054..564cd6fb5 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -44,7 +44,7 @@ public static void Export(TR2Level level, string lvlName) BuildLevelSelect(levelSel, lvlName, TR2LevelNames.AsOrderedList); StringBuilder skyboxInfo = new(); - Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR2Entities.Skybox_H), level.Palette16); + Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR2Entities.Skybox_H), level.Palette16.ToArray()); // Temporary until TR3 converted BuildSkyBox(skyboxInfo, skyColours); Write("TR2", lvlName, tiles, levelSel, skyboxInfo); From a0f93b813c2b8d4c012018dd00fcc7cf5f83af86 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:59:41 +0100 Subject: [PATCH 06/15] Convert TR3 palette arrays to lists --- TRLevelControl/Control/TR3LevelControl.cs | 70 ++----------------- TRLevelControl/Model/TR3/TR3Level.cs | 11 +-- .../Handlers/ColourTransportHandler.cs | 2 +- TRTexture16Importer/PaletteUtilities.cs | 2 +- .../Textures/Mapping/TR3TextureMapping.cs | 4 +- TextureExport/Types/HtmlExporter.cs | 2 +- 6 files changed, 14 insertions(+), 77 deletions(-) diff --git a/TRLevelControl/Control/TR3LevelControl.cs b/TRLevelControl/Control/TR3LevelControl.cs index bd4b5728b..34379d5e0 100644 --- a/TRLevelControl/Control/TR3LevelControl.cs +++ b/TRLevelControl/Control/TR3LevelControl.cs @@ -6,8 +6,6 @@ namespace TRLevelControl; public class TR3LevelControl : TRLevelControlBase { - private const uint MAX_PALETTE_SIZE = 256; - protected override TR3Level CreateLevel(TRFileVersion version) { TR3Level level = new() @@ -25,10 +23,9 @@ protected override TR3Level CreateLevel(TRFileVersion version) protected override void Read(TRLevelReader reader) { - //Colour palettes and textures - _level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3)); - - _level.Palette16 = PopulateColourPalette16(reader.ReadBytes((int)MAX_PALETTE_SIZE * 4)); + // Colour palettes and textures + _level.Palette = reader.ReadColours(TRConsts.PaletteSize); + _level.Palette16 = reader.ReadColour4s(TRConsts.PaletteSize); uint numImages = reader.ReadUInt32(); _level.Images8 = reader.ReadImage8s(numImages); @@ -354,8 +351,10 @@ protected override void Read(TRLevelReader reader) protected override void Write(TRLevelWriter writer) { - foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); } - foreach (TRColour4 col in _level.Palette16) { writer.Write(col.Serialize()); } + Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize); + Debug.Assert(_level.Palette16.Count == TRConsts.PaletteSize); + writer.Write(_level.Palette); + writer.Write(_level.Palette16); Debug.Assert(_level.Images8.Count == _level.Images16.Count); writer.Write((uint)_level.Images8.Count); @@ -433,61 +432,6 @@ protected override void Write(TRLevelWriter writer) foreach (uint index in _level.SampleIndices) { writer.Write(index); } } - private static TRColour[] PopulateColourPalette(byte[] palette) - { - TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE]; - - int ci = 0; - - for (int i = 0; i < MAX_PALETTE_SIZE; i++) - { - TRColour col = new() - { - Red = palette[ci] - }; - ci++; - - col.Green = palette[ci]; - ci++; - - col.Blue = palette[ci]; - ci++; - - colourPalette[i] = col; - } - - return colourPalette; - } - - private static TRColour4[] PopulateColourPalette16(byte[] palette) - { - TRColour4[] colourPalette = new TRColour4[MAX_PALETTE_SIZE]; - - int ci = 0; - - for (int i = 0; i < MAX_PALETTE_SIZE; i++) - { - TRColour4 col = new() - { - Red = palette[ci] - }; - ci++; - - col.Green = palette[ci]; - ci++; - - col.Blue = palette[ci]; - ci++; - - col.Unused = palette[ci]; - ci++; - - colourPalette[i] = col; - } - - return colourPalette; - } - private static TR3RoomData ConvertToRoomData(TR3Room room) { int RoomDataOffset = 0; diff --git a/TRLevelControl/Model/TR3/TR3Level.cs b/TRLevelControl/Model/TR3/TR3Level.cs index 41d27b7a6..fcfba2c1b 100644 --- a/TRLevelControl/Model/TR3/TR3Level.cs +++ b/TRLevelControl/Model/TR3/TR3Level.cs @@ -2,15 +2,8 @@ public class TR3Level : TRLevelBase { - /// - /// 256 entries * 3 components = 768 Bytes - /// - public TRColour[] Palette { get; set; } - - /// - /// 256 entries * 4 components = 1024 bytes - /// - public TRColour4[] Palette16 { get; set; } + public List Palette { get; set; } + public List Palette16 { get; set; } public List Images8 { get; set; } public List Images16 { get; set; } diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index 8eb9aa508..13c744db3 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -19,7 +19,7 @@ public static void Export(TR2Level level, TR2ModelDefinition definition) public static void Export(TR3Level level, TR3ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16); + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16.ToArray()); } private static Dictionary GetUsedMeshColours(TRMesh[] meshes, TRColour[] colours) diff --git a/TRTexture16Importer/PaletteUtilities.cs b/TRTexture16Importer/PaletteUtilities.cs index df4389edd..1f971028c 100644 --- a/TRTexture16Importer/PaletteUtilities.cs +++ b/TRTexture16Importer/PaletteUtilities.cs @@ -39,7 +39,7 @@ public static int Import(TR2Level lvl, TRColour4 c) public static int Import(TR3Level lvl, TRColour4 c) { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); + int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16.ToArray()); if (nextAvailableIndex != -1) { lvl.Palette16[nextAvailableIndex] = c; diff --git a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs index 13419af5c..efeb10a2e 100644 --- a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs @@ -26,12 +26,12 @@ public static TR3TextureMapping Get(TR3Level level, string mappingFilePrefix, TR protected override TRColour[] GetPalette8() { - return _level.Palette; + return _level.Palette.ToArray(); } protected override TRColour4[] GetPalette16() { - return _level.Palette16; + return _level.Palette16.ToArray(); } protected override int ImportColour(Color colour) diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index 564cd6fb5..d5cafa11c 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -60,7 +60,7 @@ public static void Export(TR3Level level, string lvlName) BuildLevelSelect(levelSel, lvlName, TR3LevelNames.AsOrderedList); StringBuilder skyboxInfo = new(); - Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR3Entities.Skybox_H), level.Palette16); + Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR3Entities.Skybox_H), level.Palette16.ToArray()); BuildSkyBox(skyboxInfo, skyColours); Write("TR3", lvlName, tiles, levelSel, skyboxInfo); From 6d441af777869809ae0cf69867e9acf37c9db13c Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:05:02 +0100 Subject: [PATCH 07/15] Update array placeholders --- .../Handlers/ColourTransportHandler.cs | 10 +++++----- TRTexture16Importer/PaletteUtilities.cs | 8 ++++---- .../Textures/Mapping/AbstractTextureMapping.cs | 12 ++++++------ .../Textures/Mapping/TR1TextureMapping.cs | 6 +++--- .../Textures/Mapping/TR2TextureMapping.cs | 8 ++++---- .../Textures/Mapping/TR3TextureMapping.cs | 8 ++++---- TextureExport/Types/HtmlExporter.cs | 6 +++--- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index 13c744db3..db13767ae 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -9,20 +9,20 @@ public class ColourTransportHandler { public static void Export(TR1Level level, TR1ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette.ToArray()); // Temporary until TR2/3 converted + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette); } public static void Export(TR2Level level, TR2ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16.ToArray()); // Temporary until TR3 converted + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16); } public static void Export(TR3Level level, TR3ModelDefinition definition) { - definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16.ToArray()); + definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16); } - private static Dictionary GetUsedMeshColours(TRMesh[] meshes, TRColour[] colours) + private static Dictionary GetUsedMeshColours(TRMesh[] meshes, List colours) { ISet colourIndices = GetAllColourIndices(meshes, false); @@ -35,7 +35,7 @@ private static Dictionary GetUsedMeshColours(TRMesh[] meshes, TRC return usedColours; } - private static Dictionary GetUsedMeshColours(TRMesh[] meshes, TRColour4[] colours) + private static Dictionary GetUsedMeshColours(TRMesh[] meshes, List colours) { ISet colourIndices = GetAllColourIndices(meshes, true); diff --git a/TRTexture16Importer/PaletteUtilities.cs b/TRTexture16Importer/PaletteUtilities.cs index 1f971028c..6afbf8942 100644 --- a/TRTexture16Importer/PaletteUtilities.cs +++ b/TRTexture16Importer/PaletteUtilities.cs @@ -27,7 +27,7 @@ private static TRColour4 FromRGB(Color c) public static int Import(TR2Level lvl, TRColour4 c) { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16.ToArray()); // Temporary until TR3 converted + int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); if (nextAvailableIndex != -1) { lvl.Palette16[nextAvailableIndex] = c; @@ -39,7 +39,7 @@ public static int Import(TR2Level lvl, TRColour4 c) public static int Import(TR3Level lvl, TRColour4 c) { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16.ToArray()); + int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); if (nextAvailableIndex != -1) { lvl.Palette16[nextAvailableIndex] = c; @@ -53,7 +53,7 @@ public static int Import(TR3Level lvl, TRColour4 c) // so instead we will check for the next available palette slot and use that. Each level // seems to only have around 30-40 used colours. We still use the Unused field to track // what we are making use of during imports. - public static int GetNextPaletteIndex(TRMesh[] meshes, TRColour4[] colours) + public static int GetNextPaletteIndex(TRMesh[] meshes, List colours) { int highestUsedPalette = -1; foreach (TRMesh mesh in meshes) @@ -68,7 +68,7 @@ public static int GetNextPaletteIndex(TRMesh[] meshes, TRColour4[] colours) } } - while (highestUsedPalette < colours.Length - 1) + while (highestUsedPalette < colours.Count - 1) { TRColour4 palette = colours[++highestUsedPalette]; if (palette.Unused == 0) diff --git a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs index e4e515deb..28db291e5 100644 --- a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs @@ -31,8 +31,8 @@ protected AbstractTextureMapping(L level) } protected abstract TRMesh[] GetModelMeshes(E entity); - protected abstract TRColour[] GetPalette8(); - protected abstract TRColour4[] GetPalette16(); + protected abstract List GetPalette8(); + protected abstract List GetPalette16(); protected abstract int ImportColour(Color colour); protected abstract TRSpriteSequence[] GetSpriteSequences(); protected abstract TRSpriteTexture[] GetSpriteTextures(); @@ -201,7 +201,7 @@ private void RedrawDynamicTargets(Dictionary> targets, HSBO private void RecolourDynamicTargets(List meshes, HSBOperation operation) { - TRColour[] palette = GetPalette8(); + List palette = GetPalette8(); ISet colourIndices = new HashSet(); Dictionary remapIndices = new(); @@ -293,7 +293,7 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D if (source.EntityColourMap != null) { - TRColour4[] palette = GetPalette16(); + List palette = GetPalette16(); foreach (E entity in source.EntityColourMap.Keys) { @@ -375,11 +375,11 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D Dictionary remapIndices = new(); - TRColour[] palette = GetPalette8(); + List palette = GetPalette8(); foreach (Color targetColour in source.EntityColourMap8[entity].Keys) { TRColour col = targetColour.ToTRColour(); - int matchedIndex = Array.FindIndex(palette, c => c.Red == col.Red && c.Green == col.Green && c.Blue == col.Blue); + int matchedIndex = palette.FindIndex(c => c.Red == col.Red && c.Green == col.Green && c.Blue == col.Blue); if (matchedIndex == -1) { continue; diff --git a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs index 09711c8af..104559ffd 100644 --- a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs @@ -27,12 +27,12 @@ public static TR1TextureMapping Get(TR1Level level, string mappingFilePrefix, TR return mapping; } - protected override TRColour[] GetPalette8() + protected override List GetPalette8() { - return _level.Palette.ToArray(); // Temporary until TR2/3 converted + return _level.Palette; } - protected override TRColour4[] GetPalette16() + protected override List GetPalette16() { return null; } diff --git a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs index a0e072871..86e212c6b 100644 --- a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs @@ -23,14 +23,14 @@ public static TR2TextureMapping Get(TR2Level level, string mappingFilePrefix, TR return mapping; } - protected override TRColour[] GetPalette8() + protected override List GetPalette8() { - return _level.Palette.ToArray(); // Temporary until TR3 converted + return _level.Palette; } - protected override TRColour4[] GetPalette16() + protected override List GetPalette16() { - return _level.Palette16.ToArray(); // Temporary until TR3 converted + return _level.Palette16; } protected override int ImportColour(Color colour) diff --git a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs index efeb10a2e..978ea1964 100644 --- a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs @@ -24,14 +24,14 @@ public static TR3TextureMapping Get(TR3Level level, string mappingFilePrefix, TR return mapping; } - protected override TRColour[] GetPalette8() + protected override List GetPalette8() { - return _level.Palette.ToArray(); + return _level.Palette; } - protected override TRColour4[] GetPalette16() + protected override List GetPalette16() { - return _level.Palette16.ToArray(); + return _level.Palette16; } protected override int ImportColour(Color colour) diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index d5cafa11c..2d4ee07f0 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -44,7 +44,7 @@ public static void Export(TR2Level level, string lvlName) BuildLevelSelect(levelSel, lvlName, TR2LevelNames.AsOrderedList); StringBuilder skyboxInfo = new(); - Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR2Entities.Skybox_H), level.Palette16.ToArray()); // Temporary until TR3 converted + Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR2Entities.Skybox_H), level.Palette16); BuildSkyBox(skyboxInfo, skyColours); Write("TR2", lvlName, tiles, levelSel, skyboxInfo); @@ -60,7 +60,7 @@ public static void Export(TR3Level level, string lvlName) BuildLevelSelect(levelSel, lvlName, TR3LevelNames.AsOrderedList); StringBuilder skyboxInfo = new(); - Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR3Entities.Skybox_H), level.Palette16.ToArray()); + Dictionary skyColours = GetSkyBoxColours(TRMeshUtilities.GetModelMeshes(level, TR3Entities.Skybox_H), level.Palette16); BuildSkyBox(skyboxInfo, skyColours); Write("TR3", lvlName, tiles, levelSel, skyboxInfo); @@ -184,7 +184,7 @@ private static void BuildLevelSelect(StringBuilder html, string currentLevel, IE } } - private static Dictionary GetSkyBoxColours(TRMesh[] meshes, TRColour4[] palette16) + private static Dictionary GetSkyBoxColours(TRMesh[] meshes, List palette16) { Dictionary colours = new(); if (meshes != null) From 174e4b5cc9ed460578dc58479c2269738a8ac697 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:12:16 +0100 Subject: [PATCH 08/15] Remove superseded methods --- TRLevelControl/Model/Common/TRColour.cs | 19 ++----------------- TRLevelControl/Model/Common/TRColour4.cs | 20 ++------------------ TRLevelControl/Model/TR3/TR3RoomLight.cs | 4 ++-- TRLevelControl/Model/TR4/TR4RoomLight.cs | 4 ++-- 4 files changed, 8 insertions(+), 39 deletions(-) diff --git a/TRLevelControl/Model/Common/TRColour.cs b/TRLevelControl/Model/Common/TRColour.cs index 8039d0527..5f932c538 100644 --- a/TRLevelControl/Model/Common/TRColour.cs +++ b/TRLevelControl/Model/Common/TRColour.cs @@ -1,8 +1,6 @@ -using TRLevelControl.Serialization; +namespace TRLevelControl.Model; -namespace TRLevelControl.Model; - -public class TRColour : ISerializableCompact +public class TRColour { public byte Red { get; set; } public byte Green { get; set; } @@ -12,17 +10,4 @@ public override string ToString() { return $"{base.ToString()} R: {Red} G: {Green} B: {Blue}"; } - - public byte[] Serialize() - { - using MemoryStream stream = new(); - using (BinaryWriter writer = new(stream)) - { - writer.Write(Red); - writer.Write(Green); - writer.Write(Blue); - } - - return stream.ToArray(); - } } diff --git a/TRLevelControl/Model/Common/TRColour4.cs b/TRLevelControl/Model/Common/TRColour4.cs index e730909ac..aa345496d 100644 --- a/TRLevelControl/Model/Common/TRColour4.cs +++ b/TRLevelControl/Model/Common/TRColour4.cs @@ -1,8 +1,6 @@ -using TRLevelControl.Serialization; +namespace TRLevelControl.Model; -namespace TRLevelControl.Model; - -public class TRColour4 : ISerializableCompact +public class TRColour4 { public byte Red { get; set; } public byte Green { get; set; } @@ -13,18 +11,4 @@ public override string ToString() { return $"{base.ToString()} R: {Red} G: {Green} B: {Blue} Unused: {Unused}"; } - - public byte[] Serialize() - { - using MemoryStream stream = new(); - using (BinaryWriter writer = new(stream)) - { - writer.Write(Red); - writer.Write(Green); - writer.Write(Blue); - writer.Write(Unused); - } - - return stream.ToArray(); - } } diff --git a/TRLevelControl/Model/TR3/TR3RoomLight.cs b/TRLevelControl/Model/TR3/TR3RoomLight.cs index f647c7bb4..08b884ff7 100644 --- a/TRLevelControl/Model/TR3/TR3RoomLight.cs +++ b/TRLevelControl/Model/TR3/TR3RoomLight.cs @@ -20,12 +20,12 @@ public class TR3RoomLight : ISerializableCompact public byte[] Serialize() { using MemoryStream stream = new(); - using (BinaryWriter writer = new(stream)) + using (TRLevelWriter writer = new(stream)) { writer.Write(X); writer.Write(Y); writer.Write(Z); - writer.Write(Colour.Serialize()); + writer.Write(Colour); writer.Write(LightType); foreach (short property in LightProperties) diff --git a/TRLevelControl/Model/TR4/TR4RoomLight.cs b/TRLevelControl/Model/TR4/TR4RoomLight.cs index ffc2e04e2..cc81c02fc 100644 --- a/TRLevelControl/Model/TR4/TR4RoomLight.cs +++ b/TRLevelControl/Model/TR4/TR4RoomLight.cs @@ -35,12 +35,12 @@ public class TR4RoomLight : ISerializableCompact public byte[] Serialize() { using MemoryStream stream = new(); - using (BinaryWriter writer = new(stream)) + using (TRLevelWriter writer = new(stream)) { writer.Write(X); writer.Write(Y); writer.Write(Z); - writer.Write(Colour.Serialize()); + writer.Write(Colour); writer.Write(LightType); writer.Write(Unknown); writer.Write(Intensity); From 70f19a55e9ae9de650deac7a60324ba6d2dc224b Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:21:15 +0100 Subject: [PATCH 09/15] Convert TR1 lightmap to list --- TRLevelControl/Control/TR1LevelControl.cs | 12 +++--------- TRLevelControl/Helpers/TRConsts.cs | 1 + TRLevelControl/Model/Base/TR1Level.cs | 6 +----- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/TRLevelControl/Control/TR1LevelControl.cs b/TRLevelControl/Control/TR1LevelControl.cs index 82fdb7b2e..7b07a32f6 100644 --- a/TRLevelControl/Control/TR1LevelControl.cs +++ b/TRLevelControl/Control/TR1LevelControl.cs @@ -284,14 +284,7 @@ protected override void Read(TRLevelReader reader) _level.Entities[i] = TRFileReadUtilities.ReadEntity(reader); } - //Light Map - 32 * 256 = 8192 bytes - _level.LightMap = new byte[32 * 256]; - - for (int i = 0; i < _level.LightMap.Length; i++) - { - _level.LightMap[i] = reader.ReadByte(); - } - + _level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize)); _level.Palette = reader.ReadColours(TRConsts.PaletteSize); //Cinematic Frames @@ -408,8 +401,9 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumEntities); foreach (TREntity entity in _level.Entities) { writer.Write(entity.Serialize()); } + Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize); Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize); - writer.Write(_level.LightMap); + writer.Write(_level.LightMap.ToArray()); writer.Write(_level.Palette); writer.Write(_level.NumCinematicFrames); diff --git a/TRLevelControl/Helpers/TRConsts.cs b/TRLevelControl/Helpers/TRConsts.cs index a9684f9cd..b802b11ad 100644 --- a/TRLevelControl/Helpers/TRConsts.cs +++ b/TRLevelControl/Helpers/TRConsts.cs @@ -8,4 +8,5 @@ public static class TRConsts public const int PaletteSize = 256; public const int Palette8Multiplier = 4; + public const int LightMapSize = PaletteSize * 32; } diff --git a/TRLevelControl/Model/Base/TR1Level.cs b/TRLevelControl/Model/Base/TR1Level.cs index 5395c3cbc..dfeea30b6 100644 --- a/TRLevelControl/Model/Base/TR1Level.cs +++ b/TRLevelControl/Model/Base/TR1Level.cs @@ -225,11 +225,7 @@ public class TR1Level : TRLevelBase /// NumEntities * 24 bytes /// public TREntity[] Entities { get; set; } - - /// - /// (32 * 256 entries) of 1 byte = 8192 bytes - /// - public byte[] LightMap { get; set; } + public List LightMap { get; set; } public List Palette { get; set; } /// From a0570f6469399a384d3a2802023730285381dea7 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:23:08 +0100 Subject: [PATCH 10/15] Convert TR2 lightmap to list --- TRLevelControl/Control/TR2LevelControl.cs | 11 +++-------- TRLevelControl/Model/TR2/TR2Level.cs | 6 +----- .../Controls/DataControls/TR/TRPaletteControl.cs | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/TRLevelControl/Control/TR2LevelControl.cs b/TRLevelControl/Control/TR2LevelControl.cs index bc59b8305..02a91734c 100644 --- a/TRLevelControl/Control/TR2LevelControl.cs +++ b/TRLevelControl/Control/TR2LevelControl.cs @@ -295,13 +295,7 @@ protected override void Read(TRLevelReader reader) _level.Entities[i] = TR2FileReadUtilities.ReadEntity(reader); } - //Light Map - 32 * 256 = 8192 bytes - _level.LightMap = new byte[32 * 256]; - - for (int i = 0; i < _level.LightMap.Length; i++) - { - _level.LightMap[i] = reader.ReadByte(); - } + _level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize)); //Cinematic Frames _level.NumCinematicFrames = reader.ReadUInt16(); @@ -414,7 +408,8 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumEntities); foreach (TR2Entity entity in _level.Entities) { writer.Write(entity.Serialize()); } - writer.Write(_level.LightMap); + Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize); + writer.Write(_level.LightMap.ToArray()); writer.Write(_level.NumCinematicFrames); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } diff --git a/TRLevelControl/Model/TR2/TR2Level.cs b/TRLevelControl/Model/TR2/TR2Level.cs index 8f49846a2..20f0d1191 100644 --- a/TRLevelControl/Model/TR2/TR2Level.cs +++ b/TRLevelControl/Model/TR2/TR2Level.cs @@ -231,11 +231,7 @@ public class TR2Level : TRLevelBase /// NumEntities * 24 bytes /// public TR2Entity[] Entities { get; set; } - - /// - /// (32 * 256 entries) of 1 byte = 8192 bytes - /// - public byte[] LightMap { get; set; } + public List LightMap { get; set; } /// /// 2 bytes diff --git a/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs index 4ba1e0311..9eb6b7cca 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRPaletteControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Palette Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Light map Count: " + IOManager.CurrentLevelAsTR1?.LightMap.Length); + ImGui.Text("Light map Count: " + IOManager.CurrentLevelAsTR1?.LightMap.Count); ImGui.Text("Palette Count: " + IOManager.CurrentLevelAsTR1?.Palette.Count); ImGui.TreePop(); } From 7f23a7d7ee9252514612caec4bf5f3dd6ab2e732 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:25:06 +0100 Subject: [PATCH 11/15] Convert TR3 lightmap to list --- TRLevelControl/Control/TR3LevelControl.cs | 11 +++-------- TRLevelControl/Model/TR3/TR3Level.cs | 6 +----- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/TRLevelControl/Control/TR3LevelControl.cs b/TRLevelControl/Control/TR3LevelControl.cs index 34379d5e0..14de7eac6 100644 --- a/TRLevelControl/Control/TR3LevelControl.cs +++ b/TRLevelControl/Control/TR3LevelControl.cs @@ -297,13 +297,7 @@ protected override void Read(TRLevelReader reader) _level.Entities[i] = TR2FileReadUtilities.ReadEntity(reader); } - //Light Map - 32 * 256 = 8192 bytes - _level.LightMap = new byte[32 * 256]; - - for (int i = 0; i < _level.LightMap.Length; i++) - { - _level.LightMap[i] = reader.ReadByte(); - } + _level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize)); //Cinematic Frames _level.NumCinematicFrames = reader.ReadUInt16(); @@ -417,7 +411,8 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.NumEntities); foreach (TR2Entity entity in _level.Entities) { writer.Write(entity.Serialize()); } - writer.Write(_level.LightMap); + Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize); + writer.Write(_level.LightMap.ToArray()); writer.Write(_level.NumCinematicFrames); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } diff --git a/TRLevelControl/Model/TR3/TR3Level.cs b/TRLevelControl/Model/TR3/TR3Level.cs index fcfba2c1b..97c327289 100644 --- a/TRLevelControl/Model/TR3/TR3Level.cs +++ b/TRLevelControl/Model/TR3/TR3Level.cs @@ -231,11 +231,7 @@ public class TR3Level : TRLevelBase /// NumEntities * 24 bytes /// public TR2Entity[] Entities { get; set; } - - /// - /// (32 * 256 entries) of 1 byte = 8192 bytes - /// - public byte[] LightMap { get; set; } + public List LightMap { get; set; } /// /// 2 bytes From 28194161d2f1b578cfaae53b979c359a60eb13a7 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Tue, 12 Sep 2023 20:27:16 +0100 Subject: [PATCH 12/15] Rename alpha channel and use correct tracking --- TRLevelControl/IO/TRLevelReader.cs | 2 +- TRLevelControl/IO/TRLevelWriter.cs | 13 ++- TRLevelControl/Model/Common/TRColour4.cs | 4 +- .../Handlers/ColourTransportHandler.cs | 22 +--- .../Wireframing/AbstractTRWireframer.cs | 2 +- .../Textures/Wireframing/TR2Wireframer.cs | 11 +- .../Textures/Wireframing/TR3Wireframer.cs | 11 +- TRTexture16Importer/PaletteTracker.cs | 104 ++++++++++++++++++ TRTexture16Importer/PaletteUtilities.cs | 93 ---------------- .../Mapping/AbstractTextureMapping.cs | 3 - .../Textures/Mapping/TR2TextureMapping.cs | 5 +- .../Textures/Mapping/TR3TextureMapping.cs | 5 +- 12 files changed, 137 insertions(+), 138 deletions(-) create mode 100644 TRTexture16Importer/PaletteTracker.cs delete mode 100644 TRTexture16Importer/PaletteUtilities.cs diff --git a/TRLevelControl/IO/TRLevelReader.cs b/TRLevelControl/IO/TRLevelReader.cs index 145bc2b67..f7744b8f8 100644 --- a/TRLevelControl/IO/TRLevelReader.cs +++ b/TRLevelControl/IO/TRLevelReader.cs @@ -115,7 +115,7 @@ public List ReadColour4s(long numColours) Red = ReadByte(), Green = ReadByte(), Blue = ReadByte(), - Unused = ReadByte() + Alpha = ReadByte() }); } return colours; diff --git a/TRLevelControl/IO/TRLevelWriter.cs b/TRLevelControl/IO/TRLevelWriter.cs index 6c2c77c36..79dfc65c4 100644 --- a/TRLevelControl/IO/TRLevelWriter.cs +++ b/TRLevelControl/IO/TRLevelWriter.cs @@ -96,10 +96,15 @@ public void Write(IEnumerable colours) { foreach (TRColour4 colour in colours) { - Write(colour.Red); - Write(colour.Green); - Write(colour.Blue); - Write(colour.Unused); + Write(colour); } } + + public void Write(TRColour4 colour) + { + Write(colour.Red); + Write(colour.Green); + Write(colour.Blue); + Write(colour.Alpha); + } } diff --git a/TRLevelControl/Model/Common/TRColour4.cs b/TRLevelControl/Model/Common/TRColour4.cs index aa345496d..4751a7e45 100644 --- a/TRLevelControl/Model/Common/TRColour4.cs +++ b/TRLevelControl/Model/Common/TRColour4.cs @@ -5,10 +5,10 @@ public class TRColour4 public byte Red { get; set; } public byte Green { get; set; } public byte Blue { get; set; } - public byte Unused { get; set; } + public byte Alpha { get; set; } public override string ToString() { - return $"{base.ToString()} R: {Red} G: {Green} B: {Blue} Unused: {Unused}"; + return $"{base.ToString()} R: {Red} G: {Green} B: {Blue} Alpha: {Alpha}"; } } diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index db13767ae..f10f75641 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -82,44 +82,30 @@ public static void Import(TR1ModelDefinition definition, TR1PaletteManager palet public static void Import(TR2Level level, TR2ModelDefinition definition) { - List palette16 = level.Palette16.ToList(); Dictionary indexMap = new(); + PaletteTracker tracker = new(); foreach (int paletteIndex in definition.Colours.Keys) { TRColour4 newColour = definition.Colours[paletteIndex]; - int existingIndex = FindPaletteIndex(palette16, newColour); - indexMap[paletteIndex] = existingIndex == -1 ? PaletteUtilities.Import(level, newColour) : existingIndex; + indexMap[paletteIndex] = tracker.Import(level, newColour); } ReindexMeshTextures(definition.Meshes, indexMap, true); - - PaletteUtilities.ResetPaletteTracking(level.Palette16); } public static void Import(TR3Level level, TR3ModelDefinition definition) { - List palette16 = level.Palette16.ToList(); Dictionary indexMap = new(); + PaletteTracker tracker = new(); foreach (int paletteIndex in definition.Colours.Keys) { TRColour4 newColour = definition.Colours[paletteIndex]; - int existingIndex = FindPaletteIndex(palette16, newColour); - indexMap[paletteIndex] = existingIndex == -1 ? PaletteUtilities.Import(level, newColour) : existingIndex; + indexMap[paletteIndex] = tracker.Import(level, newColour); } ReindexMeshTextures(definition.Meshes, indexMap, true); - - PaletteUtilities.ResetPaletteTracking(level.Palette16); - } - - private static int FindPaletteIndex(List colours, TRColour4 colour) - { - return colours.FindIndex - ( - e => e.Red == colour.Red && e.Green == colour.Green && e.Blue == colour.Blue - ); } private static void ReindexMeshTextures(TRMesh[] meshes, Dictionary indexMap, bool has16Bit) diff --git a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs index 04d80c3bc..78f298bc6 100644 --- a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs @@ -714,7 +714,6 @@ private void DeleteAnimatedTextures(L level) protected abstract Dictionary GetModelMeshes(L level); protected abstract int GetBlackPaletteIndex(L level); protected abstract int ImportColour(L level, Color c); - protected abstract void ResetPaletteTracking(L level); protected abstract TRModel[] GetModels(L level); protected abstract TRMesh[] GetModelMeshes(L level, TRModel model); protected abstract TRMesh[] GetLevelMeshes(L level); @@ -731,4 +730,5 @@ private void DeleteAnimatedTextures(L level) protected abstract void SetAnimatedTextures(L level, TRAnimatedTexture[] animatedTextures, ushort length); public virtual bool Is8BitPalette { get; } + protected virtual void ResetPaletteTracking(L level) { } } diff --git a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs index 172386d0f..9d151f5c2 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs @@ -28,6 +28,8 @@ public class TR2Wireframer : AbstractTRWireframer TR2Entities.DragonFront_H, TR2Entities.DragonBack_H, TR2Entities.XianGuardSpearStatue, TR2Entities.XianGuardSwordStatue }; + private PaletteTracker _paletteTracker; + protected override AbstractTexturePacker CreatePacker(TR2Level level) { return new TR2TexturePacker(level); @@ -123,8 +125,8 @@ protected override TRStaticMesh[] GetStaticMeshes(TR2Level level) protected override int ImportColour(TR2Level level, Color c) { - int index = level.Palette16.ToList().FindIndex(col => col.Red == c.R && col.Green == c.G && col.Blue == c.B); - return index == -1 ? PaletteUtilities.Import(level, c) : index; + _paletteTracker ??= new(); + return _paletteTracker.Import(level, c); } protected override bool IsLaraModel(TRModel model) @@ -138,11 +140,6 @@ protected override bool IsEnemyModel(TRModel model) return TR2EntityUtilities.IsEnemyType(id) || _additionalEnemyEntities.Contains(id); } - protected override void ResetPaletteTracking(TR2Level level) - { - PaletteUtilities.ResetPaletteTracking(level.Palette16); - } - protected override void ResetUnusedTextures(TR2Level level) { level.ResetUnusedTextures(); diff --git a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs index 5c734f1aa..02cb295f1 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs @@ -29,6 +29,8 @@ public class TR3Wireframer : AbstractTRWireframer TR3Entities.ShivaStatue, TR3Entities.MonkeyKeyMeshswap, TR3Entities.MonkeyMedMeshswap }; + private PaletteTracker _paletteTracker; + protected override AbstractTexturePacker CreatePacker(TR3Level level) { return new TR3TexturePacker(level); @@ -119,8 +121,8 @@ protected override TRStaticMesh[] GetStaticMeshes(TR3Level level) protected override int ImportColour(TR3Level level, Color c) { - int index = level.Palette16.ToList().FindIndex(col => col.Red == c.R && col.Green == c.G && col.Blue == c.B); - return index == -1 ? PaletteUtilities.Import(level, c) : index; + _paletteTracker ??= new(); + return _paletteTracker.Import(level, c); } protected override bool IsLaraModel(TRModel model) @@ -145,11 +147,6 @@ protected override bool ShouldSolidifyModel(TRModel model) return TR3EntityUtilities.IsAnyPickupType(type) || TR3EntityUtilities.IsCrystalPickup(type); } - protected override void ResetPaletteTracking(TR3Level level) - { - PaletteUtilities.ResetPaletteTracking(level.Palette16); - } - protected override void ResetUnusedTextures(TR3Level level) { level.ResetUnusedTextures(); diff --git a/TRTexture16Importer/PaletteTracker.cs b/TRTexture16Importer/PaletteTracker.cs new file mode 100644 index 000000000..9e432caf7 --- /dev/null +++ b/TRTexture16Importer/PaletteTracker.cs @@ -0,0 +1,104 @@ +using System.Drawing; +using TRLevelControl.Model; + +namespace TRTexture16Importer; + +public class PaletteTracker +{ + private readonly List _replacedColours; + + public PaletteTracker() + { + _replacedColours = new(); + } + + public int Import(TR2Level lvl, Color c) + { + return Import(lvl, FromRGB(c)); + } + + public int Import(TR3Level lvl, Color c) + { + return Import(lvl, FromRGB(c)); + } + + private static TRColour4 FromRGB(Color c) + { + return new() + { + Red = c.R, + Green = c.G, + Blue = c.B + }; + } + + public int Import(TR2Level lvl, TRColour4 c) + { + return Import(c, lvl.Meshes, lvl.Palette16); + } + + public int Import(TR3Level lvl, TRColour4 c) + { + return Import(c, lvl.Meshes, lvl.Palette16); + } + + public int Import(TRColour4 colour, TRMesh[] meshes, List palette) + { + int existingIndex = palette.FindIndex(c + => c.Red == colour.Red && c.Green == colour.Green && c.Blue == colour.Blue); + if (existingIndex != -1) + { + return existingIndex; + } + + int highestIndex = -1; + foreach (TRMesh mesh in meshes) + { + foreach (TRFace4 t in mesh.ColouredRectangles) + { + highestIndex = Math.Max(highestIndex, BitConverter.GetBytes(t.Texture)[1]); + } + foreach (TRFace3 t in mesh.ColouredTriangles) + { + highestIndex = Math.Max(highestIndex, BitConverter.GetBytes(t.Texture)[1]); + } + } + + while (highestIndex < palette.Count - 1) + { + TRColour4 oldColour = palette[++highestIndex]; + if (!_replacedColours.Contains(oldColour)) + { + _replacedColours.Add(oldColour); + palette[highestIndex] = colour; + return highestIndex; + } + } + + return FindClosestColour(colour, palette); + } + + public static int FindClosestColour(TRColour4 colour, List palette) + { + int colIndex = 0; + double bestMatch = double.MaxValue; + + for (int i = 1; i < palette.Count; i++) + { + double match = Math.Sqrt + ( + Math.Pow(colour.Red - palette[i].Red, 2) + + Math.Pow(colour.Green - palette[i].Green, 2) + + Math.Pow(colour.Blue - palette[i].Blue, 2) + ); + + if (match < bestMatch) + { + colIndex = i; + bestMatch = match; + } + } + + return colIndex; + } +} diff --git a/TRTexture16Importer/PaletteUtilities.cs b/TRTexture16Importer/PaletteUtilities.cs deleted file mode 100644 index 6afbf8942..000000000 --- a/TRTexture16Importer/PaletteUtilities.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Drawing; -using TRLevelControl.Model; - -namespace TRTexture16Importer; - -public static class PaletteUtilities -{ - public static int Import(TR2Level lvl, Color c) - { - return Import(lvl, FromRGB(c)); - } - - public static int Import(TR3Level lvl, Color c) - { - return Import(lvl, FromRGB(c)); - } - - private static TRColour4 FromRGB(Color c) - { - return new TRColour4 - { - Red = c.R, - Green = c.G, - Blue = c.B - }; - } - - public static int Import(TR2Level lvl, TRColour4 c) - { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); - if (nextAvailableIndex != -1) - { - lvl.Palette16[nextAvailableIndex] = c; - c.Unused = 255; // Avoid anything else trying to use this index - } - - return nextAvailableIndex; - } - - public static int Import(TR3Level lvl, TRColour4 c) - { - int nextAvailableIndex = GetNextPaletteIndex(lvl.Meshes, lvl.Palette16); - if (nextAvailableIndex != -1) - { - lvl.Palette16[nextAvailableIndex] = c; - c.Unused = 255; // Avoid anything else trying to use this index - } - - return nextAvailableIndex; - } - - // #159 Using high indices as we were doing previously appears not to work in TR2Main, - // so instead we will check for the next available palette slot and use that. Each level - // seems to only have around 30-40 used colours. We still use the Unused field to track - // what we are making use of during imports. - public static int GetNextPaletteIndex(TRMesh[] meshes, List colours) - { - int highestUsedPalette = -1; - foreach (TRMesh mesh in meshes) - { - foreach (TRFace4 t in mesh.ColouredRectangles) - { - highestUsedPalette = Math.Max(highestUsedPalette, BitConverter.GetBytes(t.Texture)[1]); - } - foreach (TRFace3 t in mesh.ColouredTriangles) - { - highestUsedPalette = Math.Max(highestUsedPalette, BitConverter.GetBytes(t.Texture)[1]); - } - } - - while (highestUsedPalette < colours.Count - 1) - { - TRColour4 palette = colours[++highestUsedPalette]; - if (palette.Unused == 0) - { - return highestUsedPalette; - } - } - - return -1; - } - - public static void ResetPaletteTracking(IEnumerable colours) - { - foreach (TRColour4 c in colours) - { - if (c.Unused == 255) - { - c.Unused = 0; - } - } - } -} diff --git a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs index 28db291e5..cab3b8c84 100644 --- a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs @@ -353,9 +353,6 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D } } } - - // Reset the palette tracking - PaletteUtilities.ResetPaletteTracking(palette); } if (source.EntityColourMap8 != null) diff --git a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs index 86e212c6b..a8a80e01e 100644 --- a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs @@ -7,6 +7,8 @@ namespace TRTexture16Importer.Textures; public class TR2TextureMapping : AbstractTextureMapping { + private PaletteTracker _paletteTracker; + protected TR2TextureMapping(TR2Level level) : base(level) { } @@ -35,7 +37,8 @@ protected override List GetPalette16() protected override int ImportColour(Color colour) { - return PaletteUtilities.Import(_level, colour); + _paletteTracker ??= new(); + return _paletteTracker.Import(_level, colour); } protected override TRMesh[] GetModelMeshes(TR2Entities entity) diff --git a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs index 978ea1964..2d8ca8459 100644 --- a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs @@ -7,6 +7,8 @@ namespace TRTexture16Importer.Textures; public class TR3TextureMapping : AbstractTextureMapping { + private PaletteTracker _paletteTracker; + protected TR3TextureMapping(TR3Level level) : base(level) { } @@ -36,7 +38,8 @@ protected override List GetPalette16() protected override int ImportColour(Color colour) { - return PaletteUtilities.Import(_level, colour); + _paletteTracker ??= new(); + return _paletteTracker.Import(_level, colour); } protected override TRMesh[] GetModelMeshes(TR3Entities entity) From 9a53bfcd8ef301848fedb0a20c6ca1a47c01aa2d Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Wed, 13 Sep 2023 20:05:41 +0100 Subject: [PATCH 13/15] Simplify palette tracking --- .../Types/Textures/EMImportTextureFunction.cs | 2 +- .../Handlers/ColourTransportHandler.cs | 13 +-- .../Textures/TR1/TR1TextureImportHandler.cs | 2 +- .../Packing/Types/TR1TexturePacker.cs | 4 +- .../Transport/TR1/TR1ModelImporter.cs | 4 +- .../Textures/Wireframing/TR2Wireframer.cs | 8 +- .../Textures/Wireframing/TR3Wireframer.cs | 7 +- .../Helpers/ColourExtensions.cs | 39 +++++++ .../Helpers/TRPalette16Control.cs | 66 +++++++++++ ...PaletteManager.cs => TRPalette8Control.cs} | 48 ++------ TRTexture16Importer/PaletteTracker.cs | 104 ------------------ .../Textures/Mapping/TR1TextureMapping.cs | 2 +- .../Textures/Mapping/TR2TextureMapping.cs | 7 +- .../Textures/Mapping/TR3TextureMapping.cs | 7 +- 14 files changed, 144 insertions(+), 169 deletions(-) create mode 100644 TRTexture16Importer/Helpers/TRPalette16Control.cs rename TRTexture16Importer/Helpers/{TR1PaletteManager.cs => TRPalette8Control.cs} (82%) delete mode 100644 TRTexture16Importer/PaletteTracker.cs diff --git a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs index 52b55bf94..4ffbbb73c 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs @@ -26,7 +26,7 @@ public override void ApplyToLevel(TR1Level level) } else { - colIndex = TR1PaletteManager.FindClosestColour(c, palette); + colIndex = TRPalette8Control.FindClosestColour(c, palette); c = palette[colIndex]; } diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index f10f75641..002ebac27 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -1,6 +1,5 @@ using TRLevelControl.Model; using TRModelTransporter.Model.Definitions; -using TRTexture16Importer; using TRTexture16Importer.Helpers; namespace TRModelTransporter.Handlers; @@ -66,7 +65,7 @@ private static ISet GetAllColourIndices(TRMesh[] meshes, bool has16Bit) return colourIndices; } - public static void Import(TR1ModelDefinition definition, TR1PaletteManager paletteManager) + public static void Import(TR1ModelDefinition definition, TRPalette8Control paletteManager) { Dictionary indexMap = new(); @@ -83,12 +82,12 @@ public static void Import(TR1ModelDefinition definition, TR1PaletteManager palet public static void Import(TR2Level level, TR2ModelDefinition definition) { Dictionary indexMap = new(); - PaletteTracker tracker = new(); + TRPalette16Control tracker = new(level); foreach (int paletteIndex in definition.Colours.Keys) { TRColour4 newColour = definition.Colours[paletteIndex]; - indexMap[paletteIndex] = tracker.Import(level, newColour); + indexMap[paletteIndex] = tracker.Import(newColour); } ReindexMeshTextures(definition.Meshes, indexMap, true); @@ -97,12 +96,12 @@ public static void Import(TR2Level level, TR2ModelDefinition definition) public static void Import(TR3Level level, TR3ModelDefinition definition) { Dictionary indexMap = new(); - PaletteTracker tracker = new(); + TRPalette16Control tracker = new(level); foreach (int paletteIndex in definition.Colours.Keys) { TRColour4 newColour = definition.Colours[paletteIndex]; - indexMap[paletteIndex] = tracker.Import(level, newColour); + indexMap[paletteIndex] = tracker.Import(newColour); } ReindexMeshTextures(definition.Meshes, indexMap, true); @@ -125,7 +124,7 @@ private static void ReindexMeshTextures(TRMesh[] meshes, Dictionary in private static ushort ReindexTexture(ushort value, Dictionary indexMap, bool has16Bit) { - int p16 = value;; + int p16 = value; if (has16Bit) { p16 >>= 8; diff --git a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs index fdf6c22ae..42cebfaec 100644 --- a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs @@ -9,7 +9,7 @@ namespace TRModelTransporter.Handlers.Textures; public class TR1TextureImportHandler : AbstractTextureImportHandler { - public TR1PaletteManager PaletteManager { get; set; } + public TRPalette8Control PaletteManager { get; set; } protected override IEnumerable GetExistingSpriteSequences() { diff --git a/TRModelTransporter/Packing/Types/TR1TexturePacker.cs b/TRModelTransporter/Packing/Types/TR1TexturePacker.cs index ffbd2491d..fb1dbdc4d 100644 --- a/TRModelTransporter/Packing/Types/TR1TexturePacker.cs +++ b/TRModelTransporter/Packing/Types/TR1TexturePacker.cs @@ -14,7 +14,7 @@ public class TR1TexturePacker : AbstractTexturePacker { private const int _maximumTiles = 16; - public TR1PaletteManager PaletteManager { get; set; } + public TRPalette8Control PaletteManager { get; set; } public override int NumLevelImages => Level.Images8.Count; @@ -97,7 +97,7 @@ public override Bitmap GetTile(int tileIndex) public override void SetTile(int tileIndex, Bitmap bitmap) { - PaletteManager ??= new TR1PaletteManager + PaletteManager ??= new() { Level = Level }; diff --git a/TRModelTransporter/Transport/TR1/TR1ModelImporter.cs b/TRModelTransporter/Transport/TR1/TR1ModelImporter.cs index efd2ac93b..3097c0992 100644 --- a/TRModelTransporter/Transport/TR1/TR1ModelImporter.cs +++ b/TRModelTransporter/Transport/TR1/TR1ModelImporter.cs @@ -12,13 +12,13 @@ namespace TRModelTransporter.Transport; public class TR1ModelImporter : AbstractTRModelImporter { - public TR1PaletteManager PaletteManager { get; set; } + public TRPalette8Control PaletteManager { get; set; } public TR1ModelImporter(bool isCommunityPatch = false) { Data = new TR1DefaultDataProvider(); SortModels = true; - PaletteManager = new TR1PaletteManager(); + PaletteManager = new(); if (isCommunityPatch) { diff --git a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs index 9d151f5c2..338a00d1e 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs @@ -6,7 +6,7 @@ using TRModelTransporter.Helpers; using TRModelTransporter.Packing; using TRRandomizerCore.Utilities; -using TRTexture16Importer; +using TRTexture16Importer.Helpers; namespace TRRandomizerCore.Textures; @@ -28,7 +28,7 @@ public class TR2Wireframer : AbstractTRWireframer TR2Entities.DragonFront_H, TR2Entities.DragonBack_H, TR2Entities.XianGuardSpearStatue, TR2Entities.XianGuardSwordStatue }; - private PaletteTracker _paletteTracker; + private TRPalette16Control _paletteTracker; protected override AbstractTexturePacker CreatePacker(TR2Level level) { @@ -125,8 +125,8 @@ protected override TRStaticMesh[] GetStaticMeshes(TR2Level level) protected override int ImportColour(TR2Level level, Color c) { - _paletteTracker ??= new(); - return _paletteTracker.Import(level, c); + _paletteTracker ??= new(level); + return _paletteTracker.Import(c); } protected override bool IsLaraModel(TRModel model) diff --git a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs index 02cb295f1..0fad41709 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs @@ -8,7 +8,6 @@ using TRModelTransporter.Model.Textures; using TRModelTransporter.Packing; using TRRandomizerCore.Utilities; -using TRTexture16Importer; using TRTexture16Importer.Helpers; namespace TRRandomizerCore.Textures; @@ -29,7 +28,7 @@ public class TR3Wireframer : AbstractTRWireframer TR3Entities.ShivaStatue, TR3Entities.MonkeyKeyMeshswap, TR3Entities.MonkeyMedMeshswap }; - private PaletteTracker _paletteTracker; + private TRPalette16Control _paletteTracker; protected override AbstractTexturePacker CreatePacker(TR3Level level) { @@ -121,8 +120,8 @@ protected override TRStaticMesh[] GetStaticMeshes(TR3Level level) protected override int ImportColour(TR3Level level, Color c) { - _paletteTracker ??= new(); - return _paletteTracker.Import(level, c); + _paletteTracker ??= new(level); + return _paletteTracker.Import(c); } protected override bool IsLaraModel(TRModel model) diff --git a/TRTexture16Importer/Helpers/ColourExtensions.cs b/TRTexture16Importer/Helpers/ColourExtensions.cs index 97b09ebbf..2557f209a 100644 --- a/TRTexture16Importer/Helpers/ColourExtensions.cs +++ b/TRTexture16Importer/Helpers/ColourExtensions.cs @@ -155,6 +155,11 @@ public static Color ToColor(this TRColour c) return Color.FromArgb(c.Red * multiplier, c.Green * multiplier, c.Blue * multiplier); } + public static Color ToColor(this TRColour4 c) + { + return Color.FromArgb(c.Red, c.Green, c.Blue); + } + public static TRColour ToTRColour(this Color c) { int divisor = TRConsts.Palette8Multiplier; @@ -165,4 +170,38 @@ public static TRColour ToTRColour(this Color c) Blue = (byte)(c.B / divisor) }; } + + public static TRColour4 ToTRColour4(this Color c) + { + return new() + { + Red = c.R, + Green = c.G, + Blue = c.B + }; + } + + public static int FindClosest(this List palette, Color colour, int startIndex = 0) + { + int colIndex = 0; + double bestMatch = double.MaxValue; + + for (int i = startIndex; i < palette.Count; i++) + { + double match = Math.Sqrt + ( + Math.Pow(colour.R - palette[i].R, 2) + + Math.Pow(colour.G - palette[i].G, 2) + + Math.Pow(colour.B - palette[i].B, 2) + ); + + if (match < bestMatch) + { + colIndex = i; + bestMatch = match; + } + } + + return colIndex; + } } diff --git a/TRTexture16Importer/Helpers/TRPalette16Control.cs b/TRTexture16Importer/Helpers/TRPalette16Control.cs new file mode 100644 index 000000000..c57612bf6 --- /dev/null +++ b/TRTexture16Importer/Helpers/TRPalette16Control.cs @@ -0,0 +1,66 @@ +using System.Drawing; +using TRLevelControl.Model; + +namespace TRTexture16Importer.Helpers; + +public class TRPalette16Control +{ + private readonly List _palette; + private readonly Queue _freeIndices; + + public TRPalette16Control(TR2Level level) + : this(level.Palette16, level.Meshes) { } + + public TRPalette16Control(TR3Level level) + : this(level.Palette16, level.Meshes) { } + + public TRPalette16Control(List palette16, IEnumerable meshes) + { + _palette = palette16; + + IEnumerable colourRefs = meshes + .SelectMany(m => m.ColouredRectangles) + .Select(f => f.Texture >> 8) + .Concat(meshes + .SelectMany(m => m.ColouredTriangles) + .Select(f => f.Texture >> 8)); + + List range = new(Enumerable.Range(0, palette16.Count)); + _freeIndices = new(range.Except(colourRefs)); + } + + public int Import(Color colour) + => Import(colour.ToTRColour4()); + + public int Import(TRColour4 colour) + { + int index = _palette.FindIndex(c + => c.Red == colour.Red && c.Green == colour.Green && c.Blue == colour.Blue); + + if (index == -1) + { + if (_freeIndices.Count > 0) + { + index = _freeIndices.Dequeue(); + _palette[index] = colour; + } + else + { + index = FindClosestColour(colour); + } + } + + return index; + } + + private int FindClosestColour(TRColour4 colour) + { + return FindClosestColour( + colour.ToColor(), new(_palette.Select(c => c.ToColor()))); + } + + public static int FindClosestColour(Color colour, List palette) + { + return palette.FindClosest(colour); + } +} diff --git a/TRTexture16Importer/Helpers/TR1PaletteManager.cs b/TRTexture16Importer/Helpers/TRPalette8Control.cs similarity index 82% rename from TRTexture16Importer/Helpers/TR1PaletteManager.cs rename to TRTexture16Importer/Helpers/TRPalette8Control.cs index 8ea390342..71adef31b 100644 --- a/TRTexture16Importer/Helpers/TR1PaletteManager.cs +++ b/TRTexture16Importer/Helpers/TRPalette8Control.cs @@ -6,14 +6,11 @@ namespace TRTexture16Importer.Helpers; -public class TR1PaletteManager : IDisposable +public class TRPalette8Control : IDisposable { private const int _paletteLimit = TRConsts.PaletteSize - 1; - private const double _weightR = 1; - private const double _weightG = 1; - private const double _weightB = 1; - private readonly Rectangle _defaultBounds = new(0, 0, 256, 256); + private readonly Rectangle _defaultBounds = new(0, 0, TRConsts.TPageWidth, TRConsts.TPageHeight); public TR1Level Level { get; set; } public Dictionary ChangedTiles { get; set; } @@ -21,10 +18,10 @@ public class TR1PaletteManager : IDisposable private List _palette, _predefinedPalette; - public TR1PaletteManager() + public TRPalette8Control() { - ChangedTiles = new Dictionary(); - ObsoleteModels = new List(); + ChangedTiles = new(); + ObsoleteModels = new(); } public Bitmap GetOriginalTile(int tileIndex) @@ -34,7 +31,7 @@ public Bitmap GetOriginalTile(int tileIndex) public void MergeTiles() { - _palette = new List + _palette = new() { Color.FromArgb(0, 0, 0, 0) // Placeholder for transparency }; @@ -60,7 +57,7 @@ public void MergeTiles() } // Store the pointer in the level tiles - Level.Images8[i].Pixels[y * 256 + x] = (byte)colIndex; + Level.Images8[i].Pixels[y * TRConsts.TPageWidth + x] = (byte)colIndex; return c; }); @@ -115,10 +112,8 @@ private ushort GetMeshFaceColour(ushort colourRef) colourRef -= (_paletteLimit + 1); return (ushort)GetOrAddPaletteIndex(_predefinedPalette[colourRef]); } - else - { - return 0; - } + + return 0; } return (ushort)GetOrAddPaletteIndex(Level.Palette[colourRef]); @@ -217,29 +212,8 @@ private int FindClosestColour(Color colour) public static int FindClosestColour(Color colour, List palette) { - // Compare the colour with each in the palette by finding its closest match. - // We start at 1 because we don't want to match black to transparency. - - int colIndex = 0; - double bestMatch = double.MaxValue; - - for (int i = 1; i < palette.Count; i++) - { - double match = Math.Sqrt - ( - Math.Pow((colour.R - palette[i].R) * _weightR, 2) + - Math.Pow((colour.G - palette[i].G) * _weightG, 2) + - Math.Pow((colour.B - palette[i].B) * _weightB, 2) - ); - - if (match < bestMatch) - { - colIndex = i; - bestMatch = match; - } - } - - return colIndex; + // Start at 1 to avoid matching black to transparency. + return palette.FindClosest(colour, 1); } public void Dispose() diff --git a/TRTexture16Importer/PaletteTracker.cs b/TRTexture16Importer/PaletteTracker.cs deleted file mode 100644 index 9e432caf7..000000000 --- a/TRTexture16Importer/PaletteTracker.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Drawing; -using TRLevelControl.Model; - -namespace TRTexture16Importer; - -public class PaletteTracker -{ - private readonly List _replacedColours; - - public PaletteTracker() - { - _replacedColours = new(); - } - - public int Import(TR2Level lvl, Color c) - { - return Import(lvl, FromRGB(c)); - } - - public int Import(TR3Level lvl, Color c) - { - return Import(lvl, FromRGB(c)); - } - - private static TRColour4 FromRGB(Color c) - { - return new() - { - Red = c.R, - Green = c.G, - Blue = c.B - }; - } - - public int Import(TR2Level lvl, TRColour4 c) - { - return Import(c, lvl.Meshes, lvl.Palette16); - } - - public int Import(TR3Level lvl, TRColour4 c) - { - return Import(c, lvl.Meshes, lvl.Palette16); - } - - public int Import(TRColour4 colour, TRMesh[] meshes, List palette) - { - int existingIndex = palette.FindIndex(c - => c.Red == colour.Red && c.Green == colour.Green && c.Blue == colour.Blue); - if (existingIndex != -1) - { - return existingIndex; - } - - int highestIndex = -1; - foreach (TRMesh mesh in meshes) - { - foreach (TRFace4 t in mesh.ColouredRectangles) - { - highestIndex = Math.Max(highestIndex, BitConverter.GetBytes(t.Texture)[1]); - } - foreach (TRFace3 t in mesh.ColouredTriangles) - { - highestIndex = Math.Max(highestIndex, BitConverter.GetBytes(t.Texture)[1]); - } - } - - while (highestIndex < palette.Count - 1) - { - TRColour4 oldColour = palette[++highestIndex]; - if (!_replacedColours.Contains(oldColour)) - { - _replacedColours.Add(oldColour); - palette[highestIndex] = colour; - return highestIndex; - } - } - - return FindClosestColour(colour, palette); - } - - public static int FindClosestColour(TRColour4 colour, List palette) - { - int colIndex = 0; - double bestMatch = double.MaxValue; - - for (int i = 1; i < palette.Count; i++) - { - double match = Math.Sqrt - ( - Math.Pow(colour.Red - palette[i].Red, 2) + - Math.Pow(colour.Green - palette[i].Green, 2) + - Math.Pow(colour.Blue - palette[i].Blue, 2) - ); - - if (match < bestMatch) - { - colIndex = i; - bestMatch = match; - } - } - - return colIndex; - } -} diff --git a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs index 104559ffd..3ee210099 100644 --- a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs @@ -8,7 +8,7 @@ namespace TRTexture16Importer.Textures; public class TR1TextureMapping : AbstractTextureMapping { - public TR1PaletteManager PaletteManager { get; set; } + public TRPalette8Control PaletteManager { get; set; } protected TR1TextureMapping(TR1Level level) : base(level) { } diff --git a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs index a8a80e01e..977de9b5e 100644 --- a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs @@ -2,12 +2,13 @@ using TRLevelControl.Helpers; using TRLevelControl.Model; using TRLevelControl.Model.Enums; +using TRTexture16Importer.Helpers; namespace TRTexture16Importer.Textures; public class TR2TextureMapping : AbstractTextureMapping { - private PaletteTracker _paletteTracker; + private TRPalette16Control _paletteTracker; protected TR2TextureMapping(TR2Level level) : base(level) { } @@ -37,8 +38,8 @@ protected override List GetPalette16() protected override int ImportColour(Color colour) { - _paletteTracker ??= new(); - return _paletteTracker.Import(_level, colour); + _paletteTracker ??= new(_level); + return _paletteTracker.Import(colour); } protected override TRMesh[] GetModelMeshes(TR2Entities entity) diff --git a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs index 2d8ca8459..c136c6e61 100644 --- a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs @@ -2,12 +2,13 @@ using TRLevelControl.Helpers; using TRLevelControl.Model; using TRLevelControl.Model.Enums; +using TRTexture16Importer.Helpers; namespace TRTexture16Importer.Textures; public class TR3TextureMapping : AbstractTextureMapping { - private PaletteTracker _paletteTracker; + private TRPalette16Control _paletteTracker; protected TR3TextureMapping(TR3Level level) : base(level) { } @@ -38,8 +39,8 @@ protected override List GetPalette16() protected override int ImportColour(Color colour) { - _paletteTracker ??= new(); - return _paletteTracker.Import(_level, colour); + _paletteTracker ??= new(_level); + return _paletteTracker.Import(colour); } protected override TRMesh[] GetModelMeshes(TR3Entities entity) From 047bb4bc80caec640b2065eda28244b33cbd42f0 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:28:22 +0100 Subject: [PATCH 14/15] TR1 colour conversion name --- .../Model/Types/Textures/EMImportTextureFunction.cs | 2 +- TRTexture16Importer/Helpers/ColourExtensions.cs | 2 +- TRTexture16Importer/Helpers/TRPalette8Control.cs | 2 +- TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs | 2 +- TextureExport/Types/HtmlExporter.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs index 4ffbbb73c..ec5ad1a2c 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMImportTextureFunction.cs @@ -15,7 +15,7 @@ public class EMImportTextureFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { using BitmapGraphics bg = new(new Bitmap(Bitmap)); - List palette = level.Palette.Select(c => c.ToColor()).ToList(); + List palette = level.Palette.Select(c => c.ToTR1Color()).ToList(); Rectangle size = new(0, 0, bg.Bitmap.Width, bg.Bitmap.Height); bg.Scan(size, (c, x, y) => { diff --git a/TRTexture16Importer/Helpers/ColourExtensions.cs b/TRTexture16Importer/Helpers/ColourExtensions.cs index 2557f209a..62c65f341 100644 --- a/TRTexture16Importer/Helpers/ColourExtensions.cs +++ b/TRTexture16Importer/Helpers/ColourExtensions.cs @@ -149,7 +149,7 @@ public static ushort ToRGB555(this Color c) return (ushort)(a | r | g | b); } - public static Color ToColor(this TRColour c) + public static Color ToTR1Color(this TRColour c) { int multiplier = TRConsts.Palette8Multiplier; return Color.FromArgb(c.Red * multiplier, c.Green * multiplier, c.Blue * multiplier); diff --git a/TRTexture16Importer/Helpers/TRPalette8Control.cs b/TRTexture16Importer/Helpers/TRPalette8Control.cs index 71adef31b..f2a8f9f8b 100644 --- a/TRTexture16Importer/Helpers/TRPalette8Control.cs +++ b/TRTexture16Importer/Helpers/TRPalette8Control.cs @@ -181,7 +181,7 @@ public void MergePredefinedColours() public int GetOrAddPaletteIndex(TRColour c) { - return GetOrAddPaletteIndex(c.ToColor()); + return GetOrAddPaletteIndex(c.ToTR1Color()); } public int GetOrAddPaletteIndex(Color c) diff --git a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs index cab3b8c84..0557863f1 100644 --- a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs @@ -224,7 +224,7 @@ private void RecolourDynamicTargets(List meshes, HSBOperation operation) continue; } TRColour col = palette[colourIndex]; - HSB hsb = col.ToColor().ToHSB(); + HSB hsb = col.ToTR1Color().ToHSB(); hsb.H = operation.ModifyHue(hsb.H); hsb.S = operation.ModifySaturation(hsb.S); hsb.B = operation.ModifyBrightness(hsb.B); diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index 2d4ee07f0..c62ebbb08 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -27,7 +27,7 @@ public static void Export(TR1Level level, string lvlName) StringBuilder palette = new(); IEnumerable colors = level.Palette - .Select(c => c.ToColor()) + .Select(c => c.ToTR1Color()) .Distinct(); palette.Append(colors.Count()).Append(" unique colours"); From 0124ad8d743c8cb9750e7810cff8f099ee34a33e Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:32:32 +0100 Subject: [PATCH 15/15] Simplify palette matcher --- .../Helpers/ColourExtensions.cs | 30 +++++++------------ .../Helpers/TRPalette16Control.cs | 4 +-- .../Helpers/TRPalette8Control.cs | 2 +- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/TRTexture16Importer/Helpers/ColourExtensions.cs b/TRTexture16Importer/Helpers/ColourExtensions.cs index 62c65f341..a13b4109a 100644 --- a/TRTexture16Importer/Helpers/ColourExtensions.cs +++ b/TRTexture16Importer/Helpers/ColourExtensions.cs @@ -181,27 +181,17 @@ public static TRColour4 ToTRColour4(this Color c) }; } - public static int FindClosest(this List palette, Color colour, int startIndex = 0) + public static int FindClosest(this IEnumerable palette, Color colour, int startIndex = 0) { - int colIndex = 0; - double bestMatch = double.MaxValue; - - for (int i = startIndex; i < palette.Count; i++) - { - double match = Math.Sqrt - ( - Math.Pow(colour.R - palette[i].R, 2) + - Math.Pow(colour.G - palette[i].G, 2) + - Math.Pow(colour.B - palette[i].B, 2) - ); - - if (match < bestMatch) + return palette + .Select((paletteColour, index) => new { - colIndex = i; - bestMatch = match; - } - } - - return colIndex; + Index = index, + Delta = Math.Pow(colour.R - paletteColour.R, 2) + + Math.Pow(colour.G - paletteColour.G, 2) + + Math.Pow(colour.B - paletteColour.B, 2) + }) + .Where(item => item.Index >= startIndex) + .MinBy(item => item.Delta).Index; } } diff --git a/TRTexture16Importer/Helpers/TRPalette16Control.cs b/TRTexture16Importer/Helpers/TRPalette16Control.cs index c57612bf6..d2dad97e9 100644 --- a/TRTexture16Importer/Helpers/TRPalette16Control.cs +++ b/TRTexture16Importer/Helpers/TRPalette16Control.cs @@ -56,10 +56,10 @@ public int Import(TRColour4 colour) private int FindClosestColour(TRColour4 colour) { return FindClosestColour( - colour.ToColor(), new(_palette.Select(c => c.ToColor()))); + colour.ToColor(), _palette.Select(c => c.ToColor())); } - public static int FindClosestColour(Color colour, List palette) + public static int FindClosestColour(Color colour, IEnumerable palette) { return palette.FindClosest(colour); } diff --git a/TRTexture16Importer/Helpers/TRPalette8Control.cs b/TRTexture16Importer/Helpers/TRPalette8Control.cs index f2a8f9f8b..6ac8e6e9f 100644 --- a/TRTexture16Importer/Helpers/TRPalette8Control.cs +++ b/TRTexture16Importer/Helpers/TRPalette8Control.cs @@ -210,7 +210,7 @@ private int FindClosestColour(Color colour) return FindClosestColour(colour, _palette); } - public static int FindClosestColour(Color colour, List palette) + public static int FindClosestColour(Color colour, IEnumerable palette) { // Start at 1 to avoid matching black to transparency. return palette.FindClosest(colour, 1);