/// <summary> /// Build a tile and link all the polygons togther, both internally and externally. /// Make sure to link off-mesh connections as well. /// </summary> /// <param name="data">Navigation Mesh data</param> /// <param name="lastRef">Last polygon reference</param> /// <param name="result">Last tile reference</param> public void AddTile(NavMeshBuilder data, PolyId lastRef, out PolyId result) { result = PolyId.Null; //make sure data is in right format PathfindingCommon.NavMeshInfo header = data.Header; //make sure location is free if (GetTileAt(header.X, header.Y, header.Layer) != null) { return; } //allocate a tile MeshTile tile = null; if (lastRef == PolyId.Null) { if (nextFree != null) { tile = nextFree; nextFree = tile.Next; tile.Next = null; } } else { //try to relocate tile to specific index with the same salt int tileIndex = lastRef.DecodeTileIndex(polyBits, tileBits); if (tileIndex >= maxTiles) { return; } //try to find specific tile id from free list MeshTile target = tiles[tileIndex]; MeshTile prev = null; tile = nextFree; while (tile != null && tile != target) { prev = tile; tile = tile.Next; } //couldn't find correct location if (tile != target) { return; } //remove from freelist if (prev == null) { nextFree = tile.Next; } else { prev.Next = tile.Next; } //restore salt tile.Salt = lastRef.DecodeSalt(polyBits, tileBits, saltBits); } //make sure we could allocate a tile if (tile == null) { return; } //insert tile into position LookUp Table (lut) int h = ComputeTileHash(header.X, header.Y, tileLookupTableMask); tile.Next = posLookup[h]; posLookup[h] = tile; if (header.BvNodeCount == 0) { tile.BVTree = null; } //patch header tile.Verts = data.NavVerts; tile.Polys = data.NavPolys; tile.DetailMeshes = data.NavDMeshes; tile.DetailVerts = data.NavDVerts; tile.DetailTris = data.NavDTris; tile.BVTree = data.NavBvTree; tile.OffMeshConnections = data.OffMeshCons; //build links freelist tile.LinksFreeList = 0; tile.Links = new Link[header.MaxLinkCount]; for (int i = 0; i < header.MaxLinkCount; i++) { tile.Links[i] = new Link(); } tile.Links[header.MaxLinkCount - 1].Next = Link.Null; for (int i = 0; i < header.MaxLinkCount - 1; i++) { tile.Links[i].Next = i + 1; } //init tile tile.Header = header; tile.Data = data; ConnectIntLinks(ref tile); BaseOffMeshLinks(ref tile); //create connections with neighbor tiles MeshTile[] neis = new MeshTile[32]; int nneis; //connect with layers in current tile nneis = GetTilesAt(header.X, header.Y, neis); for (int j = 0; j < nneis; j++) { if (neis[j] != tile) { ConnectExtLinks(ref tile, ref neis[j], BoundarySide.Internal); ConnectExtLinks(ref neis[j], ref tile, BoundarySide.Internal); } ConnectExtOffMeshLinks(ref tile, ref neis[j], BoundarySide.Internal); ConnectExtOffMeshLinks(ref neis[j], ref tile, BoundarySide.Internal); } //connect with neighbour tiles for (int i = 0; i < 8; i++) { BoundarySide b = (BoundarySide)i; BoundarySide bo = b.GetOpposite(); nneis = GetNeighbourTilesAt(header.X, header.Y, b, neis); for (int j = 0; j < nneis; j++) { ConnectExtLinks(ref tile, ref neis[j], b); ConnectExtLinks(ref neis[j], ref tile, bo); ConnectExtOffMeshLinks(ref tile, ref neis[j], b); ConnectExtOffMeshLinks(ref neis[j], ref tile, bo); } } result = GetTileRef(tile); }
/// <summary> /// Build a tile and link all the polygons togther, both internally and externally. /// Make sure to link off-mesh connections as well. /// </summary> /// <param name="data">Navigation Mesh data</param> /// <param name="lastRef">Last polygon reference</param> /// <param name="result">Last tile reference</param> public void AddTile(NavMeshBuilder data, PolyId lastRef, out PolyId result) { result = PolyId.Null; //make sure data is in right format PathfindingCommon.NavMeshInfo header = data.Header; //make sure location is free if (GetTileAt(header.X, header.Y, header.Layer) != null) return; //allocate a tile MeshTile tile = null; if (lastRef == PolyId.Null) { if (nextFree != null) { tile = nextFree; nextFree = tile.Next; tile.Next = null; } } else { //try to relocate tile to specific index with the same salt int tileIndex = lastRef.DecodeTileIndex(polyBits, tileBits); if (tileIndex >= maxTiles) return; //try to find specific tile id from free list MeshTile target = tiles[tileIndex]; MeshTile prev = null; tile = nextFree; while (tile != null && tile != target) { prev = tile; tile = tile.Next; } //couldn't find correct location if (tile != target) return; //remove from freelist if (prev == null) nextFree = tile.Next; else prev.Next = tile.Next; //restore salt tile.Salt = lastRef.DecodeSalt(polyBits, tileBits, saltBits); } //make sure we could allocate a tile if (tile == null) return; //insert tile into position LookUp Table (lut) int h = ComputeTileHash(header.X, header.Y, tileLookupTableMask); tile.Next = posLookup[h]; posLookup[h] = tile; if (header.BvNodeCount == 0) tile.BVTree = null; //patch header tile.Verts = data.NavVerts; tile.Polys = data.NavPolys; tile.DetailMeshes = data.NavDMeshes; tile.DetailVerts = data.NavDVerts; tile.DetailTris = data.NavDTris; tile.BVTree = data.NavBvTree; tile.OffMeshConnections = data.OffMeshCons; //build links freelist tile.LinksFreeList = 0; tile.Links = new Link[header.MaxLinkCount]; for (int i = 0; i < header.MaxLinkCount; i++) tile.Links[i] = new Link(); tile.Links[header.MaxLinkCount - 1].Next = Link.Null; for (int i = 0; i < header.MaxLinkCount - 1; i++) tile.Links[i].Next = i + 1; //init tile tile.Header = header; tile.Data = data; ConnectIntLinks(ref tile); BaseOffMeshLinks(ref tile); //create connections with neighbor tiles MeshTile[] neis = new MeshTile[32]; int nneis; //connect with layers in current tile nneis = GetTilesAt(header.X, header.Y, neis); for (int j = 0; j < nneis; j++) { if (neis[j] != tile) { ConnectExtLinks(ref tile, ref neis[j], BoundarySide.Internal); ConnectExtLinks(ref neis[j], ref tile, BoundarySide.Internal); } ConnectExtOffMeshLinks(ref tile, ref neis[j], BoundarySide.Internal); ConnectExtOffMeshLinks(ref neis[j], ref tile, BoundarySide.Internal); } //connect with neighbour tiles for (int i = 0; i < 8; i++) { BoundarySide b = (BoundarySide)i; BoundarySide bo = b.GetOpposite(); nneis = GetNeighbourTilesAt(header.X, header.Y, b, neis); for (int j = 0; j < nneis; j++) { ConnectExtLinks(ref tile, ref neis[j], b); ConnectExtLinks(ref neis[j], ref tile, bo); ConnectExtOffMeshLinks(ref tile, ref neis[j], b); ConnectExtOffMeshLinks(ref neis[j], ref tile, bo); } } result = GetTileRef(tile); }