private NavTile DeserializeMeshTile(ref Stream stream, NavPolyIdManager manager, out NavPolyId baseRef) { NavTile tile; using (var binaryReader = new BinaryReader(stream)) { var id = binaryReader.ReadInt32(); baseRef = new NavPolyId(id); var x = binaryReader.ReadInt32(); var y = binaryReader.ReadInt32(); var location = new Vector2i(x, y); var layer = binaryReader.ReadInt32(); tile = new NavTile(location, layer, manager, baseRef); tile.Salt = binaryReader.ReadInt32(); var minX = binaryReader.ReadSingle(); var minY = binaryReader.ReadSingle(); var minZ = binaryReader.ReadSingle(); var maxX = binaryReader.ReadSingle(); var maxY = binaryReader.ReadSingle(); var maxZ = binaryReader.ReadSingle(); tile.Bounds = new BBox3(minX, minY, minZ, maxX, maxY, maxZ); var polysCount = binaryReader.ReadInt32(); var polys = new NavPoly[polysCount]; for (var i = 0; i < polysCount; i++) { var poly = new NavPoly(); poly.PolyType = (NavPolyType)binaryReader.ReadByte(); var polyLinksCount = binaryReader.ReadInt32(); for (var j = 0; j < polyLinksCount; j++) { var navPolyId = binaryReader.ReadInt32(); var link = new Link(); link.Reference = new NavPolyId(navPolyId); link.Edge = binaryReader.ReadInt32(); link.Side = (BoundarySide)binaryReader.ReadByte(); link.BMin = binaryReader.ReadInt32(); link.BMax = binaryReader.ReadInt32(); poly.Links.Add(link); } var polyVertsCount = binaryReader.ReadInt32(); poly.Verts = new int[polyVertsCount]; for (var j = 0; j < polyVertsCount; j++) { poly.Verts[j] = binaryReader.ReadInt32(); } var polyNeisCount = binaryReader.ReadInt32(); poly.Neis = new int[polyNeisCount]; for (var j = 0; j < polyNeisCount; j++) { poly.Neis[j] = binaryReader.ReadInt32(); } var polyTag = binaryReader.ReadByte(); if (polyTag == 0xFE) { poly.Tag = null; } else { poly.Tag = (OffMeshConnectionFlags)polyTag; } poly.VertCount = binaryReader.ReadInt32(); var areaId = binaryReader.ReadByte(); poly.Area = new Area(areaId); polys[i] = poly; } tile.Polys = polys; tile.PolyCount = polysCount; var vertsCount = binaryReader.ReadInt32(); var verts = new Vector3[vertsCount]; for (var i = 0; i < vertsCount; i++) { var vx = binaryReader.ReadSingle(); var vy = binaryReader.ReadSingle(); var vz = binaryReader.ReadSingle(); var vert = new Vector3(vx, vy, vz); verts[i] = vert; } tile.Verts = verts; var detailMeshesCount = binaryReader.ReadInt32(); var detailMeshes = new PolyMeshDetail.MeshData[detailMeshesCount]; for (var i = 0; i < detailMeshesCount; i++) { var detailMesh = new PolyMeshDetail.MeshData(); detailMesh.VertexIndex = binaryReader.ReadInt32(); detailMesh.VertexCount = binaryReader.ReadInt32(); detailMesh.TriangleIndex = binaryReader.ReadInt32(); detailMesh.TriangleCount = binaryReader.ReadInt32(); detailMeshes[i] = detailMesh; } tile.DetailMeshes = detailMeshes; var detailVertsCount = binaryReader.ReadInt32(); var detailVerts = new Vector3[detailVertsCount]; for (var i = 0; i < detailVertsCount; i++) { var vx = binaryReader.ReadSingle(); var vy = binaryReader.ReadSingle(); var vz = binaryReader.ReadSingle(); var detailVert = new Vector3(vx, vy, vz); detailVerts[i] = detailVert; } tile.DetailVerts = detailVerts; var detailTrisCount = binaryReader.ReadInt32(); var detailTris = new PolyMeshDetail.TriangleData[detailTrisCount]; for (var i = 0; i < detailTrisCount; i++) { var hash0 = binaryReader.ReadInt32(); var hash1 = binaryReader.ReadInt32(); var hash2 = binaryReader.ReadInt32(); var flags = binaryReader.ReadInt32(); var detailTri = new PolyMeshDetail.TriangleData(hash0, hash1, hash2, flags); detailTris[i] = detailTri; } tile.DetailTris = detailTris; var offMeshConnectionsCount = binaryReader.ReadInt32(); for (var i = 0; i < offMeshConnectionsCount; i++) { } var nodesCount = binaryReader.ReadInt32(); var nodes = new BVTree.Node[nodesCount]; for (var i = 0; i < nodesCount; i++) { var node = new BVTree.Node(); node.Bounds.Min.X = binaryReader.ReadInt32(); node.Bounds.Min.Y = binaryReader.ReadInt32(); node.Bounds.Min.Z = binaryReader.ReadInt32(); node.Bounds.Max.X = binaryReader.ReadInt32(); node.Bounds.Max.Y = binaryReader.ReadInt32(); node.Bounds.Max.Z = binaryReader.ReadInt32(); node.Index = binaryReader.ReadInt32(); nodes[i] = node; } tile.BVTree = new BVTree(nodes); tile.BvQuantFactor = binaryReader.ReadSingle(); tile.BvNodeCount = binaryReader.ReadInt32(); tile.WalkableClimb = binaryReader.ReadSingle(); } return(tile); }
/// <summary> /// Find all the polygons within a certain bounding box. /// </summary> /// <param name="tile">Current tile</param> /// <param name="qbounds">The bounds</param> /// <param name="polys">List of polygons</param> /// <returns>Number of polygons found</returns> public int QueryPolygonsInTile(MeshTile tile, BBox3 qbounds, List <PolyId> polys) { if (tile.BVTree.Count != 0) { int node = 0; int end = tile.Header.BvNodeCount; Vector3 tbmin = tile.Header.Bounds.Min; Vector3 tbmax = tile.Header.Bounds.Max; //Clamp query box to world box Vector3 qbmin = qbounds.Min; Vector3 qbmax = qbounds.Max; PolyBounds b; float bminx = MathHelper.Clamp(qbmin.X, tbmin.X, tbmax.X) - tbmin.X; float bminy = MathHelper.Clamp(qbmin.Y, tbmin.Y, tbmax.Y) - tbmin.Y; float bminz = MathHelper.Clamp(qbmin.Z, tbmin.Z, tbmax.Z) - tbmin.Z; float bmaxx = MathHelper.Clamp(qbmax.X, tbmin.X, tbmax.X) - tbmin.X; float bmaxy = MathHelper.Clamp(qbmax.Y, tbmin.Y, tbmax.Y) - tbmin.Y; float bmaxz = MathHelper.Clamp(qbmax.Z, tbmin.Z, tbmax.Z) - tbmin.Z; const int MinMask = unchecked ((int)0xfffffffe); b.Min.X = (int)(bminx * tile.Header.BvQuantFactor) & MinMask; b.Min.Y = (int)(bminy * tile.Header.BvQuantFactor) & MinMask; b.Min.Z = (int)(bminz * tile.Header.BvQuantFactor) & MinMask; b.Max.X = (int)(bmaxx * tile.Header.BvQuantFactor + 1) | 1; b.Max.Y = (int)(bmaxy * tile.Header.BvQuantFactor + 1) | 1; b.Max.Z = (int)(bmaxz * tile.Header.BvQuantFactor + 1) | 1; //traverse tree PolyId polyBase = GetPolyRefBase(tile); while (node < end) { BVTree.Node bvNode = tile.BVTree[node]; bool overlap = PolyBounds.Overlapping(ref b, ref bvNode.Bounds); bool isLeafNode = bvNode.Index >= 0; if (isLeafNode && overlap) { if (polys.Count < polys.Capacity) { PolyId polyRef; PolyId.SetPolyIndex(ref polyBase, bvNode.Index, out polyRef); polys.Add(polyRef); } } if (overlap || isLeafNode) { node++; } else { int escapeIndex = -bvNode.Index; node += escapeIndex; } } return(polys.Count); } else { BBox3 b; PolyId polyBase = GetPolyRefBase(tile); for (int i = 0; i < tile.Header.PolyCount; i++) { var poly = tile.Polys[i]; //don't return off-mesh connection polygons if (poly.PolyType == PolygonType.OffMeshConnection) { continue; } //calculate polygon bounds b.Max = b.Min = tile.Verts[poly.Verts[0]]; for (int j = 1; j < poly.VertCount; j++) { Vector3 v = tile.Verts[poly.Verts[j]]; Vector3Extensions.ComponentMin(ref b.Min, ref v, out b.Min); Vector3Extensions.ComponentMax(ref b.Max, ref v, out b.Max); } if (BBox3.Overlapping(ref qbounds, ref b)) { if (polys.Count < polys.Capacity) { PolyId polyRef; PolyId.SetPolyIndex(ref polyBase, i, out polyRef); polys.Add(polyRef); } } } return(polys.Count); } }