feat(world-gen): larger biomes, smooth height blending, capped mountains; centralize tunables in Configuration
Terrain feel: biome regions ~10x larger (Voronoi cell size 96->960); terrain height now eases across biome borders via a Voronoi distance blend (smooth, and ~25x cheaper than the old 169-sample box blur); mountains capped to ~2/3 world height and gentled (ridged amplitude/frequency lowered), snow line lowered to match. Centralization: ~27 world-gen/render tuning constants (biome amplitudes & frequencies, climate-noise frequencies/octaves, biome-selection thresholds, blend width, cell size, filler depth, snow line, camera near plane, spawn offset, overlay scale) hoisted from scattered literals into a region-organized, fully-commented Configuration. Configuration is threaded into NoiseSource, the biomes, BiomeRegistry, BiomeMap (+Classify), TerrainSampler, WorldGenerator (+BlockAt filler depth), and Camera via Player. Defaults equal the prior values, so generation is unchanged; worldgen tests updated for the new constructor signatures.
This commit is contained in:
@@ -16,8 +16,8 @@ public sealed class VoronoiCells
|
||||
|
||||
public Cell Nearest(float x, float z)
|
||||
{
|
||||
int gx = (int)System.MathF.Floor(x / this._cellSize);
|
||||
int gz = (int)System.MathF.Floor(z / this._cellSize);
|
||||
int gx = (int)MathF.Floor(x / this._cellSize);
|
||||
int gz = (int)MathF.Floor(z / this._cellSize);
|
||||
|
||||
float bestDist = float.MaxValue;
|
||||
int bestId = 0;
|
||||
@@ -28,8 +28,8 @@ public sealed class VoronoiCells
|
||||
{
|
||||
int cgx = gx + ox;
|
||||
int cgz = gz + oz;
|
||||
float jitterX = VoronoiCells.Jitter(cgx, cgz, this._seed);
|
||||
float jitterZ = VoronoiCells.Jitter(cgx, cgz, this._seed + 9871);
|
||||
float jitterX = Jitter(cgx, cgz, this._seed);
|
||||
float jitterZ = Jitter(cgx, cgz, this._seed + 9871);
|
||||
float cx = (cgx + jitterX) * this._cellSize;
|
||||
float cz = (cgz + jitterZ) * this._cellSize;
|
||||
float dx = cx - x, dz = cz - z;
|
||||
@@ -37,7 +37,7 @@ public sealed class VoronoiCells
|
||||
if (dist < bestDist)
|
||||
{
|
||||
bestDist = dist;
|
||||
bestId = (int)VoronoiCells.Hash(cgx, cgz, this._seed);
|
||||
bestId = (int)Hash(cgx, cgz, this._seed);
|
||||
bestCx = cx;
|
||||
bestCz = cz;
|
||||
}
|
||||
@@ -45,8 +45,48 @@ public sealed class VoronoiCells
|
||||
return new Cell(bestId, bestCx, bestCz);
|
||||
}
|
||||
|
||||
public readonly record struct NearestPair(Cell First, Cell Second, float FirstDist, float SecondDist);
|
||||
|
||||
// The two nearest cells to (x,z) with their (Euclidean) distances. Used to
|
||||
// ease terrain height across the border between adjacent biome cells. Same
|
||||
// 3x3 jittered-grid search as Nearest — the two closest centres always fall
|
||||
// within that neighbourhood for jitter in [0,1).
|
||||
public NearestPair NearestTwo(float x, float z)
|
||||
{
|
||||
int gx = (int)MathF.Floor(x / this._cellSize);
|
||||
int gz = (int)MathF.Floor(z / this._cellSize);
|
||||
|
||||
float best = float.MaxValue, second = float.MaxValue;
|
||||
Cell bestCell = default, secondCell = default;
|
||||
|
||||
for (int oz = -1; oz <= 1; oz++)
|
||||
for (int ox = -1; ox <= 1; ox++)
|
||||
{
|
||||
int cgx = gx + ox;
|
||||
int cgz = gz + oz;
|
||||
float jitterX = Jitter(cgx, cgz, this._seed);
|
||||
float jitterZ = Jitter(cgx, cgz, this._seed + 9871);
|
||||
float cx = (cgx + jitterX) * this._cellSize;
|
||||
float cz = (cgz + jitterZ) * this._cellSize;
|
||||
float dx = cx - x, dz = cz - z;
|
||||
float dist = dx * dx + dz * dz;
|
||||
Cell cell = new((int)Hash(cgx, cgz, this._seed), cx, cz);
|
||||
if (dist < best)
|
||||
{
|
||||
second = best; secondCell = bestCell;
|
||||
best = dist; bestCell = cell;
|
||||
}
|
||||
else if (dist < second)
|
||||
{
|
||||
second = dist; secondCell = cell;
|
||||
}
|
||||
}
|
||||
return new NearestPair(bestCell, secondCell,
|
||||
MathF.Sqrt(best), MathF.Sqrt(second));
|
||||
}
|
||||
|
||||
private static float Jitter(int x, int z, int seed)
|
||||
=> (VoronoiCells.Hash(x, z, seed) & 0xFFFFFF) / (float)0x1000000; // [0,1)
|
||||
=> (Hash(x, z, seed) & 0xFFFFFF) / (float)0x1000000; // [0,1)
|
||||
|
||||
private static uint Hash(int x, int z, int seed)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user