public static void Process(PNavMesh pNavMesh) { using (new SProfiler("Finding Islands")) { // find islands List <PNavIsland> islands = new List <PNavIsland>(); int maxX = pNavMesh.columns.GetLength(0) - 1; int maxZ = pNavMesh.columns.GetLength(1) - 1; PNavPoint pointMax = new PNavPoint(maxX, maxZ); int islandIndex = 0; PNavIsland island = new PNavIsland(); for (int x = 0; x < maxX; x++) { for (int z = 0; z < maxZ; z++) { PNavPoint point = new PNavPoint(x, z); bool foundIsland = DetectIsland(pNavMesh.columns, point, pointMax, 1, pNavMesh.verticalDrop, islandIndex, island); if (foundIsland) { islandIndex++; islands.Add(island); PNavMeshHelper.DetectEdgeCorner(pNavMesh.columns, pointMax, island); PNavMeshHelper.ApplyEdgeGap(pNavMesh.columns, pointMax, island, pNavMesh.edgeGap); island = new PNavIsland(); } } } pNavMesh.islands = islands; Debug.Log($"Found {islands.Count} islands"); } }
static bool isWalkableNode(PNavPoint self, PNavPoint max, PNavPoint delta, PNavColumn[,] columns) { PNavPoint pOut; bool valid = PNavMeshHelper.GetPoint(self, max, delta, out pOut); if (valid) { PNavNode n = columns[pOut.x, pOut.z].SurfaceNode(); valid = (n != null && n.walkable); } return(valid); }
static bool isInnerNode(PNavPoint point, PNavPoint max, PNavPoint delta, int nodes, PNavColumn[,] columns) { PNavPoint pOut; PNavPoint newDelta = new PNavPoint(delta.x * nodes, delta.z * nodes); bool valid = PNavMeshHelper.GetPoint(point, max, newDelta, out pOut); if (valid) { PNavNode n = columns[pOut.x, pOut.z].SurfaceNode(); valid = (n != null && n.IsInner); } return(valid); }
static bool isEdgeNode(PNavPoint point, PNavPoint max, PNavPoint delta, PNavColumn[,] columns) { PNavPoint pOut; bool valid = PNavMeshHelper.GetPoint(point, max, delta, out pOut); if (valid) { PNavNode n = columns[pOut.x, pOut.z].SurfaceNode(); if (n == null) { return(false); } return(n.IsLeftEdge || n.IsRghtEdge || n.IsBackEdge || n.IsFrontEdge); } return(false); }
static bool CheckIfNodeIsValidEdge(PNavNode node, PNavColumn[,] columns, PNavPoint pointMax) { node.isEdge = false; node.edgeFlag = 0; bool allSurroundingAreInner = true; for (int i = 0; i < 8; i++) { walkables[i] = false; PNavPoint pOut; bool valid = PNavMeshHelper.GetPoint(node.point, pointMax, points2[i], out pOut); if (valid) { PNavNode n = columns[pOut.x, pOut.z].SurfaceNode(); if (n != null) { if (n.walkable) { walkables[i] = true; node.edgeFlag = (byte)(node.edgeFlag | 1 << i); } if (!n.IsInner) { allSurroundingAreInner = false; } } } } if (!allSurroundingAreInner) { node.isEdge = true; } if (walkables[0] != walkables[4]) //left and right { node.isEdge = true; // if top and bot are not walkable, not valid if (!walkables[2] && !walkables[6]) { node.isEdge = false; } } if (walkables[2] != walkables[6]) // top and bot { node.isEdge = true; // if left and right are not walkable, not valid if (!walkables[0] && !walkables[4]) { node.isEdge = false; } } // if all diagonal nodes are not walkable, not valid if (!walkables[1] && !walkables[3] && !walkables[5] && !walkables[7]) { node.isEdge = false; } return(node.isEdge); }
static bool DetectEdgeLoop(PNavNode node, PNavEdgeLoop edgeLoop, int edgeLoopIndex, PNavColumn[,] columns, PNavPoint pointMax) { bool foundLoop = false; if (node == null || !node.walkable || node.edgeLoopIndex >= 0) { return(false); } bool isEdge = CheckIfNodeIsValidEdge(node, columns, pointMax); if (!isEdge) { return(false); } Stack <PNavNode> stack = new Stack <PNavNode>(); stack.Push(node); while (stack.Count > 0) { PNavNode n = stack.Pop(); //possible to be added more than once if (n.edgeLoopIndex >= 0) { continue; } edgeLoop.nodes.Add(n); n.edgeLoopIndex = edgeLoopIndex; foundLoop = true; for (int i = 0; i < 8; i++) { PNavPoint pOut; bool valid = PNavMeshHelper.GetPoint(n.point, pointMax, points[i], out pOut); if (valid) { PNavNode nPush = columns[pOut.x, pOut.z].SurfaceNode(); if (nPush != null) { if (!nPush.walkable || nPush.edgeLoopIndex >= 0) { continue; } bool isEdge1 = CheckIfNodeIsValidEdge(nPush, columns, pointMax); if (!isEdge1) { continue; } stack.Push(nPush); } } } } return(foundLoop); }
static bool DetectIsland(PNavColumn[,] columns, PNavPoint point, PNavPoint pointMax, int edgeGap, int verticalDrop, int islandIndex, PNavIsland island) { PNavColumn column = columns[point.x, point.z]; if (column.type != ParallelNavColumnType.Walkable) { return(false); } PNavNode surfaceNode = column.SurfaceNode(); if (surfaceNode == null) { return(false); } //already checked if (surfaceNode.islandIndex >= 0) { return(false); } surfaceNode.islandIndex = islandIndex; island.nodes.Add(surfaceNode); Queue <PNavPoint> queue = new Queue <PNavPoint>(); queue.Enqueue(point); while (queue.Count > 0) { PNavPoint p = queue.Dequeue(); PNavColumn c = columns[p.x, p.z]; //check top edge PNavPoint pTopOut; bool addedTop = PNavMeshHelper.AddTop(columns, p, out pTopOut, pointMax, verticalDrop, edgeGap, islandIndex, island); if (addedTop) { queue.Enqueue(pTopOut); } //check bottom edge PNavPoint pBottomOut; bool addedBottom = PNavMeshHelper.AddBottom(columns, p, out pBottomOut, pointMax, verticalDrop, edgeGap, islandIndex, island); if (addedBottom) { queue.Enqueue(pBottomOut); } //search left PNavPoint left = p; while (true) { PNavPoint pLeftOut; bool added = PNavMeshHelper.AddLeft(columns, left, out pLeftOut, pointMax, verticalDrop, edgeGap, islandIndex, island, queue); if (!added) { break; } else { left = pLeftOut; } } //search right PNavPoint right = p; while (true) { PNavPoint pRightOut; bool added = PNavMeshHelper.AddRight(columns, right, out pRightOut, pointMax, verticalDrop, edgeGap, islandIndex, island, queue); if (!added) { break; } else { right = pRightOut; } } } return(true); }