diff --git a/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs index 8118c79..7658eed 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs @@ -14,7 +14,7 @@ namespace CodeWalker.GameFiles public List Vertices { get; set; } public List Indices { get; set; } - public List AdjPolys { get; set; } + public List Edges { get; set; } public List Polys { get; set; } public List Portals { get; set; } public List Points { get; set; } @@ -101,9 +101,9 @@ namespace CodeWalker.GameFiles { Indices = Nav.Indices.GetFullList(); } - if (Nav.AdjPolys != null) + if (Nav.Edges != null) { - AdjPolys = Nav.AdjPolys.GetFullList(); + Edges = Nav.Edges.GetFullList(); } if (Nav.Polys != null) { @@ -114,7 +114,6 @@ namespace CodeWalker.GameFiles YnvPoly poly = new YnvPoly(); poly.Init(this, polys[i]); poly.Index = i; - poly.CalculatePosition(); //calc poly center for display purposes.. Polys.Add(poly); if (poly.PortalType > 0) @@ -209,23 +208,46 @@ namespace CodeWalker.GameFiles Vector3 aabbsizeinv = 1.0f / aabbsize; var vertlist = new List(); - if (Vertices != null) - { - for (int i = 0; i < Vertices.Count; i++) - { - vertlist.Add(NavMeshVertex.Create((Vertices[i] - posoffset) * aabbsizeinv)); - } - } + var indslist = new List(); + var edgelist = new List(); var polylist = new List(); - if (Polys != null) + var portallist = new List(); + + var vertdict = new Dictionary(); + var blankedgepart1 = new NavMeshEdgePart() { Value = 0x0FFFE1 };//1, -, 1, 0 + var blankedgepart2 = new NavMeshEdgePart() { Value = 0x2FFFE1 };//1, -, 1, 1 + var blankedge = new NavMeshEdge() { Unknown_0h = blankedgepart1, Unknown_4h = blankedgepart2 }; + + if (Polys != null) //rebuild vertices, indices, edges and polys lists from poly data. { for (int i = 0; i < Polys.Count; i++) { - Polys[i].Index = i; - polylist.Add(Polys[i].RawData); + var poly = Polys[i]; + var vc = poly.Vertices?.Length ?? 0; + for (int n = 0; n < vc; n++) + { + Vector3 v = poly.Vertices[n]; + NavMeshEdge e = ((poly.Edges != null) && (n < poly.Edges.Length)) ? poly.Edges[n] : blankedge; + ushort ind; + if (!vertdict.TryGetValue(v, out ind)) + { + ind = (ushort)vertlist.Count; + vertdict[v] = ind; + vertlist.Add(NavMeshVertex.Create((v - posoffset) * aabbsizeinv)); + } + if ((poly.Indices != null) && (n < poly.Indices.Length)) + { + poly.Indices[n] = ind; + } + indslist.Add(ind); + edgelist.Add(e); + } + poly._RawData.IndexCount = vc; + poly.Index = i;//this should be redundant... + polylist.Add(poly.RawData); } } - var portallist = new List(); + if (Portals != null) { for (int i = 0; i < Portals.Count; i++) @@ -238,7 +260,7 @@ namespace CodeWalker.GameFiles } } - if (Points != null) + if (Points != null) //points will be built into the sector tree { for (int i = 0; i < Points.Count; i++) { @@ -259,10 +281,10 @@ namespace CodeWalker.GameFiles Nav.Indices = new NavMeshList(); Nav.Indices.VFT = 1080158424; } - if (Nav.AdjPolys == null) + if (Nav.Edges == null) { - Nav.AdjPolys = new NavMeshList(); - Nav.AdjPolys.VFT = 1080158440; + Nav.Edges = new NavMeshList(); + Nav.Edges.VFT = 1080158440; } if (Nav.Polys == null) { @@ -273,9 +295,9 @@ namespace CodeWalker.GameFiles Nav.Vertices.RebuildList(vertlist); - Nav.Indices.RebuildList(Indices); + Nav.Indices.RebuildList(indslist); - Nav.AdjPolys.RebuildList(AdjPolys); + Nav.Edges.RebuildList(edgelist); Nav.Polys.RebuildList(polylist); @@ -474,67 +496,39 @@ namespace CodeWalker.GameFiles //go through the nav mesh polys and generate verts to render... - if ((Vertices == null) || (Vertices.Count == 0)) return; - if ((Indices == null) || (Indices.Count == 0)) return; if ((Polys == null) || (Polys.Count == 0)) return; int vc = Vertices.Count; List rverts = new List(); + EditorVertex p0 = new EditorVertex(); + EditorVertex p1 = new EditorVertex(); + EditorVertex p2 = new EditorVertex(); foreach (var ypoly in Polys) { - var poly = ypoly.RawData; + if ((ypoly.Vertices == null) || (ypoly.Vertices.Length < 3)) + { continue; } + var colour = ypoly.GetColour(); var colourval = (uint)colour.ToRgba(); - var ic = poly.IndexCount; - var startid = poly.IndexID; - var endid = startid + ic; - if (startid >= Indices.Count) - { continue; } - if (endid > Indices.Count) - { continue; } - - - if(ic<3) - { continue; }//not enough verts to make a triangle... - - if (ic > 15) - { } - - - EditorVertex p0 = new EditorVertex(); - EditorVertex p1 = new EditorVertex(); - EditorVertex p2 = new EditorVertex(); p0.Colour = colourval; p1.Colour = colourval; p2.Colour = colourval; - var startind = Indices[startid]; - if (startind >= vc) - { continue; } - - p0.Position = Vertices[startind]; + p0.Position = ypoly.Vertices[0]; //build triangles for the poly. - int tricount = ic - 2; + int tricount = ypoly.Vertices.Length - 2; for (int t = 0; t < tricount; t++) { - int tid = startid + t; - int ind1 = Indices[tid + 1]; - int ind2 = Indices[tid + 2]; - if ((ind1 >= vc) || (ind2 >= vc)) - { continue; } - - p1.Position = Vertices[ind1]; - p2.Position = Vertices[ind2]; - + p1.Position = ypoly.Vertices[t + 1]; + p2.Position = ypoly.Vertices[t + 2]; rverts.Add(p0); rverts.Add(p1); rverts.Add(p2); } - } TriangleVerts = rverts.ToArray(); @@ -624,14 +618,58 @@ namespace CodeWalker.GameFiles public Vector3 Position { get; set; } public int Index { get; set; } + public ushort[] Indices { get; set; } + public Vector3[] Vertices { get; set; } + public NavMeshEdge[] Edges { get; set; } + public void Init(YnvFile ynv, NavMeshPoly poly) { Ynv = ynv; RawData = poly; + LoadIndices(); + CalculatePosition(); //calc poly center for display purposes.. } + + public void LoadIndices() + { + //load indices, vertices and edges + var indices = Ynv.Indices; + var vertices = Ynv.Vertices; + var edges = Ynv.Edges; + if ((indices == null) || (vertices == null) || (edges == null)) + { return; } + var vc = vertices.Count; + var ic = _RawData.IndexCount; + var startid = _RawData.IndexID; + var endid = startid + ic; + if (startid >= indices.Count) + { return; } + if (endid > indices.Count) + { return; } + if (endid > edges.Count) + { return; } + + Indices = new ushort[ic]; + Vertices = new Vector3[ic]; + Edges = new NavMeshEdge[ic]; + + int i = 0; + for (int id = startid; id < endid; id++) + { + var ind = indices[id]; + + Indices[i] = ind; + Vertices[i] = (ind < vc) ? vertices[ind] : Vector3.Zero; + Edges[i] = edges[id]; + + i++; + } + } + + public void SetPosition(Vector3 pos) { Vector3 delta = pos - Position; @@ -709,30 +747,15 @@ namespace CodeWalker.GameFiles public void CalculatePosition() { //calc poly center for display purposes. - var indices = Ynv.Indices; - var vertices = Ynv.Vertices; - if ((indices == null) || (vertices == null)) - { return; } - var vc = vertices.Count; - var ic = _RawData.IndexCount; - var startid = _RawData.IndexID; - var endid = startid + ic; - if (startid >= indices.Count) - { return; } - if (endid > indices.Count) - { return; } Vector3 pcenter = Vector3.Zero; - float pcount = 0.0f; - for (int id = startid; id < endid; id++) + if (Vertices != null) { - var ind = indices[id]; - if (ind >= vc) - { continue; } - - pcenter += vertices[ind]; - pcount += 1.0f; + for (int i = 0; i < Vertices.Length; i++) + { + pcenter += Vertices[i]; + } } - Position = pcenter * (1.0f / pcount); + Position = pcenter * (1.0f / ((float)Vertices?.Length)); } diff --git a/CodeWalker.Core/GameFiles/Resources/Nav.cs b/CodeWalker.Core/GameFiles/Resources/Nav.cs index 8f0e0c7..d28ef25 100644 --- a/CodeWalker.Core/GameFiles/Resources/Nav.cs +++ b/CodeWalker.Core/GameFiles/Resources/Nav.cs @@ -54,8 +54,8 @@ namespace CodeWalker.GameFiles public uint Unused_078h { get; set; } // 0x00000000 public uint Unused_07Ch { get; set; } // 0x00000000 public ulong IndicesPointer { get; set; } - public ulong AdjPolysPointer { get; set; } - public uint AdjPolysIndicesCount { get; set; } + public ulong EdgesPointer { get; set; } + public uint EdgesIndicesCount { get; set; } public NavMeshUintArray AdjAreaIDs { get; set; } public ulong PolysPointer { get; set; } public ulong SectorTreePointer { get; set; } @@ -79,7 +79,7 @@ namespace CodeWalker.GameFiles public NavMeshList Vertices { get; set; } public NavMeshList Indices { get; set; } - public NavMeshList AdjPolys { get; set; } + public NavMeshList Edges { get; set; } public NavMeshList Polys { get; set; } public NavMeshSector SectorTree { get; set; } public NavMeshPortal[] Portals { get; set; } @@ -109,8 +109,8 @@ namespace CodeWalker.GameFiles Unused_078h = reader.ReadUInt32(); Unused_07Ch = reader.ReadUInt32(); IndicesPointer = reader.ReadUInt64(); - AdjPolysPointer = reader.ReadUInt64(); - AdjPolysIndicesCount = reader.ReadUInt32(); + EdgesPointer = reader.ReadUInt64(); + EdgesIndicesCount = reader.ReadUInt32(); AdjAreaIDs = reader.ReadStruct(); PolysPointer = reader.ReadUInt64(); SectorTreePointer = reader.ReadUInt64(); @@ -135,7 +135,7 @@ namespace CodeWalker.GameFiles Vertices = reader.ReadBlockAt>(VerticesPointer); Indices = reader.ReadBlockAt>(IndicesPointer); - AdjPolys = reader.ReadBlockAt>(AdjPolysPointer); + Edges = reader.ReadBlockAt>(EdgesPointer); Polys = reader.ReadBlockAt>(PolysPointer); SectorTree = reader.ReadBlockAt(SectorTreePointer); Portals = reader.ReadStructsAt(PortalsPointer, PortalsCount); @@ -150,7 +150,7 @@ namespace CodeWalker.GameFiles VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0); IndicesPointer = (ulong)(Indices != null ? Indices.FilePosition : 0); - AdjPolysPointer = (ulong)(AdjPolys != null ? AdjPolys.FilePosition : 0); + EdgesPointer = (ulong)(Edges != null ? Edges.FilePosition : 0); PolysPointer = (ulong)(Polys != null ? Polys.FilePosition : 0); SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0); PortalsPointer = (ulong)(PortalsBlock?.FilePosition ?? 0); @@ -169,8 +169,8 @@ namespace CodeWalker.GameFiles writer.Write(Unused_078h); writer.Write(Unused_07Ch); writer.Write(IndicesPointer); - writer.Write(AdjPolysPointer); - writer.Write(AdjPolysIndicesCount); + writer.Write(EdgesPointer); + writer.Write(EdgesIndicesCount); writer.WriteStruct(AdjAreaIDs); writer.Write(PolysPointer); writer.Write(SectorTreePointer); @@ -198,7 +198,7 @@ namespace CodeWalker.GameFiles var list = new List(base.GetReferences()); if (Vertices != null) list.Add(Vertices); if (Indices != null) list.Add(Indices); - if (AdjPolys != null) list.Add(AdjPolys); + if (Edges != null) list.Add(Edges); if (Polys != null) list.Add(Polys); if (SectorTree != null) list.Add(SectorTree); @@ -592,10 +592,10 @@ namespace CodeWalker.GameFiles - [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPoly + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshEdge { - public NavMeshAdjPolyPart Unknown_0h { get; set; } - public NavMeshAdjPolyPart Unknown_4h { get; set; } + public NavMeshEdgePart Unknown_0h { get; set; } + public NavMeshEdgePart Unknown_4h { get; set; } public override string ToString() { @@ -604,7 +604,7 @@ namespace CodeWalker.GameFiles } } - [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPolyPart + [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshEdgePart { public uint Value { get; set; } @@ -623,7 +623,8 @@ namespace CodeWalker.GameFiles public override string ToString() { - return AreaIDInd.ToString() + ", " + PolyID.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString(); + string pid = (PolyID == 0x3FFF) ? "-" : PolyID.ToString(); + return AreaIDInd.ToString() + ", " + pid + ", " + Unk2.ToString() + ", " + Unk3.ToString(); } } @@ -647,7 +648,7 @@ namespace CodeWalker.GameFiles //public int IndexUnk { get { return (IndexFlags >> 0) & 31; } } //always 0 - public int IndexCount { get { return (IndexFlags >> 5); } } + public int IndexCount { get { return (IndexFlags >> 5); } set { IndexFlags = (ushort)((IndexFlags & 31) | ((value & 0x7FF) << 5)); } } //public int PartUnk1 { get { return (PartFlags >> 0) & 0xF; } } //always 0 public ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = (ushort)((PartFlags & 0xF00F) | ((value & 0xFF) << 4)); } }