public override TiledNavMesh Deserialize(string path)
        {
            JObject root = JObject.Parse(File.ReadAllText(path));

            if (root["meta"]["version"]["snj"].ToObject <int>() != FormatVersion)
            {
                throw new ArgumentException("The version of the file does not match the version of the parser. Consider using an older version of SharpNav or re-generating your .snj meshes.");
            }

            Vector3 origin     = root["origin"].ToObject <Vector3>(serializer);
            float   tileWidth  = root["tileWidth"].ToObject <float>(serializer);
            float   tileHeight = root["tileHeight"].ToObject <float>(serializer);
            int     maxTiles   = root["maxTiles"].ToObject <int>(serializer);
            int     maxPolys   = root["maxPolys"].ToObject <int>(serializer);

            var mesh = new TiledNavMesh(origin, tileWidth, tileHeight, maxTiles, maxPolys);

            JArray         tilesToken = (JArray)root["tiles"];
            List <NavTile> tiles      = new List <NavTile>();

            foreach (JToken tileToken in tilesToken)
            {
                NavPolyId tileRef;
                NavTile   tile = DeserializeMeshTile(tileToken, mesh.IdManager, out tileRef);
                mesh.AddTileAt(tile, tileRef);
            }

            return(mesh);
        }
Exemple #2
0
        public void AddTileAt(NavTile tile, NavPolyId id)
        {
            if (!idManager.HasSameConfigAs(tile.IdManager))
            {
                throw new ArgumentException("Added tile has a different id manager. This likely means it came from another nav mesh");
            }

            //TODO more error checking, what if tile already exists?
            Vector2i       loc = tile.Location;
            List <NavTile> locList;

            if (!tileSet.TryGetValue(loc, out locList))
            {
                locList = new List <NavTile>();
                locList.Add(tile);
                tileSet.Add(loc, locList);
            }
            else
            {
                locList.Add(tile);
            }

            tileRefs.Add(tile, id);

            int index = idManager.DecodeTileIndex(ref id);

            tileIndices.Add(index, tile);

            ++totalSpawnedTiles;
        }
        private JObject SerializeMeshTile(NavTile tile, NavPolyId id)
        {
            var result = new JObject();

            result.Add("polyId", JToken.FromObject(id, serializer));
            result.Add("location", JToken.FromObject(tile.Location, serializer));
            result.Add("layer", JToken.FromObject(tile.Layer, serializer));
            result.Add("salt", JToken.FromObject(tile.Salt, serializer));
            result.Add("bounds", JToken.FromObject(tile.Bounds, serializer));
            result.Add("polys", JToken.FromObject(tile.Polys, serializer));
            result.Add("verts", JToken.FromObject(tile.Verts, serializer));
            result.Add("detailMeshes", JToken.FromObject(tile.DetailMeshes, serializer));
            result.Add("detailVerts", JToken.FromObject(tile.DetailVerts, serializer));
            result.Add("detailTris", JToken.FromObject(tile.DetailTris, serializer));
            result.Add("offMeshConnections", JToken.FromObject(tile.OffMeshConnections, serializer));

            JObject treeObject = new JObject();
            JArray  treeNodes  = new JArray();

            for (int i = 0; i < tile.BVTree.Count; i++)
            {
                treeNodes.Add(JToken.FromObject(tile.BVTree[i], serializer));
            }
            treeObject.Add("nodes", treeNodes);

            result.Add("bvTree", treeObject);
            result.Add("bvQuantFactor", JToken.FromObject(tile.BvQuantFactor, serializer));
            result.Add("bvNodeCount", JToken.FromObject(tile.BvNodeCount, serializer));
            result.Add("walkableClimb", JToken.FromObject(tile.WalkableClimb, serializer));

            return(result);
        }
        private NavTile DeserializeMeshTile(JToken token, NavPolyIdManager manager, out NavPolyId refId)
        {
            refId = token["polyId"].ToObject <NavPolyId>(serializer);
            Vector2i location = token["location"].ToObject <Vector2i>(serializer);
            int      layer    = token["layer"].ToObject <int>(serializer);
            NavTile  result   = new NavTile(location, layer, manager, refId);

            result.Salt                   = token["salt"].ToObject <int>(serializer);
            result.Bounds                 = token["bounds"].ToObject <BBox3>(serializer);
            result.Polys                  = token["polys"].ToObject <NavPoly[]>(serializer);
            result.PolyCount              = result.Polys.Length;
            result.Verts                  = token["verts"].ToObject <Vector3[]>(serializer);
            result.DetailMeshes           = token["detailMeshes"].ToObject <PolyMeshDetail.MeshData[]>(serializer);
            result.DetailVerts            = token["detailVerts"].ToObject <Vector3[]>(serializer);
            result.DetailTris             = token["detailTris"].ToObject <PolyMeshDetail.TriangleData[]>(serializer);
            result.OffMeshConnections     = token["offMeshConnections"].ToObject <OffMeshConnection[]>(serializer);
            result.OffMeshConnectionCount = result.OffMeshConnections.Length;
            result.BvNodeCount            = token["bvNodeCount"].ToObject <int>(serializer);
            result.BvQuantFactor          = token["bvQuantFactor"].ToObject <float>(serializer);
            result.WalkableClimb          = token["walkableClimb"].ToObject <float>(serializer);

            var treeObject = (JObject)token["bvTree"];
            var nodes      = treeObject.GetValue("nodes").ToObject <BVTree.Node[]>();

            result.BVTree = new BVTree(nodes);

            return(result);
        }
Exemple #5
0
        public void AddTileAt(NavTile tile, NavPolyId id)
        {
            //TODO more error checking, what if tile already exists?

            Vector2i       loc = tile.Location;
            List <NavTile> locList;

            if (!tileSet.TryGetValue(loc, out locList))
            {
                locList = new List <NavTile>();
                locList.Add(tile);
                tileSet.Add(loc, locList);
            }
            else
            {
                locList.Add(tile);
            }

            tileRefs.Add(tile, id);

            int index = idManager.DecodeTileIndex(ref id);

            //HACK this is pretty bad but only way to insert at index
            //TODO tileIndex should have a level of indirection from the list?
            while (index >= tileList.Count)
            {
                tileList.Add(null);
            }

            tileList[index] = tile;
        }
Exemple #6
0
        private void UnconnectLinks(NavTile tile, NavTile target)
        {
            if (tile == null || target == null)
            {
                return;
            }

            foreach (NavPoly poly in tile.Polys)
            {
                for (int n = 0; n < poly.Links.Count; ++n)
                {
                    Link    link = poly.Links[n];
                    NavTile linkTile;
                    NavPoly linkPoly;

                    TryGetTileAndPolyByRefUnsafe(link.Reference, out linkTile, out linkPoly);

                    if (linkTile == target)
                    {
                        poly.Links.RemoveAt(n);
                        --n;
                    }
                }
            }
        }
Exemple #7
0
    // Use this for initialization
    public List <Node> FindPath(GameObject obj1, GameObject obj2)
    {
        //Preload values
        mapHeight = backgroundContainer.transform.childCount;
        mapWidth  = backgroundContainer.transform.GetChild(0).childCount;

        //Parse the map
        nodeMap = new Node[mapWidth, mapHeight];
        Node start = null;
        Node goal  = null;

        for (int y = 0; y < mapHeight; y++)
        {
            Transform backgroundRow = backgroundContainer.transform.GetChild(y);

            for (int x = 0; x < mapWidth; x++)
            {
                NavTile tile = backgroundRow.GetChild(x).GetComponent <NavTile>();

                Node node = new Node(x, y);
                node.value    = tile;
                nodeMap[x, y] = node;
            }
        }

        start = FindNode(obj1);
        goal  = FindNode(obj2);

        //Execute AStar algorithm
        List <Node> nodePath = ExecuteAStar(start, goal);

        nodePath.Reverse();

        return(nodePath);
    }
        public virtual float GetCost(Vector3 a, Vector3 b,
			NavPolyId prevRef, NavTile prevTile, NavPoly prevPoly,
			NavPolyId curRef, NavTile curTile, NavPoly curPoly,
			NavPolyId nextRef, NavTile nextTile, NavPoly nextPoly)
        {
            return (a - b).Length() * areaCost[(int)curPoly.Area.Id];
        }
Exemple #9
0
    //find the node the obj is on
    private Node FindNode(GameObject obj)
    {
        Collider2D[] collidingObjects = Physics2D.OverlapCircleAll(obj.transform.position, 0.2f);
        foreach (Collider2D collidingObject in collidingObjects)
        {
            if (collidingObject.gameObject.GetComponent <NavTile>() != null)
            {
                //tile obj is on
                NavTile tile = collidingObject.gameObject.GetComponent <NavTile>();
                //find node that contains the tile
                for (int y = 0; y < mapHeight; y++)
                {
                    for (int x = 0; x < mapWidth; x++)
                    {
                        Node node = nodeMap[x, y];
                        if (node.value == tile)
                        {
                            return(node);
                        }
                    }
                }
            }
        }

        return(null);
    }
Exemple #10
0
        /// <summary>
        /// Only use this function if it is known that the provided polygon reference is valid.
        /// </summary>
        /// <param name="reference">Polygon reference</param>
        /// <param name="tile">Resulting tile</param>
        /// <param name="poly">Resulting poly</param>
        public void TryGetTileAndPolyByRefUnsafe(NavPolyId reference, out NavTile tile, out NavPoly poly)
        {
            int salt, polyIndex, tileIndex;

            idManager.Decode(ref reference, out polyIndex, out tileIndex, out salt);
            tile = tileIndices[tileIndex];
            poly = tileIndices[tileIndex].Polys[polyIndex];
        }
        public static TileBase DefaultTile(Sprite sprite)
        {
            NavTile tile = CreateDefaultNavTile();

            tile.name   = sprite.name;
            tile.sprite = sprite;
            tile.color  = Color.white;
            return(tile);
        }
Exemple #12
0
    public void SelectMovementDestination(NavTile goal)
    {
        Physics.Raycast(transform.position + Vector3.up * 0.001f, Vector3.down, out RaycastHit startHitInfo, float.MaxValue, LayerMask.GetMask("NavGrid"));
        NavTile        start     = startHitInfo.collider.GetComponent <NavTile>();
        List <NavTile> pathTiles = FindObjectOfType <NavGrid>().FindPath(start, goal);

        if (pathTiles != null && pathTiles[pathTiles.Count - 1] != start)
        {
            StartCoroutine(Animate(pathTiles));
        }
    }
Exemple #13
0
        /// <summary>
        /// Retrieve the endpoints of the offmesh connection at the specified polygon
        /// </summary>
        /// <param name="prevRef">The previous polygon reference</param>
        /// <param name="polyRef">The current polygon reference</param>
        /// <param name="startPos">The starting position</param>
        /// <param name="endPos">The ending position</param>
        /// <returns>True if endpoints found, false if not</returns>
        public bool GetOffMeshConnectionPolyEndPoints(NavPolyId prevRef, NavPolyId polyRef, ref Vector3 startPos, ref Vector3 endPos)
        {
            int salt = 0, indexTile = 0, indexPoly = 0;

            if (polyRef == NavPolyId.Null)
            {
                return(false);
            }

            //get current polygon
            idManager.Decode(ref polyRef, out indexPoly, out indexTile, out salt);
            if (indexTile >= maxTiles)
            {
                return(false);
            }
            if (tileList[indexTile].Salt != salt)
            {
                return(false);
            }
            NavTile tile = tileList[indexTile];

            if (indexPoly >= tile.PolyCount)
            {
                return(false);
            }
            NavPoly poly = tile.Polys[indexPoly];

            if (poly.PolyType != NavPolyType.OffMeshConnection)
            {
                return(false);
            }

            int idx0 = 0, idx1 = 1;

            //find the link that points to the first vertex
            foreach (Link link in poly.Links)
            {
                if (link.Edge == 0)
                {
                    if (link.Reference != prevRef)
                    {
                        idx0 = 1;
                        idx1 = 0;
                    }

                    break;
                }
            }

            startPos = tile.Verts[poly.Verts[idx0]];
            endPos   = tile.Verts[poly.Verts[idx1]];

            return(true);
        }
Exemple #14
0
    public NavTilemap(BoundsInt bounds)
    {
        navBounds = bounds;
        tiles     = new NavTile[bounds.size.x, bounds.size.y];

        for (int x = 0; x < tiles.GetLength(0); x++)
        {
            for (int y = 0; y < tiles.GetLength(1); y++)
            {
                tiles[x, y] = new NavTile(new Vector3Int(x, y, 0));
            }
        }
    }
    public List <NavTile> FindNodesInRange(NavTile startNode, float range)
    {
        HashSet <NavTile> closedSet = new HashSet <NavTile>();
        HashSet <NavTile> openSet   = new HashSet <NavTile>()
        {
            startNode
        };
        Dictionary <NavTile, float> gCost = new Dictionary <NavTile, float>
        {
            [startNode] = 0
        };

        while (openSet.Count > 0)
        {
            NavTile current = openSet.OrderBy(n => gCost[n]).First();

            if (gCost[current] > range)
            {
                return(new List <NavTile>(closedSet));
            }
            openSet.Remove(current);
            closedSet.Add(current);

            foreach (NavTile.Edge edge in current.Edges)
            {
                NavTile neighbor   = edge.tile;
                float   edgeWeight = edge.weight;

                if (closedSet.Contains(neighbor))
                {
                    continue;
                }

                float gCostTemp = gCost[current] + edgeWeight;
                if (!openSet.Contains(neighbor))
                {
                    openSet.Add(neighbor);
                }
                else if (gCostTemp >= gCost[neighbor])
                {
                    continue;
                }
                gCost[neighbor] = gCostTemp;
            }
        }

        return(new List <NavTile>(closedSet));
    }
Exemple #16
0
        /// <summary>
        /// Get the tile reference
        /// </summary>
        /// <param name="tile">Tile to look for</param>
        /// <returns>Tile reference</returns>
        public NavPolyId GetTileRef(NavTile tile)
        {
            if (tile == null)
            {
                return(NavPolyId.Null);
            }

            NavPolyId id;

            if (!tileRefs.TryGetValue(tile, out id))
            {
                id = NavPolyId.Null;
            }

            return(id);
        }
    private List <NavTile> ReconstructPath(Dictionary <NavTile, NavTile> cameFrom, NavTile goal)
    {
        List <NavTile> path    = new List <NavTile>();
        NavTile        current = goal;

        path.Add(current);

        while (cameFrom.ContainsKey(current))
        {
            current = cameFrom[current];
            path.Add(current);
        }

        path.Reverse();
        return(path);
    }
Exemple #18
0
        /// <summary>
        /// Retrieve the tile and poly based off of a polygon reference
        /// </summary>
        /// <param name="reference">Polygon reference</param>
        /// <param name="tile">Resulting tile</param>
        /// <param name="poly">Resulting poly</param>
        /// <returns>True if tile and poly successfully retrieved</returns>
        public bool TryGetTileAndPolyByRef(NavPolyId reference, out NavTile tile, out NavPoly poly)
        {
            tile = null;
            poly = null;

            if (reference == NavPolyId.Null)
            {
                return(false);
            }

            //Get tile and poly indices
            int salt, polyIndex, tileIndex;

            idManager.Decode(ref reference, out polyIndex, out tileIndex, out salt);

            //Make sure indices are valid
            if (tileIndex >= maxTiles)
            {
                return(false);
            }

            NavTile foundTile;

            if (!tileIndices.TryGetValue(tileIndex, out foundTile))
            {
                return(false);
            }

            if (foundTile.Salt != salt)
            {
                return(false);
            }

            if (polyIndex >= foundTile.PolyCount)
            {
                return(false);
            }

            //Retrieve tile and poly
            tile = tileIndices[tileIndex];
            poly = tileIndices[tileIndex].Polys[polyIndex];
            return(true);
        }
Exemple #19
0
        public bool RemoveTile(NavTile tile)
        {
            List <NavTile> tiles;

            if (tileSet.TryGetValue(tile.Location, out tiles))
            {
                tiles.Remove(tile);
            }
            else
            {
                return(false);
            }

            foreach (NavTile neighbourTile in GetTilesAt(tile.Location))
            {
                if (tile != neighbourTile)
                {
                    UnconnectLinks(neighbourTile, tile);
                }
            }

            for (int n = 0; n < 8; ++n)
            {
                foreach (NavTile neighbourTile in GetNeighborTilesAt(tile.Location, (BoundarySide)n))
                {
                    UnconnectLinks(neighbourTile, tile);
                }
            }

            NavPolyId id    = tileRefs[tile];
            int       index = idManager.DecodeTileIndex(ref id);

            tileIndices.Remove(index);

            tileRefs.Remove(tile);

            return(true);
        }
        private JObject SerializeMeshTile(NavTile tile, NavPolyId id)
        {
            var result = new JObject();
            result.Add("polyId", JToken.FromObject(id, serializer));
            result.Add("location", JToken.FromObject(tile.Location, serializer));
            result.Add("layer", JToken.FromObject(tile.Layer, serializer));
            result.Add("salt", JToken.FromObject(tile.Salt, serializer));
            result.Add("bounds", JToken.FromObject(tile.Bounds, serializer));
            result.Add("polys", JToken.FromObject(tile.Polys, serializer));
            result.Add("verts", JToken.FromObject(tile.Verts, serializer));
            result.Add("detailMeshes", JToken.FromObject(tile.DetailMeshes, serializer));
            result.Add("detailVerts", JToken.FromObject(tile.DetailVerts, serializer));
            result.Add("detailTris", JToken.FromObject(tile.DetailTris, serializer));
            result.Add("offMeshConnections", JToken.FromObject(tile.OffMeshConnections, serializer));

            JObject treeObject = new JObject();
            JArray treeNodes = new JArray();
            for (int i = 0; i < tile.BVTree.Count; i++)
                treeNodes.Add(JToken.FromObject(tile.BVTree[i], serializer));
            treeObject.Add("nodes", treeNodes);

            result.Add("bvTree", treeObject);
            result.Add("bvQuantFactor", JToken.FromObject(tile.BvQuantFactor, serializer));
            result.Add("bvNodeCount", JToken.FromObject(tile.BvNodeCount, serializer));
            result.Add("walkableClimb", JToken.FromObject(tile.WalkableClimb, serializer));

            return result;
        }
    public List <NavTile> FindPath(NavTile startNode, NavTile goalNode, float range)
    {
        HashSet <NavTile> closedSet = new HashSet <NavTile>();
        HashSet <NavTile> openSet   = new HashSet <NavTile>()
        {
            startNode
        };
        Dictionary <NavTile, float> gCost = new Dictionary <NavTile, float>
        {
            [startNode] = 0
        };
        Dictionary <NavTile, float> fCost = new Dictionary <NavTile, float>
        {
            [startNode] = HeuristicFunction(startNode, goalNode)
        };
        Dictionary <NavTile, NavTile> cameFrom = new Dictionary <NavTile, NavTile>();

        while (openSet.Count > 0)
        {
            NavTile current = openSet.OrderBy(n => fCost[n]).First();

            if (gCost[current] > range)
            {
                return(null);
            }

            if (current == goalNode)
            {
                return(ReconstructPath(cameFrom, goalNode));
            }

            openSet.Remove(current);
            closedSet.Add(current);

            foreach (NavTile.Edge edge in current.Edges)
            {
                NavTile neighbor   = edge.tile;
                float   edgeWeight = edge.weight;

                if (closedSet.Contains(neighbor))
                {
                    continue;
                }

                float gCostTemp = gCost[current] + edgeWeight;
                if (!openSet.Contains(neighbor))
                {
                    openSet.Add(neighbor);
                }
                else if (gCostTemp >= gCost[neighbor])
                {
                    continue;
                }
                gCost[neighbor]    = gCostTemp;
                fCost[neighbor]    = gCost[neighbor] + HeuristicFunction(neighbor, goalNode);
                cameFrom[neighbor] = current;
            }
        }

        return(null);
    }
Exemple #22
0
 public static void HandleTileMouseDown(NavTile tile)
 {
     OnTileMouseDown?.Invoke(tile);
 }
        private NavTile DeserializeMeshTile(JToken token, NavPolyIdManager manager, out NavPolyId refId)
        {
            refId = token["polyId"].ToObject<NavPolyId>(serializer);
            Vector2i location = token["location"].ToObject<Vector2i>(serializer);
            int layer = token["layer"].ToObject<int>(serializer);
            NavTile result = new NavTile(location, layer, manager, refId);

            result.Salt = token["salt"].ToObject<int>(serializer);
            result.Bounds = token["bounds"].ToObject<BBox3>(serializer);
            result.Polys = token["polys"].ToObject<NavPoly[]>(serializer);
            result.PolyCount = result.Polys.Length;
            result.Verts = token["verts"].ToObject<Vector3[]>(serializer);
            result.DetailMeshes = token["detailMeshes"].ToObject<PolyMeshDetail.MeshData[]>(serializer);
            result.DetailVerts = token["detailVerts"].ToObject<Vector3[]>(serializer);
            result.DetailTris = token["detailTris"].ToObject<PolyMeshDetail.TriangleData[]>(serializer);
            result.OffMeshConnections = token["offMeshConnections"].ToObject<OffMeshConnection[]>(serializer);
            result.OffMeshConnectionCount = result.OffMeshConnections.Length;
            result.BvNodeCount = token["bvNodeCount"].ToObject<int>(serializer);
            result.BvQuantFactor = token["bvQuantFactor"].ToObject<float>(serializer);
            result.WalkableClimb = token["walkableClimb"].ToObject<float>(serializer);

            var treeObject = (JObject) token["bvTree"];
            var nodes = treeObject.GetValue("nodes").ToObject<BVTree.Node[]>();

            result.BVTree = new BVTree(nodes);

            return result;
        }
 public List <NavTile> FindPath(NavTile startNode, NavTile goalNode)
 {
     return(FindPath(startNode, goalNode, float.MaxValue));
 }
Exemple #25
0
 public static void HandleTileMouseOver(NavTile tile)
 {
     OnTileMouseOver?.Invoke(tile);
 }
Exemple #26
0
 public List <NavTile> FindPath(NavTile start, NavTile goal)
 {
     return(pathfinder.FindPath(start, goal));
 }
Exemple #27
0
        /// <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 NavPolyId AddTile(NavMeshBuilder data)
        {
            //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(NavPolyId.Null);
            }

            NavPolyId newTileId = GetNextTileRef();
            NavTile   tile      = new NavTile(new Vector2i(header.X, header.Y), header.Layer, idManager, newTileId);

            tile.Salt = idManager.DecodeSalt(ref newTileId);

            if (header.BvNodeCount == 0)
            {
                tile.BVTree = null;
            }

            //patch header
            tile.Verts                  = data.NavVerts;
            tile.Polys                  = data.NavPolys;
            tile.PolyCount              = header.PolyCount;
            tile.DetailMeshes           = data.NavDMeshes;
            tile.DetailVerts            = data.NavDVerts;
            tile.DetailTris             = data.NavDTris;
            tile.BVTree                 = data.NavBvTree;
            tile.OffMeshConnections     = data.OffMeshCons;
            tile.OffMeshConnectionCount = header.OffMeshConCount;
            tile.BvQuantFactor          = header.BvQuantFactor;
            tile.BvNodeCount            = header.BvNodeCount;
            tile.Bounds                 = header.Bounds;
            tile.WalkableClimb          = header.WalkableClimb;

            //create connections within tile

            tile.ConnectIntLinks();
            tile.BaseOffMeshLinks();

            //create connections with neighbor tiles

            //connect with layers in current tile
            foreach (NavTile layerTile in GetTilesAt(header.X, header.Y))
            {
                if (layerTile != tile)
                {
                    tile.ConnectExtLinks(layerTile, BoundarySide.Internal);
                    layerTile.ConnectExtLinks(tile, BoundarySide.Internal);
                }

                tile.ConnectExtOffMeshLinks(layerTile, BoundarySide.Internal);
                layerTile.ConnectExtOffMeshLinks(tile, BoundarySide.Internal);
            }

            //connect with neighbor tiles
            for (int i = 0; i < 8; i++)
            {
                BoundarySide b  = (BoundarySide)i;
                BoundarySide bo = b.GetOpposite();
                foreach (NavTile neighborTile in GetNeighborTilesAt(header.X, header.Y, b))
                {
                    tile.ConnectExtLinks(neighborTile, b);
                    neighborTile.ConnectExtLinks(tile, bo);
                    tile.ConnectExtOffMeshLinks(neighborTile, b);
                    neighborTile.ConnectExtOffMeshLinks(tile, bo);
                }
            }

            AddTileAt(tile, GetNextTileRef());

            return(newTileId);
        }
Exemple #28
0
        public void AddTileAt(NavTile tile, NavPolyId id)
        {
            //TODO more error checking, what if tile already exists?

            Vector2i loc = tile.Location;
            List<NavTile> locList;
            if (!tileSet.TryGetValue(loc, out locList))
            {
                locList = new List<NavTile>();
                locList.Add(tile);
                tileSet.Add(loc, locList);
            }
            else
            {
                locList.Add(tile);
            }

            tileRefs.Add(tile, id);

            int index = idManager.DecodeTileIndex(ref id);

            //HACK this is pretty bad but only way to insert at index
            //TODO tileIndex should have a level of indirection from the list?
            while (index >= tileList.Count)
                tileList.Add(null);

            tileList[index] = tile;
        }
Exemple #29
0
        /// <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 NavPolyId AddTile(NavMeshBuilder data)
        {
            //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 NavPolyId.Null;

            NavPolyId newTileId = GetNextTileRef();
            NavTile tile = new NavTile(new Vector2i(header.X, header.Y), header.Layer, idManager, newTileId);
            tile.Salt = idManager.DecodeSalt(ref newTileId);

            if (header.BvNodeCount == 0)
                tile.BVTree = null;

            //patch header
            tile.Verts = data.NavVerts;
            tile.Polys = data.NavPolys;
            tile.PolyCount = header.PolyCount;
            tile.DetailMeshes = data.NavDMeshes;
            tile.DetailVerts = data.NavDVerts;
            tile.DetailTris = data.NavDTris;
            tile.BVTree = data.NavBvTree;
            tile.OffMeshConnections = data.OffMeshCons;
            tile.OffMeshConnectionCount = header.OffMeshConCount;
            tile.BvQuantFactor = header.BvQuantFactor;
            tile.BvNodeCount = header.BvNodeCount;
            tile.Bounds = header.Bounds;
            tile.WalkableClimb = header.WalkableClimb;

            //create connections within tile

            tile.ConnectIntLinks();
            tile.BaseOffMeshLinks();

            //create connections with neighbor tiles

            //connect with layers in current tile
            foreach (NavTile layerTile in GetTilesAt(header.X, header.Y))
            {
                if (layerTile != tile)
                {
                    tile.ConnectExtLinks(layerTile, BoundarySide.Internal);
                    layerTile.ConnectExtLinks(tile, BoundarySide.Internal);
                }

                tile.ConnectExtOffMeshLinks(layerTile, BoundarySide.Internal);
                layerTile.ConnectExtOffMeshLinks(tile, BoundarySide.Internal);
            }

            //connect with neighbor tiles
            for (int i = 0; i < 8; i++)
            {
                BoundarySide b = (BoundarySide)i;
                BoundarySide bo = b.GetOpposite();
                foreach (NavTile neighborTile in GetNeighborTilesAt(header.X, header.Y, b))
                {
                    tile.ConnectExtLinks(neighborTile, b);
                    neighborTile.ConnectExtLinks(tile, bo);
                    tile.ConnectExtOffMeshLinks(neighborTile, b);
                    neighborTile.ConnectExtOffMeshLinks(tile, bo);
                }
            }

            AddTileAt(tile, GetNextTileRef());

            return newTileId;
        }
Exemple #30
0
        /// <summary>
        /// Get the tile reference
        /// </summary>
        /// <param name="tile">Tile to look for</param>
        /// <returns>Tile reference</returns>
        public NavPolyId GetTileRef(NavTile tile)
        {
            if (tile == null)
                return NavPolyId.Null;

            NavPolyId id;
            if (!tileRefs.TryGetValue(tile, out id))
                id = NavPolyId.Null;

            return id;
        }
Exemple #31
0
        /// <summary>
        /// Retrieve the tile and poly based off of a polygon reference
        /// </summary>
        /// <param name="reference">Polygon reference</param>
        /// <param name="tile">Resulting tile</param>
        /// <param name="poly">Resulting poly</param>
        /// <returns>True if tile and poly successfully retrieved</returns>
        public bool TryGetTileAndPolyByRef(NavPolyId reference, out NavTile tile, out NavPoly poly)
        {
            tile = null;
            poly = null;

            if (reference == NavPolyId.Null)
                return false;

            //Get tile and poly indices
            int salt, polyIndex, tileIndex;
            idManager.Decode(ref reference, out polyIndex, out tileIndex, out salt);

            //Make sure indices are valid
            if (tileIndex >= maxTiles)
                return false;

            if (tileList[tileIndex].Salt != salt)
                return false;

            if (polyIndex >= tileList[tileIndex].PolyCount)
                return false;

            //Retrieve tile and poly
            tile = tileList[tileIndex];
            poly = tileList[tileIndex].Polys[polyIndex];
            return true;
        }
Exemple #32
0
 /// <summary>
 /// Only use this function if it is known that the provided polygon reference is valid.
 /// </summary>
 /// <param name="reference">Polygon reference</param>
 /// <param name="tile">Resulting tile</param>
 /// <param name="poly">Resulting poly</param>
 public void TryGetTileAndPolyByRefUnsafe(NavPolyId reference, out NavTile tile, out NavPoly poly)
 {
     int salt, polyIndex, tileIndex;
     idManager.Decode(ref reference, out polyIndex, out tileIndex, out salt);
     tile = tileList[tileIndex];
     poly = tileList[tileIndex].Polys[polyIndex];
 }
        private byte[] SerializeMeshTile(NavTile tile, NavPolyId baseRef)
        {
            var memoryStream = new MemoryStream();

            using (var binaryWriter = new BinaryWriter(memoryStream))
            {
                binaryWriter.Write(baseRef.Id);

                binaryWriter.Write(tile.Location.X);
                binaryWriter.Write(tile.Location.Y);

                binaryWriter.Write(tile.Layer);
                binaryWriter.Write(tile.Salt);

                binaryWriter.Write(tile.Bounds.Min.X);
                binaryWriter.Write(tile.Bounds.Min.Y);
                binaryWriter.Write(tile.Bounds.Min.Z);
                binaryWriter.Write(tile.Bounds.Max.X);
                binaryWriter.Write(tile.Bounds.Max.Y);
                binaryWriter.Write(tile.Bounds.Max.Z);

                var polys = new List <NavPoly>(tile.Polys);
                binaryWriter.Write(polys.Count);

                foreach (var poly in polys)
                {
                    binaryWriter.Write((byte)poly.PolyType);

                    var polyLinks = new List <Link>(poly.Links);
                    binaryWriter.Write(polyLinks.Count);

                    foreach (var polyLink in polyLinks)
                    {
                        binaryWriter.Write(polyLink.Reference.Id);
                        binaryWriter.Write(polyLink.Edge);
                        binaryWriter.Write((byte)polyLink.Side);
                        binaryWriter.Write(polyLink.BMin);
                        binaryWriter.Write(polyLink.BMax);
                    }

                    var polyVerts = new List <int>(poly.Verts);
                    binaryWriter.Write(polyVerts.Count);

                    foreach (var polyVert in polyVerts)
                    {
                        binaryWriter.Write(polyVert);
                    }

                    var polyNeis = new List <int>(poly.Neis);
                    binaryWriter.Write(polyNeis.Count);

                    foreach (var polyNei in polyNeis)
                    {
                        binaryWriter.Write(polyNei);
                    }

                    if (poly.Tag == null)
                    {
                        binaryWriter.Write((byte)0xFE);
                    }
                    else
                    {
                        binaryWriter.Write((byte)poly.Tag);
                    }

                    binaryWriter.Write(poly.VertCount);
                    binaryWriter.Write(poly.Area.Id);
                }

                var verts = new List <Vector3>(tile.Verts);
                binaryWriter.Write(verts.Count);

                foreach (var vert in verts)
                {
                    binaryWriter.Write(vert.X);
                    binaryWriter.Write(vert.Y);
                    binaryWriter.Write(vert.Z);
                }

                var detailMeshes = new List <PolyMeshDetail.MeshData>(tile.DetailMeshes);
                binaryWriter.Write(detailMeshes.Count);

                foreach (var detailMesh in detailMeshes)
                {
                    binaryWriter.Write(detailMesh.VertexIndex);
                    binaryWriter.Write(detailMesh.VertexCount);
                    binaryWriter.Write(detailMesh.TriangleIndex);
                    binaryWriter.Write(detailMesh.TriangleCount);
                }

                var detailVerts = new List <Vector3>(tile.DetailVerts);
                binaryWriter.Write(detailVerts.Count);

                foreach (var detailVert in detailVerts)
                {
                    binaryWriter.Write(detailVert.X);
                    binaryWriter.Write(detailVert.Y);
                    binaryWriter.Write(detailVert.Z);
                }

                var detailTris = new List <PolyMeshDetail.TriangleData>(tile.DetailTris);
                binaryWriter.Write(detailTris.Count);

                foreach (var detailTri in detailTris)
                {
                    binaryWriter.Write(detailTri.VertexHash0);
                    binaryWriter.Write(detailTri.VertexHash1);
                    binaryWriter.Write(detailTri.VertexHash2);
                    binaryWriter.Write(detailTri.Flags);
                }

                var offMeshConnections = new List <OffMeshConnection>(tile.OffMeshConnections);
                binaryWriter.Write(offMeshConnections.Count);

                foreach (var offMeshConnection in offMeshConnections)
                {
                }

                binaryWriter.Write(tile.BVTree.Count);

                for (var i = 0; i < tile.BVTree.Count; i++)
                {
                    var node = tile.BVTree[i];

                    binaryWriter.Write(node.Bounds.Min.X);
                    binaryWriter.Write(node.Bounds.Min.Y);
                    binaryWriter.Write(node.Bounds.Min.Z);
                    binaryWriter.Write(node.Bounds.Max.X);
                    binaryWriter.Write(node.Bounds.Max.Y);
                    binaryWriter.Write(node.Bounds.Max.Z);
                    binaryWriter.Write(node.Index);
                }

                binaryWriter.Write(tile.BvQuantFactor);
                binaryWriter.Write(tile.BvNodeCount);
                binaryWriter.Write(tile.WalkableClimb);
            }

            return(memoryStream.ToArray());
        }
Exemple #34
0
 public virtual bool PassFilter(NavPolyId polyId, NavTile tile, NavPoly poly)
 {
     return true;
 }
        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);
        }
Exemple #36
0
        /// <summary>
        /// Get edge midpoint between two prolygons
        /// </summary>
        /// <param name="from">"From" polygon reference</param>
        /// <param name="fromPoly">"From" polygon data</param>
        /// <param name="fromTile">"From" mesh tile</param>
        /// <param name="to">"To" polygon reference</param>
        /// <param name="toPoly">"To" polygon data</param>
        /// <param name="toTile">"To" mesh tile</param>
        /// <param name="mid">Edge midpoint</param>
        /// <returns>True, if midpoint found. False, if otherwise.</returns>
        public bool GetEdgeMidPoint(NavPolyId from, NavPoly fromPoly, NavTile fromTile, NavPolyId to, NavPoly toPoly, NavTile toTile, ref Vector3 mid)
        {
            Vector3 left = new Vector3();
            Vector3 right = new Vector3();
            if (!GetPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, ref left, ref right))
                return false;

            mid = (left + right) * 0.5f;

            return true;
        }
Exemple #37
0
        /// <summary>
        /// Find points on the left and right side.
        /// </summary>
        /// <param name="from">"From" polygon reference</param>
        /// <param name="fromPoly">"From" polygon data</param>
        /// <param name="fromTile">"From" mesh tile</param>
        /// <param name="to">"To" polygon reference</param>
        /// <param name="toPoly">"To" polygon data</param>
        /// <param name="toTile">"To" mesh tile</param>
        /// <param name="left">Resulting point on the left side</param>
        /// <param name="right">Resulting point on the right side</param>
        /// <returns>True, if points found. False, if otherwise.</returns>
        public bool GetPortalPoints(NavPolyId from, NavPoly fromPoly, NavTile fromTile, NavPolyId to, NavPoly toPoly, NavTile toTile, ref Vector3 left, ref Vector3 right)
        {
            //find the link that points to the 'to' polygon
            Link link = null;
            foreach (Link fromLink in fromPoly.Links)
            {
                if (fromLink.Reference == to)
                {
                    link = fromLink;
                    break;
                }
            }

            if (link == null)
                return false;

            //handle off-mesh connections
            if (fromPoly.PolyType == NavPolyType.OffMeshConnection)
            {
                //find link that points to first vertex
                foreach (Link fromLink in fromPoly.Links)
                {
                    if (fromLink.Reference == to)
                    {
                        int v = fromLink.Edge;
                        left = fromTile.Verts[fromPoly.Verts[v]];
                        right = fromTile.Verts[fromPoly.Verts[v]];
                        return true;
                    }
                }

                return false;
            }

            if (toPoly.PolyType == NavPolyType.OffMeshConnection)
            {
                //find link that points to first vertex
                foreach (Link toLink in toPoly.Links)
                {
                    if (toLink.Reference == from)
                    {
                        int v = toLink.Edge;
                        left = toTile.Verts[toPoly.Verts[v]];
                        right = toTile.Verts[toPoly.Verts[v]];
                        return true;
                    }
                }

                return false;
            }

            //find portal vertices
            int v0 = fromPoly.Verts[link.Edge];
            int v1 = fromPoly.Verts[(link.Edge + 1) % fromPoly.VertCount];
            left = fromTile.Verts[v0];
            right = fromTile.Verts[v1];

            //if the link is at the tile boundary, clamp the vertices to tile width
            if (link.Side != BoundarySide.Internal)
            {
                //unpack portal limits
                if (link.BMin != 0 || link.BMax != 255)
                {
                    float s = 1.0f / 255.0f;
                    float tmin = link.BMin * s;
                    float tmax = link.BMax * s;
                    left = Vector3.Lerp(fromTile.Verts[v0], fromTile.Verts[v1], tmin);
                    right = Vector3.Lerp(fromTile.Verts[v0], fromTile.Verts[v1], tmax);
                }
            }

            return true;
        }
 private float HeuristicFunction(NavTile source, NavTile dest)
 {
     return(Vector3.Distance(source.transform.position, dest.transform.position));
 }