Files
ViewDesignEngine/include/vde/sdf/sdf_tree.h
T
茂之钳 89640cc33b
CI / Build & Test (push) Failing after 37s
CI / Release Build (push) Failing after 37s
fix: SdfNode constructor public for make_shared
2026-07-24 07:10:17 +00:00

141 lines
4.9 KiB
C++

#pragma once
#include "vde/sdf/sdf_primitives.h"
#include "vde/sdf/sdf_operations.h"
#include "vde/core/point.h"
#include <memory>
#include <string>
#include <vector>
namespace vde::sdf {
using core::Point3D;
using core::Vector3D;
// Forward declaration
class SdfNode;
using SdfNodePtr = std::shared_ptr<SdfNode>;
/// All node types in the CSG tree
enum class SdfOp : uint8_t {
// Primitives
Sphere, Box, RoundBox, Torus, Capsule, Cylinder, Cone, Plane,
Ellipsoid, TriangularPrism, HexPrism, Link, Wedge,
// Boolean CSG
Union, Intersection, Difference,
SmoothUnion, SmoothIntersection, SmoothDifference,
// Modifiers
Round, Onion,
// Domain transforms
Repeat, MirrorX, MirrorY, MirrorZ, Translate, Rotate, Scale,
Twist, Bend, Elongate, CheapBend,
// Displacement
Displace
};
/// Parameter payload — one struct to rule them all
struct SdfParams {
// Primitives
double radius = 1.0;
Point3D extents = Point3D(1, 1, 1);
Point3D pt_a = Point3D(0, -1, 0);
Point3D pt_b = Point3D(0, 1, 0);
double major_radius = 1.0;
double minor_radius = 0.3;
double angle_rad = 0.5;
double height = 2.0;
double thickness = 0.1;
Vector3D normal = Vector3D(0, 1, 0);
double offset = 0.0;
// Operations
double blend_k = 0.2;
double amount = 0.5;
double amplitude = 0.1;
double frequency = 1.0;
Point3D repeat_cell = Point3D(2, 2, 2);
Point3D translate_offset = Point3D(0, 0, 0);
Point3D scale_factors = Point3D(1, 1, 1);
};
/// A single node in the SDF expression tree
class SdfNode {
public:
SdfOp op;
SdfParams params;
std::vector<SdfNodePtr> children;
std::string name;
// ── Primitive factories ──
static SdfNodePtr sphere(double r);
static SdfNodePtr box(const Point3D& half_extents);
static SdfNodePtr round_box(const Point3D& half_extents, double r);
static SdfNodePtr cylinder(double r, double h);
static SdfNodePtr torus(double major_r, double minor_r);
static SdfNodePtr capsule(const Point3D& a, const Point3D& b, double r);
static SdfNodePtr cone(double angle_rad, double h);
static SdfNodePtr plane(const Vector3D& normal, double offset);
static SdfNodePtr ellipsoid(const Point3D& radii);
static SdfNodePtr triangular_prism(double h);
static SdfNodePtr hex_prism(double h);
static SdfNodePtr link(double r, double length, double thickness);
static SdfNodePtr wedge(const Point3D& extents);
// ── Boolean CSG factories (two children) ──
static SdfNodePtr op_union(SdfNodePtr a, SdfNodePtr b);
static SdfNodePtr op_intersection(SdfNodePtr a, SdfNodePtr b);
static SdfNodePtr op_difference(SdfNodePtr a, SdfNodePtr b);
static SdfNodePtr smooth_union(SdfNodePtr a, SdfNodePtr b, double k);
static SdfNodePtr smooth_intersection(SdfNodePtr a, SdfNodePtr b, double k);
static SdfNodePtr smooth_difference(SdfNodePtr a, SdfNodePtr b, double k);
// ── Modifier factories (one child) ──
static SdfNodePtr round(SdfNodePtr child, double r);
static SdfNodePtr onion(SdfNodePtr child, double thickness);
// ── Domain transform factories (one child) ──
static SdfNodePtr repeat(SdfNodePtr child, const Point3D& cell);
static SdfNodePtr mirror_x(SdfNodePtr child);
static SdfNodePtr mirror_y(SdfNodePtr child);
static SdfNodePtr mirror_z(SdfNodePtr child);
static SdfNodePtr translate(SdfNodePtr child, const Point3D& offset);
static SdfNodePtr rotate(SdfNodePtr child, double angle_rad);
static SdfNodePtr scale(SdfNodePtr child, const Point3D& factors);
static SdfNodePtr twist(SdfNodePtr child, double amount);
static SdfNodePtr bend(SdfNodePtr child, double amount);
static SdfNodePtr elongate(SdfNodePtr child, const Point3D& h);
static SdfNodePtr cheap_bend(SdfNodePtr child, double amount);
static SdfNodePtr displace(SdfNodePtr child, double amplitude, double frequency);
/// Visit all nodes in the tree (pre-order)
template <typename Fn>
void visit(Fn&& fn) {
fn(*this);
for (auto& c : children) c->visit(std::forward<Fn>(fn));
}
/// Visit all nodes in the tree (const pre-order)
template <typename Fn>
void visit(Fn&& fn) const {
fn(*this);
for (auto& c : children) c->visit(std::forward<Fn>(fn));
}
public:
explicit SdfNode(SdfOp o) : op(o) {}
};
/// Evaluate the SDF tree at a point in world space
/// Returns signed distance: negative = inside, positive = outside
[[nodiscard]] double evaluate(const SdfNodePtr& root, const Point3D& p);
/// Estimate bounding box of the SDF tree
/// Returns the half-extent from center to corner (bounding radius)
[[nodiscard]] Point3D estimate_bounds(const SdfNodePtr& root, double margin = 1.0);
/// Compute full AABB from estimate_bounds result
struct SdfBBox {
Point3D min;
Point3D max;
};
[[nodiscard]] SdfBBox estimate_bbox(const SdfNodePtr& root, double margin = 1.0);
} // namespace vde::sdf