// Token: 0x0600265C RID: 9820 RVA: 0x001A99D0 File Offset: 0x001A7BD0
		public void RecalculatePivots()
		{
			if (this.mode == HeuristicOptimizationMode.None)
			{
				this.pivotCount = 0;
				this.pivots = null;
				return;
			}
			this.rval = (uint)this.seed;
			List<GraphNode> list = ListPool<GraphNode>.Claim();
			switch (this.mode)
			{
			case HeuristicOptimizationMode.Random:
				this.PickNRandomNodes(this.spreadOutCount, list);
				break;
			case HeuristicOptimizationMode.RandomSpreadOut:
			{
				if (this.pivotPointRoot != null)
				{
					this.GetClosestWalkableNodesToChildrenRecursively(this.pivotPointRoot, list);
				}
				if (list.Count == 0)
				{
					GraphNode graphNode = this.PickAnyWalkableNode();
					if (graphNode == null)
					{
						Debug.LogError("Could not find any walkable node in any of the graphs.");
						ListPool<GraphNode>.Release(ref list);
						return;
					}
					list.Add(graphNode);
				}
				int num = this.spreadOutCount - list.Count;
				for (int i = 0; i < num; i++)
				{
					list.Add(null);
				}
				break;
			}
			case HeuristicOptimizationMode.Custom:
				if (this.pivotPointRoot == null)
				{
					throw new Exception("heuristicOptimizationMode is HeuristicOptimizationMode.Custom, but no 'customHeuristicOptimizationPivotsRoot' is set");
				}
				this.GetClosestWalkableNodesToChildrenRecursively(this.pivotPointRoot, list);
				break;
			default:
				throw new Exception("Invalid HeuristicOptimizationMode: " + this.mode);
			}
			this.pivots = list.ToArray();
			ListPool<GraphNode>.Release(ref list);
		}
Exemple #2
0
        private void AddGraphObstacles(Simulator sim, INavmesh ng)
        {
            int[] uses = new int[3];
            Dictionary <int, int>  outline         = new Dictionary <int, int>();
            Dictionary <int, Int3> vertexPositions = new Dictionary <int, Int3>();
            HashSet <int>          hasInEdge       = new HashSet <int>();

            ng.GetNodes(delegate(GraphNode _node)
            {
                TriangleMeshNode triangleMeshNode = _node as TriangleMeshNode;
                uses[0] = (uses[1] = (uses[2] = 0));
                if (triangleMeshNode != null)
                {
                    for (int i = 0; i < triangleMeshNode.connections.Length; i++)
                    {
                        TriangleMeshNode triangleMeshNode2 = triangleMeshNode.connections[i].node as TriangleMeshNode;
                        if (triangleMeshNode2 != null)
                        {
                            int num = triangleMeshNode.SharedEdge(triangleMeshNode2);
                            if (num != -1)
                            {
                                uses[num] = 1;
                            }
                        }
                    }
                    for (int j = 0; j < 3; j++)
                    {
                        if (uses[j] == 0)
                        {
                            int i2 = j;
                            int i3 = (j + 1) % triangleMeshNode.GetVertexCount();
                            outline[triangleMeshNode.GetVertexIndex(i2)] = triangleMeshNode.GetVertexIndex(i3);
                            hasInEdge.Add(triangleMeshNode.GetVertexIndex(i3));
                            vertexPositions[triangleMeshNode.GetVertexIndex(i2)] = triangleMeshNode.GetVertex(i2);
                            vertexPositions[triangleMeshNode.GetVertexIndex(i3)] = triangleMeshNode.GetVertex(i3);
                        }
                    }
                }
            });
            List <Vector3> vertices = ListPool <Vector3> .Claim();

            RVONavmesh.CompressContour(outline, hasInEdge, delegate(List <int> chain, bool cycle)
            {
                for (int i = 0; i < chain.Count; i++)
                {
                    vertices.Add((Vector3)vertexPositions[chain[i]]);
                }
                this.obstacles.Add(sim.AddObstacle(vertices.ToArray(), this.wallHeight, cycle));
                vertices.Clear();
            });
            ListPool <Vector3> .Release(vertices);
        }
Exemple #3
0
        public void BuildFunnelCorridor(List <GraphNode> nodes, int start, int end)
        {
            this.exactStart = (nodes[start] as MeshNode).ClosestPointOnNode(this.exactStart);
            this.exactEnd   = (nodes[end] as MeshNode).ClosestPointOnNode(this.exactEnd);
            this.left.Clear();
            this.right.Clear();
            this.left.Add(this.exactStart);
            this.right.Add(this.exactStart);
            this.nodes.Clear();
            IRaycastableGraph raycastableGraph = this.graph as IRaycastableGraph;

            if (raycastableGraph != null && this.funnelSimplification)
            {
                List <GraphNode> list = ListPool <GraphNode> .Claim(end - start);

                this.SimplifyPath(raycastableGraph, nodes, start, end, list, this.exactStart, this.exactEnd);
                if (this.nodes.Capacity < list.Count)
                {
                    this.nodes.Capacity = list.Count;
                }
                for (int i = 0; i < list.Count; i++)
                {
                    TriangleMeshNode triangleMeshNode = list[i] as TriangleMeshNode;
                    if (triangleMeshNode != null)
                    {
                        this.nodes.Add(triangleMeshNode);
                    }
                }
                ListPool <GraphNode> .Release(list);
            }
            else
            {
                if (this.nodes.Capacity < end - start)
                {
                    this.nodes.Capacity = end - start;
                }
                for (int j = start; j <= end; j++)
                {
                    TriangleMeshNode triangleMeshNode2 = nodes[j] as TriangleMeshNode;
                    if (triangleMeshNode2 != null)
                    {
                        this.nodes.Add(triangleMeshNode2);
                    }
                }
            }
            for (int k = 0; k < this.nodes.Count - 1; k++)
            {
                this.nodes[k].GetPortal(this.nodes[k + 1], this.left, this.right, false);
            }
            this.left.Add(this.exactEnd);
            this.right.Add(this.exactEnd);
        }
Exemple #4
0
        public void CollectRecastMeshObjs(List <RasterizationMesh> buffer)
        {
            List <RecastMeshObj> list = ListPool <RecastMeshObj> .Claim();

            RecastMeshObj.GetAllInBounds(list, this.bounds);
            Dictionary <Mesh, Vector3[]> dictionary  = new Dictionary <Mesh, Vector3[]>();
            Dictionary <Mesh, int[]>     dictionary2 = new Dictionary <Mesh, int[]>();

            for (int i = 0; i < list.Count; i++)
            {
                MeshFilter meshFilter = list[i].GetMeshFilter();
                Renderer   renderer   = (meshFilter != null) ? meshFilter.GetComponent <Renderer>() : null;
                if (meshFilter != null && renderer != null)
                {
                    Mesh sharedMesh = meshFilter.sharedMesh;
                    RasterizationMesh rasterizationMesh;
                    if (dictionary.ContainsKey(sharedMesh))
                    {
                        rasterizationMesh = new RasterizationMesh(dictionary[sharedMesh], dictionary2[sharedMesh], renderer.bounds);
                    }
                    else
                    {
                        rasterizationMesh       = new RasterizationMesh(sharedMesh.vertices, sharedMesh.triangles, renderer.bounds);
                        dictionary[sharedMesh]  = rasterizationMesh.vertices;
                        dictionary2[sharedMesh] = rasterizationMesh.triangles;
                    }
                    rasterizationMesh.matrix   = renderer.localToWorldMatrix;
                    rasterizationMesh.original = meshFilter;
                    rasterizationMesh.area     = list[i].area;
                    buffer.Add(rasterizationMesh);
                }
                else
                {
                    Collider collider = list[i].GetCollider();
                    if (collider == null)
                    {
                        Debug.LogError("RecastMeshObject (" + list[i].gameObject.name + ") didn't have a collider or MeshFilter+Renderer attached", list[i].gameObject);
                    }
                    else
                    {
                        RasterizationMesh rasterizationMesh2 = this.RasterizeCollider(collider);
                        if (rasterizationMesh2 != null)
                        {
                            rasterizationMesh2.area = list[i].area;
                            buffer.Add(rasterizationMesh2);
                        }
                    }
                }
            }
            this.capsuleCache.Clear();
            ListPool <RecastMeshObj> .Release(list);
        }
        public List <Vector3> SmoothBezier(List <Vector3> path)
        {
            if (subdivisions < 0)
            {
                subdivisions = 0;
            }

            int            subMult    = 1 << subdivisions;
            List <Vector3> subdivided = ListPool <Vector3> .Claim();

            for (int i = 0; i < path.Count - 1; i++)
            {
                Vector3 tangent1;
                Vector3 tangent2;
                if (i == 0)
                {
                    tangent1 = path[i + 1] - path[i];
                }
                else
                {
                    tangent1 = path[i + 1] - path[i - 1];
                }

                if (i == path.Count - 2)
                {
                    tangent2 = path[i] - path[i + 1];
                }
                else
                {
                    tangent2 = path[i] - path[i + 2];
                }

                tangent1 *= bezierTangentLength;
                tangent2 *= bezierTangentLength;

                Vector3 v1 = path[i];
                Vector3 v2 = v1 + tangent1;
                Vector3 v4 = path[i + 1];
                Vector3 v3 = v4 + tangent2;


                for (int j = 0; j < subMult; j++)
                {
                    subdivided.Add(AstarMath.CubicBezier(v1, v2, v3, v4, (float)j / subMult));
                }
            }

            //Assign the last point
            subdivided.Add(path[path.Count - 1]);

            return(subdivided);
        }
Exemple #6
0
        /// <summary>
        /// Returns all nodes reachable from the seed node.
        /// This function performs a DFS (depth-first-search) or flood fill of the graph and returns all nodes which can be reached from
        /// the seed node. In almost all cases this will be identical to returning all nodes which have the same area as the seed node.
        /// In the editor areas are displayed as different colors of the nodes.
        /// The only case where it will not be so is when there is a one way path from some part of the area to the seed node
        /// but no path from the seed node to that part of the graph.
        ///
        /// The returned list is not sorted in any particular way.
        ///
        /// Depending on the number of reachable nodes, this function can take quite some time to calculate
        /// so don't use it too often or it might affect the framerate of your game.
        ///
        /// See: bitmasks (view in online documentation for working links).
        ///
        /// Returns: A List<Node> containing all nodes reachable from the seed node.
        /// For better memory management the returned list should be pooled, see Pathfinding.Util.ListPool.
        /// </summary>
        /// <param name="seed">The node to start the search from.</param>
        /// <param name="tagMask">Optional mask for tags. This is a bitmask.</param>
        /// <param name="filter">Optional filter for which nodes to search. You can combine this with tagMask = -1 to make the filter determine everything.
        ///      Only walkable nodes are searched regardless of the filter. If the filter function returns false the node will be treated as unwalkable.</param>
        public static List <GraphNode> GetReachableNodes(GraphNode seed, int tagMask          = -1,
                                                         System.Func <GraphNode, bool> filter = null)
        {
            var dfsStack = StackPool <GraphNode> .Claim();

            var reachable = ListPool <GraphNode> .Claim();

            /// <summary>TODO: Pool</summary>
            var map = new HashSet <GraphNode>();

            System.Action <GraphNode> callback;
            // Check if we can use the fast path
            if (tagMask == -1 && filter == null)
            {
                callback = (GraphNode node) =>
                {
                    if (node.Walkable && map.Add(node))
                    {
                        reachable.Add(node);
                        dfsStack.Push(node);
                    }
                }
            }
            ;
            else
            {
                callback = (GraphNode node) =>
                {
                    if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && map.Add(node))
                    {
                        if (filter != null && !filter(node))
                        {
                            return;
                        }

                        reachable.Add(node);
                        dfsStack.Push(node);
                    }
                }
            };

            callback(seed);

            while (dfsStack.Count > 0)
            {
                dfsStack.Pop().GetConnections(callback);
            }

            StackPool <GraphNode> .Release(dfsStack);

            return(reachable);
        }
Exemple #7
0
 /** Should be called on every node which is updated with this GUO before it is updated.
  * \param node The node to save fields for. If null, nothing will be done
  * \see #trackChangedNodes
  */
 public virtual void WillUpdateNode(GraphNode node)
 {
     if (trackChangedNodes && node != null)
     {
         if (changedNodes == null)
         {
             changedNodes = ListPool <GraphNode> .Claim(); backupData = ListPool <ulong> .Claim(); backupPositionData = ListPool <Int3> .Claim();
         }
         changedNodes.Add(node);
         backupPositionData.Add(node.position);
         backupData.Add((ulong)node.Penalty << 32 | (ulong)node.Flags);
     }
 }
        /// <summary>
        /// Register blocker as being present at the specified node.
        /// Calling this method multiple times will add multiple instances of the blocker to the node.
        ///
        /// Note: The node will not be blocked immediately. Instead the pathfinding
        /// threads will be paused and then the update will be applied. It is however
        /// guaranteed to be applied before the next path request is started.
        /// </summary>
        public void InternalBlock(GraphNode node, SingleNodeBlocker blocker)
        {
            AstarPath.active.AddWorkItem(new AstarWorkItem(() =>
            {
                List <SingleNodeBlocker> blockersInNode;
                if (!blocked.TryGetValue(node, out blockersInNode))
                {
                    blockersInNode = blocked[node] = ListPool <SingleNodeBlocker> .Claim();
                }

                blockersInNode.Add(blocker);
            }));
        }
        /** Updates graphs and checks if all nodes are still reachable from each other.
         * Graphs are updated, then a check is made to see if the nodes are still reachable from each other.
         * If they are not, the graphs are reverted to before the update and \a false is returned.\n
         * This is slower than a normal graph update.
         * All queued graph updates and thread safe callbacks will be flushed during this function.
         *
         * \note This might return true for small areas even if there is no possible path if AstarPath.minAreaSize is greater than zero (0).
         * So when using this, it is recommended to set AstarPath.minAreaSize to 0 (A* Inspector -> Settings -> Pathfinding)
         *
         * \param guo The GraphUpdateObject to update the graphs with
         * \param node1 Node which should have a valid path to \a node2. All nodes should be walkable or \a false will be returned.
         * \param node2 Node which should have a valid path to \a node1. All nodes should be walkable or \a false will be returned.
         * \param alwaysRevert If true, reverts the graphs to the old state even if no blocking ocurred
         */
        public static bool UpdateGraphsNoBlock(GraphUpdateObject guo, GraphNode node1, GraphNode node2, bool alwaysRevert = false)
        {
            List <GraphNode> buffer = ListPool <GraphNode> .Claim();

            buffer.Add(node1);
            buffer.Add(node2);

            bool worked = UpdateGraphsNoBlock(guo, buffer, alwaysRevert);

            ListPool <GraphNode> .Release(buffer);

            return(worked);
        }
Exemple #10
0
        public static List <NavmeshAdd> GetAllInRange(Bounds b)
        {
            List <NavmeshAdd> list = ListPool <NavmeshAdd> .Claim();

            for (int i = 0; i < NavmeshAdd.allCuts.Count; i++)
            {
                if (NavmeshAdd.allCuts[i].enabled && NavmeshAdd.Intersects(b, NavmeshAdd.allCuts[i].GetBounds()))
                {
                    list.Add(NavmeshAdd.allCuts[i]);
                }
            }
            return(list);
        }
Exemple #11
0
 public void InternalBlock(GraphNode node, SingleNodeBlocker blocker)
 {
     AstarPath.active.AddWorkItem(new AstarWorkItem(delegate
     {
         List <SingleNodeBlocker> list;
         if (!this.blocked.TryGetValue(node, out list))
         {
             List <SingleNodeBlocker> list2 = ListPool <SingleNodeBlocker> .Claim();
             this.blocked[node]             = list2;
             list = list2;
         }
         list.Add(blocker);
     }, null));
 }
        protected override IEnumerable <Progress> ScanInternal()
        {
            cachedSourceMeshBoundsMin = sourceMesh != null ? sourceMesh.bounds.min : Vector3.zero;
            transform  = CalculateTransform();
            tileZCount = tileXCount = 1;
            tiles      = new NavmeshTile[tileZCount * tileXCount];
            TriangleMeshNode.SetNavmeshHolder(AstarPath.active.data.GetGraphIndex(this), this);

            if (sourceMesh == null)
            {
                FillWithEmptyTiles();
                yield break;
            }

            yield return(new Progress(0.0f, "Transforming Vertices"));

            forcedBoundsSize = sourceMesh.bounds.size * scale;
            Vector3[] vectorVertices = sourceMesh.vertices;
            var       intVertices    = ListPool <Int3> .Claim(vectorVertices.Length);

            var matrix = Matrix4x4.TRS(-sourceMesh.bounds.min * scale, Quaternion.identity, Vector3.one * scale);

            // Convert the vertices to integer coordinates and also position them in graph space
            // so that the minimum of the bounding box of the mesh is at the origin
            // (the vertices will later be transformed to world space)
            for (int i = 0; i < vectorVertices.Length; i++)
            {
                intVertices.Add((Int3)matrix.MultiplyPoint3x4(vectorVertices[i]));
            }

            yield return(new Progress(0.1f, "Compressing Vertices"));

            // Remove duplicate vertices
            Int3[] compressedVertices  = null;
            int[]  compressedTriangles = null;
            Polygon.CompressMesh(intVertices, new List <int>(sourceMesh.triangles), out compressedVertices,
                                 out compressedTriangles);
            ListPool <Int3> .Release(ref intVertices);

            yield return(new Progress(0.2f, "Building Nodes"));

            ReplaceTile(0, 0, compressedVertices, compressedTriangles);

            // Signal that tiles have been recalculated to the navmesh cutting system.
            navmeshUpdateData.OnRecalculatedTiles(tiles);
            if (OnRecalculatedTiles != null)
            {
                OnRecalculatedTiles(tiles.Clone() as NavmeshTile[]);
            }
        }
Exemple #13
0
        /** Returns all nodes reachable from the seed node.
         * This function performs a BFS (breadth-first-search) or flood fill of the graph and returns all nodes which can be reached from
         * the seed node. In almost all cases this will be identical to returning all nodes which have the same area as the seed node.
         * In the editor areas are displayed as different colors of the nodes.
         * The only case where it will not be so is when there is a one way path from some part of the area to the seed node
         * but no path from the seed node to that part of the graph.
         *
         * The returned list is sorted by node distance from the seed node
         * i.e distance is measured in the number of nodes the shortest path from \a seed to that node would pass through.
         * Note that the distance measurement does not take heuristics, penalties or tag penalties.
         *
         * Depending on the number of reachable nodes, this function can take quite some time to calculate
         * so don't use it too often or it might affect the framerate of your game.
         *
         * \param seed The node to start the search from
         * \param tagMask Optional mask for tags. This is a bitmask.
         *
         * \returns A List<Node> containing all nodes reachable from the seed node.
         * For better memory management the returned list should be pooled, see Pathfinding.Util.ListPool
         */
        public static List <GraphNode> GetReachableNodes(GraphNode seed, int tagMask = -1)
        {
#if ASTAR_PROFILE
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
#endif
            Stack <GraphNode> stack = StackPool <GraphNode> .Claim();

            List <GraphNode> list = ListPool <GraphNode> .Claim();

            /** \todo Pool */
            var map = new HashSet <GraphNode>();

            GraphNodeDelegate callback;
            if (tagMask == -1)
            {
                callback = delegate(GraphNode node) {
                    if (node.Walkable && map.Add(node))
                    {
                        list.Add(node);
                        stack.Push(node);
                    }
                };
            }
            else
            {
                callback = delegate(GraphNode node) {
                    if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && map.Add(node))
                    {
                        list.Add(node);
                        stack.Push(node);
                    }
                };
            }

            callback(seed);

            while (stack.Count > 0)
            {
                stack.Pop().GetConnections(callback);
            }

            StackPool <GraphNode> .Release(stack);

#if ASTAR_PROFILE
            watch.Stop();
            Debug.Log((1000 * watch.Elapsed.TotalSeconds).ToString("0.0 ms"));
#endif
            return(list);
        }
Exemple #14
0
        public override void OnDrawGizmosSelected()
        {
            base.OnDrawGizmosSelected();
            List <Vector3> list = ListPool <Vector3> .Claim();

            Vector3 zero = Vector3.zero;

            this.CalculateOffsets(list, out zero);
            Gizmos.color = Color.blue;
            for (int i = 0; i < list.Count - 1; i++)
            {
                Gizmos.DrawLine(list[i], list[i + 1]);
            }
        }
Exemple #15
0
        public override void OnDrawGizmosSelected()
        {
            base.OnDrawGizmosSelected();
            var buffer = ListPool <Vector3> .Claim();

            var endPosition = Vector3.zero;

            CalculateOffsets(buffer, out endPosition);
            Gizmos.color = Color.blue;
            for (var i = 0; i < buffer.Count - 1; i++)
            {
                Gizmos.DrawLine(buffer[i], buffer[i + 1]);
            }
        }
Exemple #16
0
        public static FunnelPortals ConstructFunnelPortals(List <GraphNode> nodes, PathPart part)
        {
            if (nodes == null || nodes.Count == 0)
            {
                return new FunnelPortals {
                           left = ListPool <Vector3> .Claim(0), right = ListPool <Vector3> .Claim(0)
                }
            }
            ;

            if (part.endIndex < part.startIndex || part.startIndex < 0 || part.endIndex > nodes.Count)
            {
                throw new System.ArgumentOutOfRangeException();
            }

            // Claim temporary lists and try to find lists with a high capacity
            var left = ListPool <Vector3> .Claim(nodes.Count + 1);

            var right = ListPool <Vector3> .Claim(nodes.Count + 1);

            // Add start point
            left.Add(part.startPoint);
            right.Add(part.startPoint);

            // Loop through all nodes in the path (except the last one)
            for (var i = part.startIndex; i < part.endIndex; i++)
            {
                // Get the portal between path[i] and path[i+1] and add it to the left and right lists
                var portalWasAdded = nodes[i].GetPortal(nodes[i + 1], left, right, false);

                if (!portalWasAdded)
                {
                    // Fallback, just use the positions of the nodes
                    left.Add((Vector3)nodes[i].position);
                    right.Add((Vector3)nodes[i].position);

                    left.Add((Vector3)nodes[i + 1].position);
                    right.Add((Vector3)nodes[i + 1].position);
                }
            }

            // Add end point
            left.Add(part.endPoint);
            right.Add(part.endPoint);

            return(new FunnelPortals {
                left = left, right = right
            });
        }
        // Token: 0x0600229B RID: 8859 RVA: 0x00190E64 File Offset: 0x0018F064
        public static void GetContours(INavmesh navmesh, Action <List <Int3>, bool> results)
        {
            bool[] uses = new bool[3];
            Dictionary <int, int>  outline         = new Dictionary <int, int>();
            Dictionary <int, Int3> vertexPositions = new Dictionary <int, Int3>();
            HashSet <int>          hasInEdge       = new HashSet <int>();

            navmesh.GetNodes(delegate(GraphNode _node)
            {
                TriangleMeshNode triangleMeshNode = _node as TriangleMeshNode;
                uses[0] = (uses[1] = (uses[2] = false));
                if (triangleMeshNode != null)
                {
                    for (int i = 0; i < triangleMeshNode.connections.Length; i++)
                    {
                        TriangleMeshNode triangleMeshNode2 = triangleMeshNode.connections[i].node as TriangleMeshNode;
                        if (triangleMeshNode2 != null)
                        {
                            int num = triangleMeshNode.SharedEdge(triangleMeshNode2);
                            if (num != -1)
                            {
                                uses[num] = true;
                            }
                        }
                    }
                    for (int j = 0; j < 3; j++)
                    {
                        if (!uses[j])
                        {
                            int i2 = j;
                            int i3 = (j + 1) % triangleMeshNode.GetVertexCount();
                            outline[triangleMeshNode.GetVertexIndex(i2)] = triangleMeshNode.GetVertexIndex(i3);
                            hasInEdge.Add(triangleMeshNode.GetVertexIndex(i3));
                            vertexPositions[triangleMeshNode.GetVertexIndex(i2)] = triangleMeshNode.GetVertex(i2);
                            vertexPositions[triangleMeshNode.GetVertexIndex(i3)] = triangleMeshNode.GetVertex(i3);
                        }
                    }
                }
            });
            Polygon.TraceContours(outline, hasInEdge, delegate(List <int> chain, bool cycle)
            {
                List <Int3> list = ListPool <Int3> .Claim();
                for (int i = 0; i < chain.Count; i++)
                {
                    list.Add(vertexPositions[chain[i]]);
                }
                results(list, cycle);
            });
        }
Exemple #18
0
        public static Vector3[] ConvexHullXZ(Vector3[] points)
        {
            if (points.Length == 0)
            {
                return(new Vector3[0]);
            }
            List <Vector3> list = ListPool <Vector3> .Claim();

            int num = 0;

            for (int i = 1; i < points.Length; i++)
            {
                if (points[i].x < points[num].x)
                {
                    num = i;
                }
            }
            int num2 = num;
            int num3 = 0;

            for (;;)
            {
                list.Add(points[num]);
                int num4 = 0;
                for (int j = 0; j < points.Length; j++)
                {
                    if (num4 == num || !VectorMath.RightOrColinearXZ(points[num], points[num4], points[j]))
                    {
                        num4 = j;
                    }
                }
                num = num4;
                num3++;
                if (num3 > 10000)
                {
                    break;
                }
                if (num == num2)
                {
                    goto IL_E3;
                }
            }
            Debug.LogWarning("Infinite Loop in Convex Hull Calculation");
IL_E3:
            Vector3[] result = list.ToArray();
            ListPool <Vector3> .Release(list);

            return(result);
        }
        public virtual void Reset()
        {
            if (object.ReferenceEquals(AstarPath.active, null))
            {
                Debug.LogError("No AstarPath object found in the scene. Make sure there is one or do not create paths in Awake");
            }
            this.hasBeenReset      = true;
            this.state             = PathState.Created;
            this.releasedNotSilent = false;
            this.pathHandler       = null;
            this.callback          = null;
            this._errorLog         = string.Empty;
            this.pathCompleteState = PathCompleteState.NotCalculated;
            this.path = ListPool <GraphNode> .Claim(64);

            this.vectorPath = ListPool <VInt3> .Claim(64);

            this.currentR         = null;
            this.duration         = 0f;
            this.searchIterations = 0;
            this.searchedNodes    = 0;
            this.nnConstraint     = PathNNConstraint.Default;
            this.next             = null;
            this.radius           = 0;
            this.walkabilityMask  = -1;
            this.height           = 0;
            this.turnRadius       = 0;
            this.speed            = 0;
            this.pathID           = 0;
            this.enabledTags      = -1;
            this.tagPenalties     = null;
            this.callTime         = DateTime.get_UtcNow();
            AstarPath active = AstarPath.active;

            if (active != null)
            {
                this.pathID         = AstarPath.active.GetNextPathID();
                this.heuristic      = AstarPath.active.heuristic;
                this.heuristicScale = AstarPath.active.heuristicScale;
            }
            else
            {
                this.heuristic      = Heuristic.Manhattan;
                this.heuristicScale = 1f;
            }
            this.hTarget     = VInt3.zero;
            this.hTargetNode = null;
        }
        public override IEnumerable <Progress> ScanInternal()
        {
            transform  = CalculateTransform();
            tileZCount = tileXCount = 1;
            tiles      = new NavmeshTile[tileZCount * tileXCount];
            TriangleMeshNode.SetNavmeshHolder(AstarPath.active.data.GetGraphIndex(this), this);

            if (sourceMesh == null)
            {
                FillWithEmptyTiles();
                yield break;
            }

            yield return(new Progress(0.0f, "Transforming Vertices"));

            forcedBoundsSize = sourceMesh.bounds.size * scale;
            Vector3[] vectorVertices = sourceMesh.vertices;
            var       intVertices    = ListPool <Int3> .Claim(vectorVertices.Length);

            var matrix = Matrix4x4.TRS(-sourceMesh.bounds.min * scale, Quaternion.identity, Vector3.one * scale);

            // Convert the vertices to integer coordinates and also position them in graph space
            // so that the minimum of the bounding box of the mesh is at the origin
            // (the vertices will later be transformed to world space)
            for (int i = 0; i < vectorVertices.Length; i++)
            {
                intVertices.Add((Int3)matrix.MultiplyPoint3x4(vectorVertices[i]));
            }

            yield return(new Progress(0.1f, "Compressing Vertices"));

            // Remove duplicate vertices
            Int3[] compressedVertices  = null;
            int[]  compressedTriangles = null;
            Polygon.CompressMesh(intVertices, new List <int>(sourceMesh.triangles), out compressedVertices, out compressedTriangles);
            ListPool <Int3> .Release(intVertices);

            yield return(new Progress(0.2f, "Building Nodes"));

            ReplaceTile(0, 0, compressedVertices, compressedTriangles);

            // This may be used by the TileHandlerHelper script to update the tiles
            // while taking NavmeshCuts into account after the graph has been completely recalculated.
            if (OnRecalculatedTiles != null)
            {
                OnRecalculatedTiles(tiles.Clone() as NavmeshTile[]);
            }
        }
        // Token: 0x06002648 RID: 9800 RVA: 0x001A5D98 File Offset: 0x001A3F98
        public override void Apply(Path p)
        {
            if (p.path == null || p.path.Count == 0 || p.vectorPath == null || p.vectorPath.Count == 0)
            {
                return;
            }
            List <Vector3> list = ListPool <Vector3> .Claim();

            List <Funnel.PathPart> list2 = Funnel.SplitIntoParts(p);

            if (list2.Count == 0)
            {
                return;
            }
            for (int i = 0; i < list2.Count; i++)
            {
                Funnel.PathPart pathPart = list2[i];
                if (!pathPart.isLink)
                {
                    Funnel.FunnelPortals funnel     = Funnel.ConstructFunnelPortals(p.path, pathPart);
                    List <Vector3>       collection = Funnel.Calculate(funnel, this.unwrap, this.splitAtEveryPortal);
                    list.AddRange(collection);
                    ListPool <Vector3> .Release(ref funnel.left);

                    ListPool <Vector3> .Release(ref funnel.right);

                    ListPool <Vector3> .Release(ref collection);
                }
                else
                {
                    if (i == 0 || list2[i - 1].isLink)
                    {
                        list.Add(pathPart.startPoint);
                    }
                    if (i == list2.Count - 1 || list2[i + 1].isLink)
                    {
                        list.Add(pathPart.endPoint);
                    }
                }
            }
            ListPool <Funnel.PathPart> .Release(ref list2);

            ListPool <Vector3> .Release(ref p.vectorPath);

            p.vectorPath = list;
        }
Exemple #22
0
        /** Displays a LayerMask field.
         * \param label Label to display
         * \param selected Current LayerMask
         */
        public static LayerMask LayerMaskField(string label, LayerMask selected)
        {
            if (Event.current.type == EventType.Layout && System.DateTime.UtcNow.Ticks - lastUpdateTick > 10000000L)
            {
                layerNames.Clear();
                lastUpdateTick = System.DateTime.UtcNow.Ticks;
            }

            string[] currentLayerNames;
            if (!layerNames.TryGetValue(selected.value, out currentLayerNames))
            {
                var layers = ListPool <string> .Claim();

                int emptyLayers = 0;
                for (int i = 0; i < 32; i++)
                {
                    string layerName = LayerMask.LayerToName(i);

                    if (layerName != "")
                    {
                        for (; emptyLayers > 0; emptyLayers--)
                        {
                            layers.Add("Layer " + (i - emptyLayers));
                        }
                        layers.Add(layerName);
                    }
                    else
                    {
                        emptyLayers++;
                        if (((selected.value >> i) & 1) != 0 && selected.value != -1)
                        {
                            for (; emptyLayers > 0; emptyLayers--)
                            {
                                layers.Add("Layer " + (i + 1 - emptyLayers));
                            }
                        }
                    }
                }

                currentLayerNames = layerNames[selected.value] = layers.ToArray();
                ListPool <string> .Release(ref layers);
            }

            selected.value = EditorGUILayout.MaskField(label, selected.value, currentLayerNames);
            return(selected);
        }
Exemple #23
0
        /** Convenience method to get a list of all segments of the contours of a graph.
         * \returns A list of segments. Every 2 elements form a line segment. The first segment is (result[0], result[1]), the second one is (result[2], result[3]) etc.
         * The line segments are oriented so that the navmesh is on the right side of the segments when seen from above.
         *
         * This method works for navmesh, recast, grid graphs and layered grid graphs. For other graph types it will return an empty list.
         *
         * If you need more information about how the contours are connected you can take a look at the other variants of this method.
         *
         * \snippet MiscSnippets.cs GraphUtilities.GetContours2
         *
         * \shadowimage{navmesh_contour.png}
         * \shadowimage{grid_contour.png}
         */
        public static List <Vector3> GetContours(NavGraph graph)
        {
            List <Vector3> result = ListPool <Vector3> .Claim();

            if (graph is INavmesh)
            {
                GetContours(graph as INavmesh, (vertices, cycle) =>
                {
                    for (int j = cycle? vertices.Count - 1 : 0, i = 0; i < vertices.Count; j = i, i++)
                    {
                        result.Add((Vector3)vertices[j]);
                        result.Add((Vector3)vertices[i]);
                    }
                });
            }

            return(result);
        }
Exemple #24
0
        /** Should be called on every node which is updated with this GUO before it is updated.
         * \param node The node to save fields for. If null, nothing will be done
         * \see #trackChangedNodes
         */
        public virtual void WillUpdateNode(GraphNode node)
        {
            if (trackChangedNodes && node != null)
            {
                if (changedNodes == null)
                {
                    changedNodes = ListPool <GraphNode> .Claim(); backupData = ListPool <uint> .Claim(); backupPositionData = ListPool <Int3> .Claim();
                }
                changedNodes.Add(node);
                backupPositionData.Add(node.position);
                backupData.Add(node.Penalty);
                backupData.Add(node.Flags);
#if !ASTAR_NO_GRID_GRAPH
                //	var gg = node as GridNode;
                //	if (gg != null) backupData.Add(gg.InternalGridFlags);
#endif
            }
        }
Exemple #25
0
        public virtual void WillUpdateNode(GraphNode node)
        {
            if (this.trackChangedNodes && node != null)
            {
                if (this.changedNodes == null)
                {
                    this.changedNodes = ListPool <GraphNode> .Claim();

                    this.backupData = ListPool <uint> .Claim();

                    this.backupPositionData = ListPool <VInt3> .Claim();
                }
                this.changedNodes.Add(node);
                this.backupPositionData.Add(node.position);
                this.backupData.Add(node.Penalty);
                this.backupData.Add(node.Flags);
            }
        }
        // Token: 0x0600279F RID: 10143 RVA: 0x001B30BC File Offset: 0x001B12BC
        public static List <GraphNode> GetReachableNodes(GraphNode seed, int tagMask = -1, Func <GraphNode, bool> filter = null)
        {
            Stack <GraphNode> dfsStack = StackPool <GraphNode> .Claim();

            List <GraphNode> reachable = ListPool <GraphNode> .Claim();

            HashSet <GraphNode> map = new HashSet <GraphNode>();
            Action <GraphNode>  action;

            if (tagMask == -1 && filter == null)
            {
                action = delegate(GraphNode node)
                {
                    if (node.Walkable && map.Add(node))
                    {
                        reachable.Add(node);
                        dfsStack.Push(node);
                    }
                };
            }
            else
            {
                action = delegate(GraphNode node)
                {
                    if (node.Walkable && (tagMask >> (int)node.Tag & 1) != 0 && map.Add(node))
                    {
                        if (filter != null && !filter(node))
                        {
                            return;
                        }
                        reachable.Add(node);
                        dfsStack.Push(node);
                    }
                };
            }
            action(seed);
            while (dfsStack.Count > 0)
            {
                dfsStack.Pop().GetConnections(action);
            }
            StackPool <GraphNode> .Release(dfsStack);

            return(reachable);
        }
Exemple #27
0
        public static Vector3[] ConvexHullXZ(Vector3[] points)
        {
            if (points.Length == 0)
            {
                return(new Vector3[0]);
            }
            List <Vector3> list = ListPool <Vector3> .Claim();

            int index = 0;

            for (int i = 1; i < points.Length; i++)
            {
                if (points[i].x < points[index].x)
                {
                    index = i;
                }
            }
            int num3 = index;
            int num4 = 0;

            do
            {
                list.Add(points[index]);
                int num5 = 0;
                for (int j = 0; j < points.Length; j++)
                {
                    if ((num5 == index) || !VectorMath.RightOrColinearXZ(points[index], points[num5], points[j]))
                    {
                        num5 = j;
                    }
                }
                index = num5;
                num4++;
                if (num4 > 0x2710)
                {
                    Debug.LogWarning("Infinite Loop in Convex Hull Calculation");
                    break;
                }
            }while (index != num3);
            Vector3[] vectorArray = list.ToArray();
            ListPool <Vector3> .Release(list);

            return(vectorArray);
        }
        public List <Vector3> CurvedNonuniform(List <Vector3> path)
        {
            if (this.maxSegmentLength <= 0f)
            {
                Debug.LogWarning("Max Segment Length is <= 0 which would cause DivByZero-exception or other nasty errors (avoid this)");
                return(path);
            }
            int capacity = 0;

            for (int i = 0; i < (path.Count - 1); i++)
            {
                Vector3 vector8   = path[i] - path[i + 1];
                float   magnitude = vector8.magnitude;
                for (float k = 0f; k <= magnitude; k += this.maxSegmentLength)
                {
                    capacity++;
                }
            }
            List <Vector3> list = ListPool <Vector3> .Claim(capacity);

            Vector3 vector9    = path[1] - path[0];
            Vector3 normalized = vector9.normalized;

            for (int j = 0; j < (path.Count - 1); j++)
            {
                Vector3 vector10 = path[j] - path[j + 1];
                float   num6     = vector10.magnitude;
                Vector3 vector2  = normalized;
                Vector3 vector3  = (j >= (path.Count - 2)) ? (path[j + 1] - path[j]).normalized : ((path[j + 2] - path[j + 1]).normalized - (path[j] - path[j + 1]).normalized).normalized;
                Vector3 vector4  = (Vector3)((vector2 * num6) * this.factor);
                Vector3 vector5  = (Vector3)((vector3 * num6) * this.factor);
                Vector3 a        = path[j];
                Vector3 b        = path[j + 1];
                float   num7     = 1f / num6;
                for (float m = 0f; m <= num6; m += this.maxSegmentLength)
                {
                    float t = m * num7;
                    list.Add(GetPointOnCubic(a, b, vector4, vector5, t));
                }
                normalized = vector3;
            }
            list[list.Count - 1] = path[path.Count - 1];
            return(list);
        }
        /** Returns all nodes reachable from the seed node.
         * This function performs a BFS (breadth-first-search) or flood fill of the graph and returns all nodes which can be reached from
         * the seed node. In almost all cases this will be identical to returning all nodes which have the same area as the seed node.
         * In the editor areas are displayed as different colors of the nodes.
         * The only case where it will not be so is when there is a one way path from some part of the area to the seed node
         * but no path from the seed node to that part of the graph.
         *
         * The returned list is sorted by node distance from the seed node
         * i.e distance is measured in the number of nodes the shortest path from \a seed to that node would pass through.
         * Note that the distance measurement does not take heuristics, penalties or tag penalties.
         *
         * Depending on the number of reachable nodes, this function can take quite some time to calculate
         * so don't use it too often or it might affect the framerate of your game.
         *
         * \param seed The node to start the search from
         * \param tagMask Optional mask for tags. This is a bitmask.
         *
         * \returns A List<Node> containing all nodes reachable from the seed node.
         * For better memory management the returned list should be pooled, see Pathfinding.Util.ListPool
         */
        public static List <GraphNode> GetReachableNodes(GraphNode seed, int tagMask = -1)
        {
            Stack <GraphNode> stack = StackPool <GraphNode> .Claim();

            List <GraphNode> list = ListPool <GraphNode> .Claim();

            /** \todo Pool */
            var map = new HashSet <GraphNode>();

            GraphNodeDelegate callback;

            if (tagMask == -1)
            {
                callback = delegate(GraphNode node) {
                    if (node.Walkable && map.Add(node))
                    {
                        list.Add(node);
                        stack.Push(node);
                    }
                };
            }
            else
            {
                callback = delegate(GraphNode node) {
                    if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && map.Add(node))
                    {
                        list.Add(node);
                        stack.Push(node);
                    }
                };
            }

            callback(seed);

            while (stack.Count > 0)
            {
                stack.Pop().GetConnections(callback);
            }

            StackPool <GraphNode> .Release(stack);

            return(list);
        }
Exemple #30
0
        /** Returns points in a spiral centered around the origin with a minimum clearance from other points.
         * The points are laid out on the involute of a circle
         * \see http://en.wikipedia.org/wiki/Involute
         * Which has some nice properties.
         * All points are separated by \a clearance world units.
         * This method is O(n), yes if you read the code you will see a binary search, but that binary search
         * has an upper bound on the number of steps, so it does not yield a log factor.
         *
         * \note Consider recycling the list after usage to reduce allocations.
         * \see Pathfinding.Util.ListPool
         */
        public static List <Vector3> GetSpiralPoints(int count, float clearance)
        {
            List <Vector3> pts = ListPool <Vector3> .Claim(count);

            // The radius of the smaller circle used for generating the involute of a circle
            // Calculated from the separation distance between the turns
            float a = clearance / (2 * Mathf.PI);
            float t = 0;


            pts.Add(InvoluteOfCircle(a, t));

            for (int i = 0; i < count; i++)
            {
                Vector3 prev = pts[pts.Count - 1];

                // d = -t0/2 + sqrt( t0^2/4 + 2d/a )
                // Minimum angle (radians) which would create an arc distance greater than clearance
                float d = -t / 2 + Mathf.Sqrt(t * t / 4 + 2 * clearance / a);

                // Binary search for separating this point and the previous one
                float mn = t + d;
                float mx = t + 2 * d;
                while (mx - mn > 0.01f)
                {
                    float   mid = (mn + mx) / 2;
                    Vector3 p   = InvoluteOfCircle(a, mid);
                    if ((p - prev).sqrMagnitude < clearance * clearance)
                    {
                        mn = mid;
                    }
                    else
                    {
                        mx = mid;
                    }
                }

                pts.Add(InvoluteOfCircle(a, mx));
                t = mx;
            }

            return(pts);
        }