08b5854c56
Add batch evaluation/gradient functions for SDF trees (sdf_torch.h/cpp). Add sdf_gradient.h with finite-difference gradient utilities. Add Python modules vde.sdf (high-level SDF API) and vde.torch_sdf (PyTorch autograd). Add test_sdf_torch_bridge.cpp with batch eval/gradient tests. Integrate into vde_sdf library and test suite.
133 lines
3.8 KiB
Python
133 lines
3.8 KiB
Python
"""
|
|
vde.sdf — Implicit Modeling & Differentiable Geometry
|
|
|
|
Usage:
|
|
from vde.sdf import Sphere, Box, Union, evaluate, to_mesh
|
|
|
|
s = Sphere(1.0)
|
|
b = Box([0.5, 0.5, 0.5])
|
|
u = Union(s, b)
|
|
|
|
d = evaluate(u, [0.5, 0, 0])
|
|
mesh = to_mesh(u, resolution=64)
|
|
"""
|
|
import numpy as np
|
|
|
|
# Re-export C++ bindings
|
|
from vde._vde import (
|
|
SdfNode, SdfOp, SdfParams, MCMesh, SdfBBox,
|
|
evaluate, sdf_to_mesh, sdf_to_mesh_lambda,
|
|
estimate_bounds, estimate_bbox,
|
|
)
|
|
|
|
# ── Convenience constructors ──────────────────────
|
|
|
|
def sphere(radius=1.0):
|
|
"""Create a sphere SDF node."""
|
|
return SdfNode.sphere(radius)
|
|
|
|
def box(half_extents):
|
|
"""Create a box SDF node.
|
|
Args:
|
|
half_extents: [hx, hy, hz] half-size in each dimension
|
|
"""
|
|
return SdfNode.box(half_extents)
|
|
|
|
def cylinder(radius=1.0, height=2.0):
|
|
"""Create a cylinder SDF node."""
|
|
return SdfNode.cylinder(radius, height)
|
|
|
|
def torus(major_radius=1.0, minor_radius=0.3):
|
|
"""Create a torus SDF node."""
|
|
return SdfNode.torus(major_radius, minor_radius)
|
|
|
|
def capsule(a, b, radius=0.5):
|
|
"""Create a capsule SDF node between points a and b."""
|
|
return SdfNode.capsule(a, b, radius)
|
|
|
|
def cone(angle=0.5, height=2.0):
|
|
"""Create a cone SDF node."""
|
|
return SdfNode.cone(angle, height)
|
|
|
|
def plane(normal, offset=0.0):
|
|
"""Create a plane SDF node."""
|
|
return SdfNode.plane(normal, offset)
|
|
|
|
def ellipsoid(radii):
|
|
"""Create an ellipsoid SDF node."""
|
|
return SdfNode.ellipsoid(radii)
|
|
|
|
# ── CSG Operations ────────────────────────────────
|
|
|
|
def union(a, b):
|
|
"""Union of two SDF nodes (min)."""
|
|
return SdfNode.op_union(a, b)
|
|
|
|
def intersection(a, b):
|
|
"""Intersection of two SDF nodes (max)."""
|
|
return SdfNode.op_intersection(a, b)
|
|
|
|
def difference(a, b):
|
|
"""Difference: subtract b from a."""
|
|
return SdfNode.op_difference(a, b)
|
|
|
|
def smooth_union(a, b, k=0.1):
|
|
"""Smooth union with blend radius k."""
|
|
return SdfNode.smooth_union(a, b, k)
|
|
|
|
def smooth_intersection(a, b, k=0.1):
|
|
"""Smooth intersection with blend radius k."""
|
|
return SdfNode.smooth_intersection(a, b, k)
|
|
|
|
def smooth_difference(a, b, k=0.1):
|
|
"""Smooth difference with blend radius k."""
|
|
return SdfNode.smooth_difference(a, b, k)
|
|
|
|
# ── Modifiers ─────────────────────────────────────
|
|
|
|
def round_shape(node, r=0.1):
|
|
"""Round (fatten) a shape."""
|
|
return SdfNode.round(node, r)
|
|
|
|
def onion(node, thickness=0.1):
|
|
"""Create a thin shell."""
|
|
return SdfNode.onion(node, thickness)
|
|
|
|
# ── Domain Transforms ─────────────────────────────
|
|
|
|
def translate(node, offset):
|
|
"""Translate a shape."""
|
|
return SdfNode.translate(node, offset)
|
|
|
|
def rotate(node, angle):
|
|
"""Rotate around Y axis (radians)."""
|
|
return SdfNode.rotate(node, angle)
|
|
|
|
def scale(node, factors):
|
|
"""Non-uniform scale."""
|
|
return SdfNode.scale(node, factors)
|
|
|
|
def repeat(node, cell):
|
|
"""Infinite repeat."""
|
|
return SdfNode.repeat(node, cell)
|
|
|
|
def twist(node, amount):
|
|
"""Twist around Y axis."""
|
|
return SdfNode.twist(node, amount)
|
|
|
|
def bend(node, amount):
|
|
"""Bend deformation."""
|
|
return SdfNode.bend(node, amount)
|
|
|
|
# ── Mesh Conversion ───────────────────────────────
|
|
|
|
def to_mesh(node, resolution=64, level=0.0):
|
|
"""Convert SDF tree to triangle mesh.
|
|
Returns: MCMesh with .vertices and .triangles (both numpy arrays)
|
|
"""
|
|
return sdf_to_mesh(node, resolution, level)
|
|
|
|
def to_mesh_lambda(fn, bmin, bmax, resolution=64, level=0.0):
|
|
"""Convert lambda SDF to mesh."""
|
|
return sdf_to_mesh_lambda(fn, bmin, bmax, resolution, level)
|