Files
ViewDesignEngine/bench/bench_boolean.cpp
T
茂之钳 a516626252
CI / Build & Test (push) Failing after 35s
CI / Release Build (push) Failing after 35s
feat: 性能基准测试套件 — M3 里程碑起步
2026-07-23 23:26:46 +00:00

91 lines
3.1 KiB
C++
Raw 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))), 4);
int seg_u = seg;
int seg_v = seg;
auto sphere_a = brep::make_sphere(1.0, seg_u, seg_v).to_mesh();
auto sphere_b = brep::make_sphere(1.0, seg_u, seg_v).to_mesh();
// 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);