diff --git a/VoxelEngine.Tests/WorldGen/CaveCarverTests.cs b/VoxelEngine.Tests/WorldGen/CaveCarverTests.cs new file mode 100644 index 0000000..e76b893 --- /dev/null +++ b/VoxelEngine.Tests/WorldGen/CaveCarverTests.cs @@ -0,0 +1,38 @@ +using OpenTK.Mathematics; +using VoxelEngine.Core; +using VoxelEngine.World.Blocks; +using VoxelEngine.World.Chunk; +using VoxelEngine.World.WorldGen; +using Xunit; + +namespace VoxelEngine.Tests.WorldGen; + +public class CaveCarverTests +{ + private static readonly BlockRegistry Blocks = new(); + private static readonly Configuration Cfg = new(); + + private static Chunk MakeStoneChunk() + { + Chunk c = new(); + for (int x = 0; x < Chunk.Size; x++) + for (int y = 0; y < Chunk.Size; y++) + for (int z = 0; z < Chunk.Size; z++) + c[x, y, z] = Blocks.Stone.Id; + return c; + } + + [Fact] + public void Carve_IsNoOpOnAirChunk() + { + var carver = new CaveCarver(seed: 42, Blocks, Cfg); + Chunk c = new(); // all-air by default + + carver.Carve(c, new Vector3i(0, 4, 0)); + + for (int x = 0; x < Chunk.Size; x++) + for (int y = 0; y < Chunk.Size; y++) + for (int z = 0; z < Chunk.Size; z++) + Assert.Equal(Blocks.Air.Id, c[x, y, z]); + } +} diff --git a/World/WorldGen/CaveCarver.cs b/World/WorldGen/CaveCarver.cs new file mode 100644 index 0000000..04c8426 --- /dev/null +++ b/World/WorldGen/CaveCarver.cs @@ -0,0 +1,33 @@ +using OpenTK.Mathematics; +using VoxelEngine.Core; +using VoxelEngine.World.Blocks; +using VoxelChunk = VoxelEngine.World.Chunk.Chunk; + +namespace VoxelEngine.World.WorldGen; + +// Carves caves into an already-terrain-filled chunk. Stateless after +// construction; the carve methods are pure functions of (chunk, chunkPos). +// Safe to share across worker threads. +public sealed class CaveCarver +{ + private readonly int _seed; + private readonly BlockRegistry _blocks; + private readonly Configuration _cfg; + private readonly FastNoiseLite _caveNoise; + + public CaveCarver(int seed, BlockRegistry blocks, Configuration cfg) + { + this._seed = seed; + this._blocks = blocks; + this._cfg = cfg; + + this._caveNoise = new FastNoiseLite(seed + 100); + this._caveNoise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2); + this._caveNoise.SetFrequency(cfg.CaveNoiseFrequency); + } + + public void Carve(VoxelChunk chunk, Vector3i chunkPos) + { + // Implemented in Tasks 5 and 6. + } +}