84 lines
2.7 KiB
C#
84 lines
2.7 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(128, 128).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(128, 128).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(128, 128).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(128, 128).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);
|
|
}
|
|
|
|
[Fact]
|
|
public void Mesher_UsesAtlasDimensions_ForTileSize()
|
|
{
|
|
var chunk = new Chunk();
|
|
chunk[0, 0, 0] = 1; // stone, tile (1,0)
|
|
|
|
// 128px atlas, 32px tiles => 4x4 grid, normalized tile size 0.25.
|
|
var mesh = new ChunkMesher(128, 128).Build(chunk, new BlockRegistry());
|
|
|
|
// Gather all U coords (offset 3) and V coords (offset 4); each must be a
|
|
// multiple of 0.25 within [0,1].
|
|
for (int i = 0; i < mesh.Length; i += 6)
|
|
{
|
|
float u = mesh[i + 3];
|
|
float v = mesh[i + 4];
|
|
Assert.InRange(u, 0f, 1f);
|
|
Assert.InRange(v, 0f, 1f);
|
|
Assert.True(System.Math.Abs(u * 4f - System.MathF.Round(u * 4f)) < 1e-4f, $"u={u} not on 0.25 grid");
|
|
Assert.True(System.Math.Abs(v * 4f - System.MathF.Round(v * 4f)) < 1e-4f, $"v={v} not on 0.25 grid");
|
|
}
|
|
}
|
|
}
|