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)); }
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); }