feat: add deterministic VoronoiCells partition

This commit is contained in:
MDietermann
2026-05-31 21:50:09 +02:00
parent 44f53e8d50
commit d0707fde9d
2 changed files with 96 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
namespace VoxelEngine.World.WorldGen;
// A jittered-grid Voronoi partition. Pure integer-hash based, fully deterministic.
public sealed class VoronoiCells
{
public readonly record struct Cell(int Id, float CenterX, float CenterZ);
private readonly int _seed;
private readonly float _cellSize;
public VoronoiCells(int seed, float cellSize)
{
this._seed = seed;
this._cellSize = cellSize;
}
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);
float bestDist = float.MaxValue;
int bestId = 0;
float bestCx = 0f, bestCz = 0f;
for (int oz = -1; oz <= 1; oz++)
for (int ox = -1; ox <= 1; ox++)
{
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 cx = (cgx + jitterX) * this._cellSize;
float cz = (cgz + jitterZ) * this._cellSize;
float dx = cx - x, dz = cz - z;
float dist = dx * dx + dz * dz;
if (dist < bestDist)
{
bestDist = dist;
bestId = (int)VoronoiCells.Hash(cgx, cgz, this._seed);
bestCx = cx;
bestCz = cz;
}
}
return new Cell(bestId, bestCx, bestCz);
}
private static float Jitter(int x, int z, int seed)
=> (VoronoiCells.Hash(x, z, seed) & 0xFFFFFF) / (float)0x1000000; // [0,1)
private static uint Hash(int x, int z, int seed)
{
unchecked
{
uint h = (uint)(x * 374761393 + z * 668265263 + seed * 362437);
h = (h ^ (h >> 13)) * 1274126177u;
return h ^ (h >> 16);
}
}
}