예제 #1
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);
        }
예제 #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;
            }
        }
예제 #3
0
        public void DistanceField_Simple_Success()
        {
            //Build a 3x3 heightfield
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), (float)(1.0f / 3.0f), 0.02f);

            for (int i = 0; i < 9; 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);

            //make sure connections are set
            Assert.AreEqual(chf.Spans[0 * 2].ConnectionCount, 2);             //corner
            Assert.AreEqual(chf.Spans[1 * 2].ConnectionCount, 3);             //edge
            Assert.AreEqual(chf.Spans[2 * 2].ConnectionCount, 2);             //corner
            Assert.AreEqual(chf.Spans[3 * 2].ConnectionCount, 3);             //edge
            Assert.AreEqual(chf.Spans[4 * 2].ConnectionCount, 4);             //center

            chf.BuildDistanceField();

            //check distance field values
            Assert.AreEqual(chf.MaxDistance, 2);

            //1st row
            Assert.AreEqual(chf.Distances[0 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[1 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[2 * 2], 0);             //boundary

            //2nd row
            Assert.AreEqual(chf.Distances[3 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[4 * 2], 2);             //center span
            Assert.AreEqual(chf.Distances[5 * 2], 0);             //boundary
        }
예제 #4
0
    public void Test()
    {
        var bounds = RecastBuilder.GetBoundsFromGameObject(gameObject);

        //bounds.Expand(2.0f);
        bounds = RecastBuilder.AlignBounds(bounds);
        bounds.Expand(new Vector3(0, 1.6f, 0));
        voxel = RecastBuilder.Creat(bounds, Size);
        RecastBuilder.AddGameObject(voxel, gameObject);
        Vector3 min = voxel.Bounds.min;

        heightfield = RecastBuilder.VoxelToHeightfield(voxel);
        var bitMask = RecastBuilder.VoxelizationWalkableFilter(voxel);

        if (ValidPoint)
        {
            var        pos       = Vector3Int.CeilToInt((ValidPoint.position - min) / voxel.CellSize);
            Vector2Int pt        = new Vector2Int(pos.x, pos.z);
            Vector2Int size      = new Vector2Int(voxel.Size.x, voxel.Size.z);
            var        validMask = RecastBuilder.CalcClosePoint(bitMask, size, pt);
            gridData = new RecastGridData
            {
                OriginPoint = new Vector3(min.x, min.z),
                Width       = voxel.Size.x,
                Length      = voxel.Size.z,
                Mask        = new SerializBitArray(validMask)
            };
        }
        else
        {
            gridData = RecastBuilder.VoxelizationToGrid(voxel);
        }
    }
예제 #5
0
        public void BuildRegions_Success()
        {
            //Build a 3x3 heightfield
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), (float)(1.0f / 3.0f), 0.02f);

            for (int i = 0; i < 9; 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, 2, 3);

            //Most spans do not have a region id because those spans are part of the border
            //Most region ids won't be assigned to any span

            //Total number of regions right now
            Assert.AreEqual(chf.MaxRegions, 7);

            //Center spans should have region id
            Assert.AreEqual((int)chf.Spans[4 * 2 + 0].Region, 5);
            Assert.AreEqual((int)chf.Spans[4 * 2 + 1].Region, 6);

            //Check that the rest of the region ids are not assigned to a span
            for (int i = 0; i < chf.Spans.Length; i++)
            {
                for (int j = 0; j <= 4; j++)
                {
                    Assert.AreNotEqual((int)chf.Spans[i].Region, j);
                }
            }
        }
예제 #6
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;
 }
예제 #7
0
        public void Filter_LowHangingWalkable_Fail()
        {
            var hf    = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.02f);
            var span  = new Span(1, 2, Area.Default);
            var span2 = new Span(10, 20, Area.Null);

            hf[2].AddSpan(span);
            hf[2].AddSpan(span2);

            //walkable step cannot cover the gap (difference between span2 maximum and span 1 maximum) so fail
            hf.FilterLowHangingWalkableObstacles(10);
            Assert.AreNotEqual(hf[0, 1].Spans[0].Area, hf[0, 1].Spans[1].Area);
        }
예제 #8
0
        public void Filter_LowHangingWalkable_Success()
        {
            var hf    = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.02f);
            var span  = new Span(10, 15, Area.Default);
            var span2 = new Span(16, 20, Area.Null);

            hf[0].AddSpan(span);
            hf[0].AddSpan(span2);

            hf.FilterLowHangingWalkableObstacles(20);

            Assert.AreEqual(hf[0].Spans[0].Area, hf[0].Spans[1].Area);
        }
        private bool PostHeightfieldCheck()
        {
            Heightfield hf = mBuildContext.Heightfield;

            if (hf == null || hf.IsDisposed)
            {
                FinalizeAbort("Custom processors destroyed the heightfield. (" + mState + " Post)");
                return(false);
            }
            else if (hf.GetSpanCount() < 1)
            {
                FinalizeNoResult("Complete at heightfield build. No spans. (" + mState + " Post)");
                return(false);
            }
            return(true);
        }
        private void BuildCompactField()
        {
            Heightfield hf = mBuildContext.Heightfield;

            CompactHeightfield chf = CompactHeightfield.Build(mBuildContext
                                                              , hf
                                                              , mConfig.WalkableHeight
                                                              , mConfig.WalkableStep);

            if (CanDispose(NMGenAssetFlag.Heightfield))
            {
                hf.RequestDisposal();
                mBuildContext.Heightfield = null;
            }

            if (chf == null)
            {
                FinalizeAbort("Aborted at compact heightfield build.");
                return;
            }

            if (chf.SpanCount < 1)
            {
                FinalizeNoResult("Complete at compact heightfield build. No spans.");
                return;
            }

            mBuildContext.CompactField = chf;

            // Note: Post process is done before eroding the walkable area
            // so that the processors can stamp additional obstructions into
            // the heightfield.
            if (PostProcess() && PostCompactFieldCheck())
            {
                if (mConfig.WalkableRadius > 0)
                {
                    chf = mBuildContext.CompactField;
                    chf.ErodeWalkableArea(mBuildContext, mConfig.WalkableRadius);
                    mBuildContext.Log("Eroded walkable area by radius: " + mConfig.walkableRadius
                                      , this);
                }

                mBuildContext.Log("Built compact heightfield. Spans: " + chf.SpanCount, this);

                mState = NMGenState.RegionBuild;
            }
        }
예제 #11
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();
            //}
        }
예제 #12
0
        public void ConvertSpans_OneCell()
        {
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.02f);

            hf[0].AddSpan(new Span(10, 20, Area.Default));
            hf[0].AddSpan(new Span(25, 30, Area.Default));

            CompactHeightfield chf = new CompactHeightfield(hf, 2, 1);

            Assert.AreEqual(chf.Spans.Length, 2);

            Assert.AreEqual(chf.Spans[0].Minimum, 20);
            Assert.AreEqual(chf.Spans[0].Height, 5);

            Assert.AreEqual(chf.Spans[1].Minimum, 30);
            Assert.AreEqual(chf.Spans[1].Height, int.MaxValue);
        }
예제 #13
0
        public void Filter_WalkableLowHeight_Success()
        {
            var hf    = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.02f);
            var span  = new Span(10, 20, Area.Default);
            var span2 = new Span(25, 30, Area.Default);

            hf[0].AddSpan(span);
            hf[0].AddSpan(span2);

            //too low to walk through. there is only a gap of 5 units to walk through,
            //but at least 15 units is needed
            hf.FilterWalkableLowHeightSpans(15);

            //so one span is unwalkable and the other is fine
            Assert.AreEqual(hf[0].Spans[0].Area, Area.Null);
            Assert.AreEqual(hf[0].Spans[1].Area, Area.Default);
        }
예제 #14
0
        public void ConvertSpans_TwoCells()
        {
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, new Vector3(1, 1, 1)), 0.5f, 0.02f);

            hf[0].AddSpan(new Span(10, 20, Area.Default));
            hf[0].AddSpan(new Span(25, 30, Area.Default));
            hf[1].AddSpan(new Span(5, 15, Area.Default));
            hf[1].AddSpan(new Span(25, 30, Area.Default));
            hf[1].AddSpan(new Span(40, 55, Area.Default));
            CompactHeightfield chf = new CompactHeightfield(hf, 2, 1);

            Assert.AreEqual(chf.Cells.Length, 4);

            Assert.AreEqual(chf.Cells[0].StartIndex, 0);
            Assert.AreEqual(chf.Cells[0].Count, 2);
            Assert.AreEqual(chf.Cells[1].StartIndex, 2);
            Assert.AreEqual(chf.Cells[1].Count, 3);
        }
예제 #15
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);
		}
예제 #16
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);
        }
예제 #17
0
        public void SetConnection_TwoCells()
        {
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.02f);

            hf[0].AddSpan(new Span(10, 20, Area.Default));
            hf[0].AddSpan(new Span(25, 30, Area.Default));
            hf[1].AddSpan(new Span(10, 21, Area.Default));
            hf[1].AddSpan(new Span(25, 30, Area.Default));
            CompactHeightfield chf = new CompactHeightfield(hf, 2, 1);

            Assert.IsTrue(chf.Spans[0].IsConnected(Direction.East));
            Assert.IsTrue(chf.Spans[1].IsConnected(Direction.East));
            Assert.IsTrue(chf.Spans[2].IsConnected(Direction.West));
            Assert.IsTrue(chf.Spans[3].IsConnected(Direction.West));

            Assert.AreEqual(chf.Spans[0].ConnectionEast, 0);
            Assert.AreEqual(chf.Spans[1].ConnectionEast, 1);
            Assert.AreEqual(chf.Spans[2].ConnectionWest, 0);
            Assert.AreEqual(chf.Spans[3].ConnectionWest, 1);
        }
예제 #18
0
    public void Test()
    {
        var bounds = RecastBuilder.GetBoundsFromGameObject(gameObject);

        //bounds.Expand(2.0f);
        bounds = RecastBuilder.AlignBounds(bounds);
        bounds.Expand(new Vector3(0, 1.6f, 0));
        voxel = RecastBuilder.Creat(bounds, Size);
        RecastBuilder.AddGameObject(voxel, gameObject);
        Vector3 min = voxel.Bounds.min;

        heightfield = RecastBuilder.VoxelToHeightfield(voxel);
        gridData    = RecastBuilder.HeightfieldToPlaneGrid(heightfield, 0, 2);
        //var bitMask = RecastBuilder.VoxelizationWalkableFilter(voxel);
        if (ValidPoint)
        {
            var        pos  = Vector3Int.CeilToInt((ValidPoint.position - min) / voxel.CellSize);
            Vector2Int pt   = new Vector2Int(pos.x, pos.z);
            Vector2Int size = new Vector2Int(voxel.Size.x, voxel.Size.z);
            gridData.Mask = RecastBuilder.CalcClosePoint(gridData.Mask, size, pt);
        }
    }
        private void BuildHeightfield()
        {
            int width;
            int depth;

            NMGen.DeriveSizeOfCellGrid(mTileConfig.BoundsMin
                                       , mTileConfig.BoundsMax
                                       , mConfig.XZCellSize
                                       , out width
                                       , out depth);

            Heightfield hf = Heightfield.Create(width, depth
                                                , mTileConfig.BoundsMin, mTileConfig.BoundsMax
                                                , mConfig.XZCellSize, mConfig.YCellSize);


            hf.AddTriangles(mBuildContext
                            , mGeometry.Mesh
                            , mTileConfig.boundsMin
                            , mTileConfig.boundsMax
                            , mConfig.WalkableStep); // Merge for any spans less than step.


            if (hf.GetSpanCount() < 1)
            {
                FinalizeNoResult("Complete at heightfield build. No spans.");
                return;
            }


            mBuildContext.Heightfield = hf;

            if (PostProcess() && PostHeightfieldCheck())
            {
                mBuildContext.Log("Voxelized triangles. Span count: " + hf.GetSpanCount(), this);
                mState = NMGenState.CompactFieldBuild;
            }
        }
예제 #20
0
        public NavMeshBuilder Build()
        {
            // Generate tile data
            LoadTileData();

            // Extract raw data from geometry
            float[] vertices;
            int[]   indices;

            s_Geometry.GetRawData(out vertices, out indices /*, out areas*/);

            var hf = new Heightfield(Bounds, NavmeshSettings);

            hf.RasterizeTriangles(vertices, Area.Default);
            hf.FilterLedgeSpans(NavmeshSettings.VoxelAgentHeight, NavmeshSettings.VoxelMaxClimb);
            hf.FilterLowHangingWalkableObstacles(NavmeshSettings.VoxelMaxClimb);
            hf.FilterWalkableLowHeightSpans(NavmeshSettings.VoxelAgentHeight);

            var chf = new CompactHeightfield(hf, NavmeshSettings);

            chf.Erode(NavmeshSettings.VoxelAgentRadius);
            chf.BuildDistanceField();
            chf.BuildRegions((int)(NavmeshSettings.AgentRadius / NavmeshSettings.CellSize) + 8, NavmeshSettings.MinRegionSize, NavmeshSettings.MergedRegionSize);

            var cset  = chf.BuildContourSet(NavmeshSettings);
            var pmesh = new PolyMesh(cset, NavmeshSettings);
            var dmesh = new PolyMeshDetail(pmesh, chf, NavmeshSettings);

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

            Console.WriteLine("Rasterized " + vertices.Length / 9 + " triangles.");
            Console.WriteLine("Generated " + cset.Count + " regions.");
            Console.WriteLine("PolyMesh contains " + pmesh.VertCount + " vertices in " + pmesh.PolyCount + " polys.");
            Console.WriteLine("PolyMeshDetail contains " + dmesh.VertCount + " vertices and " + dmesh.TrisCount + " tris in " + dmesh.MeshCount + " meshes.");

            return(buildData);
        }
예제 #21
0
        public void DistanceField_Medium_Success()
        {
            //Build a 5x5 heightfield
            Heightfield hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.2f, 0.02f);

            for (int i = 0; i < 25; 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();

            //Before box blur, MaxDistance is 4
            //After box blur, MaxDistance is 2
            Assert.AreEqual(chf.MaxDistance, 2);

            //1st row
            Assert.AreEqual(chf.Distances[0 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[4 * 2], 0);             //boundary

            //2nd row
            Assert.AreEqual(chf.Distances[5 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[6 * 2], 2);             //near boundary
            Assert.AreEqual(chf.Distances[7 * 2], 2);             //near boundary
            Assert.AreEqual(chf.Distances[8 * 2], 2);             //near boundary
            Assert.AreEqual(chf.Distances[9 * 2], 0);             //boundary

            //3rd row
            Assert.AreEqual(chf.Distances[10 * 2], 0);             //boundary
            Assert.AreEqual(chf.Distances[11 * 2], 2);             //near boundary
            Assert.AreEqual(chf.Distances[12 * 2], 2);             //center (box blurred distance is (2*8 + 5)/9)
            Assert.AreEqual(chf.Distances[13 * 2], 2);             //near boundary
            Assert.AreEqual(chf.Distances[14 * 2], 0);             //boundary
        }
예제 #22
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.");
            }
        }
예제 #23
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!");
        }
예제 #24
0
        public void Indexer_Valid_ReturnsCell()
        {
            var hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.5f);

            Assert.IsNotNull(hf[0, 1]);
        }
예제 #25
0
        public void Indexer_CellOutOfRange_Throws()
        {
            var hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.5f);

            Assert.Throws <ArgumentOutOfRangeException>(() => { var c = hf[5]; });
        }
예제 #26
0
		public bool BuildNavMesh( out string error )
		{
			DestroyNavMesh();

			if( !EnabledInHierarchy )
			{
				error = "Is not enabled.";
				return false;
			}

			//get geometry data
			var collector = GetAllGeometriesForNavigationMesh();
			Vector3[] vertices = collector.resultVertices;
			int[] indices = collector.resultIndices;
			int vertexCount = collector.resultVertexCount;
			int indexCount = collector.resultIndexCount;

			if( vertexCount == 0 )
			{
				error = "No vertices were gathered from collision objects.";
				return false;
			}

			//get settings
			var settings = new NavMeshGenerationSettings();
			settings.CellSize = (float)CellSize;
			settings.CellHeight = (float)CellHeight;
			settings.MaxClimb = (float)AgentMaxClimb;
			settings.AgentHeight = (float)AgentHeight;
			settings.AgentRadius = (float)AgentRadius;
			settings.MinRegionSize = MinRegionSize;
			settings.MergedRegionSize = MergedRegionSize;
			settings.MaxEdgeLength = MaxEdgeLength;
			settings.MaxEdgeError = (float)MaxEdgeError;
			settings.VertsPerPoly = MaxVerticesPerPolygon;
			settings.SampleDistance = DetailSampleDistance;
			settings.MaxSampleError = DetailMaxSampleError;
			settings.BuildBoundingVolumeTree = true;

			TiledNavMesh newTiledNavMesh;

			try
			{
				//level.SetBoundingBoxOffset(new SVector3(settings.CellSize * 0.5f, settings.CellHeight * 0.5f, settings.CellSize * 0.5f));

				var bounds = Bounds.Cleared;
				bounds.Add( vertices );
				var heightfield = new Heightfield( ToSharpNav( bounds ), settings );

				var vertices2 = new SharpNav.Geometry.Vector3[ indexCount ];
				for( int index = 0; index < indexCount; index++ )
					vertices2[ index ] = ToSharpNav( vertices[ indices[ index ] ] );

				//Area[] areas = AreaGenerator.From( vertices2, Area.Default )
				//	.MarkBelowSlope( (float)AgentMaxSlope.Value.InRadians(), Area.Null )
				//	.ToArray();
				//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( vertices2, areas );
				heightfield.RasterizeTriangles( vertices2, Area.Default );

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

				var compactHeightfield = new CompactHeightfield( heightfield, settings );
				compactHeightfield.Erode( settings.VoxelAgentRadius );
				compactHeightfield.BuildDistanceField();
				compactHeightfield.BuildRegions( 0, settings.MinRegionSize, settings.MergedRegionSize );

				//!!!!
				System.Random r = new System.Random();
				var regionColors = new ColorByte[ compactHeightfield.MaxRegions ];
				regionColors[ 0 ] = new ColorByte( 0, 0, 0 );
				for( int i = 1; i < regionColors.Length; i++ )
					regionColors[ i ] = new ColorByte( (byte)r.Next( 0, 255 ), (byte)r.Next( 0, 255 ), (byte)r.Next( 0, 255 ), (byte)255 );

				var contourSet = compactHeightfield.BuildContourSet( settings );
				var polyMesh = new PolyMesh( contourSet, settings );
				var polyMeshDetail = new PolyMeshDetail( polyMesh, compactHeightfield, settings );

				var buildData = new NavMeshBuilder( polyMesh, polyMeshDetail, new OffMeshConnection[ 0 ], settings );
				newTiledNavMesh = new TiledNavMesh( buildData );

				//!!!!
				////Pathfinding with multiple units
				//GenerateCrowd();
			}
			catch( Exception e )
			{
				DestroyNavMesh();
				error = e.Message;
				return false;
			}

			int dataLength;
			byte[] data;

			using( var memoryStream = new MemoryStream() )
			{
				var serializer = new NavMeshBinarySerializer();
				serializer.Serialize( memoryStream, newTiledNavMesh );

				dataLength = (int)memoryStream.Length;
				data = memoryStream.GetBuffer();
			}

			//generate nav mesh data
			var writer = new ArrayDataWriter();
			writer.Write( navMeshDataVersion );
			writer.Write( dataLength );
			writer.Write( data, 0, dataLength );

			//set NavMeshData and init
			var newNavMeshData = new byte[ writer.BitLength / 8 ];
			Buffer.BlockCopy( writer.Data, 0, newNavMeshData, 0, newNavMeshData.Length );
			NavMeshData = newNavMeshData;

			error = "";
			return true;
		}