GetNodes() 공개 메소드

public GetNodes ( GraphNodeDelegateCancelable del ) : void
del GraphNodeDelegateCancelable
리턴 void
예제 #1
0
        /// <summary>
        /// ³õʼ»¯graphNodeÕ¤¸ñÆ÷
        /// </summary>
        public void InitRasterizer(int inCellSize = 4000)
        {
            if (this.graphs == null || this.graphs.Length == 0)
            {
                return;
            }
            rasterizer = new GraphNodeRasterizer();
            Int2 min = new Int2(2147483647, 2147483647);
            Int2 max = new Int2(-2147483648, -2147483648);

            for (int j = 0; j < this.graphs.Length; j++)
            {
                RecastGraph recastGraph2 = this.graphs[j] as RecastGraph;
                if (recastGraph2 == null)
                {
                    return;
                }
                recastGraph2.GetNodes(delegate(GraphNode node)
                {
                    TriangleMeshNode triangleMeshNode = node as TriangleMeshNode;
                    if (triangleMeshNode != null)
                    {
                        Int2 xz  = triangleMeshNode.GetVertex(0).xz;
                        Int2 xz2 = triangleMeshNode.GetVertex(1).xz;
                        Int2 xz3 = triangleMeshNode.GetVertex(2).xz;
                        min.Min(ref xz);
                        min.Min(ref xz2);
                        min.Min(ref xz3);
                        max.Max(ref xz);
                        max.Max(ref xz2);
                        max.Max(ref xz3);
                    }
                    return(true);
                });
            }
            rasterizer.Init(min, max.x - min.x, max.y - min.y, inCellSize);

            for (int k = 0; k < this.graphs.Length; k++)
            {
                RecastGraph recastGraph3 = this.graphs[k] as RecastGraph;
                if (recastGraph3 != null)
                {
                    recastGraph3.GetNodes(delegate(GraphNode node)
                    {
                        TriangleMeshNode triangleMeshNode = node as TriangleMeshNode;
                        if (triangleMeshNode != null)
                        {
                            Int2 xz  = triangleMeshNode.GetVertex(0).xz;
                            Int2 xz2 = triangleMeshNode.GetVertex(1).xz;
                            Int2 xz3 = triangleMeshNode.GetVertex(2).xz;
                            rasterizer.AddTriangle(ref xz, ref xz2, ref xz3, triangleMeshNode);
                        }
                        return(true);
                    });
                }
            }
        }
예제 #2
0
        public GraphNodeRasterizer InitRasterizer(int inCellSize, bool bUseForceBoundsSize = false)
        {
            if (this.graphs == null || this.graphs.Length == 0)
            {
                return(null);
            }
            GraphNodeRasterizer r = new GraphNodeRasterizer();
            VInt2 min             = new VInt2(2147483647, 2147483647);
            VInt2 max             = new VInt2(-2147483648, -2147483648);

            if (bUseForceBoundsSize)
            {
                for (int i = 0; i < this.graphs.Length; i++)
                {
                    RecastGraph recastGraph = this.graphs[i] as RecastGraph;
                    if (recastGraph == null)
                    {
                        return(null);
                    }
                    VInt2 vInt  = new VInt2((int)(recastGraph.forcedBounds.min.x * 1000f), (int)(recastGraph.forcedBounds.min.z * 1000f));
                    VInt2 vInt2 = new VInt2((int)(recastGraph.forcedBounds.max.x * 1000f), (int)(recastGraph.forcedBounds.max.z * 1000f));
                    min.Min(ref vInt);
                    max.Max(ref vInt2);
                }
                r.Init(min, max.x - min.x, max.y - min.y, inCellSize);
            }
            else
            {
                for (int j = 0; j < this.graphs.Length; j++)
                {
                    RecastGraph recastGraph2 = this.graphs[j] as RecastGraph;
                    if (recastGraph2 == null)
                    {
                        return(null);
                    }
                    recastGraph2.GetNodes(delegate(GraphNode node)
                    {
                        TriangleMeshNode triangleMeshNode = node as TriangleMeshNode;
                        if (triangleMeshNode != null)
                        {
                            VInt2 xz  = triangleMeshNode.GetVertex(0).xz;
                            VInt2 xz2 = triangleMeshNode.GetVertex(1).xz;
                            VInt2 xz3 = triangleMeshNode.GetVertex(2).xz;
                            min.Min(ref xz);
                            min.Min(ref xz2);
                            min.Min(ref xz3);
                            max.Max(ref xz);
                            max.Max(ref xz2);
                            max.Max(ref xz3);
                        }
                        return(true);
                    });
                }
                r.Init(min, max.x - min.x, max.y - min.y, inCellSize);
            }
            for (int k = 0; k < this.graphs.Length; k++)
            {
                RecastGraph recastGraph3 = this.graphs[k] as RecastGraph;
                if (recastGraph3 != null)
                {
                    recastGraph3.GetNodes(delegate(GraphNode node)
                    {
                        TriangleMeshNode triangleMeshNode = node as TriangleMeshNode;
                        if (triangleMeshNode != null)
                        {
                            VInt2 xz  = triangleMeshNode.GetVertex(0).xz;
                            VInt2 xz2 = triangleMeshNode.GetVertex(1).xz;
                            VInt2 xz3 = triangleMeshNode.GetVertex(2).xz;
                            r.AddTriangle(ref xz, ref xz2, ref xz3, triangleMeshNode);
                        }
                        return(true);
                    });
                }
            }
            return(r);
        }
예제 #3
0
        public static IEnumerable <Progress> ScanAllTiles(this RecastGraph self)
        {
            self.transform = self.CalculateTransform();
            self.InitializeTileInfo();

            // If this is true, just fill the graph with empty tiles
            if (self.scanEmptyGraph)
            {
                self.FillWithEmptyTiles();
                yield break;
            }

            // A walkableClimb higher than walkableHeight can cause issues when generating the navmesh since then it can in some cases
            // Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with navmesh without links)
            // The editor scripts also enforce this but we enforce it here too just to be sure
            self.walkableClimb = Mathf.Min(self.walkableClimb, self.walkableHeight);

            yield return(new Progress(0, "Finding Meshes"));

            var bounds  = self.transform.Transform(new Bounds(self.forcedBoundsSize * 0.5f, self.forcedBoundsSize));
            var meshes  = self.CollectMeshes(bounds);
            var buckets = self.PutMeshesIntoTileBuckets(meshes);

            Queue <Int2> tileQueue = new Queue <Int2>();

            // Put all tiles in the queue
            for (int z = 0; z < self.tileZCount; z++)
            {
                for (int x = 0; x < self.tileXCount; x++)
                {
                    tileQueue.Enqueue(new Int2(x, z));
                }
            }

            var workQueue = new ParallelWorkQueue <Int2>(tileQueue);
            // Create the voxelizers and set all settings (one for each thread)
            var voxelizers = new Voxelize[workQueue.threadCount];

            for (int i = 0; i < voxelizers.Length; i++)
            {
                voxelizers[i] = new Voxelize(self.CellHeight, self.cellSize, self.walkableClimb, self.walkableHeight, self.maxSlope, self.maxEdgeLength);
            }
            workQueue.action = (tile, threadIndex) => {
                voxelizers[threadIndex].inputMeshes           = buckets[tile.x + tile.y * self.tileXCount];
                self.tiles[tile.x + tile.y * self.tileXCount] = self.BuildTileMesh(voxelizers[threadIndex], tile.x, tile.y, threadIndex);
            };

            // Prioritize responsiveness while playing
            // but when not playing prioritize throughput
            // (the Unity progress bar is also pretty slow to update)
            int timeoutMillis = Application.isPlaying ? 1 : 200;

            // Scan all tiles in parallel
            foreach (var done in workQueue.Run(timeoutMillis))
            {
                yield return(new Progress(Mathf.Lerp(0.1f, 0.9f, done / (float)self.tiles.Length), "Calculated Tiles: " + done + "/" + self.tiles.Length));
            }

            yield return(new Progress(0.9f, "Assigning Graph Indices"));

            // Assign graph index to nodes
            uint graphIndex = (uint)AstarPath.active.data.GetGraphIndex(self);

            self.GetNodes(node => node.GraphIndex = graphIndex);

            // First connect all tiles with an EVEN coordinate sum
            // This would be the white squares on a chess board.
            // Then connect all tiles with an ODD coordinate sum (which would be all black squares on a chess board).
            // This will prevent the different threads that do all
            // this in parallel from conflicting with each other.
            // The directions are also done separately
            // first they are connected along the X direction and then along the Z direction.
            // Looping over 0 and then 1
            for (int coordinateSum = 0; coordinateSum <= 1; coordinateSum++)
            {
                for (int direction = 0; direction <= 1; direction++)
                {
                    for (int i = 0; i < self.tiles.Length; i++)
                    {
                        if ((self.tiles[i].x + self.tiles[i].z) % 2 == coordinateSum)
                        {
                            tileQueue.Enqueue(new Int2(self.tiles[i].x, self.tiles[i].z));
                        }
                    }

                    workQueue        = new ParallelWorkQueue <Int2>(tileQueue);
                    workQueue.action = (tile, threadIndex) => {
                        // Connect with tile at (x+1,z) and (x,z+1)
                        if (direction == 0 && tile.x < self.tileXCount - 1)
                        {
                            self.ConnectTiles(self.tiles[tile.x + tile.y * self.tileXCount], self.tiles[tile.x + 1 + tile.y * self.tileXCount]);
                        }
                        if (direction == 1 && tile.y < self.tileZCount - 1)
                        {
                            self.ConnectTiles(self.tiles[tile.x + tile.y * self.tileXCount], self.tiles[tile.x + (tile.y + 1) * self.tileXCount]);
                        }
                    };

                    var numTilesInQueue = tileQueue.Count;
                    // Connect all tiles in parallel
                    foreach (var done in workQueue.Run(timeoutMillis))
                    {
                        yield return(new Progress(0.95f, "Connected Tiles " + (numTilesInQueue - done) + "/" + numTilesInQueue + " (Phase " + (direction + 1 + 2 * coordinateSum) + " of 4)"));
                    }
                }
            }

            for (int i = 0; i < meshes.Count; i++)
            {
                meshes[i].Pool();
            }
            ListPool <RasterizationMesh> .Release(ref meshes);

            // 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 (self.OnRecalculatedTiles != null)
            {
                self.OnRecalculatedTiles(self.tiles.Clone() as NavmeshTile[]);
            }
        }