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); }
public NavRegionQueueEntry(NavRegion inCurrentRegion, NavRegion inInitialRegion) { CurrentRegion = inCurrentRegion; InitialRegion = inInitialRegion; }