From e48503e130edd529c4a8efbe3e40a875daac8736 Mon Sep 17 00:00:00 2001 From: dexy Date: Sat, 14 Mar 2020 01:30:56 +1100 Subject: [PATCH] Changed DrawableModel.Geometries to array --- .../GameFiles/Resources/Drawable.cs | 174 ++++++++++++------ .../GameFiles/Resources/ResourceData.cs | 23 +++ CodeWalker.Core/Utils/FbxConverter.cs | 11 +- CodeWalker/Forms/ModelForm.cs | 4 +- CodeWalker/Forms/ModelMatForm.cs | 8 +- CodeWalker/PedsForm.cs | 4 +- CodeWalker/Rendering/Renderable.cs | 4 +- CodeWalker/VehicleForm.cs | 4 +- CodeWalker/World/WorldInfoForm.cs | 4 +- CodeWalker/WorldForm.cs | 4 +- 10 files changed, 160 insertions(+), 80 deletions(-) diff --git a/CodeWalker.Core/GameFiles/Resources/Drawable.cs b/CodeWalker.Core/GameFiles/Resources/Drawable.cs index f402407..20f9e06 100644 --- a/CodeWalker.Core/GameFiles/Resources/Drawable.cs +++ b/CodeWalker.Core/GameFiles/Resources/Drawable.cs @@ -2044,21 +2044,21 @@ namespace CodeWalker.GameFiles get { var off = (long)48; - //off += (GeometriesCount1 * 2); //ShaderMapping - //if (GeometriesCount1 == 1) off += 6; - //else off += ((16 - (off % 16)) % 16); - //off += (GeometriesCount1 * 8); //Geometries pointers - //off += ((16 - (off % 16)) % 16); - //off += (GeometriesCount1 + ((GeometriesCount1 > 1) ? 1 : 0)) * 32; //BoundsData - //for (int i = 0; i < GeometriesCount1; i++) - //{ - // var geom = Geometries?.data_items[i]; - // if (geom != null) - // { - // off += ((16 - (off % 16)) % 16); - // off += geom.BlockLength; //Geometries - // } - //} + off += (GeometriesCount1 * 2); //ShaderMapping + if (GeometriesCount1 == 1) off += 6; + else off += ((16 - (off % 16)) % 16); + off += (GeometriesCount1 * 8); //Geometries pointers + off += ((16 - (off % 16)) % 16); + off += (GeometriesCount1 + ((GeometriesCount1 > 1) ? 1 : 0)) * 32; //BoundsData + for (int i = 0; i < GeometriesCount1; i++) + { + var geom = (Geometries != null) ? Geometries[i] : null; + if (geom != null) + { + off += ((16 - (off % 16)) % 16); + off += geom.BlockLength; //Geometries + } + } return off; } } @@ -2075,6 +2075,10 @@ namespace CodeWalker.GameFiles public uint SkeletonBinding { get; set; }//4th byte is bone index, 2nd byte for skin meshes public ushort RenderMaskFlags { get; set; } //First byte is called "Mask" in GIMS EVO public ushort GeometriesCount3 { get; set; } //always equal to GeometriesCount1, is it ShaderMappingCount? + public ushort[] ShaderMapping { get; set; } + public ulong[] GeometryPointers { get; set; } + public AABB_s[] BoundsData { get; set; } + public DrawableGeometry[] Geometries { get; set; } public byte BoneIndex { @@ -2110,14 +2114,6 @@ namespace CodeWalker.GameFiles - // reference data - public ResourcePointerArray64 Geometries { get; set; } - public AABB_s[] BoundsData { get; set; } - public ushort[] ShaderMapping { get; set; } - - - private ResourceSystemStructBlock BoundsDataBlock = null; //for saving only - private ResourceSystemStructBlock ShaderMappingBlock = null; @@ -2126,9 +2122,9 @@ namespace CodeWalker.GameFiles get { long val = 0; - if ((Geometries != null) && (Geometries.data_items != null)) + if (Geometries != null) { - foreach(var geom in Geometries.data_items) + foreach(var geom in Geometries) { if (geom == null) continue; if (geom.VertexData != null) @@ -2175,17 +2171,16 @@ namespace CodeWalker.GameFiles this.RenderMaskFlags = reader.ReadUInt16(); this.GeometriesCount3 = reader.ReadUInt16(); + this.ShaderMapping = reader.ReadUshortsAt(this.ShaderMappingPointer, this.GeometriesCount1, false); + this.GeometryPointers = reader.ReadUlongsAt(this.GeometriesPointer, this.GeometriesCount1, false); + this.BoundsData = reader.ReadStructsAt(this.BoundsPointer, (uint)(this.GeometriesCount1 > 1 ? this.GeometriesCount1 + 1 : this.GeometriesCount1), false); + this.Geometries = reader.ReadBlocks(this.GeometryPointers); - // read reference data - this.Geometries = reader.ReadBlockAt>(this.GeometriesPointer, this.GeometriesCount1); - this.BoundsData = reader.ReadStructsAt(this.BoundsPointer, (uint)(this.GeometriesCount1 > 1 ? this.GeometriesCount1 + 1 : this.GeometriesCount1)); - this.ShaderMapping = reader.ReadUshortsAt(this.ShaderMappingPointer, this.GeometriesCount1); - - if (Geometries?.data_items != null) + if (Geometries != null) { - for (int i = 0; i < Geometries.data_items.Length; i++) + for (int i = 0; i < Geometries.Length; i++) { - var geom = Geometries.data_items[i]; + var geom = Geometries[i]; if (geom != null) { geom.ShaderID = ((ShaderMapping != null) && (i < ShaderMapping.Length)) ? ShaderMapping[i] : (ushort)0; @@ -2258,13 +2253,34 @@ namespace CodeWalker.GameFiles public override void Write(ResourceDataWriter writer, params object[] parameters) { // update structure data - this.GeometriesPointer = (ulong)(this.Geometries != null ? this.Geometries.FilePosition : 0); - this.GeometriesCount1 = (ushort)(this.Geometries != null ? this.Geometries.Count : 0); + this.GeometriesCount1 = (ushort)(this.Geometries != null ? this.Geometries.Length : 0); this.GeometriesCount2 = this.GeometriesCount1;//is this correct? this.GeometriesCount3 = this.GeometriesCount1;//is this correct? - this.BoundsPointer = (ulong)(this.BoundsDataBlock != null ? this.BoundsDataBlock.FilePosition : 0); - this.ShaderMappingPointer = (ulong)(this.ShaderMappingBlock != null ? this.ShaderMappingBlock.FilePosition : 0); + long pad(long o) => ((16 - (o % 16)) % 16); + var off = writer.Position + 48; + this.ShaderMappingPointer = (ulong)off; + off += (GeometriesCount1 * 2); //ShaderMapping + if (GeometriesCount1 == 1) off += 6; + else off += pad(off); + this.GeometriesPointer = (ulong)off; + off += (GeometriesCount1 * 8); //Geometries pointers + off += pad(off); + this.BoundsPointer = (ulong)off; + off += (BoundsData.Length) * 32; //BoundsData + this.GeometryPointers = new ulong[GeometriesCount1]; + for (int i = 0; i < GeometriesCount1; i++) + { + var geom = (Geometries != null) ? Geometries[i] : null; + if (geom != null) + { + off += pad(off); + this.GeometryPointers[i] = (ulong)off; + off += geom.BlockLength; //Geometries + } + } + + // write structure data writer.Write(this.VFT); @@ -2278,6 +2294,39 @@ namespace CodeWalker.GameFiles writer.Write(this.SkeletonBinding); writer.Write(this.RenderMaskFlags); writer.Write(this.GeometriesCount3); + + + for (int i = 0; i < GeometriesCount1; i++) + { + writer.Write(ShaderMapping[i]); + } + if (GeometriesCount1 == 1) + { + writer.Write(new byte[6]); + } + else + { + writer.WritePadding(16); + } + for (int i = 0; i < GeometriesCount1; i++) + { + writer.Write(GeometryPointers[i]); + } + writer.WritePadding(16); + for (int i = 0; i < BoundsData.Length; i++) + { + writer.WriteStruct(BoundsData[i]); + } + for (int i = 0; i < GeometriesCount1; i++) + { + var geom = (Geometries != null) ? Geometries[i] : null; + if (geom != null) + { + writer.WritePadding(16); + writer.WriteBlock(geom); + } + } + } public void WriteXml(StringBuilder sb, int indent) { @@ -2287,9 +2336,9 @@ namespace CodeWalker.GameFiles YdrXml.ValueTag(sb, indent, "BoneIndex", BoneIndex.ToString()); YdrXml.ValueTag(sb, indent, "Unknown1", SkeletonBindUnk1.ToString()); - if (Geometries?.data_items != null) + if (Geometries != null) { - YdrXml.WriteItemArray(sb, Geometries.data_items, indent, "Geometries"); + YdrXml.WriteItemArray(sb, Geometries, indent, "Geometries"); } } @@ -2308,8 +2357,7 @@ namespace CodeWalker.GameFiles var geoms = XmlMeta.ReadItemArray(node, "Geometries"); if (geoms != null) { - Geometries = new ResourcePointerArray64(); - Geometries.data_items = geoms; + Geometries = geoms; foreach (var geom in geoms) { aabbs.Add(geom.AABB); @@ -2330,26 +2378,35 @@ namespace CodeWalker.GameFiles } - public override IResourceBlock[] GetReferences() + public override Tuple[] GetParts() { - var list = new List(); - if (Geometries != null) list.Add(Geometries); - if (BoundsData != null) + var parts = new List>(); + parts.AddRange(base.GetParts()); + + var off = (long)48; + off += (GeometriesCount1 * 2); //ShaderMapping + if (GeometriesCount1 == 1) off += 6; + else off += ((16 - (off % 16)) % 16); + off += (GeometriesCount1 * 8); //Geometries pointers + off += ((16 - (off % 16)) % 16); + off += (GeometriesCount1 + ((GeometriesCount1 > 1) ? 1 : 0)) * 32; //BoundsData + for (int i = 0; i < GeometriesCount1; i++) { - BoundsDataBlock = new ResourceSystemStructBlock(BoundsData); - list.Add(BoundsDataBlock); + var geom = (Geometries != null) ? Geometries[i] : null; + if (geom != null) + { + off += ((16 - (off % 16)) % 16); + parts.Add(new Tuple(off, geom)); + off += geom.BlockLength; //Geometries + } } - if (ShaderMapping != null) - { - ShaderMappingBlock = new ResourceSystemStructBlock(ShaderMapping); - list.Add(ShaderMappingBlock); - } - return list.ToArray(); + + return parts.ToArray(); } public override string ToString() { - return "(" + Geometries.Count + " geometr" + (Geometries.Count != 1 ? "ies)" : "y)"); + return "(" + (Geometries?.Length ?? 0).ToString() + " geometr" + ((Geometries?.Length ?? 0) != 1 ? "ies)" : "y)"); } } @@ -4376,12 +4433,12 @@ namespace CodeWalker.GameFiles var shaders = shaderGrp.Shaders.data_items; foreach (DrawableModel model in AllModels) { - if (model?.Geometries?.data_items == null) continue; + if (model?.Geometries == null) continue; - int geomcount = model.Geometries.data_items.Length; + int geomcount = model.Geometries.Length; for (int i = 0; i < geomcount; i++) { - var geom = model.Geometries.data_items[i]; + var geom = model.Geometries[i]; var sid = geom.ShaderID; geom.Shader = (sid < shaders.Length) ? shaders[sid] : null; } @@ -4414,7 +4471,8 @@ namespace CodeWalker.GameFiles var vds = new Dictionary(); foreach (DrawableModel model in AllModels) { - foreach (var geom in model.Geometries.data_items) + if (model.Geometries == null) continue; + foreach (var geom in model.Geometries) { var info = geom.VertexBuffer.Info; var declid = info.GetDeclarationId(); diff --git a/CodeWalker.Core/GameFiles/Resources/ResourceData.cs b/CodeWalker.Core/GameFiles/Resources/ResourceData.cs index a7577d4..b239708 100644 --- a/CodeWalker.Core/GameFiles/Resources/ResourceData.cs +++ b/CodeWalker.Core/GameFiles/Resources/ResourceData.cs @@ -234,6 +234,18 @@ namespace CodeWalker.GameFiles } } + public T[] ReadBlocks(ulong[] pointers) where T : IResourceBlock, new() + { + if (pointers == null) return null; + var count = pointers.Length; + var items = new T[count]; + for (int i = 0; i < count; i++) + { + items[i] = ReadBlockAt(pointers[i]); + } + return items; + } + public byte[] ReadBytesAt(ulong position, uint count, bool cache = true) { @@ -549,6 +561,17 @@ namespace CodeWalker.GameFiles } + + /// + /// Write enough bytes to the stream to get to the specified alignment. + /// + /// value to align to + public void WritePadding(int alignment) + { + var pad = ((alignment - (Position % alignment)) % alignment); + if (pad > 0) Write(new byte[pad]); + } + } diff --git a/CodeWalker.Core/Utils/FbxConverter.cs b/CodeWalker.Core/Utils/FbxConverter.cs index f183cb3..8aeb369 100644 --- a/CodeWalker.Core/Utils/FbxConverter.cs +++ b/CodeWalker.Core/Utils/FbxConverter.cs @@ -102,8 +102,8 @@ namespace CodeWalker var bsRad = 0.0f; foreach (var m in mlistall) { - if (m?.Model?.Geometries?.data_items == null) continue; - foreach (var g in m.Model.Geometries.data_items) + if (m?.Model?.Geometries == null) continue; + foreach (var g in m.Model.Geometries) { var vb = g.VertexData.VertexBytes; var vs = g.VertexData.VertexStride; @@ -135,9 +135,9 @@ namespace CodeWalker var smapp = new List(); foreach (var m in mlAll) { - if (m?.Geometries?.data_items == null) continue; + if (m?.Geometries == null) continue; smapp.Clear(); - foreach (var g in m.Geometries.data_items) + foreach (var g in m.Geometries) { smapp.Add((ushort)slist.Count); slist.Add(g.Shader); @@ -498,8 +498,7 @@ namespace CodeWalker dModel.VFT = 1080101496;//is this needed? dModel.Unknown_4h = 1; dModel.RenderMaskFlags = 0x00FF; //GIMS "Mask" - dModel.Geometries = new ResourcePointerArray64(); - dModel.Geometries.data_items = dGeoms.ToArray(); + dModel.Geometries = dGeoms.ToArray(); dModel.GeometriesCount1 = (ushort)dGeoms.Count; dModel.GeometriesCount2 = (ushort)dGeoms.Count; dModel.GeometriesCount3 = (ushort)dGeoms.Count; diff --git a/CodeWalker/Forms/ModelForm.cs b/CodeWalker/Forms/ModelForm.cs index 87597f7..e7da035 100644 --- a/CodeWalker/Forms/ModelForm.cs +++ b/CodeWalker/Forms/ModelForm.cs @@ -1100,9 +1100,9 @@ namespace CodeWalker.Forms Renderer.SelectionModelDrawFlags[model] = false; } - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname); diff --git a/CodeWalker/Forms/ModelMatForm.cs b/CodeWalker/Forms/ModelMatForm.cs index 1a53a50..2c83c32 100644 --- a/CodeWalker/Forms/ModelMatForm.cs +++ b/CodeWalker/Forms/ModelMatForm.cs @@ -106,9 +106,9 @@ namespace CodeWalker.Forms var mnode = tnc.Add(mprefix + " " + model.ToString()); mnode.Tag = model; - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname); @@ -259,8 +259,8 @@ namespace CodeWalker.Forms { foreach (var model in dwbl.AllModels) { - if (model?.Geometries?.data_items == null) continue; - foreach (var geom in model.Geometries.data_items) + if (model?.Geometries == null) continue; + foreach (var geom in model.Geometries) { if (geom.Shader == shader) { diff --git a/CodeWalker/PedsForm.cs b/CodeWalker/PedsForm.cs index a7d0dd3..b7c417c 100644 --- a/CodeWalker/PedsForm.cs +++ b/CodeWalker/PedsForm.cs @@ -545,9 +545,9 @@ namespace CodeWalker Renderer.SelectionModelDrawFlags[model] = false; } - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname); diff --git a/CodeWalker/Rendering/Renderable.cs b/CodeWalker/Rendering/Renderable.cs index 21f40da..f5ed7cd 100644 --- a/CodeWalker/Rendering/Renderable.cs +++ b/CodeWalker/Rendering/Renderable.cs @@ -763,14 +763,14 @@ namespace CodeWalker.Rendering BoneIndex = (int)((SkeletonBinding >> 24) & 0xFF); DrawableModel = dmodel; - long geomcount = dmodel.Geometries.data_items.Length; + long geomcount = dmodel.Geometries.Length; Geometries = new RenderableGeometry[geomcount]; GeometryBounds = new AABB_s[geomcount]; GeometrySize = 0; for (int i = 0; i < geomcount; i++) { - var dgeom = dmodel.Geometries.data_items[i]; + var dgeom = dmodel.Geometries[i]; var rgeom = new RenderableGeometry(); rgeom.Init(dgeom); rgeom.Owner = this; diff --git a/CodeWalker/VehicleForm.cs b/CodeWalker/VehicleForm.cs index 62aeb08..3ebfffb 100644 --- a/CodeWalker/VehicleForm.cs +++ b/CodeWalker/VehicleForm.cs @@ -491,9 +491,9 @@ namespace CodeWalker Renderer.SelectionModelDrawFlags[model] = false; } - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname); diff --git a/CodeWalker/World/WorldInfoForm.cs b/CodeWalker/World/WorldInfoForm.cs index ce28412..024f94f 100644 --- a/CodeWalker/World/WorldInfoForm.cs +++ b/CodeWalker/World/WorldInfoForm.cs @@ -217,9 +217,9 @@ namespace CodeWalker.World var tmnode = SelDrawableTexturesTreeView.Nodes.Add(mprefix + " " + model.ToString()); tmnode.Tag = model; - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname); diff --git a/CodeWalker/WorldForm.cs b/CodeWalker/WorldForm.cs index 51453e0..efacb9d 100644 --- a/CodeWalker/WorldForm.cs +++ b/CodeWalker/WorldForm.cs @@ -3786,9 +3786,9 @@ namespace CodeWalker Renderer.SelectionModelDrawFlags[model] = false; } - if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue; + if (model.Geometries == null) continue; - foreach (var geom in model.Geometries.data_items) + foreach (var geom in model.Geometries) { var gname = geom.ToString(); var gnode = mnode.Nodes.Add(gname);