public static List <NavRegion> GenerateNavRegionsFromNodes(List <NavNode> nodes, int regionSize)
        {
            var assignedNodes   = new HashSet <NavNode>();
            var assignedRegions = new List <NavRegion>();
            var nodesToAssign   = new List <NavNode>(regionSize);

            var nodesToConsiderQueue = new List <NavNode>(64)
            {
                nodes[0]
            };
            var nodesForNextRegion = new List <NavNode>(regionSize);

            // Account for unconnected components
            while (assignedNodes.Count < nodes.Count)
            {
                nodesToConsiderQueue.Add(FindNextUnallocatedNode(nodes, assignedNodes));

                if (nodesToConsiderQueue[0] == null)
                {
                    Debug.LogWarning("Some nodes were duplicates!");
                    break;
                }

                // BFS to give nice even growth of region
                while (nodesToConsiderQueue.Count > 0)
                {
                    var currentNode = nodesToConsiderQueue[0];

                    if (!assignedNodes.Contains(currentNode))
                    {
                        nodesToAssign.Add(currentNode);
                        assignedNodes.Add(currentNode);

                        if (currentNode.NeighbourRefs != null)
                        {
                            foreach (var neighbourRef in currentNode.NeighbourRefs)
                            {
                                if (!assignedNodes.Contains(neighbourRef))
                                {
                                    nodesToConsiderQueue.Add(neighbourRef);
                                }
                            }
                        }
                    }

                    nodesToConsiderQueue.RemoveAt(0);
                }

                // Make sure we stop overlap in regions
                while (nodesToAssign.Count >= regionSize)
                {
                    for (var currentNodeIndex = 0; currentNodeIndex < regionSize; currentNodeIndex++)
                    {
                        nodesForNextRegion.Add(nodesToAssign[currentNodeIndex]);
                    }

                    nodesToAssign.RemoveRange(0, regionSize);

                    var regionBounds = NavRegion.GenerateRectFromNodes(nodesForNextRegion.ToArray());

                    var conflictingNodes = new List <NavNode>();

                    foreach (var otherNodes in nodesToAssign)
                    {
                        if (regionBounds.Contains(otherNodes.Position))
                        {
                            conflictingNodes.Add(otherNodes);
                            nodesForNextRegion.Add(otherNodes);
                        }
                    }

                    assignedRegions.Add(new NavRegion(nodesForNextRegion.ToArray()));

                    nodesToAssign.RemoveAll((node) => conflictingNodes.Contains(node));

                    conflictingNodes.Clear();
                    nodesForNextRegion.Clear();
                }

                // make sure regions don't span unconnected components (and allocate last, potentially unfilled region)
                if (nodesToAssign.Count > 0)
                {
                    assignedRegions.Add(new NavRegion(nodesToAssign.ToArray()));
                    nodesToAssign.Clear();
                }
            }

            return(assignedRegions);
        }
Exemple #2
0
 public NavRegionQueueEntry(NavRegion inCurrentRegion, NavRegion inInitialRegion)
 {
     CurrentRegion = inCurrentRegion;
     InitialRegion = inInitialRegion;
 }