Files
VoxelEngine/VoxelEngine.Tests/ChunkMesherTests.cs
MDietermann 49d35cab5b feat: add multi-chunk world with cross-chunk face culling
Add a World that stores chunks in a Dictionary keyed by chunk
coordinate, with floor-division world<->chunk coordinate mapping
(correct for negative coords). The mesher takes an optional neighbor
sampler so faces at chunk borders are culled against adjacent chunks
instead of always meshing the shell. Render one ChunkRenderer per
chunk, placed via the model matrix. Reorganize the World layer into
Blocks/ and Chunk/ sub-namespaces.
2026-05-28 15:32:45 +02:00

62 lines
1.8 KiB
C#

using VoxelEngine.World;
using VoxelEngine.World.Blocks;
using VoxelEngine.World.Chunk;
using Xunit;
namespace VoxelEngine.Tests;
public class ChunkMesherTests
{
private const int FloatsPerVertex = 6; // pos.xyz, uv, shade
private const int VerticesPerFace = 6; // quad = 2 triangles
private const int FloatsPerFace = FloatsPerVertex * VerticesPerFace; // 36
private static int FaceCount(float[] mesh) => mesh.Length / FloatsPerFace;
[Fact]
public void EmptyChunk_ProducesNoFaces()
{
var mesh = new ChunkMesher().Build(new Chunk(), new BlockRegistry());
Assert.Empty(mesh);
}
[Fact]
public void SingleBlockSurroundedByAir_Produces6Faces()
{
var chunk = new Chunk();
chunk[8, 8, 8] = 1; // stone
var mesh = new ChunkMesher().Build(chunk, new BlockRegistry());
Assert.Equal(6, FaceCount(mesh));
}
[Fact]
public void FullySolidChunk_ProducesOnlyOuterShell()
{
var chunk = new Chunk();
for (int x = 0; x < Chunk.Size; x++)
for (int y = 0; y < Chunk.Size; y++)
for (int z = 0; z < Chunk.Size; z++)
chunk[x, y, z] = 1; // stone
var mesh = new ChunkMesher().Build(chunk, new BlockRegistry());
// 6 sides * 16 * 16 visible faces
Assert.Equal(6 * Chunk.Size * Chunk.Size, FaceCount(mesh));
}
[Fact]
public void SingleBlock_EmitsExactInterleavedFloatCount()
{
var chunk = new Chunk();
chunk[0, 0, 0] = 1; // corner block: all 6 neighbors are air/out-of-bounds -> 6 faces
var mesh = new ChunkMesher().Build(chunk, new BlockRegistry());
// Pins the layout: 6 faces * 6 vertices/face * 6 floats/vertex.
Assert.Equal(6 * VerticesPerFace * FloatsPerVertex, mesh.Length);
Assert.Equal(0, mesh.Length % FloatsPerVertex);
}
}