Files
voxelforge/tests/testLitMesh.cpp
T

84 lines
2.8 KiB
C++

#include "testHarness.h"
#include "vf/LitMesh.h"
using namespace vf;
namespace {
LightField lightFor(const World& world) {
return computeLight(world, {0, 0, 0}, {chunkSize, chunkSize, chunkSize});
}
float minAo(const Mesh& mesh) {
float lo = 1.0f;
for (const Vertex& v : mesh.vertices) lo = v.ao < lo ? v.ao : lo;
return lo;
}
// Average light of the top face of the block at (5,5,5): its four vertices sit
// at y = 6 with an upward normal. Isolating it ignores the roof's own lit faces.
float coveredBlockTopLight(const Mesh& mesh) {
float sum = 0.0f;
int n = 0;
for (const Vertex& v : mesh.vertices) {
if (std::fabs(v.py - 6.0f) < 1e-3f && v.ny > 0.5f) {
sum += v.light;
++n;
}
}
return n > 0 ? sum / static_cast<float>(n) : -1.0f;
}
bool hasTile(const Mesh& mesh, int tile) {
for (const Vertex& v : mesh.vertices)
if (static_cast<int>(v.tile) == tile) return true;
return false;
}
} // namespace
VF_TEST(litIsolatedBlockHasSixUnoccludedFaces) {
World world;
world.setBlock(5, 5, 5, Block::Stone);
ChunkMesh mesh = meshChunkLit(world, {0, 0, 0}, lightFor(world));
CHECK_EQ(mesh.opaque.quadCount(), static_cast<std::size_t>(6));
CHECK(mesh.transparent.empty());
CHECK_NEAR(minAo(mesh.opaque), 1.0f, 1e-4f); // nothing occludes an isolated block
}
VF_TEST(litInnerCornerDarkensVertex) {
World world;
world.setBlock(5, 5, 5, Block::Stone);
world.setBlock(6, 6, 5, Block::Stone); // occludes one edge of the top face
world.setBlock(5, 6, 6, Block::Stone); // occludes the other edge
ChunkMesh mesh = meshChunkLit(world, {0, 0, 0}, lightFor(world));
CHECK_NEAR(minAo(mesh.opaque), 0.0f, 1e-4f); // both sides set -> AO 0 at that corner
}
VF_TEST(litTopIsBrightRoofIsNot) {
World open;
open.setBlock(5, 5, 5, Block::Stone);
ChunkMesh openMesh = meshChunkLit(open, {0, 0, 0}, lightFor(open));
CHECK(coveredBlockTopLight(openMesh.opaque) > 0.99f); // top face sees open sky
World roofed;
roofed.setBlock(5, 5, 5, Block::Stone);
for (int x = 3; x <= 7; ++x)
for (int z = 3; z <= 7; ++z)
roofed.setBlock(x, 8, z, Block::Stone);
ChunkMesh roofedMesh = meshChunkLit(roofed, {0, 0, 0}, lightFor(roofed));
CHECK(coveredBlockTopLight(roofedMesh.opaque) < 0.99f); // roof shadows this face
}
VF_TEST(litWaterGoesToTransparentPass) {
World world;
world.setBlock(2, 2, 2, Block::Stone);
world.setBlock(5, 5, 5, Block::Water);
ChunkMesh mesh = meshChunkLit(world, {0, 0, 0}, lightFor(world));
CHECK(!mesh.opaque.empty());
CHECK(!mesh.transparent.empty());
CHECK(hasTile(mesh.opaque, faceTile(Block::Stone, Face::PosY)));
CHECK(hasTile(mesh.transparent, faceTile(Block::Water, Face::PosY)));
CHECK(!hasTile(mesh.opaque, faceTile(Block::Water, Face::PosY)));
}