private void BuildContours()
        {
            ContourSet cset = ContourSet.Build(mBuildContext
                                               , mBuildContext.CompactField
                                               , mConfig.EdgeMaxDeviation
                                               , mConfig.MaxEdgeLength
                                               , mConfig.ContourOptions);

            if (cset == null)
            {
                FinalizeAbort("Aborted at contour set build.");
                return;
            }

            if (cset.Count < 1)
            {
                FinalizeNoResult("Completed after contour build. No useable contours generated.");
                return;
            }

            mBuildContext.Contours = cset;

            if (PostProcess() && PostContoursCheck() && PostCompactFieldCheck())
            {
                mBuildContext.Log("Built contour set. Contour count: " + cset.Count, this);
                mState = NMGenState.PolyMeshBuild;
            }
        }
Exemple #2
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// <para>
        /// A 'no result' object will be created if the <paramref name="polyMesh"/> parameter
        /// is null or has a polygon count of zero.
        /// </para>
        /// </remarks>
        /// <param name="tx">The x-index of the tile within the tile grid. (tx, tz)</param>
        /// <param name="tz">The z-index of the tile within the tile grid. (tx, tz)</param>
        /// <param name="polyMesh">The polymesh.</param>
        /// <param name="detailMesh">The detail mesh.</param>
        /// <param name="heightfield">The heightfield.</param>
        /// <param name="compactField">The compact field.</param>
        /// <param name="contours">The contour set.</param>
        public NMGenAssets(int tx, int tz
                           , PolyMesh polyMesh
                           , PolyMeshDetail detailMesh
                           , Heightfield heightfield
                           , CompactHeightfield compactField
                           , ContourSet contours)
        {
            mTileX = tx;
            mTileZ = tz;

            if (polyMesh == null || polyMesh.PolyCount == 0)
            {
                mPolyMesh     = null;
                mDetailMesh   = null;
                mHeightfield  = null;
                mCompactField = null;
                mContours     = null;
            }
            else
            {
                mPolyMesh     = polyMesh;
                mDetailMesh   = detailMesh; // OK to be null.
                mHeightfield  = heightfield;
                mCompactField = compactField;
                mContours     = contours;
            }
        }
Exemple #3
0
        public NavMeshBuilder GenerateNavmesh(BBox3 bbox)
        {
            float[]  vertices;
            int[]    indices;
            AreaId[] areas;
            GetRawData(out vertices, out indices, out areas);
            var settings = WoWSettings;

            var hf = new Heightfield(bbox, settings);

            hf.RasterizeTrianglesWithAreas(vertices, areas);
            hf.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            hf.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            hf.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

            var chf = new CompactHeightfield(hf, settings);

            chf.Erode(settings.VoxelAgentWidth);
            chf.BuildDistanceField();
            chf.BuildRegions((int)(settings.AgentWidth / settings.CellSize) + 8, settings.MinRegionSize, settings.MergedRegionSize);

            var cset  = new ContourSet(chf, settings);
            var pmesh = new PolyMesh(cset, settings);
            var dmesh = new PolyMeshDetail(pmesh, chf, settings);

            var buildData = new NavMeshBuilder(pmesh, dmesh, new SharpNav.Pathfinding.OffMeshConnection[0], settings);

            return(buildData);
        }
Exemple #4
0
 /// <summary>
 /// Sets the context as having produced no result.
 /// </summary>
 public void SetAsNoResult()
 {
     mHeightfield  = null;
     mCompactField = null;
     mContours     = null;
     mPolyMesh     = null;
     mDetailMesh   = null;
     mNoResult     = true;
 }
Exemple #5
0
        //private void GenerateNavMesh()
        //{
        //    Console.WriteLine("Generating NavMesh");

        //    long prevMs = 0;
        //    try
        //    {
        //        var levelTris = level.GetTriangles();
        //        var triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
        //        BBox3 bounds = triEnumerable.GetBoundingBox();

        //        settings = NavMeshGenerationSettings.Default;
        //        heightfield = new Heightfield(bounds, settings);

        //        heightfield.RasterizeTriangles(levelTris, Area.Default);
        //        heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
        //        heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
        //        heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
        //        compactHeightfield = new CompactHeightfield(heightfield, settings);
        //        compactHeightfield.Erode(settings.VoxelAgentRadius);
        //        compactHeightfield.BuildDistanceField();
        //        compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

        //        contourSet = compactHeightfield.BuildContourSet(settings);

        //        polyMesh = new PolyMesh(contourSet, settings);

        //        polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);


        //        buildData = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
        //        tiledNavMesh = new TiledNavMesh(buildData);
        //        navMeshQuery = new NavMeshQuery(tiledNavMesh, 2048);
        //    }
        //    catch (Exception e)
        //    {
        //        //if (!interceptExceptions)
        //        //    throw;
        //        //else
        //        //    Console.WriteLine("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
        //    }
        //    finally
        //    {
        //        //sw.Stop();
        //    }
        //}


        private void GenerateNavMesh()
        {
            Console.WriteLine("Generating NavMesh");

            long prevMs = 0;
            //try
            //{
            var   levelTris     = level.GetTriangles();
            var   triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
            BBox3 bounds        = triEnumerable.GetBoundingBox();

            settings    = NavMeshGenerationSettings.Default;
            heightfield = new Heightfield(bounds, settings);

            heightfield.RasterizeTriangles(levelTris, Area.Default);
            heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
            compactHeightfield = new CompactHeightfield(heightfield, settings);
            compactHeightfield.Erode(settings.VoxelAgentRadius);
            compactHeightfield.BuildDistanceField();
            compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

            contourSet = compactHeightfield.BuildContourSet(settings);

            polyMesh = new PolyMesh(contourSet, settings);

            polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);


            buildData    = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
            tiledNavMesh = new TiledNavMesh(buildData);
            navMeshQuery = new NavMeshQuery(tiledNavMesh, 2048);
            OutMesh();
            //}
            //catch (Exception e)
            //{
            //    //if (!interceptExceptions)
            //    //    throw;
            //    //else
            //    //    Console.WriteLine("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
            //}
            //finally
            //{
            //    //sw.Stop();
            //}
        }
        private bool PostContoursCheck()
        {
            ContourSet contours = mBuildContext.Contours;

            if (contours == null || contours.IsDisposed)
            {
                FinalizeAbort("Custom processors destroyed the contour set. (" + mState + " Post)");
                return(false);
            }
            else if (contours.Count < 1)
            {
                FinalizeNoResult(
                    "Aborted after contour set build. No contours generated. (" + mState + " Post)");
                return(false);
            }
            return(true);
        }
Exemple #7
0
        public void ContourConstructor()
        {
            //TODO directly build contours now that ContourSet allows it.
            //Build a 5x5 heightfield
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), (float)(1.0f / 5.0f), 0.02f);

            for (int i = 0; i < 5 * 5; i++)
            {
                hf[i].AddSpan(new Span(10, 20, Area.Default));
                hf[i].AddSpan(new Span(25, 30, Area.Default));
            }
            CompactHeightfield chf = new CompactHeightfield(hf, 2, 1);

            chf.BuildDistanceField();
            chf.BuildRegions(1, 1, 1);

            ContourSet contourSet = chf.BuildContourSet(1, 5, ContourBuildFlags.None);

            Assert.AreEqual(contourSet.Count, 2);
        }
        private void BuildPolyMesh()
        {
            ContourSet cset = mBuildContext.Contours;

            PolyMesh polyMesh = PolyMesh.Build(mBuildContext
                                               , cset
                                               , mConfig.MaxVertsPerPoly
                                               , mConfig.WalkableHeight
                                               , mConfig.WalkableRadius
                                               , mConfig.WalkableStep);

            if (CanDispose(NMGenAssetFlag.ContourSet))
            {
                cset.RequestDisposal();
                mBuildContext.Contours = null;
            }

            if (polyMesh == null)
            {
                FinalizeAbort("Aborted at poly mesh build.");
                return;
            }

            if (polyMesh.PolyCount < 1)
            {
                FinalizeNoResult("Aborted after poly mesh build. No polygons generated.");
                return;
            }

            mBuildContext.PolyMesh = polyMesh;

            if (PostProcess() & PostPolyMeshCheck() & PostCompactFieldCheck())
            {
                mBuildContext.Log("Built poly mesh. PolyCount: " + polyMesh.PolyCount, this);
                mState = NMGenState.DetailMeshBuild;
            }
        }
Exemple #9
0
        private void GenerateNavMesh()
        {
            Console.WriteLine("Generating NavMesh");

            Stopwatch sw = new Stopwatch();
            sw.Start();
            long prevMs = 0;
            try
            {
                //level.SetBoundingBoxOffset(new SVector3(settings.CellSize * 0.5f, settings.CellHeight * 0.5f, settings.CellSize * 0.5f));
                var levelTris = level.GetTriangles();
                var triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
                BBox3 bounds = triEnumerable.GetBoundingBox();

                heightfield = new Heightfield(bounds, settings);

                Console.WriteLine("Heightfield");
                Console.WriteLine(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                /*Area[] areas = AreaGenerator.From(triEnumerable, Area.Default)
                    .MarkAboveHeight(areaSettings.MaxLevelHeight, Area.Null)
                    .MarkBelowHeight(areaSettings.MinLevelHeight, Area.Null)
                    .MarkBelowSlope(areaSettings.MaxTriSlope, Area.Null)
                    .ToArray();
                heightfield.RasterizeTrianglesWithAreas(levelTris, areas);*/
                heightfield.RasterizeTriangles(levelTris, Area.Default);

                Console.WriteLine(" + Rasterization\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                Console.WriteLine(" + Filtering");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);

                Console.WriteLine("   + Ledge Spans\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);

                Console.WriteLine("   + Low Hanging Obstacles\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

                Console.WriteLine("   + Low Height Spans\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield = new CompactHeightfield(heightfield, settings);

                Console.WriteLine("CompactHeightfield");
                Console.WriteLine(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.Erode(settings.VoxelAgentRadius);

                Console.WriteLine(" + Erosion\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildDistanceField();

                Console.WriteLine(" + Distance Field\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

                Console.WriteLine(" + Regions\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                Random r = new Random();
                regionColors = new Color4[compactHeightfield.MaxRegions];
                regionColors[0] = Color4.Black;
                for (int i = 1; i < regionColors.Length; i++)
                    regionColors[i] = new Color4((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255), 255);

                Console.WriteLine(" + Colors\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                contourSet = compactHeightfield.BuildContourSet(settings);

                Console.WriteLine("ContourSet");
                Console.WriteLine(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMesh = new PolyMesh(contourSet, settings);

                Console.WriteLine("PolyMesh");
                Console.WriteLine(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);

                Console.WriteLine("PolyMeshDetail");
                Console.WriteLine(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                hasGenerated = true;

            }
            catch (Exception e)
            {
                if (!interceptExceptions)
                    throw;
                else
                    Console.WriteLine("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
            }
            finally
            {
                sw.Stop();
            }

            if (hasGenerated)
            {
                try
                {
                    GeneratePathfinding();

                    //Pathfinding with multiple units
                    GenerateCrowd();
                }
                catch (Exception e)
                {
                    Console.WriteLine("Pathfinding generation failed with exception" + Environment.NewLine + e.ToString());
                    hasGenerated = false;
                }

                Label l = (Label)statusBar.FindChildByName("GenTime");
                l.Text = "Generation Time: " + sw.ElapsedMilliseconds + "ms";

                Console.WriteLine("Navmesh generated successfully in " + sw.ElapsedMilliseconds + "ms.");
                Console.WriteLine("Rasterized " + level.GetTriangles().Length + " triangles.");
                Console.WriteLine("Generated " + contourSet.Count + " regions.");
                Console.WriteLine("PolyMesh contains " + polyMesh.VertCount + " vertices in " + polyMesh.PolyCount + " polys.");
                Console.WriteLine("PolyMeshDetail contains " + polyMeshDetail.VertCount + " vertices and " + polyMeshDetail.TrisCount + " tris in " + polyMeshDetail.MeshCount + " meshes.");
            }
        }
Exemple #10
0
        private void GenerateNavMesh()
        {
            //Debug.Log("Generating NavMesh");

            Stopwatch sw = new Stopwatch();

            sw.Start();
            long prevMs = 0;

            try
            {
                //level.SetBoundingBoxOffset(new SVector3(settings.CellSize * 0.5f, settings.CellHeight * 0.5f, settings.CellSize * 0.5f));
                var   levelTris     = level.GetTriangles();
                var   triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
                BBox3 bounds        = triEnumerable.GetBoundingBox();

                heightfield = new Heightfield(bounds, settings);

                //Debug.Log("Heightfield");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                /*Area[] areas = AreaGenerator.From(triEnumerable, Area.Default)
                 *  .MarkAboveHeight(areaSettings.MaxLevelHeight, Area.Null)
                 *  .MarkBelowHeight(areaSettings.MinLevelHeight, Area.Null)
                 *  .MarkBelowSlope(areaSettings.MaxTriSlope, Area.Null)
                 *  .ToArray();
                 * heightfield.RasterizeTrianglesWithAreas(levelTris, areas);*/
                heightfield.RasterizeTriangles(levelTris, Area.Default);

                //Debug.Log(" + Rasterization\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                //Debug.Log(" + Filtering");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);

                //Debug.Log("   + Ledge Spans\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);

                //Debug.Log("   + Low Hanging Obstacles\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

                //Debug.Log("   + Low Height Spans\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield = new CompactHeightfield(heightfield, settings);

                //Debug.Log("CompactHeightfield");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.Erode(settings.VoxelAgentRadius);

                //Debug.Log(" + Erosion\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildDistanceField();

                //Debug.Log(" + Distance Field\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

                //Debug.Log(" + Regions\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;


                contourSet = compactHeightfield.BuildContourSet(settings);

                //Debug.Log("ContourSet");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMesh = new PolyMesh(contourSet, settings);

                //Debug.Log("PolyMesh");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);

                //Debug.Log("PolyMeshDetail");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                hasGenerated = true;
            }
            catch (Exception e)
            {
                if (!interceptExceptions)
                {
                    throw;
                }
                else
                {
                    //Debug.Log("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
                }
            }
            finally
            {
                sw.Stop();
            }

            if (hasGenerated)
            {
                try
                {
                    GeneratePathfinding();

                    //Pathfinding with multiple units
                    //GenerateCrowd();
                }
                catch (Exception e)
                {
                    //Debug.Log("Pathfinding generation failed with exception" + Environment.NewLine + e.ToString());
                    hasGenerated = false;
                }

                //Label l = (Label)statusBar.FindChildByName("GenTime");
                //l.Text = "Generation Time: " + sw.ElapsedMilliseconds + "ms";

                //Debug.Log("Navmesh generated successfully in " + sw.ElapsedMilliseconds + "ms.");
                //Debug.Log("Rasterized " + level.GetTriangles().Length + " triangles.");
                //Debug.Log("Generated " + contourSet.Count + " regions.");
                //Debug.Log("PolyMesh contains " + polyMesh.VertCount + " vertices in " + polyMesh.PolyCount + " polys.");
                //Debug.Log("PolyMeshDetail contains " + polyMeshDetail.VertCount + " vertices and " + polyMeshDetail.TrisCount + " tris in " + polyMeshDetail.MeshCount + " meshes.");
            }
        }
Exemple #11
0
        public void GenNavMesh()
        {
            // MeshCollider
            List <Triangle3> colliderTringles = new List <Triangle3>();

            Collider[]        colliders  = GameObject.FindObjectsOfType <Collider>();
            List <GameObject> destroyGos = new List <GameObject>();

            foreach (Collider collider in colliders)
            {
                Mesh      mesh = null;
                Matrix4x4 localToWorldMatrix = Matrix4x4.identity;

                if (collider is MeshCollider)
                {
                    MeshCollider mc = collider as MeshCollider;
                    mesh = mc.sharedMesh;
                    localToWorldMatrix = mc.transform.localToWorldMatrix;
                }
                if (collider is BoxCollider)
                {
                    BoxCollider bc = collider as BoxCollider;
                    GameObject  go = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    mesh = go.GetComponent <MeshFilter>().sharedMesh;
                    go.transform.parent        = collider.transform;
                    go.transform.localRotation = Quaternion.identity;
                    go.transform.localPosition = bc.center;
                    go.transform.localScale    = bc.size;
                    localToWorldMatrix         = go.transform.localToWorldMatrix;
                    destroyGos.Add(go);
                }
                if (null != mesh)
                {
                    UnityEngine.Vector3[] vertices = mesh.vertices;
                    for (int i = 0; i < mesh.subMeshCount; ++i)
                    {
                        var subMesh = mesh.GetIndices(i);
                        for (int j = 0; j < subMesh.Length; j += 3)
                        {
                            UnityEngine.Vector3 a = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j]]);
                            UnityEngine.Vector3 b = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j + 1]]);
                            UnityEngine.Vector3 c = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j + 2]]);
                            colliderTringles.Add(new Triangle3(ConvertVector3(a), ConvertVector3(b), ConvertVector3(c)));
                        }
                    }
                }
            }
            foreach (var go in destroyGos)
            {
                GameObject.DestroyImmediate(go);
            }
            destroyGos.Clear();

            Triangle3[] levelTris     = colliderTringles.ToArray();
            var         triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
            BBox3       bounds        = triEnumerable.GetBoundingBox();

            heightfield = new Heightfield(bounds, settings);
            heightfield.RasterizeTriangles(levelTris, Area.Default);
            heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
            compactHeightfield = new CompactHeightfield(heightfield, settings);
            compactHeightfield.Erode(settings.VoxelAgentRadius);
            compactHeightfield.BuildDistanceField();
            compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);
            contourSet     = compactHeightfield.BuildContourSet(settings);
            polyMesh       = new PolyMesh(contourSet, settings);
            polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);
            buildData      = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
            tiledNavMesh   = new TiledNavMesh(buildData);
            navMeshQuery   = new NavMeshQuery(tiledNavMesh, 2048);

            {
                System.Random r = new System.Random();
                regionColors    = new Color[compactHeightfield.MaxRegions];
                regionColors[0] = Color.black;
                for (int i = 1; i < regionColors.Length; i++)
                {
                    regionColors[i] = new Color((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255), 255);
                }
            }

            this.GenDrawMesh();

            Debug.Log("GenNavMesh Done!");
        }
Exemple #12
0
    private LunaNav.NavMeshBuilder BuildTileMesh(int tx, int ty, RecastVertex min, RecastVertex max)
    {
        Config.Width        = Config.TileSize + Config.BorderSize * 2;
        Config.Height       = Config.TileSize + Config.BorderSize * 2;
        Config.MinBounds    = min;
        Config.MaxBounds    = max;
        Config.MinBounds.X -= Config.BorderSize * Config.CellSize;
        Config.MinBounds.Z -= Config.BorderSize * Config.CellSize;

        Config.MaxBounds.X += Config.BorderSize * Config.CellSize;
        Config.MaxBounds.Z += Config.BorderSize * Config.CellSize;

        HeightField heightfield = new HeightField(Config.Width, Config.Height, Config.MinBounds.ToArray(), Config.MaxBounds.ToArray(), Config.CellSize, Config.CellHeight);


        short[] triAreas = new short[Geometry.ChunkyTriMesh.MaxTrisPerChunk];

        float[] tbmin = new float[2], tbmax = new float[2];
        tbmin[0] = Config.MinBounds.X;
        tbmin[1] = Config.MinBounds.Z;

        tbmax[0] = Config.MaxBounds.X;
        tbmax[1] = Config.MaxBounds.Z;

        int[] cid = new int[512];

        int ncid = Geometry.ChunkyTriMesh.GetChunksOverlappingRect(tbmin, tbmax, ref cid, 512);

        if (ncid == 0)
        {
            return(null);
        }

        for (int i = 0; i < ncid; i++)
        {
            ChunkyTriMeshNode node = Geometry.ChunkyTriMesh.Nodes[cid[i]];
            int[]             tris = new int[node.n * 3];
            Array.Copy(Geometry.ChunkyTriMesh.Tris, node.i * 3, tris, 0, node.n * 3);
            List <int> ctris  = new List <int>(tris);
            int        nctris = node.n;

            Array.Clear(triAreas, 0, triAreas.Length);
            Geometry.MarkWalkableTriangles(Config.WalkableSlopeAngle, ctris, nctris, ref triAreas);

            heightfield.RasterizeTriangles(Geometry, ctris, nctris, triAreas, Config.WalkableClimb);
        }

        heightfield.FilterLowHangingWalkableObstacles(Config.WalkableClimb);
        heightfield.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb);
        heightfield.FilterWalkableLowHeightSpans(Config.WalkableHeight);


        CompactHeightfield compactHeightfield = new CompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, heightfield);

        compactHeightfield.ErodeWalkableArea(Config.WalkableRadius);

        // optional convex volumes

        compactHeightfield.BuildDistanceField();
        compactHeightfield.BuildRegions(Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea);


        ContourSet contourSet = new ContourSet(compactHeightfield, Config.MaxSimplificationError, Config.MaxEdgeLength);

        if (contourSet.NConts == 0)
        {
            return(null);
        }

        PolyMesh polyMesh = new PolyMesh(contourSet, Config.MaxVertexesPerPoly);

        DetailPolyMesh detailPolyMesh = new DetailPolyMesh(polyMesh, compactHeightfield, Config.DetailSampleDistance,
                                                           Config.DetailSampleMaxError);

        // Convert the Areas and Flags for path weighting
        for (int i = 0; i < polyMesh.NPolys; i++)
        {
            if (polyMesh.Areas[i] == Geometry.WalkableArea)
            {
                polyMesh.Areas[i] = 0; // Sample_polyarea_ground
                polyMesh.Flags[i] = 1; // Samply_polyflags_walk
            }
        }
        NavMeshCreateParams param = new NavMeshCreateParams
        {
            Verts            = polyMesh.Verts,
            VertCount        = polyMesh.NVerts,
            Polys            = polyMesh.Polys,
            PolyAreas        = polyMesh.Areas,
            PolyFlags        = polyMesh.Flags,
            PolyCount        = polyMesh.NPolys,
            Nvp              = polyMesh.Nvp,
            DetailMeshes     = detailPolyMesh.Meshes,
            DetailVerts      = detailPolyMesh.Verts,
            DetailVertsCount = detailPolyMesh.NVerts,
            DetailTris       = detailPolyMesh.Tris,
            DetailTriCount   = detailPolyMesh.NTris,

            // Off Mesh data
            OffMeshConVerts  = Geometry.OffMeshConnectionVerts.ToArray(),
            OffMeshConRad    = Geometry.OffMeshConnectionRadii.ToArray(),
            OffMeshConDir    = Geometry.OffMeshConnectionDirections.ToArray(),
            OffMeshConAreas  = Geometry.OffMeshConnectionAreas.ToArray(),
            OffMeshConFlags  = Geometry.OffMeshConnectionFlags.ToArray(),
            OffMeshConUserId = Geometry.OffMeshConnectionIds.ToArray(),
            OffMeshConCount  = (int)Geometry.OffMeshConnectionCount,
            // end off mesh data

            WalkableHeight = Config.WalkableHeight,
            WalkableRadius = Config.WalkableRadius,
            WalkableClimb  = Config.WalkableClimb,
            BMin           = new float[] { polyMesh.BMin[0], polyMesh.BMin[1], polyMesh.BMin[2] },
            BMax           = new float[] { polyMesh.BMax[0], polyMesh.BMax[1], polyMesh.BMax[2] },
            Cs             = polyMesh.Cs,
            Ch             = polyMesh.Ch,
            BuildBvTree    = true,
            TileX          = tx,
            TileY          = ty,
            TileLayer      = 0
        };

        return(new LunaNav.NavMeshBuilder(param));
    }
Exemple #13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PolyMesh"/> class by creating polygons from contours.
        /// </summary>
        /// <param name="contSet">The <see cref="ContourSet"/> to generate polygons from.</param>
        /// <param name="cellSize">The size of one voxel/cell.</param>
        /// <param name="cellHeight">The height of one voxel/cell.</param>
        /// <param name="borderSize">The size of the border around the mesh.</param>
        /// <param name="numVertsPerPoly">The maximum number of vertices per polygon.</param>
        public PolyMesh(ContourSet contSet, float cellSize, float cellHeight, int borderSize, int numVertsPerPoly)
        {
            //copy contour data
            this.bounds = contSet.Bounds;
            this.cellSize = cellSize;
            this.cellHeight = cellHeight;
            this.borderSize = borderSize;

            //get maximum limits
            //TODO move to ContourSet?
            int maxVertices = 0;
            int maxTris = 0;
            int maxVertsPerCont = 0;
            foreach (var cont in contSet)
            {
                int vertCount = cont.Vertices.Length;

                //skip null contours
                if (vertCount < 3)
                    continue;

                maxVertices += vertCount;
                maxTris += vertCount - 2;
                maxVertsPerCont = Math.Max(maxVertsPerCont, vertCount);
            }

            //initialize the mesh members
            var verts = new List<PolyVertex>(maxVertices);
            var polys = new List<Polygon>(maxTris);

            Queue<int> vertRemoveQueue = new Queue<int>(maxVertices);

            this.numVertsPerPoly = numVertsPerPoly;

            var vertDict = new Dictionary<PolyVertex, int>(new PolyVertex.RoughYEqualityComparer(2));

            int[] indices = new int[maxVertsPerCont]; //keep track of vertex hash codes
            Triangle[] tris = new Triangle[maxVertsPerCont];
            List<Polygon> contPolys = new List<Polygon>(maxVertsPerCont + 1);

            //extract contour data
            foreach (Contour cont in contSet)
            {
                //skip null contours
                if (cont.IsNull)
                    continue;

                PolyVertex[] vertices = new PolyVertex[cont.Vertices.Length];

                //triangulate contours
                for (int i = 0; i < cont.Vertices.Length; i++)
                {
                    var cv = cont.Vertices[i];
                    vertices[i] = new PolyVertex(cv.X, cv.Y, cv.Z);
                    indices[i] = i;
                }

                //Form triangles inside the area bounded by the contours
                int ntris = Triangulate(vertices, indices, tris);
                if (ntris <= 0) //TODO notify user when this happens. Logging?
                    ntris = -ntris;

                //add and merge vertices
                for (int i = 0; i < cont.Vertices.Length; i++)
                {
                    var cv = cont.Vertices[i];
                    var pv = vertices[i];

                    //save the hash code for each vertex
                    indices[i] = AddVertex(vertDict, pv, verts);

                    if (RegionId.HasFlags(cv.RegionId, RegionFlags.VertexBorder))
                    {
                        //the vertex should be removed
                        vertRemoveQueue.Enqueue(indices[i]);
                    }
                }

                contPolys.Clear();

                //iterate through all the triangles
                for (int i = 0; i < ntris; i++)
                {
                    Triangle ti = tris[i];

                    //make sure there are three distinct vertices. anything less can't be a polygon.
                    if (ti.Index0 == ti.Index1
                        || ti.Index0 == ti.Index2
                        || ti.Index1 == ti.Index2)
                        continue;

                    //each polygon has numVertsPerPoly
                    //index 0, 1, 2 store triangle vertices
                    //other polygon indexes (3 to numVertsPerPoly - 1) should be used for storing extra vertices when two polygons merge together
                    Polygon p = new Polygon(numVertsPerPoly, Area.Null, RegionId.Null, 0);
                    p.Vertices[0] = RemoveDiagonalFlag(indices[ti.Index0]);
                    p.Vertices[1] = RemoveDiagonalFlag(indices[ti.Index1]);
                    p.Vertices[2] = RemoveDiagonalFlag(indices[ti.Index2]);
                    contPolys.Add(p);
                }

                //no polygons generated, so skip
                if (contPolys.Count == 0)
                    continue;

                //merge polygons
                if (numVertsPerPoly > 3)
                {
                    while (true)
                    {
                        //find best polygons
                        int bestMergeVal = 0;
                        int bestPolyA = 0, bestPolyB = 0, bestEdgeA = 0, bestEdgeB = 0;

                        for (int i = 0; i < contPolys.Count - 1; i++)
                        {
                            int pj = i;

                            for (int j = i + 1; j < contPolys.Count; j++)
                            {
                                int pk = j;
                                int ea = 0, eb = 0;
                                int v = GetPolyMergeValue(contPolys, pj, pk, verts, out ea, out eb);
                                if (v > bestMergeVal)
                                {
                                    bestMergeVal = v;
                                    bestPolyA = i;
                                    bestPolyB = j;
                                    bestEdgeA = ea;
                                    bestEdgeB = eb;
                                }
                            }
                        }

                        if (bestMergeVal > 0)
                        {
                            int pa = bestPolyA;
                            int pb = bestPolyB;
                            MergePolys(contPolys, pa, pb, bestEdgeA, bestEdgeB);
                            contPolys[pb] = contPolys[contPolys.Count - 1];
                            contPolys.RemoveAt(contPolys.Count - 1);
                        }
                        else
                        {
                            //no more merging
                            break;
                        }
                    }
                }

                //store polygons
                for (int i = 0; i < contPolys.Count; i++)
                {
                    Polygon p = contPolys[i];
                    Polygon p2 = new Polygon(numVertsPerPoly, cont.Area, cont.RegionId, 0);

                    Buffer.BlockCopy(p.Vertices, 0, p2.Vertices, 0, numVertsPerPoly * sizeof(int));

                    polys.Add(p2);
                }
            }

            //remove edge vertices
            while (vertRemoveQueue.Count > 0)
            {
                int i = vertRemoveQueue.Dequeue();

                if (CanRemoveVertex(polys, i))
                    RemoveVertex(verts, polys, i);
            }

            //calculate adjacency (edges)
            BuildMeshAdjacency(verts, polys, numVertsPerPoly);

            //find portal edges
            if (this.borderSize > 0)
            {
                //iterate through all the polygons
                for (int i = 0; i < polys.Count; i++)
                {
                    Polygon p = polys[i];

                    //iterate through all the vertices
                    for (int j = 0; j < numVertsPerPoly; j++)
                    {
                        if (p.Vertices[j] == NullId)
                            break;

                        //skip connected edges
                        if (p.NeighborEdges[j] != NullId)
                            continue;

                        int nj = j + 1;
                        if (nj >= numVertsPerPoly || p.Vertices[nj] == NullId)
                            nj = 0;

                        //grab two consecutive vertices
                        int va = p.Vertices[j];
                        int vb = p.Vertices[nj];

                        //set some flags
                        if (verts[va].X == 0 && verts[vb].X == 0)
                            p.NeighborEdges[j] = NeighborEdgeFlag | 0;
                        else if (verts[va].Z == contSet.Height && verts[vb].Z == contSet.Height)
                            p.NeighborEdges[j] = NeighborEdgeFlag | 1;
                        else if (verts[va].X == contSet.Width && verts[vb].X == contSet.Width)
                            p.NeighborEdges[j] = NeighborEdgeFlag | 2;
                        else if (verts[va].Z == 0 && verts[vb].Z == 0)
                            p.NeighborEdges[j] = NeighborEdgeFlag | 3;
                    }
                }
            }

            this.vertices = verts.ToArray();
            this.polygons = polys.ToArray();
        }
Exemple #14
0
 //HACK borderSize is 0 here. Fix with borderSize.
 /// <summary>
 /// Initializes a new instance of the <see cref="PolyMesh"/> class.
 /// </summary>
 /// <param name="contSet">The <see cref="ContourSet"/> to generate polygons from.</param>
 /// <param name="settings">The settings to build with.</param>
 public PolyMesh(ContourSet contSet, NavMeshGenerationSettings settings)
     : this(contSet, settings.CellSize, settings.CellHeight, 0, settings.VertsPerPoly)
 {
 }
Exemple #15
0
    private Detour.AtavismNavTile BuildTileMesh(int tx, int ty, RecastVertex min, RecastVertex max)
    {
        Config.Width = Config.TileSize + Config.BorderSize * 2;
        Config.Height = Config.TileSize + Config.BorderSize * 2;
        Config.MinBounds = min;
        Config.MaxBounds = max;
        Config.MinBounds.X -= Config.BorderSize * Config.CellSize;
        Config.MinBounds.Z -= Config.BorderSize * Config.CellSize;

        Config.MaxBounds.X += Config.BorderSize * Config.CellSize;
        Config.MaxBounds.Z += Config.BorderSize * Config.CellSize;

        HeightField heightfield = new HeightField(Config.Width, Config.Height, Config.MinBounds.ToArray(), Config.MaxBounds.ToArray(), Config.CellSize, Config.CellHeight);

        short[] triAreas = new short[Geometry.ChunkyTriMesh.MaxTrisPerChunk];

        float[] tbmin = new float[2], tbmax = new float[2];
        tbmin[0] = Config.MinBounds.X;
        tbmin[1] = Config.MinBounds.Z;

        tbmax[0] = Config.MaxBounds.X;
        tbmax[1] = Config.MaxBounds.Z;

        int[] cid = new int[512];

        int ncid = Geometry.ChunkyTriMesh.GetChunksOverlappingRect(tbmin, tbmax, ref cid, 512);

        if (ncid == 0)
            return null;

        for (int i = 0; i < ncid; i++)
        {
            ChunkyTriMeshNode node = Geometry.ChunkyTriMesh.Nodes[cid[i]];
            int[] tris = new int[node.n * 3];
            Array.Copy(Geometry.ChunkyTriMesh.Tris, node.i * 3, tris, 0, node.n * 3);
            List<int> ctris = new List<int>(tris);
            int nctris = node.n;

            Array.Clear(triAreas, 0, triAreas.Length);
            Geometry.MarkWalkableTriangles(Config.WalkableSlopeAngle, ctris, nctris, ref triAreas);

            heightfield.RasterizeTriangles(Geometry, ctris, nctris, triAreas, Config.WalkableClimb);
        }

        heightfield.FilterLowHangingWalkableObstacles(Config.WalkableClimb);
        heightfield.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb);
        heightfield.FilterWalkableLowHeightSpans(Config.WalkableHeight);

        CompactHeightfield compactHeightfield = new CompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, heightfield);
        compactHeightfield.ErodeWalkableArea(Config.WalkableRadius);

        // optional convex volumes

        compactHeightfield.BuildDistanceField();
        compactHeightfield.BuildRegions(Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea);

        ContourSet contourSet = new ContourSet(compactHeightfield, Config.MaxSimplificationError, Config.MaxEdgeLength);

        if (contourSet.NConts == 0)
            return null;

        PolyMesh polyMesh = new PolyMesh(contourSet, Config.MaxVertexesPerPoly);

        DetailPolyMesh detailPolyMesh = new DetailPolyMesh(polyMesh, compactHeightfield, Config.DetailSampleDistance,
                                                            Config.DetailSampleMaxError);

        // Convert the Areas and Flags for path weighting
        for (int i = 0; i < polyMesh.NPolys; i++)
        {

            if (polyMesh.Areas[i] == Geometry.WalkableArea)
            {
                polyMesh.Areas[i] = 0; // Sample_polyarea_ground
                polyMesh.Flags[i] = 1; // Samply_polyflags_walk
            }
        }
        NavMeshCreateParams param = new NavMeshCreateParams
        {
            Verts = polyMesh.Verts,
            VertCount = polyMesh.NVerts,
            Polys = polyMesh.Polys,
            PolyAreas = polyMesh.Areas,
            PolyFlags = polyMesh.Flags,
            PolyCount = polyMesh.NPolys,
            Nvp = polyMesh.Nvp,
            DetailMeshes = detailPolyMesh.Meshes,
            DetailVerts = detailPolyMesh.Verts,
            DetailVertsCount = detailPolyMesh.NVerts,
            DetailTris = detailPolyMesh.Tris,
            DetailTriCount = detailPolyMesh.NTris,

            // Off Mesh data
            OffMeshConVerts = Geometry.OffMeshConnectionVerts.ToArray(),
            OffMeshConRad = Geometry.OffMeshConnectionRadii.ToArray(),
            OffMeshConDir = Geometry.OffMeshConnectionDirections.ToArray(),
            OffMeshConAreas = Geometry.OffMeshConnectionAreas.ToArray(),
            OffMeshConFlags = Geometry.OffMeshConnectionFlags.ToArray(),
            OffMeshConUserId = Geometry.OffMeshConnectionIds.ToArray(),
            OffMeshConCount = (int)Geometry.OffMeshConnectionCount,
            // end off mesh data

            WalkableHeight = Config.WalkableHeight,
            WalkableRadius = Config.WalkableRadius,
            WalkableClimb = Config.WalkableClimb,
            BMin = new float[] { polyMesh.BMin[0], polyMesh.BMin[1], polyMesh.BMin[2] },
            BMax = new float[] { polyMesh.BMax[0], polyMesh.BMax[1], polyMesh.BMax[2] },
            Cs = polyMesh.Cs,
            Ch = polyMesh.Ch,
            BuildBvTree = true,
            TileX = tx,
            TileY = ty,
            TileLayer = 0
        };
        return new Detour.AtavismNavTile(param);
    }