Files
茂之钳 1d35046cf8
CI / Build & Test (push) Failing after 16m51s
CI / Release Build (push) Failing after 24s
fix: boolean benchmark 传入 to_mesh(deflection=0.5) 避免 OOM + 重新启用
2026-07-24 03:02:49 +00:00

93 lines
3.3 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// bench_boolean.cpp — 3D mesh boolean operation benchmarks
///
/// Metrics:
/// MeshBoolean_Union/N{faces} — sphere sphere
/// MeshBoolean_Intersection/N{faces} — sphere ∩ sphere
///
/// Two spheres (radius 1.0, separated by 0.5 along X) are generated via BrepModel,
/// discretized to HalfedgeMesh with controlled segment counts, then passed to
/// mesh_boolean().
#include <benchmark/benchmark.h>
#include <vde/brep/brep.h>
#include <vde/brep/modeling.h>
#include <vde/mesh/mesh_boolean.h>
#include <vde/mesh/halfedge_mesh.h>
#include <cmath>
using namespace vde;
namespace {
struct SpherePair {
mesh::HalfedgeMesh a;
mesh::HalfedgeMesh b;
};
/// Create two intersecting spheres with approximately `face_count` faces each.
/// sphere_a at origin, sphere_b translated by +1.0 along X (overlap ~0.5)
SpherePair make_sphere_pair(int face_count) {
// make_sphere produces ~ 2 * seg_u * seg_v faces → solve for seg
int seg = std::max(static_cast<int>(std::ceil(std::sqrt(face_count / 2.0))), 3);
// Use deflection to control tessellation density per face
// Each NURBS face tessellates res×res quads where res = max(4, 1/deflection)
// For benchmark we want coarse tessellation: deflection = 0.5 → res=4
double deflection = 0.5;
auto sphere_a = brep::make_sphere(1.0, seg, seg).to_mesh(deflection);
auto sphere_b = brep::make_sphere(1.0, seg, seg).to_mesh(deflection);
// Translate sphere_b by +1.0 along X so they overlap by ~0.5
// Rebuild from triangles with translated vertices
mesh::HalfedgeMesh b_moved;
std::vector<core::Point3D> all_verts;
std::vector<std::array<int, 3>> all_tris;
for (size_t fi = 0; fi < sphere_b.num_faces(); ++fi) {
auto fv = sphere_b.face_vertices(static_cast<int>(fi));
if (fv.size() < 3) continue;
int base = static_cast<int>(all_verts.size());
for (int vi : fv) {
auto p = sphere_b.vertex(vi);
all_verts.push_back(core::Point3D(p.x() + 1.0, p.y(), p.z()));
}
// triangulate if > 3
for (size_t j = 1; j + 1 < fv.size(); ++j)
all_tris.push_back({base, base + static_cast<int>(j), base + static_cast<int>(j + 1)});
}
b_moved.build_from_triangles(all_verts, all_tris);
return {sphere_a, b_moved};
}
} // namespace
class MeshBooleanFixture : public benchmark::Fixture {
public:
void SetUp(const benchmark::State& state) override {
auto pair = make_sphere_pair(state.range(0));
mesh_a = std::move(pair.a);
mesh_b = std::move(pair.b);
}
mesh::HalfedgeMesh mesh_a;
mesh::HalfedgeMesh mesh_b;
};
BENCHMARK_DEFINE_F(MeshBooleanFixture, Union)(benchmark::State& state) {
for (auto _ : state) {
auto result = mesh::mesh_boolean(mesh_a, mesh_b, mesh::BooleanOp::Union);
benchmark::DoNotOptimize(result.num_faces());
}
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(MeshBooleanFixture, Union)->Arg(100)->Arg(500);
BENCHMARK_DEFINE_F(MeshBooleanFixture, Intersection)(benchmark::State& state) {
for (auto _ : state) {
auto result = mesh::mesh_boolean(mesh_a, mesh_b, mesh::BooleanOp::Intersection);
benchmark::DoNotOptimize(result.num_faces());
}
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(MeshBooleanFixture, Intersection)->Arg(100)->Arg(500);