#include "mesh/Mesh.h" #include "mesh/MeshDecimator.h" #include #include using simv::mesh::Mesh; using Catch::Matchers::WithinAbs; TEST_CASE("Mesh::RecalculateBounds finds AABB", "[mesh]") { Mesh m; m.positions = { {-1.0f, -2.0f, -3.0f}, { 4.0f, 5.0f, 6.0f}, { 0.5f, 0.0f, 1.0f}, }; m.RecalculateBounds(); REQUIRE_THAT(m.bboxMin.x, WithinAbs(-1.0f, 1e-6f)); REQUIRE_THAT(m.bboxMin.y, WithinAbs(-2.0f, 1e-6f)); REQUIRE_THAT(m.bboxMin.z, WithinAbs(-3.0f, 1e-6f)); REQUIRE_THAT(m.bboxMax.x, WithinAbs( 4.0f, 1e-6f)); REQUIRE_THAT(m.bboxMax.y, WithinAbs( 5.0f, 1e-6f)); REQUIRE_THAT(m.bboxMax.z, WithinAbs( 6.0f, 1e-6f)); } TEST_CASE("WeldVertices collapses near-duplicate vertices", "[mesh][decimator]") { Mesh m; // Two triangles sharing an edge with verts placed within tolerance. m.positions = { {0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0001f, 0.0f, 0.0f}, // ≈ #0 {1.0001f, 0.0f, 0.0f}, // ≈ #1 {1.0f, 1.0f, 0.0f}, }; m.indices = { 0, 1, 2, 3, 4, 5 }; simv::mesh::WeldVertices(m, /*tolerance=*/0.01f); REQUIRE(m.positions.size() == 4); REQUIRE(m.indices.size() == 6); // both triangles still valid // Bounds should match the "real" hull regardless of welding order. REQUIRE_THAT(m.bboxMax.x, WithinAbs(1.0001f, 1e-3f)); } TEST_CASE("WeldVertices drops degenerate triangles", "[mesh][decimator]") { Mesh m; // One real triangle + a degenerate one (all three verts within tolerance). m.positions = { {0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {2.0f, 2.0f, 0.0f}, {2.00005f, 2.0f, 0.0f}, {2.0f, 2.00005f, 0.0f}, }; m.indices = { 0, 1, 2, 3, 4, 5 }; simv::mesh::WeldVertices(m, /*tolerance=*/0.001f); // The degenerate triangle's three verts collapsed to one — that triangle // should be removed entirely. REQUIRE(m.indices.size() == 3); }