From 478e6a7e0b1701b3d6e2d4605be8182407ab5417 Mon Sep 17 00:00:00 2001 From: Norbyte Date: Thu, 13 Jul 2023 19:51:23 +0200 Subject: [PATCH] Rework sections to match DOS2/BG3 layout --- LSLib/Granny/GR2/Format.cs | 13 +++---- LSLib/Granny/GR2/Writer.cs | 34 ++++++++++++----- LSLib/Granny/Model/Animation.cs | 2 +- LSLib/Granny/Model/Exporter.cs | 2 +- LSLib/Granny/Model/Mesh.cs | 65 ++++++++++++++++++++++++++------- LSLib/Granny/Model/Root.cs | 10 ++--- LSLib/Granny/Model/Vertex.cs | 14 +------ 7 files changed, 90 insertions(+), 50 deletions(-) diff --git a/LSLib/Granny/GR2/Format.cs b/LSLib/Granny/GR2/Format.cs index c18ebf3d..c8b4408e 100644 --- a/LSLib/Granny/GR2/Format.cs +++ b/LSLib/Granny/GR2/Format.cs @@ -521,14 +521,11 @@ public UInt32 CalculateCRC(Stream stream) public enum SectionType : uint { Main = 0, - RigidVertex = 1, - RigidIndex = 2, - DeformableVertex = 3, - DeformableIndex = 4, - Texture = 5, - Discardable = 6, - Unloaded = 7, - Max = Unloaded, + TrackGroup = 1, + Skeleton = 2, + Mesh = 3, + CurveAndDiscardable = 4, + FirstVertexData = 5, Invalid = 0xffffffff }; diff --git a/LSLib/Granny/GR2/Writer.cs b/LSLib/Granny/GR2/Writer.cs index 46981af6..68dba0e9 100644 --- a/LSLib/Granny/GR2/Writer.cs +++ b/LSLib/Granny/GR2/Writer.cs @@ -802,7 +802,7 @@ public byte[] Write(object root, uint numCustomSections = 0) foreach (var defn in Types.Values) { - Sections[(int)SectionType.Discardable].WriteStructDefinition(defn); + Sections[(int)SectionType.CurveAndDiscardable].WriteStructDefinition(defn); } // We need to do this again to flush strings written by WriteMemberDefinition() @@ -894,7 +894,7 @@ private void WriteMagic(Magic magic) Writer.Write(magic.reserved2); } - private Header InitHeader() + private Header InitHeader(uint numCustomSections) { var header = new Header(); header.version = Header.Version; @@ -903,7 +903,7 @@ private Header InitHeader() header.sectionsOffset = header.Size(); header.rootType = new SectionReference(); // Updated after serialization is finished header.rootNode = new SectionReference(); // Updated after serialization is finished - header.numSections = (UInt32)SectionType.Max + 1; + header.numSections = (UInt32)SectionType.FirstVertexData + numCustomSections; header.tag = VersionTag; header.extraTags = new UInt32[Header.ExtraTagCount]; for (int i = 0; i < Header.ExtraTagCount; i++) @@ -994,9 +994,19 @@ internal void QueueStructWrite(SectionType section, bool dataArea, MemberDefinit serialization.section = section; serialization.dataArea = dataArea; if (member.PreferredSection != SectionType.Invalid) + { serialization.section = member.PreferredSection; - else if (member.SectionSelector != null) - serialization.section = member.SectionSelector.SelectSection(member, type, obj); + } + + if (member.SectionSelector != null) + { + var selectedSection = member.SectionSelector.SelectSection(member, type, obj); + if (selectedSection != SectionType.Invalid) + { + serialization.section = selectedSection; + } + } + serialization.type = type; serialization.member = member; serialization.obj = obj; @@ -1010,10 +1020,16 @@ internal void QueueArrayWrite(SectionType section, bool dataArea, Type elementTy QueuedArraySerialization serialization; serialization.section = section; serialization.dataArea = dataArea; - if (member.PreferredSection != SectionType.Invalid) - serialization.section = member.PreferredSection; - else if (member.SectionSelector != null) - serialization.section = member.SectionSelector.SelectSection(member, elementType, list); + + if (member.SectionSelector != null) + { + var selectedSection = member.SectionSelector.SelectSection(member, elementType, list); + if (selectedSection != SectionType.Invalid) + { + serialization.section = selectedSection; + } + } + serialization.elementType = elementType; serialization.member = member; serialization.list = list; diff --git a/LSLib/Granny/Model/Animation.cs b/LSLib/Granny/Model/Animation.cs index e03e0c0e..e13827d0 100644 --- a/LSLib/Granny/Model/Animation.cs +++ b/LSLib/Granny/Model/Animation.cs @@ -27,7 +27,7 @@ public static float Dot(Quaternion r, Quaternion q) public class AnimationCurve { - [Serialization(TypeSelector = typeof(AnimationCurveDataTypeSelector), Type = MemberType.VariantReference, MinVersion = 0x80000011)] + [Serialization(Section = SectionType.CurveAndDiscardable, TypeSelector = typeof(AnimationCurveDataTypeSelector), Type = MemberType.VariantReference, MinVersion = 0x80000011)] public AnimationCurveData CurveData; [Serialization(MaxVersion = 0x80000010)] public Int32 Degree; diff --git a/LSLib/Granny/Model/Exporter.cs b/LSLib/Granny/Model/Exporter.cs index cf53aa5a..f969e74a 100644 --- a/LSLib/Granny/Model/Exporter.cs +++ b/LSLib/Granny/Model/Exporter.cs @@ -213,7 +213,7 @@ private void SaveGR2(string outPath, Root root) writer.VersionTag -= 1; } - var body = writer.Write(root); + var body = writer.Write(root, (root.Meshes != null) ? (uint)root.Meshes.Count : 0); writer.Dispose(); FileStream f = File.Open(outPath, FileMode.Create, System.IO.FileAccess.Write, FileShare.None); diff --git a/LSLib/Granny/Model/Mesh.cs b/LSLib/Granny/Model/Mesh.cs index 1908f947..ae74d063 100644 --- a/LSLib/Granny/Model/Mesh.cs +++ b/LSLib/Granny/Model/Mesh.cs @@ -171,9 +171,24 @@ public class VertexAnnotationSet public List VertexAnnotationIndices; } + public class VertexDataSectionSelector : SectionSelector + { + public SectionType SelectSection(MemberDefinition member, Type type, object obj) + { + if (obj is VertexData) + { + return ((VertexData)obj).SerializationSection; + } + else + { + return SectionType.Invalid; + } + } + } + public class VertexData { - [Serialization(Type = MemberType.ReferenceToVariantArray, SectionSelector = typeof(VertexSerializer), + [Serialization(Type = MemberType.ReferenceToVariantArray, TypeSelector = typeof(VertexSerializer), Serializer = typeof(VertexSerializer), Kind = SerializationKind.UserElement)] public List Vertices; @@ -182,6 +197,9 @@ public class VertexData [Serialization(Kind = SerializationKind.None)] public VertexDeduplicator Deduplicator; + [Serialization(Kind = SerializationKind.None)] + public SectionType SerializationSection = SectionType.Invalid; + public void PostLoad() { // Fix missing vertex component names @@ -382,33 +400,51 @@ public class TriAnnotationSet [Serialization(Type = MemberType.ReferenceToVariantArray)] public object TriAnnotations; public Int32 IndicesMapFromTriToAnnotation; - [Serialization(Section = SectionType.RigidIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List TriAnnotationIndices; } + public class TriTopologySectionSelector : SectionSelector + { + public SectionType SelectSection(MemberDefinition member, Type type, object obj) + { + if (obj is TriTopology) + { + return ((TriTopology)obj).SerializationSection; + } + else + { + return SectionType.Invalid; + } +} + } + public class TriTopology { public List Groups; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List Indices; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex16), Kind = SerializationKind.UserMember, Serializer = typeof(UInt16ListSerializer))] + [Serialization(Prototype = typeof(TriIndex16), Kind = SerializationKind.UserMember, Serializer = typeof(UInt16ListSerializer))] public List Indices16; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List VertexToVertexMap; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List VertexToTriangleMap; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List SideToNeighborMap; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer), MinVersion = 0x80000038)] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer), MinVersion = 0x80000038)] public List PolygonIndexStarts; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer), MinVersion = 0x80000038)] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer), MinVersion = 0x80000038)] public List PolygonIndices; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List BonesForTriangle; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List TriangleToBoneIndices; public List TriAnnotationSets; - + + [Serialization(Kind = SerializationKind.None)] + public SectionType SerializationSection = SectionType.Invalid; + public void ChangeWindingOrder() { if (Indices != null) @@ -513,7 +549,7 @@ public class BoneBinding public float[] OBBMin; [Serialization(ArraySize = 3)] public float[] OBBMax; - [Serialization(Section = SectionType.DeformableIndex, Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] + [Serialization(Prototype = typeof(TriIndex), Kind = SerializationKind.UserMember, Serializer = typeof(Int32ListSerializer))] public List TriangleIndices; } @@ -578,6 +614,7 @@ public class MaterialBinding public class MorphTarget { public string ScalarName; + [Serialization(SectionSelector = typeof(VertexDataSectionSelector))] public VertexData VertexData; public Int32 DataIsDeltas; } @@ -585,8 +622,10 @@ public class MorphTarget public class Mesh { public string Name; + [Serialization(SectionSelector = typeof(VertexDataSectionSelector))] public VertexData PrimaryVertexData; public List MorphTargets; + [Serialization(SectionSelector = typeof(TriTopologySectionSelector))] public TriTopology PrimaryTopology; [Serialization(DataArea = true)] public List MaterialBindings; diff --git a/LSLib/Granny/Model/Root.cs b/LSLib/Granny/Model/Root.cs index 7fb808d7..258f70e1 100644 --- a/LSLib/Granny/Model/Root.cs +++ b/LSLib/Granny/Model/Root.cs @@ -15,17 +15,17 @@ public class Root public List Textures; [Serialization(Type = MemberType.ArrayOfReferences)] public List Materials; - [Serialization(Type = MemberType.ArrayOfReferences)] + [Serialization(Section = SectionType.Skeleton, Type = MemberType.ArrayOfReferences)] public List Skeletons; - [Serialization(Type = MemberType.ArrayOfReferences)] + [Serialization(Type = MemberType.ArrayOfReferences, SectionSelector = typeof(VertexDataSectionSelector))] public List VertexDatas; - [Serialization(Type = MemberType.ArrayOfReferences)] + [Serialization(Type = MemberType.ArrayOfReferences, SectionSelector = typeof(TriTopologySectionSelector))] public List TriTopologies; - [Serialization(Type = MemberType.ArrayOfReferences)] + [Serialization(Section = SectionType.Mesh, Type = MemberType.ArrayOfReferences)] public List Meshes; [Serialization(Type = MemberType.ArrayOfReferences)] public List Models; - [Serialization(Type = MemberType.ArrayOfReferences)] + [Serialization(Section = SectionType.TrackGroup, Type = MemberType.ArrayOfReferences)] public List TrackGroups; [Serialization(Type = MemberType.ArrayOfReferences)] public List Animations; diff --git a/LSLib/Granny/Model/Vertex.cs b/LSLib/Granny/Model/Vertex.cs index 06dbf96f..cd6a0acb 100644 --- a/LSLib/Granny/Model/Vertex.cs +++ b/LSLib/Granny/Model/Vertex.cs @@ -409,22 +409,10 @@ public void Unserialize(GR2Reader reader) } - public class VertexSerializer : NodeSerializer, SectionSelector + public class VertexSerializer : NodeSerializer { private Dictionary VertexTypeCache = new Dictionary(); - public SectionType SelectSection(MemberDefinition member, Type type, object obj) - { - var vertices = obj as List; - if (vertices == null || vertices.Count == 0) - return SectionType.RigidVertex; - - if (vertices[0].Format.HasBoneWeights) - return SectionType.DeformableVertex; - else - return SectionType.RigidVertex; - } - public VertexDescriptor ConstructDescriptor(MemberDefinition memberDefn, StructDefinition defn, object parent) { var desc = new VertexDescriptor();