Beispiel #1
0
        public override void Prepare()
        {
            this.nnConstraint.tags = this.enabledTags;
            NNInfo nearest = AstarPath.active.GetNearest(this.startPoint, this.nnConstraint, this.startHint);

            this.startPoint    = nearest.clampedPosition;
            this.endPoint      = this.startPoint;
            this.startIntPoint = (Int3)this.startPoint;
            this.hTarget       = (Int3)this.aim;
            this.startNode     = nearest.node;
            this.endNode       = this.startNode;
            if (this.startNode == null || this.endNode == null)
            {
                base.LogError("Couldn't find close nodes to the start point");
                base.Error();
                return;
            }
            if (!this.startNode.Walkable)
            {
                base.LogError("The node closest to the start point is not walkable");
                base.Error();
                return;
            }
            this.heuristicScale = this.aimStrength;
        }
Beispiel #2
0
        /** Prepares the path. Searches for start and end nodes and does some simple checking if a path is at all possible */
        public virtual void Prepare()
        {
            //@pathStartTime = startTime;

            //maxAngle = NmaxAngle;
            //angleCost = NangleCost;
            //stepByStep = NstepByStep;
            //unitRadius = 0;//BETA, Not used
            nnConstraint.tags = enabledTags;
            NNInfo startNNInfo = AstarPath.active.GetNearest(startPoint, nnConstraint, startHint);

            //Tell the NNConstraint which node was found as the start node if it is a PathNNConstraint and not a normal NNConstraint
            PathNNConstraint pathNNConstraint = nnConstraint as PathNNConstraint;

            if (pathNNConstraint != null)
            {
                pathNNConstraint.SetStart(startNNInfo.node);
            }

            startPoint    = startNNInfo.clampedPosition;
            startIntPoint = (Int3)startPoint;
            startNode     = startNNInfo.node;

            if (hasEndPoint)
            {
                NNInfo endNNInfo = AstarPath.active.GetNearest(endPoint, nnConstraint, endHint);
                endPoint = endNNInfo.clampedPosition;
                hTarget  = (Int3)endPoint;
                endNode  = endNNInfo.node;
            }



            if (startNode == null || (hasEndPoint == true && endNode == null))
            {
                LogError("Couldn't find close nodes to either the start or the end (start = " + (startNode != null) + " end = " + (endNode != null) + ")");
                return;
            }

            if (!startNode.walkable)
            {
                Debug.DrawRay(startPoint, Vector3.up, Color.red);
                Debug.DrawLine(startPoint, (Vector3)startNode.position, Color.red);
                Debug.Break();
                LogError("The node closest to the start point is not walkable");
                return;
            }

            if (hasEndPoint && !endNode.walkable)
            {
                LogError("The node closest to the end point is not walkable");
                return;
            }

            if (hasEndPoint && startNode.area != endNode.area)
            {
                LogError("There is no valid path to the target (start area: " + startNode.area + ", target area: " + endNode.area + ")");
                return;
            }
        }
Beispiel #3
0
        private void GetClosestWalkableNodesToChildrenRecursively(Transform tr, List <GraphNode> nodes)
        {
            IEnumerator enumerator = tr.GetEnumerator();

            try
            {
                while (enumerator.MoveNext())
                {
                    Transform current = (Transform)enumerator.Current;
                    NNInfo    nearest = AstarPath.active.GetNearest(current.position, NNConstraint.Default);
                    if ((nearest.node != null) && nearest.node.Walkable)
                    {
                        nodes.Add(nearest.node);
                    }
                    this.GetClosestWalkableNodesToChildrenRecursively(current, nodes);
                }
            }
            finally
            {
                IDisposable disposable = enumerator as IDisposable;
                if (disposable == null)
                {
                }
                disposable.Dispose();
            }
        }
Beispiel #4
0
 protected override void Prepare()
 {
     if (this.startNode == null)
     {
         this.nnConstraint.tags = this.enabledTags;
         NNInfo nearest = AstarPath.active.GetNearest(this.originalStartPoint, this.nnConstraint);
         this.startPoint = nearest.position;
         this.startNode  = nearest.node;
     }
     else
     {
         this.startPoint = (Vector3)this.startNode.position;
     }
     if (this.startNode == null)
     {
         base.Error();
         base.LogError("Couldn't find a close node to the start point");
         return;
     }
     if (!base.CanTraverse(this.startNode))
     {
         base.Error();
         base.LogError("The node closest to the start point could not be traversed");
         return;
     }
 }
 // Token: 0x06000767 RID: 1895 RVA: 0x00048238 File Offset: 0x00046638
 public override void Prepare()
 {
     if (this.startNode == null)
     {
         this.nnConstraint.tags = this.enabledTags;
         NNInfo nearest = AstarPath.active.GetNearest(this.originalStartPoint, this.nnConstraint);
         this.startPoint = nearest.clampedPosition;
         this.startNode  = nearest.node;
     }
     else
     {
         this.startPoint = (Vector3)this.startNode.position;
     }
     if (this.startNode == null)
     {
         base.Error();
         base.LogError("Couldn't find a close node to the start point");
         return;
     }
     if (!this.startNode.Walkable)
     {
         base.Error();
         base.LogError("The node closest to the start point is not walkable");
         return;
     }
 }
Beispiel #6
0
 public static NNInfo GetNearestForce(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
 {
     NNInfo nearestForceBoth = NavMeshGraph.GetNearestForceBoth(graph, navmesh, position, constraint, accurateNearestNode);
     nearestForceBoth.node = nearestForceBoth.constrainedNode;
     nearestForceBoth.clampedPosition = nearestForceBoth.constClampedPosition;
     return nearestForceBoth;
 }
Beispiel #7
0
        /** Queries the tree for the best node, searching within a circle around \a p with the specified radius */
        public NNInfo QueryCircle(Vector3 p, float radius, NNConstraint constraint)
        {
            BBTreeBox c = root;

            if (c == null)
            {
                return(null);
            }

#if DEBUG
            Vector3 prev = new Vector3(1, 0, 0) * radius + p;
            for (double i = 0; i < Math.PI * 2; i += Math.PI / 50.0)
            {
                Vector3 cpos = new Vector3((float)Math.Cos(i), 0, (float)Math.Sin(i)) * radius + p;
                Debug.DrawLine(prev, cpos, Color.yellow);
                prev = cpos;
            }
#endif

            NNInfo nnInfo = new NNInfo(null);

            SearchBoxCircle(c, p, radius, constraint, ref nnInfo);

            nnInfo.UpdateInfo();

            return(nnInfo);
        }
Beispiel #8
0
        protected override void Prepare()
        {
            this.nnConstraint.tags = this.enabledTags;
            NNInfo nearest = AstarPath.active.GetNearest(this.startPoint, this.nnConstraint);

            this.startPoint    = nearest.position;
            this.endPoint      = this.startPoint;
            this.startIntPoint = (Int3)this.startPoint;
            this.hTarget       = (Int3)this.aim;
            this.startNode     = nearest.node;
            this.endNode       = this.startNode;
            if (this.startNode == null || this.endNode == null)
            {
                base.LogError("Couldn't find close nodes to the start point");
                base.Error();
                return;
            }
            if (!base.CanTraverse(this.startNode))
            {
                base.LogError("The node closest to the start point could not be traversed");
                base.Error();
                return;
            }
            this.heuristicScale = this.aimStrength;
        }
Beispiel #9
0
        public override void Prepare()
        {
            AstarProfiler.StartProfile("Get Nearest");

            //Initialize the NNConstraint
            nnConstraint.tags = enabledTags;
            NNInfo startNNInfo = AstarPath.active.GetNearest(originalStartPoint, nnConstraint);

            startPoint = startNNInfo.clampedPosition;
            startNode  = startNNInfo.node;

            AstarProfiler.EndProfile();

#if ASTARDEBUG
            Debug.DrawLine((Vector3)startNode.position, startPoint, Color.blue);
#endif

            if (startNode == null)
            {
                Error();
                LogError("Couldn't find a close node to the start point");
                return;
            }

            if (!startNode.walkable)
            {
#if ASTARDEBUG
                Debug.DrawRay(startPoint, Vector3.up, Color.red);
                Debug.DrawLine(startPoint, (Vector3)startNode.position, Color.red);
#endif
                Error();
                LogError("The node closest to the start point is not walkable");
                return;
            }
        }
Beispiel #10
0
        public override void Prepare()
        {
            nnConstraint.tags = enabledTags;
            NNInfo startNNInfo = AstarPath.active.GetNearest(startPoint, nnConstraint, startHint);

            startPoint = startNNInfo.clampedPosition;
            endPoint   = startPoint;

            startIntPoint = (Int3)startPoint;
            hTarget       = (Int3)aim;      //startIntPoint;

            startNode = startNNInfo.node;
            endNode   = startNode;

#if ASTARDEBUG
            Debug.DrawLine((Vector3)startNode.position, startPoint, Color.blue);
            Debug.DrawLine((Vector3)endNode.position, endPoint, Color.blue);
#endif

            if (startNode == null || endNode == null)
            {
                LogError("Couldn't find close nodes to the start point");
                Error();
                return;
            }

            if (!startNode.Walkable)
            {
                LogError("The node closest to the start point is not walkable");
                Error();
                return;
            }

            heuristicScale = aimStrength;
        }
Beispiel #11
0
        public static NNInfo GetNearestForce(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
        {
            NNInfo info = GetNearestForceBoth(graph, navmesh, position, constraint, accurateNearestNode);

            info.node            = info.constrainedNode;
            info.clampedPosition = info.constClampedPosition;
            return(info);
        }
        /** This performs a linear search through all polygons returning the closest one */
        public static NNInfo GetNearestForce(Node[] nodes, Int3[] vertices, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
        {
            NNInfo nn = GetNearestForceBoth(nodes, vertices, position, constraint, accurateNearestNode);

            nn.node            = nn.constrainedNode;
            nn.clampedPosition = nn.constClampedPosition;
            return(nn);
        }
        /// <summary>
        /// This will be called on the same time as Awake on the gameObject which the AstarPath script is attached to. (remember, not in the editor)
        /// Use this for any initialization code which can't be placed in Scan
        /// </summary>
        //public override void Awake() {
        //    base.Awake();
        //}


        // IMPROVE not really necessary. I just override this NavGraph method to add the debug line at the bottom. Otherwise its identical
        public override NNInfo GetNearest(Vector3 position, NNConstraint constraint, Node hint) {

            if (nodes == null) {
                return new NNInfo();
            }

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            float minDist = float.PositiveInfinity;
            Node minNode = null;

            float minConstDist = float.PositiveInfinity;
            Node minConstNode = null;

            for (int i = 0; i < nodes.Length; i++) {

                Node node = nodes[i];
                float dist = (position - (Vector3)node.position).sqrMagnitude;

                if (dist < minDist) {
                    minDist = dist;
                    minNode = node;
                }

                if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node)) {
                    minConstDist = dist;
                    minConstNode = node;
                }
            }

            NNInfo nnInfo = new NNInfo(minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null) {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            }
            else if (minNode != null) {
                nnInfo.constrainedNode = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            #region Debugging

            if (nnInfo.constrainedNode == null) {
                float closestDistance;
                Node closestNode = __FindClosestNode(position, out closestDistance);
                D.Warn("Can't find node close enough to {0}. ClosestNode is {1} away.", position, closestDistance);
            }
            else {
                D.Log("Closest Node is at {0}, {1} from {2}.", (Vector3)nnInfo.constrainedNode.position, Mathf.Sqrt(minDist), position);
            }

            //D.Log("GetNearest() constraint.Suitable = {0}.", constraint.Suitable(nnInfo.node));
            #endregion

            return nnInfo;
        }
Beispiel #14
0
        public override void Prepare()
        {
            this.nnConstraint.tags = this.enabledTags;
            NNInfo           nearest          = AstarPath.active.GetNearest(this.startPoint, this.nnConstraint, this.startHint);
            PathNNConstraint pathNNConstraint = this.nnConstraint as PathNNConstraint;

            if (pathNNConstraint != null)
            {
                pathNNConstraint.SetStart(nearest.node);
            }
            this.startPoint    = nearest.position;
            this.startIntPoint = (Int3)this.startPoint;
            this.startNode     = nearest.node;
            if (this.startNode == null)
            {
                base.Error();
                return;
            }
            if (!this.startNode.Walkable)
            {
                base.Error();
                return;
            }
            if (this.hasEndPoint)
            {
                NNInfo nearest2 = AstarPath.active.GetNearest(this.endPoint, this.nnConstraint, this.endHint);
                this.endPoint = nearest2.position;
                this.endNode  = nearest2.node;
                if (this.startNode == null && this.endNode == null)
                {
                    base.Error();
                    return;
                }
                if (this.endNode == null)
                {
                    base.Error();
                    return;
                }
                if (!this.endNode.Walkable)
                {
                    base.Error();
                    return;
                }
                if (this.startNode.Area != this.endNode.Area)
                {
                    base.Error();
                    return;
                }
                if (!this.EndPointGridGraphSpecialCase(nearest2.node))
                {
                    this.hTarget     = (Int3)this.endPoint;
                    this.hTargetNode = this.endNode;
                    base.pathHandler.GetPathNode(this.endNode).flag1 = true;
                }
            }
        }
Beispiel #15
0
		public override void Prepare () {
			nnConstraint.tags = enabledTags;
			NNInfo startNNInfo 	= AstarPath.active.GetNearest (startPoint,nnConstraint);
			
			startNode = startNNInfo.node;
			if (startNode == null) {
				Error ();
				LogError ("Could not find close node to the start point");
				return;
			}
		}
Beispiel #16
0
        public override void Prepare()
        {
            base.nnConstraint.tags = base.enabledTags;
            NNInfo nearest = AstarPath.active.GetNearest(this.startPoint, base.nnConstraint);

            this.startNode = nearest.node;
            if (this.startNode == null)
            {
                base.Error();
            }
        }
Beispiel #17
0
        // Token: 0x06002727 RID: 10023 RVA: 0x001AFCE0 File Offset: 0x001ADEE0
        protected override void Prepare()
        {
            this.nnConstraint.tags = this.enabledTags;
            NNInfo nearest = AstarPath.active.GetNearest(this.startPoint, this.nnConstraint);

            this.startNode = nearest.node;
            if (this.startNode == null)
            {
                base.FailWithError("Could not find close node to the start point");
                return;
            }
        }
Beispiel #18
0
        public override void Prepare()
        {
            base.nnConstraint.tags = base.enabledTags;
            NNInfo nearest = AstarPath.active.GetNearest(this.startPoint, base.nnConstraint);

            this.startNode = nearest.node;
            if (this.startNode == null)
            {
                base.Error();
                base.LogError("Could not find close node to the start point");
            }
        }
 private void GetClosestWalkableNodesToChildrenRecursively(Transform tr, List <GraphNode> nodes)
 {
     foreach (Transform transform in tr)
     {
         NNInfo nearest = AstarPath.active.GetNearest(transform.position, NNConstraint.Default);
         if (nearest.node != null && nearest.node.Walkable)
         {
             nodes.Add(nearest.node);
         }
         this.GetClosestWalkableNodesToChildrenRecursively(tr, nodes);
     }
 }
Beispiel #20
0
        public NNInfo Query(Vector3 p, NNConstraint constraint)
        {
            if (this.count == 0)
            {
                return(new NNInfo(null));
            }
            NNInfo result = default(NNInfo);

            this.SearchBox(0, p, constraint, ref result);
            result.UpdateInfo();
            return(result);
        }
Beispiel #21
0
        public NNInfo QueryCircle(Vector3 p, float radius, NNConstraint constraint)
        {
            if (this.count == 0)
            {
                return(new NNInfo(null));
            }
            NNInfo result = new NNInfo(null);

            this.SearchBoxCircle(0, p, radius, constraint, ref result);
            result.UpdateInfo();
            return(result);
        }
Beispiel #22
0
        public void Apply(bool forceNewCheck)
        {
            //TODO
            //This function assumes that connections from the n1,n2 nodes never need to be removed in the future (e.g because the nodes move or something)
            NNConstraint nn    = NNConstraint.None;
            int          graph = (int)startNode.GraphIndex;

            //Search all graphs but the one which start and end nodes are on
            nn.graphMask = ~(1 << graph);

            startNode.SetPosition((Int3)StartTransform.position);
            endNode.SetPosition((Int3)EndTransform.position);

            RemoveConnections(startNode);
            RemoveConnections(endNode);

            uint cost = (uint)Mathf.RoundToInt(((Int3)(StartTransform.position - EndTransform.position)).costMagnitude * costFactor);

            startNode.AddConnection(endNode, cost);
            endNode.AddConnection(startNode, cost);

            if (connectedNode1 == null || forceNewCheck)
            {
                NNInfo n1 = AstarPath.active.GetNearest(StartTransform.position, nn);
                connectedNode1 = n1.node;
                clamped1       = n1.clampedPosition;
            }

            if (connectedNode2 == null || forceNewCheck)
            {
                NNInfo n2 = AstarPath.active.GetNearest(EndTransform.position, nn);
                connectedNode2 = n2.node;
                clamped2       = n2.clampedPosition;
            }

            if (connectedNode2 == null || connectedNode1 == null)
            {
                return;
            }

            //Add connections between nodes, or replace old connections if existing
            connectedNode1.AddConnection(startNode, (uint)Mathf.RoundToInt(((Int3)(clamped1 - StartTransform.position)).costMagnitude * costFactor));
            if (!oneWay)
            {
                connectedNode2.AddConnection(endNode, (uint)Mathf.RoundToInt(((Int3)(clamped2 - EndTransform.position)).costMagnitude * costFactor));
            }

            if (!oneWay)
            {
                startNode.AddConnection(connectedNode1, (uint)Mathf.RoundToInt(((Int3)(clamped1 - StartTransform.position)).costMagnitude * costFactor));
            }
            endNode.AddConnection(connectedNode2, (uint)Mathf.RoundToInt(((Int3)(clamped2 - EndTransform.position)).costMagnitude * costFactor));
        }
Beispiel #23
0
        public NNInfo Query(Vector3 p, NNConstraint constraint)
        {
            if (this.count == 0)
            {
                return(new NNInfo(null));
            }
            NNInfo nnInfo = new NNInfo();

            this.SearchBox(0, p, constraint, ref nnInfo);
            nnInfo.UpdateInfo();
            return(nnInfo);
        }
Beispiel #24
0
        public override void Prepare()
        {
            NNInfo startNNInfo = AstarPath.active.GetNearest(startPoint);

            startPoint = startNNInfo.constFixedClampedPosition;
            startNode  = startNNInfo.node;
            NNInfo endNNInfo = AstarPath.active.GetNearest(endPoint);

            endPoint = endNNInfo.constFixedClampedPosition;
            endNode  = endNNInfo.node;
            hTarget  = Vector3d.ToInt3(endPoint);
        }
Beispiel #25
0
        // Token: 0x06002173 RID: 8563 RVA: 0x0018E130 File Offset: 0x0018C330
        public override void Teleport(Vector3 newPosition, bool clearPath = true)
        {
            NNInfo nninfo = (AstarPath.active != null) ? AstarPath.active.GetNearest(newPosition) : default(NNInfo);
            float  elevation;

            this.movementPlane.ToPlane(newPosition, out elevation);
            newPosition = this.movementPlane.ToWorld(this.movementPlane.ToPlane((nninfo.node != null) ? nninfo.position : newPosition), elevation);
            if (clearPath)
            {
                this.richPath.Clear();
            }
            base.Teleport(newPosition, clearPath);
        }
        void GetClosestWalkableNodesToChildrenRecursively(Transform tr, List <GraphNode> nodes)
        {
            foreach (Transform ch in tr)
            {
                NNInfo info = AstarPath.active.GetNearest(ch.position, NNConstraint.Default);
                if (info.node != null && info.node.Walkable)
                {
                    nodes.Add(info.node);
                }

                GetClosestWalkableNodesToChildrenRecursively(tr, nodes);
            }
        }
Beispiel #27
0
        /** Returns the nearest node to a position using the specified NNConstraint.
         * \param position The position to try to find a close node to
         * \param hint Can be passed to enable some graph generators to find the nearest node faster.
         * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
        public virtual NNInfo GetNearest(Vector3 position, NNConstraint constraint, Node hint)
        {
            //Debug.LogError ("This function (GetNearest) is not implemented in the navigation graph generator : Type "+this.GetType ().Name);

            if (nodes == null)
            {
                return(new NNInfo());
            }

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            float minDist = float.PositiveInfinity;
            Node  minNode = null;

            float minConstDist = float.PositiveInfinity;
            Node  minConstNode = null;

            for (int i = 0; i < nodes.Length; i++)
            {
                Node  node = nodes[i];
                float dist = (position - (Vector3)node.position).sqrMagnitude;

                if (dist < minDist)
                {
                    minDist = dist;
                    minNode = node;
                }

                if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))
                {
                    minConstDist = dist;
                    minConstNode = node;
                }
            }

            NNInfo nnInfo = new NNInfo(minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null)
            {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            }
            else if (minNode != null)
            {
                nnInfo.constrainedNode      = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            return(nnInfo);
        }
Beispiel #28
0
        public override NNInfo GetNearestForce(Vector3 position, NNConstraint constraint)
        {
            //Debug.LogError ("This function (GetNearest) is not implemented in the navigation graph generator : Type "+this.GetType ().Name);

            if (nodes == null)
            {
                return(new NNInfo());
            }

            var maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            var       minDist = float.PositiveInfinity;
            GraphNode minNode = null;

            var       minConstDist = float.PositiveInfinity;
            GraphNode minConstNode = null;

            for (var i = 0; i < nodeCount; i++)
            {
                var node = nodes[i];
                var dist = (position - (Vector3)node.position).sqrMagnitude;

                if (dist < minDist)
                {
                    minDist = dist;
                    minNode = node;
                }

                if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node)))
                {
                    minConstDist = dist;
                    minConstNode = node;
                }
            }

            var nnInfo = new NNInfo(minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null)
            {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            }
            else if (minNode != null)
            {
                nnInfo.constrainedNode      = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            return(nnInfo);
        }
Beispiel #29
0
        // Token: 0x0600271A RID: 10010 RVA: 0x001AF4E8 File Offset: 0x001AD6E8
        protected override void Prepare()
        {
            this.nnConstraint.tags = this.enabledTags;
            NNInfo           nearest          = AstarPath.active.GetNearest(this.startPoint, this.nnConstraint);
            PathNNConstraint pathNNConstraint = this.nnConstraint as PathNNConstraint;

            if (pathNNConstraint != null)
            {
                pathNNConstraint.SetStart(nearest.node);
            }
            this.startPoint    = nearest.position;
            this.startIntPoint = (Int3)this.startPoint;
            this.startNode     = nearest.node;
            if (this.startNode == null)
            {
                base.FailWithError("Couldn't find a node close to the start point");
                return;
            }
            if (!base.CanTraverse(this.startNode))
            {
                base.FailWithError("The node closest to the start point could not be traversed");
                return;
            }
            if (this.hasEndPoint)
            {
                NNInfo nearest2 = AstarPath.active.GetNearest(this.endPoint, this.nnConstraint);
                this.endPoint = nearest2.position;
                this.endNode  = nearest2.node;
                if (this.endNode == null)
                {
                    base.FailWithError("Couldn't find a node close to the end point");
                    return;
                }
                if (!base.CanTraverse(this.endNode))
                {
                    base.FailWithError("The node closest to the end point could not be traversed");
                    return;
                }
                if (this.startNode.Area != this.endNode.Area)
                {
                    base.FailWithError("There is no valid path to the target");
                    return;
                }
                if (!this.EndPointGridGraphSpecialCase(nearest2.node))
                {
                    this.hTarget     = (Int3)this.endPoint;
                    this.hTargetNode = this.endNode;
                    this.pathHandler.GetPathNode(this.endNode).flag1 = true;
                }
            }
        }
Beispiel #30
0
        public void Teleport(Vector3 newPosition)
        {
            this.CancelCurrentPathRequest();
            NNInfo nearest = AstarPath.active.GetNearest(newPosition);
            float  elevation;

            this.movementPlane.ToPlane(newPosition, out elevation);
            this.prevPosition = (this.tr.position = this.movementPlane.ToWorld(this.movementPlane.ToPlane((nearest.node != null) ? nearest.position : newPosition), elevation));
            this.richPath.Clear();
            if (this.rvoController != null)
            {
                this.rvoController.Move(Vector3.zero);
            }
        }
Beispiel #31
0
        public override void Prepare()
        {
            base.nnConstraint.tags = base.enabledTags;
            NNInfo           info         = AstarPath.active.GetNearest(this.startPoint, base.nnConstraint, this.startHint);
            PathNNConstraint nnConstraint = base.nnConstraint as PathNNConstraint;

            if (nnConstraint != null)
            {
                nnConstraint.SetStart(info.node);
            }
            this.startPoint    = info.position;
            this.startIntPoint = (Int3)this.startPoint;
            this.startNode     = info.node;
            if (this.startNode == null)
            {
                base.Error();
            }
            else if (!this.startNode.Walkable)
            {
                base.Error();
            }
            else if (this.hasEndPoint)
            {
                NNInfo info2 = AstarPath.active.GetNearest(this.endPoint, base.nnConstraint, this.endHint);
                this.endPoint = info2.position;
                this.endNode  = info2.node;
                if ((this.startNode == null) && (this.endNode == null))
                {
                    base.Error();
                }
                else if (this.endNode == null)
                {
                    base.Error();
                }
                else if (!this.endNode.Walkable)
                {
                    base.Error();
                }
                else if (this.startNode.Area != this.endNode.Area)
                {
                    base.Error();
                }
                else if (!this.EndPointGridGraphSpecialCase(info2.node))
                {
                    base.hTarget     = (Int3)this.endPoint;
                    base.hTargetNode = this.endNode;
                    base.pathHandler.GetPathNode(this.endNode).flag1 = true;
                }
            }
        }
Beispiel #32
0
		public NNInfo Query (Vector3 p, NNConstraint constraint) {
			
			BBTreeBox c = root;
			
			if (c == null) {
				return new NNInfo();
			}
			
			NNInfo nnInfo = new NNInfo ();
			
			SearchBox (c,p, constraint, ref nnInfo);
			
			nnInfo.UpdateInfo ();
			
			return nnInfo;
		}
Beispiel #33
0
		/** Queries the tree for the best node, searching within a circle around \a p with the specified radius.
		  * Will fill in both the constrained node and the not constrained node in the NNInfo.
		  * 
		  * \see QueryClosest
		  */
		public NNInfo QueryCircle (Vector3 p, float radius, NNConstraint constraint) {
			BBTreeBox c = root;
			
			if (c == null) {
				return new NNInfo();
			}
			
#if ASTARDEBUG
			Vector3 prev = new Vector3 (1,0,0)*radius+p;
			for (double i=0;i< Math.PI*2; i += Math.PI/50.0) {
				Vector3 cpos = new Vector3 ((float)Math.Cos (i),0,(float)Math.Sin (i))*radius+p;
				Debug.DrawLine (prev,cpos,Color.yellow);
				prev = cpos;
			}
#endif
			
			NNInfo nnInfo = new NNInfo (null);
			
			SearchBoxCircle (c,p, radius, constraint, ref nnInfo);
			
			nnInfo.UpdateInfo ();
			
			return nnInfo;
		}
Beispiel #34
0
		/** Returns the nearest node to a position using the specified NNConstraint.
		  * \param position The position to try to find a close node to
		  * \param hint Can be passed to enable some graph generators to find the nearest node faster.
		  * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
		public virtual NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
			// This is a default implementation and it is pretty slow
			// Graphs usually override this to provide faster and more specialised implementations

			float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

			float minDist = float.PositiveInfinity;
			GraphNode minNode = null;

			float minConstDist = float.PositiveInfinity;
			GraphNode minConstNode = null;

			// Loop through all nodes and find the closest suitable node
			GetNodes (node => {
				float dist = (position-(Vector3)node.position).sqrMagnitude;

				if (dist < minDist) {
					minDist = dist;
					minNode = node;
				}

				if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable (node)) {
					minConstDist = dist;
					minConstNode = node;
				}
				return true;
			});

			var nnInfo = new NNInfo (minNode);

			nnInfo.constrainedNode = minConstNode;

			if (minConstNode != null) {
				nnInfo.constClampedPosition = (Vector3)minConstNode.position;
			} else if (minNode != null) {
				nnInfo.constrainedNode = minNode;
				nnInfo.constClampedPosition = (Vector3)minNode.position;
			}

			return nnInfo;
		}
Beispiel #35
0
        public void SearchBoxCircle(BBTreeBox box, Vector3 p, float radius, NNConstraint constraint, ref NNInfo nnInfo)
        {
            //, int intendentLevel = 0) {

            if (box.node != null) {
                //Leaf node
                if (NodeIntersectsCircle (box.node,p,radius)) {
                    //Update the NNInfo

            #if DEBUG
                    Debug.DrawLine (graph.vertices[box.node[0]],graph.vertices[box.node[1]],Color.red);
                    Debug.DrawLine (graph.vertices[box.node[1]],graph.vertices[box.node[2]],Color.red);
                    Debug.DrawLine (graph.vertices[box.node[2]],graph.vertices[box.node[0]],Color.red);
            #endif

                    Vector3 closest = NavMeshGraph.ClosestPointOnNode (box.node,graph.vertices,p);
                    float dist = (closest-p).sqrMagnitude;

                    if (nnInfo.node == null) {
                        nnInfo.node = box.node;
                        nnInfo.clampedPosition = closest;
                    } else if (dist < (nnInfo.clampedPosition - p).sqrMagnitude) {
                        nnInfo.node = box.node;
                        nnInfo.clampedPosition = closest;
                    }
                    if (constraint.Suitable (box.node)) {
                        if (nnInfo.constrainedNode == null) {
                            nnInfo.constrainedNode = box.node;
                            nnInfo.constClampedPosition = closest;
                        } else if (dist < (nnInfo.constClampedPosition - p).sqrMagnitude) {
                            nnInfo.constrainedNode = box.node;
                            nnInfo.constClampedPosition = closest;
                        }
                    }
                }
                return;
            }

            #if DEBUG
            Debug.DrawLine (new Vector3 (box.rect.xMin,0,box.rect.yMin),new Vector3 (box.rect.xMax,0,box.rect.yMin),Color.white);
            Debug.DrawLine (new Vector3 (box.rect.xMin,0,box.rect.yMax),new Vector3 (box.rect.xMax,0,box.rect.yMax),Color.white);
            Debug.DrawLine (new Vector3 (box.rect.xMin,0,box.rect.yMin),new Vector3 (box.rect.xMin,0,box.rect.yMax),Color.white);
            Debug.DrawLine (new Vector3 (box.rect.xMax,0,box.rect.yMin),new Vector3 (box.rect.xMax,0,box.rect.yMax),Color.white);
            #endif

            //Search children
            if (RectIntersectsCircle (box.c1.rect,p,radius)) {
                SearchBoxCircle (box.c1,p, radius, constraint, ref nnInfo);
            }

            if (RectIntersectsCircle (box.c2.rect,p,radius)) {
                SearchBoxCircle (box.c2,p, radius, constraint, ref nnInfo);
            }
        }
Beispiel #36
0
        public void SearchBox(BBTreeBox box, Vector3 p, NNConstraint constraint, ref NNInfo nnInfo)
        {
            //, int intendentLevel = 0) {

            if (box.node != null) {
                //Leaf node
                if (NavMeshGraph.ContainsPoint (box.node,p,graph.vertices)) {
                    //Update the NNInfo

                    if (nnInfo.node == null) {
                        nnInfo.node = box.node;
                    } else if (Mathf.Abs(((Vector3)box.node.position).y - p.y) < Mathf.Abs (((Vector3)nnInfo.node.position).y - p.y)) {
                        nnInfo.node = box.node;
                    }
                    if (constraint.Suitable (box.node)) {
                        if (nnInfo.constrainedNode == null) {
                            nnInfo.constrainedNode = box.node;
                        } else if (Mathf.Abs(box.node.position.y - p.y) < Mathf.Abs (nnInfo.constrainedNode.position.y - p.y)) {
                            nnInfo.constrainedNode = box.node;
                        }
                    }
                }
                return;
            }

            //Search children
            if (RectContains (box.c1.rect,p)) {
                SearchBox (box.c1,p, constraint, ref nnInfo);
            }

            if (RectContains (box.c2.rect,p)) {
                SearchBox (box.c2,p, constraint, ref nnInfo);
            }
        }
Beispiel #37
0
 public NNInfo QueryCircle(Vector3 p, float radius, NNConstraint constraint)
 {
     if (this.count == 0)
     {
         return new NNInfo(null);
     }
     NNInfo result = new NNInfo(null);
     this.SearchBoxCircle(0, p, radius, constraint, ref result);
     result.UpdateInfo();
     return result;
 }
Beispiel #38
0
		/** Returns the nearest node to a position using the specified NNConstraint.
		  * \param position The position to try to find a close node to
		  * \param hint Can be passed to enable some graph generators to find the nearest node faster.
		  * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
		public virtual NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
			//Debug.LogError ("This function (GetNearest) is not implemented in the navigation graph generator : Type "+this.GetType ().Name);
			
			var maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;
			
			var minDist = float.PositiveInfinity;
			GraphNode minNode = null;
			
			var minConstDist = float.PositiveInfinity;
			GraphNode minConstNode = null;
			
			GetNodes (delegate (GraphNode node) {
				var dist = (position-(Vector3)node.position).sqrMagnitude;
				
				if (dist < minDist) {
					minDist = dist;
					minNode = node;
				}
				
				if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable (node)) {
					minConstDist = dist;
					minConstNode = node;
				}
				return true;
			});
			
			var nnInfo = new NNInfo (minNode);
			
			nnInfo.constrainedNode = minConstNode;
			
			if (minConstNode != null) {
				nnInfo.constClampedPosition = (Vector3)minConstNode.position;
			} else if (minNode != null) {
				nnInfo.constrainedNode = minNode;
				nnInfo.constClampedPosition = (Vector3)minNode.position;
			}
			
			return nnInfo;
		}
		void SearchBoxCircle (int boxi, Vector3 p, float radius, NNConstraint constraint, ref NNInfo nnInfo) {//, int intendentLevel = 0) {

			BBTreeBox box = arr[boxi];

			if (box.node != null) {
				//Leaf node
				if (NodeIntersectsCircle (box.node,p,radius)) {
					//Update the NNInfo

					#if ASTARDEBUG
					Debug.DrawLine ((Vector3)box.node.GetVertex(0),(Vector3)box.node.GetVertex(1),Color.red);
					Debug.DrawLine ((Vector3)box.node.GetVertex(1),(Vector3)box.node.GetVertex(2),Color.red);
					Debug.DrawLine ((Vector3)box.node.GetVertex(2),(Vector3)box.node.GetVertex(0),Color.red);
					#endif

					Vector3 closest = box.node.ClosestPointOnNode (p);//NavMeshGraph.ClosestPointOnNode (box.node,graph.vertices,p);
					float dist = (closest-p).sqrMagnitude;

					if (nnInfo.node == null) {
						nnInfo.node = box.node;
						nnInfo.clampedPosition = closest;
					} else if (dist < (nnInfo.clampedPosition - p).sqrMagnitude) {
						nnInfo.node = box.node;
						nnInfo.clampedPosition = closest;
					}
					if (constraint == null || constraint.Suitable (box.node)) {
						if (nnInfo.constrainedNode == null) {
							nnInfo.constrainedNode = box.node;
							nnInfo.constClampedPosition = closest;
						} else if (dist < (nnInfo.constClampedPosition - p).sqrMagnitude) {
							nnInfo.constrainedNode = box.node;
							nnInfo.constClampedPosition = closest;
						}
					}
				} else {
					#if ASTARDEBUG
					Debug.DrawLine ((Vector3)box.node.GetVertex(0),(Vector3)box.node.GetVertex(1),Color.blue);
					Debug.DrawLine ((Vector3)box.node.GetVertex(1),(Vector3)box.node.GetVertex(2),Color.blue);
					Debug.DrawLine ((Vector3)box.node.GetVertex(2),(Vector3)box.node.GetVertex(0),Color.blue);
					#endif
				}
				return;
			}

			#if ASTARDEBUG
			Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymin),new Vector3 (box.rect.xmax,0,box.rect.ymin),Color.white);
			Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymax),new Vector3 (box.rect.xmax,0,box.rect.ymax),Color.white);
			Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymin),new Vector3 (box.rect.xmin,0,box.rect.ymax),Color.white);
			Debug.DrawLine (new Vector3 (box.rect.xmax,0,box.rect.ymin),new Vector3 (box.rect.xmax,0,box.rect.ymax),Color.white);
			#endif

			//Search children
			if (RectIntersectsCircle (arr[box.left].rect,p,radius)) {
				SearchBoxCircle (box.left,p, radius, constraint, ref nnInfo);
			}

			if (RectIntersectsCircle (arr[box.right].rect,p,radius)) {
				SearchBoxCircle (box.right,p, radius, constraint, ref nnInfo);
			}
		}
Beispiel #40
0
        /** This performs a linear search through all polygons returning the closest one.
          * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node
          * complying with the NNConstraint.
          * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool)
          */
        public static NNInfo GetNearestForceBoth(Node[] nodes, Int3[] vertices, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
        {
            Int3 pos = (Int3)position;

            float minDist = -1;
            Node minNode = null;

            float minConstDist = -1;
            Node minConstNode = null;

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            if (nodes == null || nodes.Length == 0) {
                return new NNInfo ();
            }

            for (int i=0;i<nodes.Length;i++) {
                MeshNode node = nodes[i] as MeshNode;

                if (accurateNearestNode) {

                    Vector3 closest = Polygon.ClosestPointOnTriangle((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],(Vector3)vertices[node.v3],position);
                    float dist = ((Vector3)pos-closest).sqrMagnitude;

                    if (minNode == null || dist < minDist) {
                        minDist = dist;
                        minNode = node;
                    }

                    if (dist < maxDistSqr && constraint.Suitable (node)) {
                        if (minConstNode == null || dist < minConstDist) {
                            minConstDist = dist;
                            minConstNode = node;
                        }
                    }

                } else {
                    #if SafeIntMath
                    if (!Polygon.IsClockwise ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],position) || !Polygon.IsClockwise ((Vector3)vertices[node.v2],(Vector3)vertices[node.v3],position) || !Polygon.IsClockwise ((Vector3)vertices[node.v3],(Vector3)vertices[node.v1],position))
                    #else
                    if (!Polygon.IsClockwise (vertices[node.v1],vertices[node.v2],pos) || !Polygon.IsClockwise (vertices[node.v2],vertices[node.v3],pos) || !Polygon.IsClockwise (vertices[node.v3],vertices[node.v1],pos))
                    #endif
                    {

                        float dist = (node.position-pos).sqrMagnitude;
                        if (minNode == null || dist < minDist) {
                            minDist = dist;
                            minNode = node;
                        }

                        if (dist < maxDistSqr && constraint.Suitable (node)) {
                            if (minConstNode == null || dist < minConstDist) {
                                minConstDist = dist;
                                minConstNode = node;
                            }
                        }

                    } else {

            #if ASTARDEBUG
                        Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.blue);
                        Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v3],Color.blue);
                        Debug.DrawLine ((Vector3)vertices[node.v3],(Vector3)vertices[node.v1],Color.blue);
            #endif

                        int dist = Mathfx.Abs (node.position.y-pos.y);

                        if (minNode == null || dist < minDist) {
                            minDist = dist;
                            minNode = node;
                        }

                        if (dist < maxDistSqr && constraint.Suitable (node)) {
                            if (minConstNode == null || dist < minConstDist) {
                                minConstDist = dist;
                                minConstNode = node;
                            }
                        }
                    }
                }
            }

            NNInfo nninfo = new NNInfo (minNode);

            //Find the point closest to the nearest triangle

            if (nninfo.node != null) {
                MeshNode node = nninfo.node as MeshNode;//minNode2 as MeshNode;

                Vector3 clP = Polygon.ClosestPointOnTriangle ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],(Vector3)vertices[node.v3],position);

                nninfo.clampedPosition = clP;
            }

            nninfo.constrainedNode = minConstNode;
            if (nninfo.constrainedNode != null) {
                MeshNode node = nninfo.constrainedNode as MeshNode;//minNode2 as MeshNode;

                Vector3 clP = Polygon.ClosestPointOnTriangle ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],(Vector3)vertices[node.v3],position);

                nninfo.constClampedPosition = clP;
            }

            return nninfo;
        }
Beispiel #41
0
        /** Returns the nearest node to a position using the specified NNConstraint.
          * \param position The position to try to find a close node to
          * \param hint Can be passed to enable some graph generators to find the nearest node faster.
          * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
        public virtual NNInfo GetNearest(Vector3 position, NNConstraint constraint, Node hint)
        {
            //Debug.LogError ("This function (GetNearest) is not implemented in the navigation graph generator : Type "+this.GetType ().Name);

            if (nodes == null) {
                return new NNInfo ();
            }

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            float minDist = float.PositiveInfinity;
            Node minNode = null;

            float minConstDist = float.PositiveInfinity;
            Node minConstNode = null;

            for (int i=0;i<nodes.Length;i++) {

                Node node = nodes[i];
                float dist = (position-(Vector3)node.position).sqrMagnitude;

                if (dist < minDist) {
                    minDist = dist;
                    minNode = node;
                }

                if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable (node)) {
                    minConstDist = dist;
                    minConstNode = node;
                }
            }

            NNInfo nnInfo = new NNInfo (minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null) {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            } else if (minNode != null) {
                nnInfo.constrainedNode = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            return nnInfo;
        }
Beispiel #42
0
 private void SearchBox(int boxi, Vector3 p, NNConstraint constraint, ref NNInfo nnInfo)
 {
     BBTree.BBTreeBox bBTreeBox = this.arr[boxi];
     if (bBTreeBox.node != null)
     {
         if (bBTreeBox.node.ContainsPoint((Int3)p))
         {
             if (nnInfo.node == null)
             {
                 nnInfo.node = bBTreeBox.node;
             }
             else if (Mathf.Abs(((Vector3)bBTreeBox.node.position).y - p.y) < Mathf.Abs(((Vector3)nnInfo.node.position).y - p.y))
             {
                 nnInfo.node = bBTreeBox.node;
             }
             if (constraint.Suitable(bBTreeBox.node))
             {
                 if (nnInfo.constrainedNode == null)
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                 }
                 else if (Mathf.Abs((float)bBTreeBox.node.position.y - p.y) < Mathf.Abs((float)nnInfo.constrainedNode.position.y - p.y))
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                 }
             }
         }
         return;
     }
     if (this.arr[bBTreeBox.left].Contains(p))
     {
         this.SearchBox(bBTreeBox.left, p, constraint, ref nnInfo);
     }
     if (this.arr[bBTreeBox.right].Contains(p))
     {
         this.SearchBox(bBTreeBox.right, p, constraint, ref nnInfo);
     }
 }
Beispiel #43
0
		public override NNInfo GetNearestForce (Vector3 position, NNConstraint constraint) {
			//return NavMeshGraph.GetNearest (this, nodes,position, constraint, accurateNearestNode);
			
			if (tiles == null) return new NNInfo ();
			
			Vector3 localPosition = position - forcedBounds.min;
			int tx = Mathf.FloorToInt (localPosition.x / (cellSize*tileSizeX));
			int tz = Mathf.FloorToInt (localPosition.z / (cellSize*tileSizeZ));
			
			//Clamp to graph borders
			tx = Mathf.Clamp (tx, 0, tileXCount-1);
			tz = Mathf.Clamp (tz, 0, tileZCount-1);
			
			int wmax = System.Math.Max (tileXCount, tileZCount);
			
			NNInfo best = new NNInfo();
			float bestDistance = float.PositiveInfinity;
			
			bool xzSearch = nearestSearchOnlyXZ || ( constraint != null && constraint.distanceXZ );
			
			//Debug.DrawRay (new Vector3(tx,0,tz)*cellSize*tileSize + forcedBounds.min, Vector3.up*15, Color.blue);
			//Debug.DrawRay (new Vector3(tx,0,tz)*cellSize*tileSize + forcedBounds.min + Vector3.forward*5, Vector3.back*10, Color.blue);
			//Debug.DrawRay (new Vector3(tx,0,tz)*cellSize*tileSize + forcedBounds.min + Vector3.left*5, Vector3.right*10, Color.blue);
			
			//Search outwards in a diamond pattern from the closest tile
			for (int w=0;w<wmax;w++) {
				
				if (!xzSearch && bestDistance < (w-1)*cellSize*System.Math.Max (tileSizeX, tileSizeZ)) break;
				
				int zmax = System.Math.Min (w+tz +1, tileZCount);
				for (int z=System.Math.Max(-w+tz, 0); z < zmax; z++) {
					
					//Solve for z such that abs(x-tx) + abs(z-tx) == w
					//Delta X coordinate
					int dx = System.Math.Abs( w - System.Math.Abs(z-tz));
					//Solution is dx + tx and -dx + tx
					
					//First solution negative delta x
					if (-dx + tx >= 0) {
						//Absolute x coordinate
						int x = -dx + tx;
						NavmeshTile tile = tiles[x + z*tileXCount];
						
						if (tile != null) {
							if (xzSearch) {
								best = tile.bbTree.QueryClosestXZ (position, constraint, ref bestDistance, best);
								if ( bestDistance < float.PositiveInfinity ) break;
							} else {
								best = tile.bbTree.QueryClosest (position, constraint, ref bestDistance, best);
							}
						}
					}
					
					//Other solution, make sure it is not the same solution by checking x != 0
					if (dx != 0 && dx + tx < tileXCount) {
						//Absolute x coordinate
						int x = dx + tx;
						NavmeshTile tile = tiles[x + z*tileXCount];
						if (tile != null) {
							if (xzSearch) {
								best = tile.bbTree.QueryClosestXZ (position, constraint, ref bestDistance, best);
								if ( bestDistance < float.PositiveInfinity ) break;
							} else {
								best = tile.bbTree.QueryClosest (position, constraint, ref bestDistance, best);
							}
						}
					}
				}
			}
			
			best.node = best.constrainedNode;
			best.constrainedNode = null;
			
			best.clampedPosition = best.constClampedPosition;
			
			return best;
			//return GetNearestForce (position, constraint);
		}
Beispiel #44
0
 private void SearchBoxCircle(int boxi, Vector3 p, float radius, NNConstraint constraint, ref NNInfo nnInfo)
 {
     BBTree.BBTreeBox bBTreeBox = this.arr[boxi];
     if (bBTreeBox.node != null)
     {
         if (BBTree.NodeIntersectsCircle(bBTreeBox.node, p, radius))
         {
             Vector3 vector = bBTreeBox.node.ClosestPointOnNode(p);
             float sqrMagnitude = (vector - p).sqrMagnitude;
             if (nnInfo.node == null)
             {
                 nnInfo.node = bBTreeBox.node;
                 nnInfo.clampedPosition = vector;
             }
             else if (sqrMagnitude < (nnInfo.clampedPosition - p).sqrMagnitude)
             {
                 nnInfo.node = bBTreeBox.node;
                 nnInfo.clampedPosition = vector;
             }
             if (constraint == null || constraint.Suitable(bBTreeBox.node))
             {
                 if (nnInfo.constrainedNode == null)
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                     nnInfo.constClampedPosition = vector;
                 }
                 else if (sqrMagnitude < (nnInfo.constClampedPosition - p).sqrMagnitude)
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                     nnInfo.constClampedPosition = vector;
                 }
             }
         }
         return;
     }
     if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.left].rect, p, radius))
     {
         this.SearchBoxCircle(bBTreeBox.left, p, radius, constraint, ref nnInfo);
     }
     if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.right].rect, p, radius))
     {
         this.SearchBoxCircle(bBTreeBox.right, p, radius, constraint, ref nnInfo);
     }
 }
Beispiel #45
0
 private void SearchBoxClosest(int boxi, Vector3 p, ref float closestDist, NNConstraint constraint, ref NNInfo nnInfo)
 {
     BBTree.BBTreeBox bBTreeBox = this.arr[boxi];
     if (bBTreeBox.node != null)
     {
         if (BBTree.NodeIntersectsCircle(bBTreeBox.node, p, closestDist))
         {
             Vector3 vector = bBTreeBox.node.ClosestPointOnNode(p);
             if (constraint == null || constraint.Suitable(bBTreeBox.node))
             {
                 float sqrMagnitude = (vector - p).sqrMagnitude;
                 if (nnInfo.constrainedNode == null)
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                     nnInfo.constClampedPosition = vector;
                     closestDist = (float)Math.Sqrt((double)sqrMagnitude);
                 }
                 else if (sqrMagnitude < closestDist * closestDist)
                 {
                     nnInfo.constrainedNode = bBTreeBox.node;
                     nnInfo.constClampedPosition = vector;
                     closestDist = (float)Math.Sqrt((double)sqrMagnitude);
                 }
             }
         }
     }
     else
     {
         if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.left].rect, p, closestDist))
         {
             this.SearchBoxClosest(bBTreeBox.left, p, ref closestDist, constraint, ref nnInfo);
         }
         if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.right].rect, p, closestDist))
         {
             this.SearchBoxClosest(bBTreeBox.right, p, ref closestDist, constraint, ref nnInfo);
         }
     }
 }
		void SearchBox (int boxi, Vector3 p, NNConstraint constraint, ref NNInfo nnInfo) {//, int intendentLevel = 0) {

			BBTreeBox box = arr[boxi];

			if (box.node != null) {
				//Leaf node
				if (box.node.ContainsPoint ((Int3)p)) {
					//Update the NNInfo

					if (nnInfo.node == null) {
						nnInfo.node = box.node;
					} else if (Mathf.Abs(((Vector3)box.node.position).y - p.y) < Mathf.Abs (((Vector3)nnInfo.node.position).y - p.y)) {
						nnInfo.node = box.node;
					}
					if (constraint.Suitable (box.node)) {
						if (nnInfo.constrainedNode == null) {
							nnInfo.constrainedNode = box.node;
						} else if (Mathf.Abs(box.node.position.y - p.y) < Mathf.Abs (nnInfo.constrainedNode.position.y - p.y)) {
							nnInfo.constrainedNode = box.node;
						}
					}
				}
				return;
			}

			//Search children
			if (arr[box.left].Contains(p)) {
				SearchBox (box.left,p, constraint, ref nnInfo);
			}

			if (arr[box.right].Contains(p)) {
				SearchBox (box.right,p, constraint, ref nnInfo);
			}
		}
		/** This performs a linear search through all polygons returning the closest one */
		public static NNInfo GetNearestForce (Node[] nodes, Int3[] vertices, Vector3 position, NNConstraint constraint) {
			Int3 pos = (Int3)position;
			//Replacement for Infinity, the maximum value a int can hold
			int minDist = -1;
			Node minNode = null;
			
			float minDist2 = -1;
			Node minNode2 = null;
			
			int minConstDist = -1;
			Node minNodeConst = null;
			
			float minConstDist2 = -1;
			Node minNodeConst2 = null;
			
			//int rnd = (int)Random.Range (0,10000);
			
			//int skipped = 0;
			
			
			for (int i=0;i<nodes.Length;i++) {
				MeshNode node = nodes[i] as MeshNode;
				
				if (!Polygon.IsClockwise (vertices[node.v1],vertices[node.v2],pos) || !Polygon.IsClockwise (vertices[node.v2],vertices[node.v3],pos) || !Polygon.IsClockwise (vertices[node.v3],vertices[node.v1],pos))
				{
				//Polygon.TriangleArea2 (vertices[node.v1],vertices[node.v2],pos) >= 0 || Polygon.TriangleArea2 (vertices[node.v2],vertices[node.v3],pos) >= 0 || Polygon.TriangleArea2 (vertices[node.v3],vertices[node.v1],pos) >= 0) {
					
					/*if (minDist2 != -1) {
						float d1 = (node.position-vertices[node.v1]).sqrMagnitude;
						d1 = Mathf.Min (d1,(node.position-vertices[node.v1]).sqrMagnitude);
						d1 = Mathf.Min (d1,(node.position-vertices[node.v1]).sqrMagnitude);
						
						//The closest distance possible from the current node to 'pos'
						d1 = (node.position-pos).sqrMagnitude-d1;
						
						if (d1 > minDist2) {
							skipped++;
							continue;
						}
					}*/
					
					/*float dist2 = Mathfx.DistancePointSegment2 (pos.x,pos.z,vertices[node.v1].x,vertices[node.v1].z,vertices[node.v2].x,vertices[node.v2].z);
					dist2 = Mathfx.Min (dist2,Mathfx.DistancePointSegment2 (pos.x,pos.z,vertices[node.v1].x,vertices[node.v1].z,vertices[node.v3].x,vertices[node.v3].z));
					dist2 = Mathfx.Min (dist2,Mathfx.DistancePointSegment2 (pos.x,pos.z,vertices[node.v3].x,vertices[node.v3].z,vertices[node.v2].x,vertices[node.v2].z));*/
					
					float dist2 = (node.position-pos).sqrMagnitude;
					if (minDist2 == -1 || dist2 < minDist2) {
						minDist2 = dist2;
						minNode2 = node;
					}
					
					if (constraint.Suitable (node)) {
						if (minConstDist2 == -1 || dist2 < minConstDist2) {
							minConstDist2 = dist2;
							minNodeConst2 = node;
						}
					}
					
					continue;
				}
				
				
				int dist = Mathfx.Abs (node.position.y-pos.y);
				
				if (minDist == -1 || dist < minDist) {
					minDist = dist;
					minNode = node;
				}
				
				if (constraint.Suitable (node)) {
					if (minConstDist == -1 || dist < minConstDist) {
						minConstDist = dist;
						minNodeConst = node;
					}
				}
			}
			
			NNInfo nninfo = new NNInfo (minNode == null ? minNode2 : minNode, minNode == null ? NearestNodePriority.Low : NearestNodePriority.High);
			
			//Find the point closest to the nearest triangle
			//if (minNode == null) {
				
			if (nninfo.node != null) {
				MeshNode node = nninfo.node as MeshNode;//minNode2 as MeshNode;
				
				Vector3[] triangle = new Vector3[3] {vertices[node.v1],vertices[node.v2],vertices[node.v3]};
				Vector3 clP = Polygon.ClosesPointOnTriangle (triangle,position);
				
				nninfo.clampedPosition = clP;
			}
			
			nninfo.constrainedNode = minNodeConst == null ? minNodeConst2 : minNodeConst;
			
			if (nninfo.constrainedNode != null) {
				MeshNode node = nninfo.constrainedNode as MeshNode;//minNode2 as MeshNode;
				
				Vector3[] triangle = new Vector3[3] {vertices[node.v1],vertices[node.v2],vertices[node.v3]};
				Vector3 clP = Polygon.ClosesPointOnTriangle (triangle,position);
				
				nninfo.constClampedPosition = clP;
			}
			
			return nninfo;
		}
        public override NNInfo GetNearestForce(Vector3 position, NNConstraint constraint) {

            if (nodes == null) return new NNInfo();

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            float minDist = float.PositiveInfinity;
            GraphNode minNode = null;

            float minConstDist = float.PositiveInfinity;
            GraphNode minConstNode = null;

            if (optimizeForSparseGraph) {
                Int3 lookupStart = WorldToLookupSpace((Int3)position);

                Int3 size = lookupStart - _minLookup;

                int mw = 0;
                mw = System.Math.Max(mw, System.Math.Abs(size.x));
                mw = System.Math.Max(mw, System.Math.Abs(size.y));
                mw = System.Math.Max(mw, System.Math.Abs(size.z));

                size = lookupStart - _maxLookup;
                mw = System.Math.Max(mw, System.Math.Abs(size.x));
                mw = System.Math.Max(mw, System.Math.Abs(size.y));
                mw = System.Math.Max(mw, System.Math.Abs(size.z));

                PointNode node;

                if (_nodeLookup.TryGetValue(lookupStart, out node)) {
                    while (node != null) {
                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                        if (dist < minDist) { minDist = dist; minNode = node; }
                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                        node = node.next;
                    }
                }

                for (int w = 1; w <= mw; w++) {
                    if (w >= 20) {
                        Debug.LogWarning("Aborting GetNearest call at maximum distance because it has iterated too many times.\n" +
                            "If you get this regularly, check your settings for PointGraph -> <b>Optimize For Sparse Graph</b> and " +
                            "PointGraph -> <b>Optimize For 2D</b>.\nThis happens when the closest node was very far away (20*link distance between nodes). " +
                            "When optimizing for sparse graphs, getting the nearest node from far away positions is <b>very slow</b>.\n");
                        break;
                    }

                    if (_lookupCellSize.y == 0) {
                        Int3 reference = lookupStart + new Int3(-w, 0, -w);

                        for (int x = 0; x <= 2 * w; x++) {
                            if (_nodeLookup.TryGetValue(reference + new Int3(x, 0, 0), out node)) {
                                while (node != null) {
                                    float dist = (position - (Vector3)node.position).sqrMagnitude;
                                    if (dist < minDist) { minDist = dist; minNode = node; }
                                    if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                    node = node.next;
                                }
                            }
                            if (_nodeLookup.TryGetValue(reference + new Int3(x, 0, 2 * w), out node)) {
                                while (node != null) {
                                    float dist = (position - (Vector3)node.position).sqrMagnitude;
                                    if (dist < minDist) { minDist = dist; minNode = node; }
                                    if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                    node = node.next;
                                }
                            }
                        }

                        for (int x = 1; x < 2 * w; x++) {
                            if (_nodeLookup.TryGetValue(reference + new Int3(0, 0, x), out node)) {
                                while (node != null) {
                                    float dist = (position - (Vector3)node.position).sqrMagnitude;
                                    if (dist < minDist) { minDist = dist; minNode = node; }
                                    if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                    node = node.next;
                                }
                            }
                            if (_nodeLookup.TryGetValue(reference + new Int3(2 * w, 0, x), out node)) {
                                while (node != null) {
                                    float dist = (position - (Vector3)node.position).sqrMagnitude;
                                    if (dist < minDist) { minDist = dist; minNode = node; }
                                    if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                    node = node.next;
                                }
                            }
                        }
                    }
                    else {
                        Int3 reference = lookupStart + new Int3(-w, -w, -w);

                        for (int x = 0; x <= 2 * w; x++) {
                            for (int y = 0; y <= 2 * w; y++) {
                                if (_nodeLookup.TryGetValue(reference + new Int3(x, y, 0), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                                if (_nodeLookup.TryGetValue(reference + new Int3(x, y, 2 * w), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                            }
                        }

                        for (int x = 1; x < 2 * w; x++) {
                            for (int y = 0; y <= 2 * w; y++) {
                                if (_nodeLookup.TryGetValue(reference + new Int3(0, y, x), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                                if (_nodeLookup.TryGetValue(reference + new Int3(2 * w, y, x), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                            }
                        }

                        for (int x = 1; x < 2 * w; x++) {
                            for (int y = 1; y < 2 * w; y++) {
                                if (_nodeLookup.TryGetValue(reference + new Int3(x, 0, y), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                                if (_nodeLookup.TryGetValue(reference + new Int3(x, 2 * w, y), out node)) {
                                    while (node != null) {
                                        float dist = (position - (Vector3)node.position).sqrMagnitude;
                                        if (dist < minDist) { minDist = dist; minNode = node; }
                                        if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) { minConstDist = dist; minConstNode = node; }

                                        node = node.next;
                                    }
                                }
                            }
                        }
                    }

                    if (minConstNode != null) {
                        // Only search one more layer
                        mw = System.Math.Min(mw, w + 1);
                    }
                }
            }
            else {

                for (int i = 0; i < nodeCount; i++) {
                    PointNode node = nodes[i];
                    float dist = (position - (Vector3)node.position).sqrMagnitude;

                    if (dist < minDist) {
                        minDist = dist;
                        minNode = node;
                    }

                    if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) {
                        minConstDist = dist;
                        minConstNode = node;
                    }
                }
            }

            var nnInfo = new NNInfo(minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null) {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            }
            else if (minNode != null) {
                nnInfo.constrainedNode = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            #region Debugging

            //D.Log("Constraint: GraphMask: {0}, ConstrainArea: {1}, Area: {2}, ConstrainWalkability: {3}, \nWalkable: {4}, ConstrainTags: {5}, Tags: {6}, ConstrainDistance: {7}.",
            //    constraint.graphMask, constraint.constrainArea, constraint.area, constraint.constrainWalkability, constraint.walkable,
            //    constraint.constrainTags, constraint.tags, constraint.constrainDistance);

            //if (minConstNode != null) {
            //    D.Log("Constraint criteria met. Closest Node is at {0}, {1} from {2}. \nNodeConstrainDistance = {3}, DistanceConstraint = {4}.",
            //        nnInfo.constClampedPosition, Vector3.Distance(nnInfo.constClampedPosition, position), position,
            //        constraint.constrainDistance, Mathf.Sqrt(maxDistSqr));
            //}
            //else {
            //    D.Log("Constraint criteria NOT met. Closest Node is at {0}, {1} from {2}. \nNodeConstrainDistance = {3}, DistanceConstraint = {4}.",
            //        nnInfo.clampedPosition, Vector3.Distance(nnInfo.clampedPosition, position), position,
            //        constraint.constrainDistance, Mathf.Sqrt(maxDistSqr));
            //}

            #endregion

            return nnInfo;
        }
		/** This performs a linear search through all polygons returning the closest one.
		  * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node
		  * complying with the NNConstraint.
		  * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool)
		  */
		public static NNInfo GetNearestForceBoth (NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) {
			Int3 pos = (Int3)position;
			
			float minDist = -1;
			GraphNode minNode = null;
			
			float minConstDist = -1;
			GraphNode minConstNode = null;
			
			float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;
			
			GraphNodeDelegateCancelable del = delegate (GraphNode _node) {
				TriangleMeshNode node = _node as TriangleMeshNode;
				
				if (accurateNearestNode) {
					
					Vector3 closest = node.ClosestPointOnNode (position);
					float dist = ((Vector3)pos-closest).sqrMagnitude;
					
					if (minNode == null || dist < minDist) {
						minDist = dist;
						minNode = node;
					}
					
					if (dist < maxDistSqr && constraint.Suitable (node)) {
						if (minConstNode == null || dist < minConstDist) {
							minConstDist = dist;
							minConstNode = node;
						}
					}
					
				} else {
					
					if (!node.ContainsPoint ((Int3)position)) {
						
						float dist = (node.position-pos).sqrMagnitude;
						if (minNode == null || dist < minDist) {
							minDist = dist;
							minNode = node;
						}
						
						if (dist < maxDistSqr && constraint.Suitable (node)) {
							if (minConstNode == null || dist < minConstDist) {
								minConstDist = dist;
								minConstNode = node;
							}
						}
						
					} else {
					
#if ASTARDEBUG
						Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.blue);
						Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.blue);
						Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.blue);
#endif
						
						int dist = AstarMath.Abs (node.position.y-pos.y);
						
						if (minNode == null || dist < minDist) {
							minDist = dist;
							minNode = node;
						}
						
						if (dist < maxDistSqr && constraint.Suitable (node)) {
							if (minConstNode == null || dist < minConstDist) {
								minConstDist = dist;
								minConstNode = node;
							}
						}
					}
				}
				return true;
			};
			
			graph.GetNodes (del);
			
			NNInfo nninfo = new NNInfo (minNode);
			
			//Find the point closest to the nearest triangle
				
			if (nninfo.node != null) {
				TriangleMeshNode node = nninfo.node as TriangleMeshNode;//minNode2 as MeshNode;
				
				Vector3 clP = node.ClosestPointOnNode (position);
				
				nninfo.clampedPosition = clP;
			}
			
			nninfo.constrainedNode = minConstNode;
			if (nninfo.constrainedNode != null) {
				TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode;//minNode2 as MeshNode;
				
				Vector3 clP = node.ClosestPointOnNode (position);
				
				nninfo.constClampedPosition = clP;
			}
			
			return nninfo;
		}
		/** Queries the tree for the closest node to \a p constrained by the NNConstraint trying to improve an existing solution.
		  * Note that this function will, unlike QueryCircle, only fill in the constrained node.
		  * If you want a node not constrained by any NNConstraint, do an additional search with constraint = NNConstraint.None
		  *
		  * \param p Point to search around
		  * \param constraint Optionally set to constrain which nodes to return
		  * \param distance The best distance for the \a previous solution. Will be updated with the best distance
		  * after this search. Will be positive infinity if no node could be found.
		  * Set to positive infinity if there was no previous solution.
		  * \param previous This search will start from the \a previous NNInfo and improve it if possible.
		  * Even if the search fails on this call, the solution will never be worse than \a previous.
		  *
		  * \see QueryCircle
		  */
		public NNInfo QueryClosest (Vector3 p, NNConstraint constraint, ref float distance, NNInfo previous) {

			if ( count == 0 ) return previous;

			SearchBoxClosest (0,p, ref distance, constraint, ref previous);

			return previous;
		}
        private static Index3D __maxAllowedSectorGridSizeToScan = new Index3D(4, 4, 4);  // limit to divisible by 2

        #region Archived

        /// <summary>
        /// This will be called on the same time as Awake on the gameObject which the AstarPath script is attached to. (remember, not in the editor)
        /// Use this for any initialization code which can't be placed in Scan
        /// </summary>
        //public override void Awake() {
        //    base.Awake();
        //}

        /// <summary>
        ///  This will be called on the same time as OnDisable on the gameObject which the AstarPath script is attached to (remember, not in the editor)
        /// Use for any cleanup code such as cleaning up static variables which otherwise might prevent resources from being collected
        /// Use by creating a function overriding this one in a graph class, but always call base.OnDestroy () in that function.
        /// </summary>
        //public override void OnDestroy() {
        //    base.OnDestroy();
        //}

        #endregion

        public override NNInfo GetNearestForce(Vector3 position, NNConstraint constraint) {
            if (nodes == null) return new NNInfo();

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            float minDist = float.PositiveInfinity;
            GraphNode minNode = null;

            float minConstDist = float.PositiveInfinity;
            GraphNode minConstNode = null;

            for (int i = 0; i < nodeCount; i++) {
                PointNode node = nodes[i];
                float dist = (position - (Vector3)node.position).sqrMagnitude;

                if (dist < minDist) {
                    minDist = dist;
                    minNode = node;
                }

                if (constraint == null || (dist < minConstDist && dist < maxDistSqr && constraint.Suitable(node))) {
                    minConstDist = dist;
                    minConstNode = node;
                }
            }

            NNInfo nnInfo = new NNInfo(minNode);

            nnInfo.constrainedNode = minConstNode;

            if (minConstNode != null) {
                nnInfo.constClampedPosition = (Vector3)minConstNode.position;
            }
            else if (minNode != null) {
                nnInfo.constrainedNode = minNode;
                nnInfo.constClampedPosition = (Vector3)minNode.position;
            }

            #region Debugging

            //D.Log("Constraint: GraphMask: {0}, ConstrainArea: {1}, Area: {2}, ConstrainWalkability: {3}, \nWalkable: {4}, ConstrainTags: {5}, Tags: {6}, ConstrainDistance: {7}.",
            //    constraint.graphMask, constraint.constrainArea, constraint.area, constraint.constrainWalkability, constraint.walkable, 
            //    constraint.constrainTags, constraint.tags, constraint.constrainDistance);

            //if (minConstNode != null) {
            //    D.Log("Constraint criteria met. Closest Node is at {0}, {1} from {2}. \nNodeConstrainDistance = {3}, DistanceConstraint = {4}.",
            //        nnInfo.constClampedPosition, Vector3.Distance(nnInfo.constClampedPosition, position), position,
            //        constraint.constrainDistance, Mathf.Sqrt(maxDistSqr));
            //}
            //else {
            //    D.Log("Constraint criteria NOT met. Closest Node is at {0}, {1} from {2}. \nNodeConstrainDistance = {3}, DistanceConstraint = {4}.",
            //        nnInfo.clampedPosition, Vector3.Distance(nnInfo.clampedPosition, position), position,
            //        constraint.constrainDistance, Mathf.Sqrt(maxDistSqr));
            //}

            #endregion

            return nnInfo;
        }
		void SearchBoxClosest (int boxi, Vector3 p, ref float closestDist, NNConstraint constraint, ref NNInfo nnInfo) {

			BBTreeBox box = arr[boxi];

			if (box.node != null) {
				//Leaf node
				if (NodeIntersectsCircle (box.node,p,closestDist)) {
					//Update the NNInfo
					#if ASTARDEBUG
					Debug.DrawLine ((Vector3)box.node.GetVertex(1) + Vector3.up*0.2f,(Vector3)box.node.GetVertex(2) + Vector3.up*0.2f,Color.red);
					Debug.DrawLine ((Vector3)box.node.GetVertex(0) + Vector3.up*0.2f,(Vector3)box.node.GetVertex(1) + Vector3.up*0.2f,Color.red);
					Debug.DrawLine ((Vector3)box.node.GetVertex(2) + Vector3.up*0.2f,(Vector3)box.node.GetVertex(0) + Vector3.up*0.2f,Color.red);
					#endif

					Vector3 closest = box.node.ClosestPointOnNode (p);

					if (constraint == null || constraint.Suitable (box.node)) {
						float dist = (closest-p).sqrMagnitude;

						if (nnInfo.constrainedNode == null) {
							nnInfo.constrainedNode = box.node;
							nnInfo.constClampedPosition = closest;
							closestDist = (float)Math.Sqrt (dist);
						} else if (dist < closestDist*closestDist) {
							nnInfo.constrainedNode = box.node;
							nnInfo.constClampedPosition = closest;
							closestDist = (float)Math.Sqrt (dist);
						}
					}
				} else {
					#if ASTARDEBUG
					Debug.DrawLine ((Vector3)box.node.GetVertex(0),(Vector3)box.node.GetVertex(1),Color.blue);
					Debug.DrawLine ((Vector3)box.node.GetVertex(1),(Vector3)box.node.GetVertex(2),Color.blue);
					Debug.DrawLine ((Vector3)box.node.GetVertex(2),(Vector3)box.node.GetVertex(0),Color.blue);
					#endif
				}
			} else {

				#if ASTARDEBUG
				Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymin),new Vector3 (box.rect.xmax,0,box.rect.ymin),Color.white);
				Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymax),new Vector3 (box.rect.xmax,0,box.rect.ymax),Color.white);
				Debug.DrawLine (new Vector3 (box.rect.xmin,0,box.rect.ymin),new Vector3 (box.rect.xmin,0,box.rect.ymax),Color.white);
				Debug.DrawLine (new Vector3 (box.rect.xmax,0,box.rect.ymin),new Vector3 (box.rect.xmax,0,box.rect.ymax),Color.white);
				#endif

				//Search children
				if (RectIntersectsCircle (arr[box.left].rect,p,closestDist)) {
					SearchBoxClosest (box.left,p, ref closestDist, constraint, ref nnInfo);
				}

				if (RectIntersectsCircle (arr[box.right].rect,p,closestDist)) {
					SearchBoxClosest (box.right,p, ref closestDist, constraint, ref nnInfo);
				}
			}
		}
Beispiel #53
0
		public override NNInfo GetNearestForce (Vector3 position, NNConstraint constraint) {
			if (nodes == null || depth*width != nodes.Length) {
				return new NNInfo();
			}

			// Position in global space
			Vector3 globalPosition = position;

			// Position in graph space
			position = inverseMatrix.MultiplyPoint3x4(position);

			// Find the coordinates of the closest node
			float xf = position.x-0.5F;
			float zf = position.z-0.5f;
			int x = Mathf.Clamp(Mathf.RoundToInt(xf), 0, width-1);
			int z = Mathf.Clamp(Mathf.RoundToInt(zf), 0, depth-1);

			// Closest node
			GridNode node = nodes[x+z*width];

			GridNode minNode = null;
			float minDist = float.PositiveInfinity;
			int overlap = getNearestForceOverlap;

			Vector3 clampedPosition = Vector3.zero;
			var nn = new NNInfo(null);

			// If the closest node was suitable
			if (constraint.Suitable(node)) {
				minNode = node;
				minDist = ((Vector3)minNode.position-globalPosition).sqrMagnitude;
				float y = inverseMatrix.MultiplyPoint3x4((Vector3)node.position).y;
				clampedPosition = matrix.MultiplyPoint3x4(new Vector3(Mathf.Clamp(xf, x-0.5f, x+0.5f)+0.5f, y, Mathf.Clamp(zf, z-0.5f, z+0.5f)+0.5f));
			}

			if (minNode != null) {
				nn.node = minNode;
				nn.clampedPosition = clampedPosition;

				// We have a node, and we don't need to search more, so just return
				if (overlap == 0) return nn;
				overlap--;
			}

			// Search up to this distance
			float maxDist = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistance : float.PositiveInfinity;
			float maxDistSqr = maxDist*maxDist;

			// Search a square/spiral pattern around the point
			for (int w = 1;; w++) {
				//Check if the nodes are within distance limit
				if (nodeSize*w > maxDist) {
					nn.node = minNode;
					nn.clampedPosition = clampedPosition;
					return nn;
				}

				bool anyInside = false;

				int nx;
				int nz = z+w;
				int nz2 = nz*width;

				// Side 1 on the square
				for (nx = x-w; nx <= x+w; nx++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable(nodes[nx+nz2])) {
						float dist = ((Vector3)nodes[nx+nz2].position-globalPosition).sqrMagnitude;
						if (dist < minDist && dist < maxDistSqr) {
							// Minimum distance so far
							minDist = dist;
							minNode = nodes[nx+nz2];

							// Closest point on the node if the node is treated as a square
							clampedPosition = matrix.MultiplyPoint3x4(new Vector3(Mathf.Clamp(xf, nx-0.5f, nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf, nz-0.5f, nz+0.5f)+0.5f));
						}
					}
				}

				nz = z-w;
				nz2 = nz*width;

				// Side 2 on the square
				for (nx = x-w; nx <= x+w; nx++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable(nodes[nx+nz2])) {
						float dist = ((Vector3)nodes[nx+nz2].position-globalPosition).sqrMagnitude;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz2];
							clampedPosition = matrix.MultiplyPoint3x4(new Vector3(Mathf.Clamp(xf, nx-0.5f, nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf, nz-0.5f, nz+0.5f)+0.5f));
						}
					}
				}

				nx = x-w;

				// Side 3 on the square
				for (nz = z-w+1; nz <= z+w-1; nz++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable(nodes[nx+nz*width])) {
						float dist = ((Vector3)nodes[nx+nz*width].position-globalPosition).sqrMagnitude;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz*width];
							clampedPosition = matrix.MultiplyPoint3x4(new Vector3(Mathf.Clamp(xf, nx-0.5f, nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf, nz-0.5f, nz+0.5f)+0.5f));
						}
					}
				}

				nx = x+w;

				// Side 4 on the square
				for (nz = z-w+1; nz <= z+w-1; nz++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable(nodes[nx+nz*width])) {
						float dist = ((Vector3)nodes[nx+nz*width].position-globalPosition).sqrMagnitude;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz*width];
							clampedPosition = matrix.MultiplyPoint3x4(new Vector3(Mathf.Clamp(xf, nx-0.5f, nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf, nz-0.5f, nz+0.5f)+0.5f));
						}
					}
				}

				// We found a suitable node
				if (minNode != null) {
					// If we don't need to search more, just return
					// Otherwise search for 'overlap' iterations more
					if (overlap == 0) {
						nn.node = minNode;
						nn.clampedPosition = clampedPosition;
						return nn;
					}
					overlap--;
				}

				// No nodes were inside grid bounds
				// We will not be able to find any more valid nodes
				// so just return
				if (!anyInside) {
					nn.node = minNode;
					nn.clampedPosition = clampedPosition;
					return nn;
				}
			}
		}
Beispiel #54
0
		//public void GenerateBounds () {
			//bounds.center = offset+new Vector3 (0,height*0.5F,0);
			//bounds.size = new Vector3 (width*scale,height,depth*scale);
		//}
		
		/** \todo Set clamped position for Grid Graph */
		public override NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
			
			if (nodes == null || depth*width != nodes.Length) {
				return new NNInfo ();
			}
			
			position = inverseMatrix.MultiplyPoint3x4 (position);
			
			float xf = position.x-0.5F;
			float zf = position.z-0.5f;
			int x = Mathf.Clamp (Mathf.RoundToInt (xf)  , 0, width-1);
			int z = Mathf.Clamp (Mathf.RoundToInt (zf)  , 0, depth-1);
			
			NNInfo nn = new NNInfo(nodes[z*width+x]);
			
			float y = inverseMatrix.MultiplyPoint3x4((Vector3)nodes[z*width+x].position).y;
			nn.clampedPosition = matrix.MultiplyPoint3x4 (new Vector3(Mathf.Clamp(xf,x-0.5f,x+0.5f)+0.5f,y,Mathf.Clamp(zf,z-0.5f,z+0.5f)+0.5f));
			
			//Set clamped position
			//nn.clampedPosition = new Vector3(Mathf.Clamp (xf,x-0.5f,x+0.5f),position.y,Mathf.Clamp (zf,z-0.5f,z+0.5f));
			//nn.clampedPosition = matrix.MultiplyPoint3x4 (nn.clampedPosition);
			
			return nn;
		}
Beispiel #55
0
 private void SearchBoxClosestXZ(int boxi, Vector3 p, ref float closestDist, NNConstraint constraint, ref NNInfo nnInfo)
 {
     BBTree.BBTreeBox bBTreeBox = this.arr[boxi];
     if (bBTreeBox.node != null)
     {
         Vector3 constClampedPosition = bBTreeBox.node.ClosestPointOnNodeXZ(p);
         if (constraint == null || constraint.Suitable(bBTreeBox.node))
         {
             float num = (constClampedPosition.x - p.x) * (constClampedPosition.x - p.x) + (constClampedPosition.z - p.z) * (constClampedPosition.z - p.z);
             if (nnInfo.constrainedNode == null)
             {
                 nnInfo.constrainedNode = bBTreeBox.node;
                 nnInfo.constClampedPosition = constClampedPosition;
                 closestDist = (float)Math.Sqrt((double)num);
             }
             else if (num < closestDist * closestDist)
             {
                 nnInfo.constrainedNode = bBTreeBox.node;
                 nnInfo.constClampedPosition = constClampedPosition;
                 closestDist = (float)Math.Sqrt((double)num);
             }
         }
     }
     else
     {
         if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.left].rect, p, closestDist))
         {
             this.SearchBoxClosestXZ(bBTreeBox.left, p, ref closestDist, constraint, ref nnInfo);
         }
         if (BBTree.RectIntersectsCircle(this.arr[bBTreeBox.right].rect, p, closestDist))
         {
             this.SearchBoxClosestXZ(bBTreeBox.right, p, ref closestDist, constraint, ref nnInfo);
         }
     }
 }
Beispiel #56
0
		/** Queries the tree for the closest node to \a p constrained by the NNConstraint trying to improve an existing solution.
		  * Note that this function will, unlike QueryCircle, only fill in the constrained node.
		  * If you want a node not constrained by any NNConstraint, do an additional search with constraint = NNConstraint.None
		  * 
		  * This search will start from the \a previous NNInfo and improve it if possible.
		  * Even if the search fails on this call, the solution will never be worse than \a previous.
		  * 
		  * This method will completely ignore any Y-axis differences in positions.
		  * 
		  * \param distance The best distance for the \a previous solution. Will be updated with the best distance
		  * after this search. Will be positive infinity if no node could be found.
		  * Set to positive infinity if there was no previous solution.
		  * 
		  * 
		  * \see QueryCircle
		  */
		public NNInfo QueryClosestXZ (Vector3 p, NNConstraint constraint, ref float distance, NNInfo previous) {
			BBTreeBox c = root;
			
			if (c == null) {
				return previous;
			}
			
			SearchBoxClosestXZ (c,p, ref distance, constraint, ref previous);
			
			return previous;
		}
Beispiel #57
0
	/** Returns the nearest node to a position using the specified NNConstraint.
	 Searches through all graphs for their nearest nodes to the specified position and picks the closest one.
	 The NNConstraint can be used to specify constraints on which nodes can be chosen such as only picking walkable nodes.
	 \see Pathfinding.NNConstraint
	 */
	public NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
		
		if (graphs == null) { return new NNInfo(); }
		
		float minDist = float.PositiveInfinity;//Math.Infinity;
		NNInfo nearestNode = new NNInfo ();
		int nearestGraph = -1;
		
		for (int i=0;i<graphs.Length;i++) {
			
			NavGraph graph = graphs[i];
			
			if (graph == null) continue;
			
			//Check if this graph should be searched
			if (!constraint.SuitableGraph (i,graph)) {
				continue;
			}
			
			NNInfo nnInfo;
			if (fullGetNearestSearch) {
				nnInfo = graph.GetNearestForce (position, constraint);
			} else {
				nnInfo = graph.GetNearest (position, constraint);
			}
			
			GraphNode node = nnInfo.node;
			
			if (node == null) {
				continue;
			}
			
			float dist = ((Vector3)nnInfo.clampedPosition-position).magnitude;
			
			if (prioritizeGraphs && dist < prioritizeGraphsLimit) {
				//The node is close enough, choose this graph and discard all others
				minDist = dist;
				nearestNode = nnInfo;
				nearestGraph = i;
				break;
			} else {
				if (dist < minDist) {
					minDist = dist;
					nearestNode = nnInfo;
					nearestGraph = i;
				}
			}
		}
		
		//No matches found
		if (nearestGraph == -1) {
			return nearestNode;
		}
		
		//Check if a constrained node has already been set
		if (nearestNode.constrainedNode != null) {
			nearestNode.node = nearestNode.constrainedNode;
			nearestNode.clampedPosition = nearestNode.constClampedPosition;
		}
		
		if (!fullGetNearestSearch && nearestNode.node != null && !constraint.Suitable (nearestNode.node)) {
			
			//Otherwise, perform a check to force the graphs to check for a suitable node
			NNInfo nnInfo = graphs[nearestGraph].GetNearestForce (position, constraint);
			
			if (nnInfo.node != null) {
				nearestNode = nnInfo;
			}
		}
		
		if (!constraint.Suitable (nearestNode.node) || (constraint.constrainDistance && (nearestNode.clampedPosition - position).sqrMagnitude > maxNearestNodeDistanceSqr)) {
			return new NNInfo();
		}
		
		return nearestNode;
	}
		public NNInfo Query (Vector3 p, NNConstraint constraint) {

			if ( count == 0 ) return new NNInfo(null);

			var nnInfo = new NNInfo ();

			SearchBox (0,p, constraint, ref nnInfo);

			nnInfo.UpdateInfo ();

			return nnInfo;
		}
Beispiel #59
0
		/** \todo Set clamped position for Grid Graph */
		public override NNInfo GetNearestForce (Vector3 position, NNConstraint constraint) {
			
			if (nodes == null || depth*width != nodes.Length) {
				return new NNInfo ();
			}
			
			Vector3 globalPosition = position;
			
			position = inverseMatrix.MultiplyPoint3x4 (position);
			
			float xf = position.x-0.5F;
			float zf = position.z-0.5f;
			int x = Mathf.Clamp (Mathf.RoundToInt (xf)  , 0, width-1);
			int z = Mathf.Clamp (Mathf.RoundToInt (zf)  , 0, depth-1);
			
			GridNode node = nodes[x+z*width];
			
			GridNode minNode = null;
			float minDist = float.PositiveInfinity;
			int overlap = getNearestForceOverlap;
			
			Vector3 clampedPosition = Vector3.zero;
			NNInfo nn = new NNInfo(null);
			
			if (constraint.Suitable (node)) {
				minNode = node;
				minDist = ((Vector3)minNode.position-globalPosition).sqrMagnitude;
				float y = inverseMatrix.MultiplyPoint3x4((Vector3)node.position).y;
				clampedPosition = matrix.MultiplyPoint3x4 (new Vector3(Mathf.Clamp(xf,x-0.5f,x+0.5f)+0.5f, y, Mathf.Clamp(zf,z-0.5f,z+0.5f)+0.5f));
			}
			
			if (minNode != null) {
				nn.node = minNode;
				nn.clampedPosition = clampedPosition;
				
				if (overlap == 0) return nn;
				else overlap--;
			}
			
			
			//int counter = 0;
			
			
			float maxDist = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistance : float.PositiveInfinity;
			float maxDistSqr = maxDist*maxDist;
			
			
			//for (int w = 1; w < getNearestForceLimit;w++) {
			for (int w = 1;;w++) {
				
				//Check if the nodes are within distance limit
				if (nodeSize*w > maxDist) {
					nn.node = minNode;
					nn.clampedPosition = clampedPosition;
					return nn;
				}
				
				bool anyInside = false;
				
				int nx = x;
				int nz = z+w;
				
				int nz2 = nz*width;
				
				for (nx = x-w;nx <= x+w;nx++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable (nodes[nx+nz2])) {
						float dist = ((Vector3)nodes[nx+nz2].position-globalPosition).sqrMagnitude;
						//Debug.DrawRay (nodes[nx+nz2].position,Vector3.up*dist,Color.cyan);counter++;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz2];
							clampedPosition = matrix.MultiplyPoint3x4 (new Vector3 (Mathf.Clamp(xf,nx-0.5f,nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf,nz-0.5f,nz+0.5f)+0.5f));
						}
					}
				}
				
				nz = z-w;
				nz2 = nz*width;
				
				for (nx = x-w;nx <= x+w;nx++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable (nodes[nx+nz2])) {
						float dist = ((Vector3)nodes[nx+nz2].position-globalPosition).sqrMagnitude;
						//Debug.DrawRay (nodes[nx+nz2].position,Vector3.up*dist,Color.cyan);counter++;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz2];
							clampedPosition = matrix.MultiplyPoint3x4 (new Vector3 (Mathf.Clamp(xf,nx-0.5f,nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf,nz-0.5f,nz+0.5f)+0.5f));
						}
					}
				}
				
				nx = x-w;
				nz = z-w+1;
				
				for (nz = z-w+1;nz <= z+w-1; nz++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable (nodes[nx+nz*width])) {
						float dist = ((Vector3)nodes[nx+nz*width].position-globalPosition).sqrMagnitude;
						//Debug.DrawRay (nodes[nx+nz*width].position,Vector3.up*dist,Color.cyan);counter++;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz*width];
							clampedPosition = matrix.MultiplyPoint3x4 (new Vector3 (Mathf.Clamp(xf,nx-0.5f,nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf,nz-0.5f,nz+0.5f)+0.5f));
						}
					}
				}
				
				nx = x+w;
				
				for (nz = z-w+1;nz <= z+w-1; nz++) {
					if (nx < 0 || nz < 0 || nx >= width || nz >= depth) continue;
					anyInside = true;
					if (constraint.Suitable (nodes[nx+nz*width])) {
						float dist = ((Vector3)nodes[nx+nz*width].position-globalPosition).sqrMagnitude;
						//Debug.DrawRay (nodes[nx+nz*width].position,Vector3.up*dist,Color.cyan);counter++;
						if (dist < minDist && dist < maxDistSqr) {
							minDist = dist;
							minNode = nodes[nx+nz*width];
							clampedPosition = matrix.MultiplyPoint3x4 (new Vector3 (Mathf.Clamp(xf,nx-0.5f,nx+0.5f)+0.5f, inverseMatrix.MultiplyPoint3x4((Vector3)minNode.position).y, Mathf.Clamp(zf,nz-0.5f,nz+0.5f)+0.5f));
						}
					}
				}
				
				if (minNode != null) {
					if (overlap == 0) {
						nn.node = minNode;
						nn.clampedPosition = clampedPosition;
						return nn;
					}
					else overlap--;
				}
				
				//No nodes were inside grid bounds
				if (!anyInside) {
					nn.node = minNode;
					nn.clampedPosition = clampedPosition;
					return nn;
				}
			}
			//return new NNInfo ();
		}
		/** Queries the tree for the best node, searching within a circle around \a p with the specified radius.
		  * Will fill in both the constrained node and the not constrained node in the NNInfo.
		  *
		  * \see QueryClosest
		  */
		public NNInfo QueryCircle (Vector3 p, float radius, NNConstraint constraint) {

			if ( count == 0 ) return new NNInfo(null);

			var nnInfo = new NNInfo (null);

			SearchBoxCircle (0,p, radius, constraint, ref nnInfo);

			nnInfo.UpdateInfo ();

			return nnInfo;
		}