static int PrepareCornerVerts(PNavEdgeLoop edgeLoop, PNavIsland island, Fix64Vec2[] verts, int[] indexes) { List <PNavNode> corners = new List <PNavNode>(); foreach (PNavNode node in edgeLoop.nodes) { if (node.isCorner) { corners.Add(node); } } int cornersCount = corners.Count; for (int i = 0; i < cornersCount; i++) { PNavNode node = corners[i]; Fix64Vec3 center = node.Center; verts[i] = new Fix64Vec2(center.x, center.z); indexes[i] = island.nodes.IndexOf(node); } bool isClockwise = IsClockwise(verts, cornersCount); if (!isClockwise) { InverseVerticesAndIndexes(verts, indexes, cornersCount); } return(cornersCount); }
static void FindEdgeLoops(PNavColumn[,] columns, PNavPoint pointMax, PNavMesh pNavMesh) { List <PNavIsland> islandsToRemove = new List <PNavIsland>(); foreach (PNavIsland island in pNavMesh.islands) { int edgeLoopIndex = 0; int maxNodeCount = 0; PNavEdgeLoop edgeLoop = new PNavEdgeLoop(); foreach (PNavNode node in island.nodes) { if (node.walkable) { bool foundLoop = DetectEdgeLoop(node, edgeLoop, edgeLoopIndex, columns, pointMax); if (foundLoop) { int nodeCount = edgeLoop.nodes.Count; if (nodeCount > maxNodeCount) { maxNodeCount = nodeCount; island.boundaryEdgeLoopIndex = edgeLoopIndex; } edgeLoopIndex++; island.edgeLoops.Add(edgeLoop); edgeLoop = new PNavEdgeLoop(); } } } if (island.boundaryEdgeLoopIndex < 0) { islandsToRemove.Add(island); } } foreach (PNavIsland island in islandsToRemove) { pNavMesh.islands.Remove(island); } }
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); }
public static void Process(PNavMesh pNavMesh) { const int INDICE_COUNT = 1024; using (new SProfiler("Triangulation")) { int[] indices = new int[INDICE_COUNT]; int[] indiceCounts = new int[INDICE_COUNT]; Fix64Vec2[] verts = new Fix64Vec2[INDICE_COUNT]; int[] indexes = new int[INDICE_COUNT]; int index = 0; foreach (PNavIsland island in pNavMesh.islands) { //build island with island boundary if (island.boundaryEdgeLoopIndex < 0) { continue; } Debug.Log($"Generating Polygon graph for island={index}"); index++; PNavEdgeLoop boundary = island.edgeLoops[island.boundaryEdgeLoopIndex]; int boundaryCornersCount = PrepareCornerVerts(boundary, island, verts, indexes); PolyIsland polyIsland = Parallel3D.CreatePolyIsland(verts, indexes, boundaryCornersCount); //add other edgeloops as holes int edgeLoopIndex = -1; foreach (PNavEdgeLoop edgeLoop in island.edgeLoops) { edgeLoopIndex++; if (edgeLoopIndex == island.boundaryEdgeLoopIndex) { continue; } int holeCornersCount = PrepareCornerVerts(edgeLoop, island, verts, indexes); Parallel3D.AddHolePolyIsland(verts, indexes, holeCornersCount, polyIsland); } int polygonCount = 0; int totalIndicsCount = 0; bool ok = Parallel3D.TriangulatePolyIsland(indices, indiceCounts, ref polygonCount, ref totalIndicsCount, 2, polyIsland); int[] indicesCopy = new int[totalIndicsCount]; Array.Copy(indices, 0, indicesCopy, 0, totalIndicsCount); int[] indiceCountsCopy = new int[polygonCount]; Array.Copy(indiceCounts, 0, indiceCountsCopy, 0, polygonCount); island.indices = indicesCopy; island.indiceCountsOfPolygons = indiceCountsCopy; island.indicsCount = totalIndicsCount; island.polygonCount = polygonCount; Parallel3D.DestroyPolyIsland(polyIsland); } } }