From 972c12ee85fbf11a6dac40de26deedd3cfc21a43 Mon Sep 17 00:00:00 2001 From: MeltyPlayer Date: Wed, 25 Oct 2023 03:05:56 -0500 Subject: [PATCH] Cleaned up the Melee code a bit more. --- .../Formats/Dat/src/schema/DObj.cs | 53 ++++++-- FinModelUtility/Formats/Dat/src/schema/Dat.cs | 115 ++---------------- .../Formats/Dat/src/schema/JObj.cs | 17 ++- .../Formats/Dat/src/schema/MObj.cs | 21 +++- .../Formats/Dat/src/schema/PObj.cs | 24 ++-- .../Formats/Dat/src/schema/TObj.cs | 6 +- .../Dat/src/schema/VertexDescriptor.cs | 63 ++++++++++ README.md | 1 + 8 files changed, 164 insertions(+), 136 deletions(-) create mode 100644 FinModelUtility/Formats/Dat/src/schema/VertexDescriptor.cs diff --git a/FinModelUtility/Formats/Dat/src/schema/DObj.cs b/FinModelUtility/Formats/Dat/src/schema/DObj.cs index 686eee827..ba86aa86e 100644 --- a/FinModelUtility/Formats/Dat/src/schema/DObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/DObj.cs @@ -1,24 +1,30 @@ -using fin.data.queues; - -using schema.binary; +using schema.binary; namespace dat.schema { /// /// Data object. /// - [BinarySchema] - public partial class DObjData : IBinaryConvertible { - public uint StringOffset { get; set; } - public uint NextObjectOffset { get; set; } - public uint MaterialStructOffset { get; set; } - public uint MeshStructOffset { get; set; } - } + public partial class DObj : IBinaryDeserializable { + private readonly Dat dat_; + + public DObj(Dat dat) { + this.dat_ = dat; + } - public class DObj { - public DObjData Data { get; } = new(); + [BinarySchema] + public partial class DObjHeader : IBinaryConvertible { + public uint StringOffset { get; set; } + public uint NextDObjOffset { get; set; } + public uint MObjOffset { get; set; } + public uint FirstPObjOffset { get; set; } + } + + public DObjHeader Header { get; } = new(); public string Name { get; set; } - public PObj? FirstPObj { get; set; } + public DObj? NextDObj { get; private set; } + public MObj? MObj { get; private set; } + public PObj? FirstPObj { get; private set; } public IEnumerable PObjs { get { @@ -29,5 +35,26 @@ public IEnumerable PObjs { } } } + + public void Read(IBinaryReader br) { + this.Header.Read(br); + + if (this.Header.FirstPObjOffset != 0) { + br.Position = this.Header.FirstPObjOffset; + this.FirstPObj = new PObj(this.dat_); + this.FirstPObj.Read(br); + } + + if (this.Header.MObjOffset != 0) { + br.Position = this.Header.MObjOffset; + this.MObj = br.ReadNew(); + } + + if (this.Header.NextDObjOffset != 0) { + br.Position = this.Header.NextDObjOffset; + this.NextDObj = new DObj(this.dat_); + this.NextDObj.Read(br); + } + } } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Dat/src/schema/Dat.cs b/FinModelUtility/Formats/Dat/src/schema/Dat.cs index ddcddbe17..a1042e9e4 100644 --- a/FinModelUtility/Formats/Dat/src/schema/Dat.cs +++ b/FinModelUtility/Formats/Dat/src/schema/Dat.cs @@ -1,14 +1,9 @@ -using System.Diagnostics; -using System.Numerics; +using System.Numerics; using CommunityToolkit.HighPerformance; using fin.color; -using fin.model; -using fin.schema.vector; using fin.util.asserts; -using fin.util.color; -using fin.util.enums; using gx; @@ -22,10 +17,7 @@ namespace dat.schema { // FObj: keyframe descriptor // IObj: image // JObj: joint (bone) - // MObj: material - // PObj: primitive // SObj: Scene object - // TObj: texture /// /// References: @@ -154,13 +146,10 @@ uint jObjDataOffset jObj.Name = br.ReadStringNT(); } - var jObjFlags = jObjData.Flags; - var isSpline = jObjFlags.CheckFlag(JObjFlags.SPLINE); - var isParticleJoint = jObjFlags.CheckFlag(JObjFlags.PTCL); - var isDObj = !isSpline && !isParticleJoint; - - if (isDObj) { - this.ReadDObjIntoJObj_(br, jObj, jObj.Data.ObjectStructOffset); + if (jObj.Data.FirstDObjOffset != 0) { + br.Position = jObj.Data.FirstDObjOffset; + jObj.FirstDObj = new DObj(this); + jObj.FirstDObj.Read(br); } var firstChildOffset = jObj.Data.FirstChildBoneOffset; @@ -176,36 +165,11 @@ uint jObjDataOffset br.PopLocalSpace(); } - - private void ReadDObjIntoJObj_(IBinaryReader br, - JObj jObj, - uint objectStructOffset) { - if (!this.AssertNullOrValidPointer_(objectStructOffset)) { - return; - } - - var dObj = new DObj(); - jObj.DObjs.Add(dObj); - - br.Position = objectStructOffset; - dObj.Data.Read(br); - - if (dObj.Data.MeshStructOffset != 0) { - br.Position = dObj.Data.MeshStructOffset; - - var firstPObj = new PObj(this); - firstPObj.Read(br); - - dObj.FirstPObj = firstPObj; - } - - this.ReadDObjIntoJObj_(br, jObj, dObj.Data.NextObjectOffset); - } } public static class BinaryReaderExtensions { public static Vector2 ReadVector2(this IBinaryReader br, - VertexDescriptorData descriptor) { + VertexDescriptor descriptor) { var vec2 = new Vector2(); br.ReadIntoVector(descriptor, new Span(ref vec2).Cast()); @@ -213,7 +177,7 @@ public static Vector2 ReadVector2(this IBinaryReader br, } public static Vector3 ReadVector3(this IBinaryReader br, - VertexDescriptorData descriptor) { + VertexDescriptor descriptor) { var vec3 = new Vector3(); br.ReadIntoVector(descriptor, new Span(ref vec3).Cast()); @@ -221,7 +185,7 @@ public static Vector3 ReadVector3(this IBinaryReader br, } public static Vector4 ReadVector4(this IBinaryReader br, - VertexDescriptorData descriptor) { + VertexDescriptor descriptor) { var vec4 = new Vector4(); br.ReadIntoVector(descriptor, new Span(ref vec4).Cast()); @@ -229,7 +193,7 @@ public static Vector4 ReadVector4(this IBinaryReader br, } public static void ReadIntoVector(this IBinaryReader br, - VertexDescriptorData descriptor, + VertexDescriptor descriptor, Span floats) { Asserts.True(floats.Length >= descriptor.ComponentCount); @@ -362,65 +326,4 @@ private static RootNodeType GetTypeFromName_(string name) { return RootNodeType.Undefined; } } - - [BinarySchema] - public partial class VertexDescriptorData : IBinaryConvertible { - public GxAttribute Attribute { get; set; } - - [IntegerFormat(SchemaIntegerType.UINT32)] - public GxAttributeType AttributeType { get; set; } - - - [IntegerFormat(SchemaIntegerType.UINT32)] - public GxComponentCount ComponentCountType { get; set; } - - [Ignore] - public int ComponentCount => this.Attribute switch { - GxAttribute.POS => this.ComponentCountType switch { - GxComponentCount.POS_XY => 2, - GxComponentCount.POS_XYZ => 3, - }, - GxAttribute.NRM => this.ComponentCountType switch { - GxComponentCount.NRM_XYZ => 3, - }, - GxAttribute.TEX0 or GxAttribute.TEX1 => this.ComponentCountType switch { - GxComponentCount.TEX_S => 1, - GxComponentCount.TEX_ST => 2, - }, - }; - - - [IntegerFormat(SchemaIntegerType.UINT32)] - public uint RawComponentType { get; set; } - - [Ignore] - public GxComponentType AxesComponentType - => (GxComponentType) this.RawComponentType; - - [Ignore] - public ColorComponentType ColorComponentType - => (ColorComponentType) this.RawComponentType; - - - public byte Scale { get; set; } - - public byte Padding { get; set; } - - public ushort Stride { get; set; } - - public uint ArrayOffset { get; set; } - } - - public class VertexDescriptor { - public VertexDescriptorData Data { get; } = new(); - } - - public enum ColorComponentType : uint { - RGB565, - RGB888, - RGBX8888, - RGBA4444, - RGBA6, - RGBA8888, - } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Dat/src/schema/JObj.cs b/FinModelUtility/Formats/Dat/src/schema/JObj.cs index e804878f1..6dc86522c 100644 --- a/FinModelUtility/Formats/Dat/src/schema/JObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/JObj.cs @@ -56,7 +56,7 @@ public partial class JObjData : IBinaryConvertible { public JObjFlags Flags { get; set; } public uint FirstChildBoneOffset { get; set; } public uint NextSiblingBoneOffset { get; set; } - public uint ObjectStructOffset { get; set; } + public uint FirstDObjOffset { get; set; } public Vector3f RotationRadians { get; } = new(); public Vector3f Scale { get; } = new(); public Vector3f Position { get; } = new(); @@ -65,12 +65,25 @@ public partial class JObjData : IBinaryConvertible { public uint UnknownPointer { get; set; } } + /// + /// Joint object. + /// public class JObj { public JObjData Data { get; } = new(); public string Name { get; set; } - public List DObjs { get; } = new(); + public DObj FirstDObj { get; set; } + + public IEnumerable DObjs { + get { + var current = this.FirstDObj; + while (current != null) { + yield return current; + current = current.NextDObj; + } + } + } public List Children { get; } = new(); } diff --git a/FinModelUtility/Formats/Dat/src/schema/MObj.cs b/FinModelUtility/Formats/Dat/src/schema/MObj.cs index 15b3dc683..89bdf5676 100644 --- a/FinModelUtility/Formats/Dat/src/schema/MObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/MObj.cs @@ -1,4 +1,5 @@ using schema.binary; +using schema.binary.attributes; namespace dat.schema { /// @@ -7,6 +8,24 @@ namespace dat.schema { /// Shamelessly copied from: /// https://github.com/jam1garner/Smash-Forge/blob/c0075bca364366bbea2d3803f5aeae45a4168640/Smash%20Forge/Filetypes/Melee/DAT.cs#L1256 /// - public class MObj { + [BinarySchema] + public partial class MObj : IBinaryDeserializable { + public uint Unk1 { get; set; } + public uint Unk2 { get; set; } + + private uint tObjOffset_; + + [Ignore] + private bool hasTObj_ => this.tObjOffset_ != 0; + + [RIfBoolean(nameof(hasTObj_))] + [RAtPosition(nameof(tObjOffset_))] + public TObj? TObj { get; set; } + + // TODO: What is this used for, is this another MObj? + public uint MaterialOffset { get; private set; } + + public uint Unk3 { get; set; } + public uint Unk4 { get; set; } } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Dat/src/schema/PObj.cs b/FinModelUtility/Formats/Dat/src/schema/PObj.cs index 48bf6c76d..795a616af 100644 --- a/FinModelUtility/Formats/Dat/src/schema/PObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/PObj.cs @@ -60,10 +60,9 @@ public void Read(IBinaryReader br) { // Reads vertex descriptors while (true) { var vertexDescriptor = new VertexDescriptor(); - var vertexDescriptorData = vertexDescriptor.Data; - vertexDescriptorData.Read(br); + vertexDescriptor.Read(br); - if (vertexDescriptorData.Attribute == GxAttribute.NULL) { + if (vertexDescriptor.Attribute == GxAttribute.NULL) { break; } @@ -124,13 +123,12 @@ public void Read(IBinaryReader br) { IColor? color = null; foreach (var vertexDescriptor in this.VertexDescriptors) { - var vertexDescriptorData = vertexDescriptor.Data; - var vertexAttribute = vertexDescriptorData.Attribute; - var vertexFormat = vertexDescriptorData.AttributeType; + var vertexAttribute = vertexDescriptor.Attribute; + var vertexFormat = vertexDescriptor.AttributeType; if (vertexAttribute == GxAttribute.CLR0 && vertexFormat == GxAttributeType.DIRECT) { - switch (vertexDescriptor.Data.ColorComponentType) { + switch (vertexDescriptor.ColorComponentType) { case ColorComponentType.RGB565: { color = ColorUtil.ParseRgb565(br.ReadUInt16()); break; @@ -193,8 +191,8 @@ public void Read(IBinaryReader br) { _ => throw new NotImplementedException(), }; - var offset = vertexDescriptorData.ArrayOffset + - vertexDescriptorData.Stride * value; + var offset = vertexDescriptor.ArrayOffset + + vertexDescriptor.Stride * value; switch (vertexAttribute) { case GxAttribute.PNMTXIDX: { @@ -204,25 +202,25 @@ public void Read(IBinaryReader br) { case GxAttribute.POS: { position = br.SubreadAt( offset, - sbr => sbr.ReadVector3(vertexDescriptorData)); + sbr => sbr.ReadVector3(vertexDescriptor)); break; } case GxAttribute.NRM: { normal = br.SubreadAt( offset, - sbr => sbr.ReadVector3(vertexDescriptorData)); + sbr => sbr.ReadVector3(vertexDescriptor)); break; } case GxAttribute.TEX0: { uv0 = br.SubreadAt( offset, - sbr => sbr.ReadVector2(vertexDescriptorData)); + sbr => sbr.ReadVector2(vertexDescriptor)); break; } case GxAttribute.TEX1: { uv1 = br.SubreadAt( offset, - sbr => sbr.ReadVector2(vertexDescriptorData)); + sbr => sbr.ReadVector2(vertexDescriptor)); break; } default: throw new NotImplementedException(); diff --git a/FinModelUtility/Formats/Dat/src/schema/TObj.cs b/FinModelUtility/Formats/Dat/src/schema/TObj.cs index 19f5ecd33..f5ea258dc 100644 --- a/FinModelUtility/Formats/Dat/src/schema/TObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/TObj.cs @@ -6,8 +6,12 @@ namespace dat.schema { /// /// Shamelessly copied from: /// https://github.com/jam1garner/Smash-Forge/blob/c0075bca364366bbea2d3803f5aeae45a4168640/Smash%20Forge/Filetypes/Melee/DAT.cs#L1281 + /// https://github.com/jam1garner/Smash-Forge/blob/c0075bca364366bbea2d3803f5aeae45a4168640/Smash%20Forge/Filetypes/Melee/LibWii/TLP.cs#L166 /// - public class TObj { + [BinarySchema] + public partial class TObj : IBinaryDeserializable { private readonly int[] unk_ = new int[13]; + + public void Read(IBinaryReader br) { } } } \ No newline at end of file diff --git a/FinModelUtility/Formats/Dat/src/schema/VertexDescriptor.cs b/FinModelUtility/Formats/Dat/src/schema/VertexDescriptor.cs new file mode 100644 index 000000000..36d96c5fa --- /dev/null +++ b/FinModelUtility/Formats/Dat/src/schema/VertexDescriptor.cs @@ -0,0 +1,63 @@ +using gx; + +using schema.binary; +using schema.binary.attributes; + +namespace dat.schema { + public enum ColorComponentType : uint { + RGB565, + RGB888, + RGBX8888, + RGBA4444, + RGBA6, + RGBA8888, + } + + [BinarySchema] + public partial class VertexDescriptor : IBinaryConvertible { + public GxAttribute Attribute { get; set; } + + [IntegerFormat(SchemaIntegerType.UINT32)] + public GxAttributeType AttributeType { get; set; } + + + [IntegerFormat(SchemaIntegerType.UINT32)] + public GxComponentCount ComponentCountType { get; set; } + + [Ignore] + public int ComponentCount => this.Attribute switch { + GxAttribute.POS => this.ComponentCountType switch { + GxComponentCount.POS_XY => 2, + GxComponentCount.POS_XYZ => 3, + }, + GxAttribute.NRM => this.ComponentCountType switch { + GxComponentCount.NRM_XYZ => 3, + }, + GxAttribute.TEX0 or GxAttribute.TEX1 => this.ComponentCountType switch { + GxComponentCount.TEX_S => 1, + GxComponentCount.TEX_ST => 2, + }, + }; + + + [IntegerFormat(SchemaIntegerType.UINT32)] + public uint RawComponentType { get; set; } + + [Ignore] + public GxComponentType AxesComponentType + => (GxComponentType) this.RawComponentType; + + [Ignore] + public ColorComponentType ColorComponentType + => (ColorComponentType) this.RawComponentType; + + + public byte Scale { get; set; } + + public byte Padding { get; set; } + + public ushort Stride { get; set; } + + public uint ArrayOffset { get; set; } + } +} diff --git a/README.md b/README.md index 896321ea2..0c313a10d 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ If you'd like to vote on new games or features that should be supported, please - [@HimeWorks](https://github.com/HimeWorks), whose [Noesis plugins](https://himeworks.com/noesis-plugins/) were used to add support for various formats. - [@intns](https://github.com/intns), whose [MODConv](https://github.com/intns/MODConv) tool was used as the basis for the .mod importer. - [@IronLanguages](https://github.com/IronLanguages), whose [IronPython](https://github.com/IronLanguages/ironpython3) was used to add support for calling Python plugins from C#. +- [@jam1garner](https://github.com/jam1garner), whose [Smash-Forge](https://github.com/jam1garner/Smash-Forge) tool was referenced to add support for Melee models. - [@Julgodis](https://github.com/Julgodis), whose [picori](https://github.com/Julgodis/picori) library was referenced to implement parsing .ciso files. - [@KillzXGaming](https://github.com/KillzXGaming), whose [Switch-Toolbox](https://github.com/KillzXGaming/Switch-Toolbox) was referenced to add support for LZSS decompression. - [@kornman00](https://github.com/kornman00), AKA [@KornnerStudios](https://github.com/KornnerStudios), for documenting the Halo Wars formats in [HaloWarsDocs](https://github.com/HaloMods/HaloWarsDocs) and providing the [KSoft suite](https://github.com/KornnerStudios/KSoft) to extract the contents of the game.