#[allow(unused_imports)]
use super::functions::*;
#[derive(Debug, Clone)]
pub struct SdfSmoothIntersection<A, B> {
pub a: A,
pub b: B,
pub k: f64,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfSmoothIntersection<A, B> {
pub fn new(a: A, b: B, k: f64) -> Self {
Self { a, b, k }
}
}
#[derive(Debug, Clone)]
pub struct SdfSmoothUnion<A, B> {
pub a: A,
pub b: B,
pub k: f64,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfSmoothUnion<A, B> {
pub fn new(a: A, b: B, k: f64) -> Self {
Self { a, b, k }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfHexagonalPrism {
pub radius: f64,
pub half_height: f64,
}
#[allow(dead_code)]
impl SdfHexagonalPrism {
pub fn new(radius: f64, half_height: f64) -> Self {
Self {
radius,
half_height,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BoolOp {
Union,
Intersection,
Difference,
SmoothUnion,
SmoothIntersection,
SmoothDifference,
}
#[derive(Debug, Clone, Copy)]
pub struct ContactPoint {
pub position: [f64; 3],
pub normal: [f64; 3],
pub depth: f64,
}
#[derive(Debug, Clone)]
pub struct SdfTranslate<S> {
pub inner: S,
pub offset: [f64; 3],
}
#[allow(dead_code)]
impl<S: Sdf> SdfTranslate<S> {
pub fn new(inner: S, offset: [f64; 3]) -> Self {
Self { inner, offset }
}
}
#[derive(Debug, Clone)]
pub struct SdfRepeat<S> {
pub inner: S,
pub period_x: f64,
pub period_y: f64,
pub period_z: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfRepeat<S> {
pub fn new(inner: S, period_x: f64, period_y: f64, period_z: f64) -> Self {
Self {
inner,
period_x,
period_y,
period_z,
}
}
}
#[derive(Debug, Clone)]
pub struct SdfScale<S> {
pub inner: S,
pub factor: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfScale<S> {
pub fn new(inner: S, factor: f64) -> Self {
Self { inner, factor }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfTorus {
pub major: f64,
pub minor: f64,
}
#[allow(dead_code)]
impl SdfTorus {
pub fn new(major: f64, minor: f64) -> Self {
Self { major, minor }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfPlane {
pub normal: [f64; 3],
pub offset: f64,
}
#[allow(dead_code)]
impl SdfPlane {
pub fn new(normal: [f64; 3], offset: f64) -> Self {
Self {
normal: norm(normal),
offset,
}
}
}
#[derive(Debug, Clone)]
pub struct SdfSmoothDifference<A, B> {
pub a: A,
pub b: B,
pub k: f64,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfSmoothDifference<A, B> {
pub fn new(a: A, b: B, k: f64) -> Self {
Self { a, b, k }
}
}
#[derive(Debug, Clone)]
pub struct SdfTwist<S> {
pub inner: S,
pub strength: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfTwist<S> {
pub fn new(inner: S, strength: f64) -> Self {
Self { inner, strength }
}
}
#[derive(Debug, Clone)]
pub struct SdfGrid {
pub nx: usize,
pub ny: usize,
pub nz: usize,
pub origin: [f64; 3],
pub spacing: f64,
pub data: Vec<f64>,
}
#[allow(dead_code)]
impl SdfGrid {
pub fn new(nx: usize, ny: usize, nz: usize, origin: [f64; 3], spacing: f64) -> Self {
Self {
nx,
ny,
nz,
origin,
spacing,
data: vec![f64::INFINITY; nx * ny * nz],
}
}
pub fn from_sdf<S: Sdf>(
sdf: &S,
nx: usize,
ny: usize,
nz: usize,
origin: [f64; 3],
spacing: f64,
) -> Self {
let mut grid = Self::new(nx, ny, nz, origin, spacing);
for iz in 0..nz {
for iy in 0..ny {
for ix in 0..nx {
let p = grid.cell_center(ix, iy, iz);
grid.data[iz * ny * nx + iy * nx + ix] = sdf.dist(p);
}
}
}
grid
}
pub fn cell_center(&self, ix: usize, iy: usize, iz: usize) -> [f64; 3] {
[
self.origin[0] + ix as f64 * self.spacing,
self.origin[1] + iy as f64 * self.spacing,
self.origin[2] + iz as f64 * self.spacing,
]
}
pub fn get(&self, ix: usize, iy: usize, iz: usize) -> f64 {
self.data[iz * self.ny * self.nx + iy * self.nx + ix]
}
pub fn set(&mut self, ix: usize, iy: usize, iz: usize, v: f64) {
self.data[iz * self.ny * self.nx + iy * self.nx + ix] = v;
}
pub fn interpolate(&self, p: [f64; 3]) -> f64 {
let fx = (p[0] - self.origin[0]) / self.spacing;
let fy = (p[1] - self.origin[1]) / self.spacing;
let fz = (p[2] - self.origin[2]) / self.spacing;
let ix = (fx as usize).min(self.nx.saturating_sub(2));
let iy = (fy as usize).min(self.ny.saturating_sub(2));
let iz = (fz as usize).min(self.nz.saturating_sub(2));
let tx = (fx - ix as f64).clamp(0.0, 1.0);
let ty = (fy - iy as f64).clamp(0.0, 1.0);
let tz = (fz - iz as f64).clamp(0.0, 1.0);
let v000 = self.get(ix, iy, iz);
let v100 = self.get(ix + 1, iy, iz);
let v010 = self.get(ix, iy + 1, iz);
let v110 = self.get(ix + 1, iy + 1, iz);
let v001 = self.get(ix, iy, iz + 1);
let v101 = self.get(ix + 1, iy, iz + 1);
let v011 = self.get(ix, iy + 1, iz + 1);
let v111 = self.get(ix + 1, iy + 1, iz + 1);
let c00 = v000 * (1.0 - tx) + v100 * tx;
let c10 = v010 * (1.0 - tx) + v110 * tx;
let c01 = v001 * (1.0 - tx) + v101 * tx;
let c11 = v011 * (1.0 - tx) + v111 * tx;
let c0 = c00 * (1.0 - ty) + c10 * ty;
let c1 = c01 * (1.0 - ty) + c11 * ty;
c0 * (1.0 - tz) + c1 * tz
}
pub fn dilate(&mut self, delta: f64) {
for v in self.data.iter_mut() {
*v -= delta;
}
}
pub fn erode(&mut self, delta: f64) {
for v in self.data.iter_mut() {
*v += delta;
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfRoundedCylinder {
pub radius: f64,
pub half_height: f64,
pub rounding: f64,
}
#[allow(dead_code)]
impl SdfRoundedCylinder {
pub fn new(radius: f64, half_height: f64, rounding: f64) -> Self {
Self {
radius,
half_height,
rounding,
}
}
}
#[derive(Debug, Clone)]
pub struct SdfIntersection<A, B> {
pub a: A,
pub b: B,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfIntersection<A, B> {
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
}
pub struct SdfExtrude<F> {
pub profile: F,
pub half_height: f64,
}
#[allow(dead_code)]
impl<F: Fn([f64; 2]) -> f64 + Send + Sync> SdfExtrude<F> {
pub fn new(profile: F, half_height: f64) -> Self {
Self {
profile,
half_height,
}
}
}
pub struct SdfRevolution<F> {
pub profile: F,
}
#[allow(dead_code)]
impl<F: Fn(f64, f64) -> f64 + Send + Sync> SdfRevolution<F> {
pub fn new(profile: F) -> Self {
Self { profile }
}
}
#[derive(Debug, Clone)]
pub struct SdfUnion<A, B> {
pub a: A,
pub b: B,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfUnion<A, B> {
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfCone {
pub half_angle: f64,
pub height: f64,
}
#[allow(dead_code)]
impl SdfCone {
pub fn new(half_angle: f64, height: f64) -> Self {
Self { half_angle, height }
}
}
#[derive(Debug, Clone)]
pub struct SdfOffset<S> {
pub inner: S,
pub offset: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfOffset<S> {
pub fn new(inner: S, offset: f64) -> Self {
Self { inner, offset }
}
}
#[derive(Debug, Clone, Default)]
pub struct IsoMeshResult {
pub triangles: Vec<Triangle>,
pub vertex_count: usize,
}
#[derive(Debug, Clone, Copy)]
pub struct SdfPyramid {
pub half_base: f64,
pub height: f64,
}
#[allow(dead_code)]
impl SdfPyramid {
pub fn new(half_base: f64, height: f64) -> Self {
Self { half_base, height }
}
}
#[derive(Debug, Clone)]
pub struct SdfDifference<A, B> {
pub a: A,
pub b: B,
}
#[allow(dead_code)]
impl<A: Sdf, B: Sdf> SdfDifference<A, B> {
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
}
#[derive(Debug, Clone)]
pub struct SdfNoiseDisplace<S> {
pub inner: S,
pub noise_scale: f64,
pub amplitude: f64,
pub octaves: u32,
}
#[allow(dead_code)]
impl<S: Sdf> SdfNoiseDisplace<S> {
pub fn new(inner: S, noise_scale: f64, amplitude: f64, octaves: u32) -> Self {
Self {
inner,
noise_scale,
amplitude,
octaves,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfEllipsoid {
pub radii: [f64; 3],
}
#[allow(dead_code)]
impl SdfEllipsoid {
pub fn new(rx: f64, ry: f64, rz: f64) -> Self {
Self {
radii: [rx, ry, rz],
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Triangle {
pub v0: [f64; 3],
pub v1: [f64; 3],
pub v2: [f64; 3],
}
impl Triangle {
pub fn normal(&self) -> [f64; 3] {
cross(sub(self.v1, self.v0), sub(self.v2, self.v0))
}
}
pub enum SdfNode {
Leaf(Box<dyn Sdf>),
Binary {
op: BoolOp,
left: Box<SdfNode>,
right: Box<SdfNode>,
k: f64,
},
}
#[allow(dead_code)]
impl SdfNode {
pub fn leaf<S: Sdf + 'static>(s: S) -> Self {
Self::Leaf(Box::new(s))
}
pub fn combine(op: BoolOp, left: Self, right: Self, k: f64) -> Self {
Self::Binary {
op,
left: Box::new(left),
right: Box::new(right),
k,
}
}
pub fn eval(&self, p: [f64; 3]) -> f64 {
match self {
Self::Leaf(s) => s.dist(p),
Self::Binary { op, left, right, k } => {
let a = left.eval(p);
let b = right.eval(p);
match op {
BoolOp::Union => a.min(b),
BoolOp::Intersection => a.max(b),
BoolOp::Difference => a.max(-b),
BoolOp::SmoothUnion => sdf_smooth_union(a, b, *k),
BoolOp::SmoothIntersection => sdf_smooth_intersection(a, b, *k),
BoolOp::SmoothDifference => sdf_smooth_difference(a, b, *k),
}
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfTriangularPrism {
pub side: f64,
pub half_height: f64,
}
#[allow(dead_code)]
impl SdfTriangularPrism {
pub fn new(side: f64, half_height: f64) -> Self {
Self { side, half_height }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfGyroid {
pub scale: f64,
pub thickness: f64,
}
#[allow(dead_code)]
impl SdfGyroid {
pub fn new(scale: f64, thickness: f64) -> Self {
Self { scale, thickness }
}
}
#[derive(Debug, Clone)]
pub struct SdfShell<S> {
pub inner: S,
pub thickness: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfShell<S> {
pub fn new(inner: S, thickness: f64) -> Self {
Self { inner, thickness }
}
}
#[derive(Debug, Clone)]
pub struct SdfBend<S> {
pub inner: S,
pub strength: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfBend<S> {
pub fn new(inner: S, strength: f64) -> Self {
Self { inner, strength }
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfLineSegment {
pub a: [f64; 3],
pub b: [f64; 3],
pub radius: f64,
}
#[allow(dead_code)]
impl SdfLineSegment {
pub fn new(a: [f64; 3], b: [f64; 3], radius: f64) -> Self {
Self { a, b, radius }
}
}
#[derive(Debug, Clone, Copy)]
pub struct RayMarchResult {
pub hit: bool,
pub t: f64,
pub point: [f64; 3],
pub steps: u32,
}
#[derive(Debug, Clone)]
pub struct SdfBoundedProxy<S> {
pub inner: S,
pub bsphere_center: [f64; 3],
pub bsphere_radius: f64,
}
#[allow(dead_code)]
impl<S: Sdf> SdfBoundedProxy<S> {
pub fn new(inner: S, bsphere_center: [f64; 3], bsphere_radius: f64) -> Self {
Self {
inner,
bsphere_center,
bsphere_radius,
}
}
pub fn outside_bounds(&self, p: [f64; 3]) -> bool {
len(sub(p, self.bsphere_center)) > self.bsphere_radius
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfBox {
pub half_extents: [f64; 3],
}
#[allow(dead_code)]
impl SdfBox {
pub fn new(hx: f64, hy: f64, hz: f64) -> Self {
Self {
half_extents: [hx, hy, hz],
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SdfCollisionResult {
pub depth: f64,
pub normal: [f64; 3],
pub contact_point: [f64; 3],
}
#[derive(Debug, Clone, Copy)]
pub struct SdfSphere {
pub radius: f64,
}
#[allow(dead_code)]
impl SdfSphere {
pub fn new(radius: f64) -> Self {
Self { radius }
}
}