Пример #1
0
		/// <summary>
		/// Try to find the node. If it doesn't exist, create a new node.
		/// </summary>
		/// <param name="id">Node's id</param>
		/// <returns>The node</returns>
		public Node GetNode(PolyId id)
		{
			Node node;
			if (nodeDict.TryGetValue(id, out node))
			{
				return node;
			}

			if (nodes.Count >= maxNodes)
				return null;

			Node newNode = new Node();
			newNode.ParentIdx = 0;
			newNode.cost = 0;
			newNode.total = 0;
			newNode.Id = id;
			newNode.Flags = 0;
			
			nodes.Add(newNode);
			nodeDict.Add(id, newNode);

			return newNode;
		}
Пример #2
0
        /// <summary>
        /// Store polygons that are within a certain range from the current polygon
        /// </summary>
        /// <param name="centerPoint">Starting position</param>
        /// <param name="radius">Range to search within</param>
        /// <param name="resultRef">All the polygons within range</param>
        /// <param name="resultParent">Polygon's parents</param>
        /// <param name="resultCount">Number of polygons stored</param>
        /// <param name="maxResult">Maximum number of polygons allowed</param>
        /// <returns>True, unless input is invalid</returns>
        public bool FindLocalNeighbourhood(NavPoint centerPoint, float radius, PolyId[] resultRef, PolyId[] resultParent, ref int resultCount, int maxResult)
        {
            resultCount = 0;

            //validate input
            if (centerPoint.Polygon == PolyId.Null || !nav.IsValidPolyRef(centerPoint.Polygon))
                return false;

            int MAX_STACK = 48;
            Node[] stack = new Node[MAX_STACK];
            int nstack = 0;

            tinyNodePool.Clear();

            Node startNode = tinyNodePool.GetNode(centerPoint.Polygon);
            startNode.ParentIdx = 0;
            startNode.Id = centerPoint.Polygon;
            startNode.Flags = NodeFlags.Closed;
            stack[nstack++] = startNode;

            float radiusSqr = radius * radius;

            Vector3[] pa = new Vector3[PathfindingCommon.VERTS_PER_POLYGON];
            Vector3[] pb = new Vector3[PathfindingCommon.VERTS_PER_POLYGON];

            int n = 0;
            if (n < maxResult)
            {
                resultRef[n] = startNode.Id;
                resultParent[n] = PolyId.Null;
                ++n;
            }

            while (nstack > 0)
            {
                //pop front
                Node curNode = stack[0];
                for (int i = 0; i < nstack - 1; i++)
                    stack[i] = stack[i + 1];
                nstack--;

                //get poly and tile
                PolyId curRef = curNode.Id;
                MeshTile curTile;
                Poly curPoly;
                nav.TryGetTileAndPolyByRefUnsafe(curRef, out curTile, out curPoly);

                for (int i = curPoly.FirstLink; i != Link.Null; i = curTile.Links[i].Next)
                {
                    Link link = curTile.Links[i];
                    PolyId neighbourRef = link.Reference;

                    //skip invalid neighbours
                    if (neighbourRef == PolyId.Null)
                        continue;

                    //skip if cannot allocate more nodes
                    Node neighbourNode = tinyNodePool.GetNode(neighbourRef);
                    if (neighbourNode == null)
                        continue;

                    //skip visited
                    if ((neighbourNode.Flags & NodeFlags.Closed) != 0)
                        continue;

                    //expand to neighbour
                    MeshTile neighbourTile;
                    Poly neighbourPoly;
                    nav.TryGetTileAndPolyByRefUnsafe(neighbourRef, out neighbourTile, out neighbourPoly);

                    //skip off-mesh connections
                    if (neighbourPoly.PolyType == PolygonType.OffMeshConnection)
                        continue;

                    //find edge and calculate distance to edge
                    Vector3 va = new Vector3();
                    Vector3 vb = new Vector3();
                    if (!GetPortalPoints(curRef, curPoly, curTile, neighbourRef, neighbourPoly, neighbourTile, ref va, ref vb))
                        continue;

                    //if the circle is not touching the next polygon, skip it
                    float tseg;
                    float distSqr = Distance.PointToSegment2DSquared(ref centerPoint.Position, ref va, ref vb, out tseg);
                    if (distSqr > radiusSqr)
                        continue;

                    //mark node visited
                    neighbourNode.Flags |= NodeFlags.Closed;
                    neighbourNode.ParentIdx = tinyNodePool.GetNodeIdx(curNode);

                    //check that the polygon doesn't collide with existing polygons

                    //collect vertices of the neighbour poly
                    int npa = neighbourPoly.VertCount;
                    for (int k = 0; k < npa; k++)
                        pa[k] = neighbourTile.Verts[neighbourPoly.Verts[k]];

                    bool overlap = false;
                    for (int j = 0; j < n; j++)
                    {
                        PolyId pastRef = resultRef[j];

                        //connected polys do not overlap
                        bool connected = false;
                        for (int k = curPoly.FirstLink; k != Link.Null; k = curTile.Links[k].Next)
                        {
                            if (curTile.Links[k].Reference == pastRef)
                            {
                                connected = true;
                                break;
                            }
                        }

                        if (connected)
                            continue;

                        //potentially overlapping
                        MeshTile pastTile;
                        Poly pastPoly;
                        nav.TryGetTileAndPolyByRefUnsafe(pastRef, out pastTile, out pastPoly);

                        //get vertices and test overlap
                        int npb = pastPoly.VertCount;
                        for (int k = 0; k < npb; k++)
                            pb[k] = pastTile.Verts[pastPoly.Verts[k]];

                        if (Intersection.PolyPoly2D(pa, npa, pb, npb))
                        {
                            overlap = true;
                            break;
                        }
                    }

                    if (overlap)
                        continue;

                    //store poly
                    if (n < maxResult)
                    {
                        resultRef[n] = neighbourRef;
                        resultParent[n] = curRef;
                        ++n;
                    }

                    if (nstack < MAX_STACK)
                    {
                        stack[nstack++] = neighbourNode;
                    }
                }
            }

            resultCount = n;

            return true;
        }
Пример #3
0
 public void SetNodeFlagOpen(ref Node node)
 {
     node.Flags |= NodeFlags.Open;
 }
Пример #4
0
 public void SetNodeFlagClosed(ref Node node)
 {
     node.Flags &= ~NodeFlags.Open;
     node.Flags |= NodeFlags.Closed;
 }
Пример #5
0
 public NodeFlags RemoveNodeFlagClosed(Node node)
 {
     return node.Flags & ~NodeFlags.Closed;
 }
Пример #6
0
 public bool IsInOpenList(Node node)
 {
     return (node.Flags & NodeFlags.Open) != 0;
 }
Пример #7
0
 public bool IsInClosedList(Node node)
 {
     return (node.Flags & NodeFlags.Closed) != 0;
 }
Пример #8
0
		/// <summary>
		/// Gets the id of the node.
		/// </summary>
		/// <param name="node">The node</param>
		/// <returns>The id</returns>
		public int GetNodeIdx(Node node)
		{
			if (node == null)
				return 0;

			for (int i = 0; i < nodes.Count; i++)
			{
				if (nodes[i] == node)
					return i + 1;
			}

			return 0;
		}