public static void DrawPolygonGraph(PNavMesh pNavMesh)
        {
            Color c = Handles.color;

            foreach (PNavIsland island in pNavMesh.islands)
            {
                int index = 0;
                foreach (PNavPolygon polygon in island.graph.polygons)
                {
                    Handles.color = Color.green;
                    Handles.SphereHandleCap(0, (Vector3)polygon.Centroid3D, Quaternion.identity, 0.1f, EventType.Repaint);

                    Handles.Label((Vector3)polygon.Centroid3D + Vector3.forward * 0.5f, index.ToString());

                    foreach (PNavEdge edge in polygon.edges)
                    {
                        if (edge.hasOther)
                        {
                            PNavPolygon self  = island.graph.polygons[edge.selfPolygonIndex];
                            PNavPolygon other = island.graph.polygons[edge.otherPolygonIndex];
                            Handles.DrawLine((Vector3)self.Centroid3D, (Vector3)other.Centroid3D);
                        }
                    }

                    index++;
                }
            }
            Handles.color = c;
        }
        public static void DrawEdgeGap(PNavMesh pNavMesh)
        {
            foreach (PNavIsland island in pNavMesh.islands)
            {
                foreach (PNavNode node in island.nodes)
                {
                    Color c = Handles.color;

                    if (node.IsInner)
                    {
                        if (node.walkable)
                        {
                        }
                        else
                        {
                            Handles.color = Color.yellow;
                            Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);
                        }

                        continue;
                    }

                    Handles.color = c;
                }
            }
        }
        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");
            }
        }
        public static void DrawWalkable(PNavMesh pNavMesh)
        {
            foreach (PNavIsland island in pNavMesh.islands)
            {
                foreach (PNavNode node in island.nodes)
                {
                    Color c = Handles.color;

                    if (node.IsInner)
                    {
                        if (node.walkable)
                        {
                            if (node.isCorner)
                            {
                                Handles.color = Color.cyan;
                                Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);
                            }
                            else if (node.isEdge)
                            {
                                Handles.color = Color.magenta;
                                Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);
                            }
                            else
                            {
                                Handles.color = Color.green;
                                Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);
                            }
                        }
                    }

                    Handles.color = c;
                }
            }
        }
示例#5
0
        static void CreateNewNavMesh()
        {
            PNavMesh newNavMesh = ScriptableObject.CreateInstance <PNavMesh>();

            AssetDatabase.CreateAsset(newNavMesh, "Assets/NewParallelNavMesh.asset");
            AssetDatabase.SaveAssets();

            EditorUtility.FocusProjectWindow();
            Selection.activeObject = newNavMesh;
        }
        public static void Process(PNavMesh pNavMesh)
        {
            using (new SProfiler("Finding Edge Loops"))
            {
                int       maxX     = pNavMesh.columns.GetLength(0);
                int       maxZ     = pNavMesh.columns.GetLength(1);
                PNavPoint pointMax = new PNavPoint(maxX, maxZ);

                FindEdgeLoops(pNavMesh.columns, pointMax, pNavMesh);
            }
        }
示例#7
0
 public static void Process(PNavMesh pNavMesh)
 {
     using (new SProfiler($"Remove Narrow Path"))
     {
         foreach (PNavIsland island in pNavMesh.islands)
         {
             foreach (PNavNode node in island.nodes)
             {
             }
         }
     }
 }
        void OnEnable()
        {
            if (EditorPrefs.HasKey("ObjectPath"))
            {
                string objectPath = EditorPrefs.GetString("ObjectPath");
                pNavMesh = AssetDatabase.LoadAssetAtPath(objectPath, typeof(PNavMesh)) as PNavMesh;
                if (pNavMesh)
                {
                    so = new SerializedObject(pNavMesh);
                }
            }

            SceneView.duringSceneGui += this.OnSceneGUI;
        }
        void ShowSelectWndow()
        {
            string[] filters = { "Parallel NavMesh", "asset" };
            string   absPath = EditorUtility.OpenFilePanelWithFilters("Select Parallel NavMesh ScriptableObject", "Assets", filters);

            //string absPath = EditorUtility.OpenFilePanel("Select Parallel NavMesh ScriptableObject", "", "");

            if (absPath.StartsWith(Application.dataPath))
            {
                string relPath = absPath.Substring(Application.dataPath.Length - "Assets".Length);
                pNavMesh = AssetDatabase.LoadAssetAtPath(relPath, typeof(PNavMesh)) as PNavMesh;

                if (pNavMesh)
                {
                    EditorPrefs.SetString("ObjectPath", relPath);
                    so = new SerializedObject(pNavMesh);
                }
            }
        }
        public static void DrawEdge(PNavMesh pNavMesh)
        {
            float arrowSize = (float)pNavMesh.gridSize.x / 2;

            foreach (PNavIsland island in pNavMesh.islands)
            {
                foreach (PNavNode node in island.nodes)
                {
                    Color c = Handles.color;

                    if (node.IsInner)
                    {
                    }
                    else
                    {
                        Handles.color = Color.red;
                        Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);

                        if (node.IsLeftEdge)
                        {
                            Handles.DrawLine((Vector3)node.LeftCenter - arrowSize * Vector3.forward, (Vector3)node.LeftCenter + arrowSize * Vector3.forward);
                        }

                        if (node.IsRghtEdge)
                        {
                            Handles.DrawLine((Vector3)node.RightCenter - arrowSize * Vector3.forward, (Vector3)node.RightCenter + arrowSize * Vector3.forward);
                        }

                        if (node.IsFrontEdge)
                        {
                            Handles.DrawLine((Vector3)node.FrontCenter - arrowSize * Vector3.right, (Vector3)node.FrontCenter + arrowSize * Vector3.right);
                        }

                        if (node.IsBackEdge)
                        {
                            Handles.DrawLine((Vector3)node.BackCenter - arrowSize * Vector3.right, (Vector3)node.BackCenter + arrowSize * Vector3.right);
                        }
                    }

                    Handles.color = c;
                }
            }
        }
        public static void CheckVolume(PNavMesh pNavMesh, int xStart, int xEnd, int zStart, int zEnd, int yStart, int yEnd, int scale, Action <int, int, int, int, int, int> callback)
        {
            PShapeOverlapResult3D result = new PShapeOverlapResult3D();

            Fix64Vec3 size     = pNavMesh.gridSize * (Fix64)scale;
            Fix64Vec3 toCenter = Fix64.half * size;

            int scaledXEnd = xEnd / scale;
            int scaledYEnd = yEnd / scale;
            int scaledZEnd = zEnd / scale;

            for (int x = xStart; x < scaledXEnd; x++)
            {
                for (int z = zStart; z < scaledZEnd; z++)
                {
                    for (int y = yStart; y < scaledZEnd; y++)
                    {
                        int scaledX = x * scale;
                        int scaledY = y * scale;
                        int scaledZ = z * scale;

                        Fix64Vec3 l;
                        Fix64Vec3 u;
                        pNavMesh.GetAABB(scaledX, scaledY, scaledZ, out l, out u);

                        Fix64Vec3 center = l + toCenter;
                        Fix64Quat rot    = Fix64Quat.identity;

                        Parallel3D.OverlapCube(
                            center, rot,
                            size.x, size.y, size.z,
                            -1,
                            result);

                        if (result.count > 0)
                        {
                            callback(scaledX, scaledX + scale, scaledZ, scaledZ + scale, scaledY, scaledY + scale);
                        }
                    }
                }
            }
        }
        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);
            }
        }
        public static void DrawEdgeLoop(PNavMesh pNavMesh)
        {
            Color c = Handles.color;

            foreach (PNavIsland island in pNavMesh.islands)
            {
                int loopIndex = 0;
                foreach (PNavEdgeLoop loop in island.edgeLoops)
                {
                    loopIndex++;
                    Handles.color = colors[loopIndex];

                    foreach (PNavNode node in loop.nodes)
                    {
                        Handles.SphereHandleCap(0, (Vector3)node.Center, Quaternion.identity, 0.1f, EventType.Repaint);
                    }
                }
            }
            Handles.color = c;
        }
        public static void Process(PNavMesh pNavMesh)
        {
            using (new SProfiler($"Build polygon graph"))
            {
                foreach (PNavIsland island in pNavMesh.islands)
                {
                    Dictionary <long, PNavEdge> edgeMap = new Dictionary <long, PNavEdge>();
                    PNavPolygonGraph            graph   = new PNavPolygonGraph();

                    int indiceRead = 0;
                    for (int p = 0; p < island.polygonCount; p++)
                    {
                        int ic = island.indiceCountsOfPolygons[p];

                        Fix64Vec2[] verts   = new Fix64Vec2[ic];
                        int[]       indices = new int[ic];

                        for (int indiceOfPolygon = 0; indiceOfPolygon < ic; indiceOfPolygon++)
                        {
                            int      nodeIndex = island.indices[indiceRead];
                            PNavNode vertNode  = island.nodes[nodeIndex];
                            verts[indiceOfPolygon]   = new Fix64Vec2(vertNode.Center.x, vertNode.Center.z);
                            indices[indiceOfPolygon] = nodeIndex;
                            indiceRead++;
                        }

                        PNavPolygon polygon = new PNavPolygon(verts, ic);

                        //polygon index should match its index in graph.polygons list
                        polygon.index = p;
                        graph.AddPolygon(polygon);

                        BuildEdges(graph, indices, ic, polygon, edgeMap);
                    }

                    island.graph = graph;
                }
            }
        }
        public static void DrawPolygon(PNavMesh pNavMesh)
        {
            foreach (PNavIsland island in pNavMesh.islands)
            {
                Fix64Vec3[] verts = new Fix64Vec3[1024];

                int indiceRead = 0;
                for (int p = 0; p < island.polygonCount; p++)
                {
                    int ic = island.indiceCountsOfPolygons[p];
                    for (int indiceOfPolygon = 0; indiceOfPolygon < ic; indiceOfPolygon++)
                    {
                        int      nodeIndex = island.indices[indiceRead];
                        PNavNode vertNode  = island.nodes[nodeIndex];
                        verts[indiceOfPolygon] = vertNode.Center;
                        indiceRead++;
                    }

                    DrawPolygon(verts, ic, Color.cyan);
                }
            }
        }
        public static void DrawAABB(PNavMesh pNavMesh)
        {
            if (pNavMesh.columns != null)
            {
                for (int x = 0; x < pNavMesh.columns.GetLength(0); x++)
                {
                    //if (x * pNavMesh.gridSize.x < 95)
                    {
                        //continue;
                    }

                    for (int z = 0; z < pNavMesh.columns.GetLength(1); z++)
                    {
                        PNavColumn column = pNavMesh.columns[x, z];

                        for (int y = 0; y < column.nodes.Length; y++)
                        {
                            int       objectCount = column.nodes[y].objectCount;
                            Fix64Vec3 l           = column.nodes[y].lower;
                            Fix64Vec3 u           = column.nodes[y].upper;

                            //if (l.x * pNavMesh.gridSize.x < 30)
                            {
                                //continue;
                            }

                            if (objectCount > 0)
                            {
                                SceneDebugDraw.DrawAABB(l, u, Color.green);
                            }
                            else
                            {
                                //DrawAABB(l, u, Color.green);
                            }
                        }
                    }
                }
            }
        }
示例#17
0
        public static void Process(PNavMesh pNavMesh)
        {
            foreach (PNavIsland island in pNavMesh.islands)
            {
                foreach (PNavEdgeLoop edgeLoop in island.edgeLoops)
                {
                    PNavNode previousNode = edgeLoop.nodes[edgeLoop.nodes.Count - 1];
                    Vector2  direction    = Vector2.zero;

                    foreach (PNavNode node in edgeLoop.nodes)
                    {
                        node.isCorner = false;

                        Vector2 newDirection = new Vector2(node.point.x - previousNode.point.x, node.point.z - previousNode.point.z).normalized;
                        float   angle        = Vector2.Angle(newDirection, direction);
                        previousNode.angle = angle;

                        if (angle >= 45)
                        {
                            previousNode.isCorner = true;
                        }

                        direction    = newDirection;
                        previousNode = node;
                    }

                    PNavNode node1         = edgeLoop.nodes[0];
                    Vector2  newDirection1 = new Vector2(node1.point.x - previousNode.point.x, node1.point.z - previousNode.point.z).normalized;
                    float    angle1        = Vector2.Angle(newDirection1, direction);
                    previousNode.angle = angle1;

                    if (angle1 >= 45)
                    {
                        previousNode.isCorner = true;
                    }
                }
            }
        }
示例#18
0
 public NavMeshGenerator(PNavMesh pNavMesh)
 {
     _pNavMesh = pNavMesh;
 }
        public static void CubeCastInRange(PNavMesh pNavMesh, int xStart, int xEnd, int zStart, int zEnd, int yStart, int yEnd)
        {
            PShapeOverlapResult3D result = new PShapeOverlapResult3D();

            if (xEnd > pNavMesh.xCount)
            {
                xEnd = pNavMesh.xCount;
            }

            if (zEnd > pNavMesh.zCount)
            {
                zEnd = pNavMesh.zCount;
            }

            if (yEnd > pNavMesh.yCount)
            {
                yEnd = pNavMesh.yCount;
            }

            Debug.Log("CubeCastInRange:" + " xStart=" + xStart + " xEnd=" + xEnd + " zStart=" + zStart + " zEnd=" + zEnd + " yStart=" + yStart + " yEnd=" + yEnd);

            for (int x = xStart; x < xEnd; x++)
            {
                for (int z = zStart; z < zEnd; z++)
                {
                    PNavColumn column = pNavMesh.columns[x, z];

                    int surfaceIndex = -1;

                    for (int y = yStart; y < yEnd; y++)
                    {
                        Fix64Vec3 l;
                        Fix64Vec3 u;
                        pNavMesh.GetAABB(x, y, z, out l, out u);
                        Fix64Vec3 center = Fix64.half * (l + u);
                        Fix64Quat rot    = Fix64Quat.identity;
                        Parallel3D.OverlapCube(
                            center, rot,
                            pNavMesh.gridSize.x, pNavMesh.gridSize.y, pNavMesh.gridSize.z,
                            -1,
                            result
                            );

                        PNavNode node = new PNavNode();

                        node.lower       = l;
                        node.upper       = u;
                        node.objectCount = result.count;
                        node.islandIndex = -1;
                        node.point       = new PNavPoint(x, z);

                        if (result.count > 0 && y > surfaceIndex)
                        {
                            surfaceIndex = y;
                        }

                        column.nodes[y] = node;
                    }

                    column.surfaceNodeIndexes[0] = surfaceIndex;

                    if (surfaceIndex >= 0)
                    {
                        column.type = ParallelNavColumnType.Walkable;
                    }
                    else
                    {
                        column.type = ParallelNavColumnType.Empty;
                    }
                }
            }
        }
        public static void Process(PNavMesh pNavMesh)
        {
            ParallelRigidbody3D[] pRigidbody3Ds = GameObject.FindObjectsOfType <ParallelRigidbody3D>();

            using (new SProfiler($"Insert static bodies"))
            {
                //insert static bodies
                foreach (ParallelRigidbody3D rigidbody3D in pRigidbody3Ds)
                {
                    if (rigidbody3D.bodyType != BodyType.Static)
                    {
                        continue;
                    }

                    rigidbody3D.AddToWorldForPathFinding();
                }
            }

            // make grid
            pNavMesh.xCount = (int)((pNavMesh.worldSize.x) / pNavMesh.gridSize.x);
            pNavMesh.yCount = (int)((pNavMesh.worldSize.y) / pNavMesh.gridSize.y);
            pNavMesh.zCount = (int)((pNavMesh.worldSize.z) / pNavMesh.gridSize.z);

            PNavColumn[,] columns = new PNavColumn[pNavMesh.xCount, pNavMesh.zCount];

            for (int x = 0; x < columns.GetLength(0); x++)
            {
                for (int z = 0; z < columns.GetLength(1); z++)
                {
                    PNavColumn column = new PNavColumn();
                    column.nodes = new PNavNode[pNavMesh.yCount];
                    column.type  = ParallelNavColumnType.Empty;
                    column.surfaceNodeIndexes    = new int[1];
                    column.surfaceNodeIndexes[0] = -1;
                    columns[x, z] = column;
                }
            }
            pNavMesh.columns = columns;

            using (new SProfiler($"CubeCast"))
            {
                int xStart1 = 0;
                int xEnd1   = columns.GetLength(0);
                int zStart1 = 0;
                int zEnd1   = columns.GetLength(1);
                int yStart1 = 0;
                int yEnd1   = pNavMesh.yCount;

                CubeCastInRange(pNavMesh, xStart1, xEnd1, zStart1, zEnd1, yStart1, yEnd1);

                /*
                 * int scale2 = 5;
                 *
                 * CheckVolume(xStart1, xEnd1, zStart1, zEnd1, yStart1, yEnd1, scale1, (xS, xE, zS, zE, yS, yE) =>
                 * {
                 *  CubeCastInRange(xS, xE, zS, zE, yS, yE);
                 *  CheckVolume(xS, xE, zS, zE, yS, yE, scale2, (xS2, xE2, zS2, zE2, yS2, yE2) =>
                 *  {
                 *      CubeCastInRange(xS2, xE2, zS2, zE2, yS2, yE2);
                 *  });
                 *
                 * });
                 */
            }

            Parallel3D.CleanUp();
        }
示例#21
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);
                }
            }
        }