Files

184 lines
6.1 KiB
C++
Raw Permalink Normal View History

#include <gtest/gtest.h>
#include "vde/brep/brep.h"
#include "vde/brep/modeling.h"
#include "vde/brep/incremental_mesh.h"
#include <cmath>
using namespace vde::brep;
using namespace vde::core;
// ═══════════════════════════════════════════════════════════
// Basic Operations
// ═══════════════════════════════════════════════════════════
TEST(IncrementalMeshTest, EmptyMesher) {
IncrementalMesher mesher;
EXPECT_EQ(mesher.dirty_count(), 0);
EXPECT_EQ(mesher.total_faces(), 0);
EXPECT_EQ(mesher.hit_rate(), 0.0);
EXPECT_EQ(mesher.memory_estimate(), 0u);
}
TEST(IncrementalMeshTest, RebuildAll_UnitBox) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
int count = mesher.rebuild_all(box, 0.01);
EXPECT_GT(count, 0);
EXPECT_EQ(mesher.dirty_count(), 0);
}
TEST(IncrementalMeshTest, RebuildAll_Cylinder) {
auto cyl = make_cylinder(2, 6, 32);
IncrementalMesher mesher;
int count = mesher.rebuild_all(cyl);
EXPECT_GT(count, 0);
}
// ═══════════════════════════════════════════════════════════
// Invalidate & Incremental Rebuild
// ═══════════════════════════════════════════════════════════
TEST(IncrementalMeshTest, InvalidateFace_MarksDirty) {
IncrementalMesher mesher;
mesher.invalidate_face(0);
EXPECT_EQ(mesher.dirty_count(), 1);
}
TEST(IncrementalMeshTest, InvalidateFace_ThenRebuild) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
// Full rebuild first
mesher.rebuild_all(box);
// Invalidate one face
mesher.invalidate_face(0);
EXPECT_EQ(mesher.dirty_count(), 1);
// Rebuild only dirty
int count = mesher.rebuild_dirty(box);
EXPECT_GT(count, 0);
EXPECT_EQ(mesher.dirty_count(), 0);
}
TEST(IncrementalMeshTest, RebuildDirty_Empty) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
// No faces marked dirty → rebuild_dirty should do nothing
int count = mesher.rebuild_dirty(box);
EXPECT_EQ(count, 0);
}
TEST(IncrementalMeshTest, MultipleInvalidates) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
mesher.invalidate_face(0);
mesher.invalidate_face(1);
mesher.invalidate_face(0); // duplicate — should still be 2 dirty
EXPECT_EQ(mesher.dirty_count(), 2);
int count = mesher.rebuild_dirty(box);
EXPECT_GE(count, 2);
EXPECT_EQ(mesher.dirty_count(), 0);
}
// ═══════════════════════════════════════════════════════════
// Cache
// ═══════════════════════════════════════════════════════════
TEST(IncrementalMeshTest, GetMesh_AfterRebuild) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
const auto* mesh = mesher.get_mesh(0);
EXPECT_TRUE(mesh != nullptr);
EXPECT_GT(mesher.cache_hits(), 0);
}
TEST(IncrementalMeshTest, GetMesh_AfterInvalidate) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
mesher.invalidate_face(0);
const auto* mesh = mesher.get_mesh(0);
EXPECT_TRUE(mesh == nullptr); // dirty face → cache miss
EXPECT_GT(mesher.cache_misses(), 0);
}
TEST(IncrementalMeshTest, GetMesh_InvalidFaceId) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
const auto* mesh = mesher.get_mesh(999);
EXPECT_TRUE(mesh == nullptr);
}
TEST(IncrementalMeshTest, HitRate_AfterRebuild) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
// Access a cached mesh → hit
mesher.get_mesh(0);
EXPECT_GT(mesher.hit_rate(), 0.0);
}
// ═══════════════════════════════════════════════════════════
// Merged Mesh
// ═══════════════════════════════════════════════════════════
TEST(IncrementalMeshTest, MergedMesh_AfterFullRebuild) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
auto merged = mesher.merged_mesh();
EXPECT_GT(merged.num_vertices(), 0u);
EXPECT_GT(merged.num_faces(), 0u);
}
TEST(IncrementalMeshTest, MergedMesh_AfterPartialInvalidate) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
// Invalidate one face → merged mesh should miss it
mesher.invalidate_face(0);
auto merged = mesher.merged_mesh();
// Still should produce a valid (but partial) mesh
EXPECT_GE(merged.num_vertices(), 0u);
}
// ═══════════════════════════════════════════════════════════
// Clear & Memory
// ═══════════════════════════════════════════════════════════
TEST(IncrementalMeshTest, ClearAll) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
EXPECT_GT(mesher.total_faces(), 0);
mesher.clear_all();
EXPECT_EQ(mesher.total_faces(), 0);
EXPECT_EQ(mesher.dirty_count(), 0);
EXPECT_EQ(mesher.hit_rate(), 0.0);
}
TEST(IncrementalMeshTest, MemoryEstimate) {
auto box = make_box(2, 2, 2);
IncrementalMesher mesher;
mesher.rebuild_all(box);
size_t mem = mesher.memory_estimate();
EXPECT_GT(mem, 0u);
}