using VoxelEngine.World; 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); } }