namespace VoxelEngine.World.WorldGen; public sealed class TerrainSampler { // Box-blur radius (in blocks) applied to the biome-height field to smooth // biome borders. A full (2R+1)x(2R+1) kernel at 1-block spacing bounds the // per-block height change to ~maxBiomeHeightDiff / (2R+1), preventing cliffs. // A sparse kernel does NOT bound it (axis-aligned borders flip several samples // at once), so the kernel must be dense. private const int BlendRadius = 6; private readonly NoiseSource _noise; private readonly BiomeMap _biomes; public TerrainSampler(NoiseSource noise, BiomeMap biomes) { this._noise = noise; this._biomes = biomes; } public int HeightAt(float worldX, float worldZ) { // For each kernel point find the biome THERE, but evaluate its height AT the // column. Averaging blurs the hard biome borders into smooth transitions. float sum = 0f; int count = 0; for (int dz = -TerrainSampler.BlendRadius; dz <= TerrainSampler.BlendRadius; dz++) for (int dx = -TerrainSampler.BlendRadius; dx <= TerrainSampler.BlendRadius; dx++) { IBiome biome = this._biomes.BiomeAt(worldX + dx, worldZ + dz); sum += biome.SampleHeight(this._noise, worldX, worldZ); count++; } float avg = sum / count; int h = (int)System.MathF.Round(avg); return System.Math.Clamp(h, 0, WorldConstants.WorldHeight - 1); } }