public void Process(ref NavMeshCreateParams param, NavMeshTileBuildContext bc) { // Update poly flags from areas. for (int i = 0; i < param.polyCount; ++i) { if ((int)bc.LMesh.Areas[i] == (int)TileCacheAreas.RC_WALKABLE_AREA) { bc.LMesh.Areas[i] = SamplePolyAreas.SAMPLE_POLYAREA_GROUND; } if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_GROUND || bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_GRASS || bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_ROAD) { bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_WALK; } else if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_WATER) { bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_SWIM; } else if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_DOOR) { bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_WALK | SamplePolyFlagTypes.SAMPLE_POLYFLAGS_DOOR; } } // Pass in off-mesh connections. if (m_geom != null) { param.offMeshCon = m_geom.GetConnections().ToArray(); param.offMeshConCount = m_geom.GetConnectionCount(); } }
public bool BuildNavMeshTile(CompressedTile tile, NavMesh navmesh) { NavMeshTileBuildContext bc = new NavMeshTileBuildContext(); int walkableClimbVx = (int)(m_params.WalkableClimb / m_params.CellHeight); // Decompress tile layer data. if (!DetourTileCache.DecompressTileCacheLayer(tile.Header, tile.Data, 0, out var layer)) { return(false); } bc.Layer = layer; // Rasterize obstacles. for (int i = 0; i < m_params.MaxObstacles; ++i) { var ob = m_obstacles[i]; if (ob.State == ObstacleState.DT_OBSTACLE_EMPTY || ob.State == ObstacleState.DT_OBSTACLE_REMOVING) { continue; } if (DetourTileCache.Contains(ob.Touched, ob.NTouched, tile)) { if (ob.Type == ObstacleType.DT_OBSTACLE_CYLINDER) { DetourTileCache.MarkCylinderArea(bc, tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight, ob.Cylinder.Pos, ob.Cylinder.Radius, ob.Cylinder.Height, 0); } else if (ob.Type == ObstacleType.DT_OBSTACLE_BOX) { DetourTileCache.MarkBoxArea(bc, tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight, ob.Box.BMin, ob.Box.BMax, 0); } else if (ob.Type == ObstacleType.DT_OBSTACLE_ORIENTED_BOX) { DetourTileCache.MarkBoxArea(bc, tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight, ob.OrientedBox.Center, ob.OrientedBox.HalfExtents, ob.OrientedBox.RotAux, 0); } } } // Build navmesh if (!DetourTileCache.BuildTileCacheRegions(bc, walkableClimbVx)) { return(false); } if (!DetourTileCache.BuildTileCacheContours(bc, walkableClimbVx, m_params.MaxSimplificationError)) { return(false); } if (!DetourTileCache.BuildTileCachePolyMesh(bc)) { return(false); } // Early out if the mesh tile is empty. if (bc.LMesh.NPolys == 0) { // Remove existing tile. navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0); return(true); } var param = new NavMeshCreateParams { Verts = bc.LMesh.Verts, VertCount = bc.LMesh.NVerts, Polys = bc.LMesh.Polys, PolyAreas = bc.LMesh.Areas, PolyFlags = bc.LMesh.Flags, polyCount = bc.LMesh.NPolys, nvp = Detour.DT_VERTS_PER_POLYGON, walkableHeight = m_params.WalkableHeight, walkableRadius = m_params.WalkableRadius, walkableClimb = m_params.WalkableClimb, tileX = tile.Header.TX, tileY = tile.Header.TY, tileLayer = tile.Header.TLayer, cs = m_params.CellSize, ch = m_params.CellHeight, buildBvTree = false, bmin = tile.Header.BBox.Minimum, bmax = tile.Header.BBox.Maximum, }; if (m_tmproc != null) { m_tmproc.Process(ref param, bc); } if (!Detour.CreateNavMeshData(param, out MeshData navData)) { return(false); } // Remove existing tile. navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0); // Add new tile, or leave the location empty. if (navData != null && !navmesh.AddTile(navData, TileFlagTypes.DT_TILE_FREE_DATA, 0, out int result)) { // Let the navmesh own the data. navData = null; return(false); } return(true); }