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); }
/// <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; } }
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 }
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); } }
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); } } }
/// <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; }
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); }
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; } }
//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(); //} }
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); }
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); }
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); }
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); }
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); }
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; } }
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); }
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 }
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."); } }
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!"); }
public void Indexer_Valid_ReturnsCell() { var hf = new Heightfield(new BBox3(Vector3.Zero, Vector3.One), 0.5f, 0.5f); Assert.IsNotNull(hf[0, 1]); }
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]; }); }
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; }