Beispiel #1
0
        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);
        }
Beispiel #4
0
        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);
                }
            }
        }