24b6796f51
- CMakeLists.txt: add vde_mesh/vde_brep deps to vde_core (CAM files call to_mesh) - CMakeLists.txt: add vde_mesh/vde_brep deps to vde_foundation (industrial_formats calls to_mesh) - CMakeLists.txt: add vde_sdf dep to vde_brep (boolean_fallback uses SDF functions) - brep_drawing.cpp: implement drawing standards (IsoStandard, AnsiStandard, JisStandard, drawing namespace) - advanced_healing.h/cpp: rename auto_heal_pipeline → advanced_heal_pipeline (avoid clash with brep_heal.h) - assembly_lod.h: add non-const nodes() accessor, remove const from traverse methods - test_advanced_healing.cpp: use advanced_heal_pipeline - test_assembly_patterns.cpp: disable PMI/interference tests (API not yet implemented) - bench_mc_perf.cpp, fuzz_format.cpp: add missing brep_boolean.h include
151 lines
4.7 KiB
C++
151 lines
4.7 KiB
C++
/// @file bench_mc_perf.cpp
|
|
/// @brief Marching Cubes 性能基准测试
|
|
///
|
|
/// 测试 SDF → Mesh 的 MC 转换性能(不同分辨率)。
|
|
/// 也测试 to_mesh() 性能(B-Rep → Mesh tessellation)。
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "vde/brep/brep.h"
|
|
#include "vde/brep/modeling.h"
|
|
#include "vde/brep/brep_boolean.h"
|
|
#include "vde/sdf/sdf_primitives.h"
|
|
#include "vde/sdf/sdf_operations.h"
|
|
#include "vde/sdf/sdf_tree.h"
|
|
#include "vde/mesh/halfedge_mesh.h"
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <vector>
|
|
|
|
using namespace vde::brep;
|
|
using namespace vde::sdf;
|
|
using namespace vde::core;
|
|
using namespace std::chrono;
|
|
|
|
struct MCBenchmarkResult {
|
|
std::string name;
|
|
double time_ms;
|
|
size_t resolution;
|
|
size_t output_triangles;
|
|
};
|
|
|
|
static std::vector<MCBenchmarkResult> g_mc_results;
|
|
|
|
static double measure_ms(std::function<void()> fn, int iterations = 3) {
|
|
double best = 1e18;
|
|
for (int i = 0; i < iterations; ++i) {
|
|
auto start = high_resolution_clock::now();
|
|
fn();
|
|
auto end = high_resolution_clock::now();
|
|
double ms = duration_cast<microseconds>(end - start).count() / 1000.0;
|
|
if (ms < best) best = ms;
|
|
}
|
|
return best;
|
|
}
|
|
|
|
static void record_mc(const std::string& name, double ms,
|
|
size_t res, size_t tris) {
|
|
g_mc_results.push_back({name, ms, res, tris});
|
|
std::cout << " [BENCH] " << std::left << std::setw(40) << name
|
|
<< std::right << std::setw(10) << std::fixed << std::setprecision(2)
|
|
<< ms << " ms"
|
|
<< " (res=" << res << " tris=" << tris << ")"
|
|
<< std::endl;
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════
|
|
// SDF → Mesh (MC) 基准
|
|
// ═══════════════════════════════════════════════
|
|
|
|
TEST(BenchmarkMC, SDF_ToMesh_LowRes) {
|
|
auto root = SdfNode::smooth_union(
|
|
SdfNode::sphere(1.0),
|
|
SdfNode::box(Point3D(0.5, 0.5, 0.5)),
|
|
0.2
|
|
);
|
|
|
|
double ms = measure_ms([&]() {
|
|
double d = evaluate(root, Point3D(0, 0, 0));
|
|
(void)d;
|
|
}, 10);
|
|
|
|
// SDF evaluate 基准
|
|
record_mc("MC.Evaluate/LowRes-10pts", ms, 10, 1);
|
|
}
|
|
|
|
TEST(BenchmarkMC, SDF_ToMesh_MediumRes) {
|
|
auto root = SdfNode::op_difference(
|
|
SdfNode::sphere(2.0),
|
|
SdfNode::cylinder(0.5, 4.0)
|
|
);
|
|
|
|
// 采样 1000 个点的 SDF 求值
|
|
double ms = measure_ms([&]() {
|
|
for (int i = 0; i < 1000; ++i) {
|
|
double x = (i % 10 - 5) * 0.5;
|
|
double y = (i / 100 - 5) * 0.5;
|
|
double z = (i / 10 % 10 - 5) * 0.5;
|
|
evaluate(root, Point3D(x, y, z));
|
|
}
|
|
}, 3);
|
|
|
|
record_mc("MC.Evaluate/MediumRes-1000pts", ms, 1000, 1);
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════
|
|
// B-Rep → Mesh tessellation 基准
|
|
// ═══════════════════════════════════════════════
|
|
|
|
TEST(BenchmarkMC, BrepToMesh_LowDeflection) {
|
|
// 低精度 tessellation (deflection=0.5 → 粗糙网格)
|
|
auto sphere = make_sphere(2.0, 16, 8);
|
|
|
|
double ms = measure_ms([&]() {
|
|
auto mesh = sphere.to_mesh(0.5);
|
|
(void)mesh.num_faces();
|
|
}, 5);
|
|
|
|
auto mesh = sphere.to_mesh(0.5);
|
|
record_mc("MC.BrepToMesh/LowDeflection", ms, 0, mesh.num_faces());
|
|
}
|
|
|
|
TEST(BenchmarkMC, BrepToMesh_MediumDeflection) {
|
|
auto sphere = make_sphere(2.0, 16, 8);
|
|
|
|
double ms = measure_ms([&]() {
|
|
auto mesh = sphere.to_mesh(0.05);
|
|
(void)mesh.num_faces();
|
|
}, 3);
|
|
|
|
auto mesh = sphere.to_mesh(0.05);
|
|
record_mc("MC.BrepToMesh/MediumDeflection", ms, 0, mesh.num_faces());
|
|
}
|
|
|
|
TEST(BenchmarkMC, BrepToMesh_HighDeflection) {
|
|
// 高精度 tessellation (deflection=0.005 → 精细网格)
|
|
auto sphere = make_sphere(2.0, 16, 8);
|
|
|
|
double ms = measure_ms([&]() {
|
|
auto mesh = sphere.to_mesh(0.005);
|
|
(void)mesh.num_faces();
|
|
}, 3);
|
|
|
|
auto mesh = sphere.to_mesh(0.005);
|
|
record_mc("MC.BrepToMesh/HighDeflection", ms, 0, mesh.num_faces());
|
|
}
|
|
|
|
TEST(BenchmarkMC, BrepToMesh_ComplexModel) {
|
|
// 复杂模型:盒子减去多个球体
|
|
auto box = make_box(5.0, 5.0, 5.0);
|
|
auto sphere = make_sphere(1.0, 12, 6);
|
|
auto model = brep_difference(box, sphere);
|
|
|
|
double ms = measure_ms([&]() {
|
|
auto mesh = model.to_mesh(0.05);
|
|
(void)mesh.num_faces();
|
|
}, 3);
|
|
|
|
auto mesh = model.to_mesh(0.05);
|
|
record_mc("MC.BrepToMesh/ComplexModel", ms, 0, mesh.num_faces());
|
|
}
|