diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs index b5fd18f..bc87e77 100644 --- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs +++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs @@ -941,10 +941,10 @@ namespace CodeWalker.GameFiles // structure data public uint Unknown_70h { get; set; } // 0x00000000 public uint Unknown_74h { get; set; } // 0x00000000 - public ulong Vertices2Pointer { get; set; } + public ulong VerticesShrunkPointer { get; set; } public ushort Unknown_80h { get; set; } // 0x0000 public ushort Unknown_82h { get; set; } //des_.ydr's? some extra data to read..?? is this some extra poly count? - public uint Vertices2Count { get; set; } //always equal to VerticesCount + public uint VerticesShrunkCount { get; set; } //always equal to VerticesCount public ulong PolygonsPointer { get; set; } public Vector3 Quantum { get; set; } public float Unknown_9Ch { get; set; } @@ -979,7 +979,7 @@ namespace CodeWalker.GameFiles public uint Unknown_12Ch { get; set; } // 0x00000000 - public Vector3[] Vertices2 { get; set; }//found in some YFTs, same count as Vertices, and contents are similar + public Vector3[] VerticesShrunk { get; set; } // Vertices but shrunk by margin along normal public BoundPolygon[] Polygons { get; set; } public Vector3[] Vertices { get; set; } public BoundMaterialColour[] VertexColours { get; set; }//not sure, it seems like colours anyway, see eg. prologue03_10.ybn @@ -988,7 +988,7 @@ namespace CodeWalker.GameFiles public BoundMaterialColour[] MaterialColours { get; set; } public byte[] PolygonMaterialIndices { get; set; } - private ResourceSystemStructBlock Vertices2Block = null; + private ResourceSystemStructBlock VerticesShrunkBlock = null; private ResourceSystemDataBlock PolygonsBlock = null; private ResourceSystemStructBlock VerticesBlock = null; private ResourceSystemStructBlock VertexColoursBlock = null; @@ -1005,10 +1005,10 @@ namespace CodeWalker.GameFiles this.Unknown_70h = reader.ReadUInt32(); this.Unknown_74h = reader.ReadUInt32(); - this.Vertices2Pointer = reader.ReadUInt64(); + this.VerticesShrunkPointer = reader.ReadUInt64(); this.Unknown_80h = reader.ReadUInt16(); this.Unknown_82h = reader.ReadUInt16(); - this.Vertices2Count = reader.ReadUInt32(); + this.VerticesShrunkCount = reader.ReadUInt32(); this.PolygonsPointer = reader.ReadUInt64(); this.Quantum = reader.ReadVector3(); this.Unknown_9Ch = reader.ReadSingle(); @@ -1043,14 +1043,14 @@ namespace CodeWalker.GameFiles this.Unknown_12Ch = reader.ReadUInt32(); - var verts2 = reader.ReadStructsAt(this.Vertices2Pointer, this.Vertices2Count); - if (verts2 != null) //seems to be in YFT's + var vertsShrunk = reader.ReadStructsAt(this.VerticesShrunkPointer, this.VerticesShrunkCount); + if (vertsShrunk != null) //seems to be in YFT's { - Vertices2 = new Vector3[verts2.Length]; - for (int i = 0; i < verts2.Length; i++) + VerticesShrunk = new Vector3[vertsShrunk.Length]; + for (int i = 0; i < vertsShrunk.Length; i++) { - var bv = verts2[i]; - Vertices2[i] = bv.Vector * Quantum; + var bv = vertsShrunk[i]; + VerticesShrunk[i] = bv.Vector * Quantum; } } @@ -1128,14 +1128,14 @@ namespace CodeWalker.GameFiles base.Write(writer, parameters); // update structure data - this.Vertices2Pointer = (ulong)(this.Vertices2Block != null ? this.Vertices2Block.FilePosition : 0); + this.VerticesShrunkPointer = (ulong)(this.VerticesShrunkBlock != null ? this.VerticesShrunkBlock.FilePosition : 0); this.PolygonsPointer = (ulong)(this.PolygonsBlock != null ? this.PolygonsBlock.FilePosition : 0); this.VerticesPointer = (ulong)(this.VerticesBlock != null ? this.VerticesBlock.FilePosition : 0); this.VertexColoursPointer = (ulong)(this.VertexColoursBlock != null ? this.VertexColoursBlock.FilePosition : 0); this.OctantsPointer = (ulong)(this.Octants != null ? this.Octants.FilePosition : 0); this.OctantItemsPointer = (OctantsPointer != 0) ? OctantsPointer + 32 : 0; this.VerticesCount = (uint)(this.VerticesBlock != null ? this.VerticesBlock.ItemCount : 0); - this.Vertices2Count = this.VerticesCount; + this.VerticesShrunkCount = this.VerticesCount; this.PolygonsCount = (uint)(this.Polygons != null ? this.Polygons.Length : 0); this.MaterialsPointer = (ulong)(this.MaterialsBlock != null ? this.MaterialsBlock.FilePosition : 0); this.MaterialColoursPointer = (ulong)(this.MaterialColoursBlock != null ? this.MaterialColoursBlock.FilePosition : 0); @@ -1147,10 +1147,10 @@ namespace CodeWalker.GameFiles // write structure data writer.Write(this.Unknown_70h); writer.Write(this.Unknown_74h); - writer.Write(this.Vertices2Pointer); + writer.Write(this.VerticesShrunkPointer); writer.Write(this.Unknown_80h); writer.Write(this.Unknown_82h); - writer.Write(this.Vertices2Count); + writer.Write(this.VerticesShrunkCount); writer.Write(this.PolygonsPointer); writer.Write(this.Quantum); writer.Write(this.Unknown_9Ch); @@ -1204,10 +1204,6 @@ namespace CodeWalker.GameFiles { YbnXml.WriteRawArray(sb, Vertices, indent, "Vertices", "", YbnXml.FormatVector3, 1); } - if (Vertices2 != null) - { - YbnXml.WriteRawArray(sb, Vertices2, indent, "Vertices2", "", YbnXml.FormatVector3, 1); - } if (VertexColours != null) { YbnXml.WriteRawArray(sb, VertexColours, indent, "VertexColours", "", YbnXml.FormatBoundMaterialColour, 1); @@ -1216,12 +1212,6 @@ namespace CodeWalker.GameFiles { YbnXml.WriteCustomItemArray(sb, Polygons, indent, "Polygons"); } - if (Octants != null) - { - YbnXml.OpenTag(sb, indent, "Octants"); - Octants.WriteXml(sb, indent + 1); - YbnXml.CloseTag(sb, indent, "Octants"); - } } public override void ReadXml(XmlNode node) { @@ -1234,7 +1224,6 @@ namespace CodeWalker.GameFiles Materials = XmlMeta.ReadItemArray(node, "Materials"); MaterialColours = XmlYbn.GetChildRawBoundMaterialColourArray(node, "MaterialColours"); Vertices = Xml.GetChildRawVector3ArrayNullable(node, "Vertices"); - Vertices2 = Xml.GetChildRawVector3ArrayNullable(node, "Vertices2"); VertexColours = XmlYbn.GetChildRawBoundMaterialColourArray(node, "VertexColours"); var pnode = node.SelectSingleNode("Polygons"); @@ -1259,12 +1248,8 @@ namespace CodeWalker.GameFiles } } - var onode = node.SelectSingleNode("Octants"); - if (onode != null) - { - Octants = new BoundGeomOctants(); - Octants.ReadXml(onode); - } + CalculateVertsShrunkByMargin(); + CalculateOctants(); BuildMaterials(); CalculateQuantum(); @@ -1282,17 +1267,17 @@ namespace CodeWalker.GameFiles UpdateTriangleAreas(); var list = new List(base.GetReferences()); - if (Vertices2 != null) + if (VerticesShrunk != null) { var verts = new List(); - foreach (var v in Vertices2) + foreach (var v in VerticesShrunk) { var vq = v / Quantum; var vs = new BoundVertex_s(vq); verts.Add(vs); } - Vertices2Block = new ResourceSystemStructBlock(verts.ToArray()); - list.Add(Vertices2Block); + VerticesShrunkBlock = new ResourceSystemStructBlock(verts.ToArray()); + list.Add(VerticesShrunkBlock); } if (Polygons != null) { @@ -1723,6 +1708,122 @@ namespace CodeWalker.GameFiles } } + public void CalculateOctants() + { + Octants = new BoundGeomOctants(); + + Vector3[] flipDirection = new Vector3[8] + { + new Vector3(1.0f, 1.0f, 1.0f), + new Vector3(-1.0f, 1.0f, 1.0f), + new Vector3(1.0f, -1.0f, 1.0f), + new Vector3(-1.0f, -1.0f, 1.0f), + new Vector3(1.0f, 1.0f, -1.0f), + new Vector3(-1.0f, 1.0f, -1.0f), + new Vector3(1.0f, -1.0f, -1.0f), + new Vector3(-1.0f, -1.0f, -1.0f) + }; + + bool isShadowed(Vector3 v1, Vector3 v2, int octant) + { + Vector3 direction = v2 - v1; + Vector3 flip = flipDirection[octant]; + direction *= flip; + + return direction.X >= 0.0 && direction.Y >= 0.0 && direction.Z >= 0.0; + } + + uint[] getVerticesInOctant(int octant) + { + List octantIndices = new List(); + + for (uint ind1 = 0; ind1 < VerticesShrunk.Length; ind1++) + { + Vector3 vertex = VerticesShrunk[ind1]; + + bool shouldAdd = true; + List octantIndices2 = new List(); + + foreach (uint ind2 in octantIndices) + { + Vector3 vertex2 = VerticesShrunk[ind2]; + + if (isShadowed(vertex, vertex2, octant)) + { + shouldAdd = false; + octantIndices2 = octantIndices; + break; + } + + if (!isShadowed(vertex2, vertex, octant)) + { + octantIndices2.Add(ind2); + } + + } + + if (shouldAdd) + { + octantIndices2.Add(ind1); + } + + octantIndices = octantIndices2; + } + + return octantIndices.ToArray(); + } + + + for (int i = 0; i < 8; i++) + { + Octants.Items[i] = getVerticesInOctant(i); + Octants.UpdateCounts(); + } + } + + public void CalculateVertsShrunkByMargin() + { + Vector3[] vertNormals = CalculateVertNormals(); + VerticesShrunk = new Vector3[Vertices.Length]; + + for (int i = 0; i < Vertices.Length; i++) + { + Vector3 normalShrunk = vertNormals[i] * -Margin; + VerticesShrunk[i] = Vertices[i] + normalShrunk; + } + } + + public Vector3[] CalculateVertNormals() + { + Vector3[] vertNormals = new Vector3[Vertices.Length]; + + for (int i = 0; i < Polygons.Length; i++) + { + var tri = Polygons[i] as BoundPolygonTriangle; + if (tri == null) { continue; } + + var p1 = tri.Vertex1; + var p2 = tri.Vertex2; + var p3 = tri.Vertex3; + var p1Local = p1 - p2; + var p3Local = p3 - p2; + var normal = Vector3.Cross(p1Local, p3Local); + normal.Normalize(); + + vertNormals[tri.vertIndex1] += normal; + vertNormals[tri.vertIndex2] += normal; + vertNormals[tri.vertIndex3] += normal; + } + + for (int i = 0; i < vertNormals.Length; i++) + { + if (vertNormals[i].IsZero) { continue; } + + vertNormals[i].Normalize(); + } + + return vertNormals; + } public void CalculateQuantum() { @@ -1736,9 +1837,9 @@ namespace CodeWalker.GameFiles max = Vector3.Max(max, v); } } - if (Vertices2 != null) + if (VerticesShrunk != null) { - foreach (var v in Vertices2) + foreach (var v in VerticesShrunk) { min = Vector3.Min(min, v); max = Vector3.Max(max, v); @@ -1991,7 +2092,7 @@ namespace CodeWalker.GameFiles } var verts = Vertices.ToList(); - var verts2 = Vertices2?.ToList(); + var verts2 = VerticesShrunk?.ToList(); var vertcols = VertexColours?.ToList(); var vertobjs = VertexObjects?.ToList(); verts.RemoveAt(index); @@ -1999,11 +2100,11 @@ namespace CodeWalker.GameFiles vertcols?.RemoveAt(index); vertobjs?.RemoveAt(index); Vertices = verts.ToArray(); - Vertices2 = verts2?.ToArray(); + VerticesShrunk = verts2?.ToArray(); VertexColours = vertcols?.ToArray(); VertexObjects = vertobjs?.ToArray(); VerticesCount = (uint)verts.Count; - Vertices2Count = VerticesCount; + VerticesShrunkCount = VerticesCount; if (VertexObjects != null) { @@ -2057,7 +2158,7 @@ namespace CodeWalker.GameFiles public int AddVertex() { var verts = Vertices?.ToList() ?? new List(); - var verts2 = Vertices2?.ToList(); + var verts2 = VerticesShrunk?.ToList(); var vertcols = VertexColours?.ToList(); var vertobjs = VertexObjects?.ToList(); var index = verts.Count; @@ -2068,11 +2169,11 @@ namespace CodeWalker.GameFiles vertobjs?.Add(null); Vertices = verts.ToArray(); - Vertices2 = verts2?.ToArray(); + VerticesShrunk = verts2?.ToArray(); VertexColours = vertcols?.ToArray(); VertexObjects = vertobjs?.ToArray(); VerticesCount = (uint)verts.Count; - Vertices2Count = VerticesCount; + VerticesShrunkCount = VerticesCount; return index; } @@ -4095,7 +4196,7 @@ namespace CodeWalker.GameFiles } } - [TC(typeof(EXP))] public class BoundGeomOctants : ResourceSystemBlock, IMetaXmlItem + [TC(typeof(EXP))] public class BoundGeomOctants : ResourceSystemBlock { public uint[] Counts { get; set; } = new uint[8]; public uint[][] Items { get; private set; } = new uint[8][]; @@ -4175,54 +4276,6 @@ namespace CodeWalker.GameFiles } writer.Write(new byte[32]); } - public void WriteXml(StringBuilder sb, int indent) - { - if (Items == null) return; - foreach (var item in Items) - { - YbnXml.Indent(sb, indent); - if (item != null) - { - bool newline = true; - foreach (var val in item) - { - if (!newline) sb.Append(", "); - sb.Append(val.ToString()); - newline = false; - } - } - sb.AppendLine(); - } - } - public void ReadXml(XmlNode node) - { - var collist = new List(); - var rowlist = new List(); - var str = node.InnerText.Trim(); - var split = str.Split('\n'); - for (int i = 0; i < split.Length; i++) - { - var s = split[i]?.Trim(); - //if (string.IsNullOrEmpty(s)) continue; - var split2 = s.Split(',');// Regex.Split(s, @"[\s\t]"); - rowlist.Clear(); - for (int n = 0; n < split2.Length; n++) - { - var ts = split2[n]?.Trim(); - if (string.IsNullOrEmpty(ts)) continue; - if (uint.TryParse(ts, out uint u)) - { - rowlist.Add(u); - } - } - collist.Add(rowlist.ToArray()); - } - Items = collist.ToArray(); - - UpdateCounts(); - } - - public void UpdateCounts() {