use super::helpers::{clamp, dot2, dot3, length2, norm3, scale2, scale3, sub2, sub3};
pub fn sdf_sphere(p: [f64; 3], r: f64) -> f64 {
norm3(p) - r
}
pub fn sdf_box(p: [f64; 3], b: [f64; 3]) -> f64 {
let q = [p[0].abs() - b[0], p[1].abs() - b[1], p[2].abs() - b[2]];
let pos_part = [q[0].max(0.0), q[1].max(0.0), q[2].max(0.0)];
norm3(pos_part) + q[0].max(q[1]).max(q[2]).min(0.0)
}
pub fn sdf_rounded_box(p: [f64; 3], b: [f64; 3], r: f64) -> f64 {
sdf_box(p, b) - r
}
pub fn sdf_capsule(p: [f64; 3], a: [f64; 3], b: [f64; 3], r: f64) -> f64 {
let pa = sub3(p, a);
let ba = sub3(b, a);
let h = clamp(dot3(pa, ba) / dot3(ba, ba).max(1e-30), 0.0, 1.0);
norm3(sub3(pa, scale3(ba, h))) - r
}
pub fn sdf_cylinder_infinite(p: [f64; 3], r: f64) -> f64 {
let xz = [p[0], p[2]];
length2(xz) - r
}
pub fn sdf_cylinder(p: [f64; 3], r: f64, h: f64) -> f64 {
let d_xy = length2([p[0], p[2]]) - r;
let d_z = p[1].abs() - h;
let outer = [d_xy.max(0.0), d_z.max(0.0)];
length2(outer) + d_xy.min(0.0).max(d_z.min(0.0))
}
pub fn sdf_torus(p: [f64; 3], r1: f64, r2: f64) -> f64 {
let xz = [p[0], p[2]];
let q = [length2(xz) - r1, p[1]];
length2(q) - r2
}
pub fn sdf_plane(p: [f64; 3], n: [f64; 3], d: f64) -> f64 {
dot3(p, n) - d
}
pub fn sdf_cone(p: [f64; 3], angle: f64, h: f64) -> f64 {
let q = length2([p[0], p[2]]);
let k = [angle.sin(), angle.cos()];
let w = [q, -p[1]]; let a = sub2(
w,
scale2(k, clamp(dot2(w, k) / dot2(k, k).max(1e-30), 0.0, h)),
);
let b = sub2(w, [k[0] * h, -k[1] * h]);
let s = if w[1] * k[0] - w[0] * k[1] > 0.0 {
-1.0
} else {
1.0
};
let la = length2(a);
let lb = length2(b);
s * la.min(lb)
}
pub fn sdf_segment(p: [f64; 3], a: [f64; 3], b: [f64; 3]) -> f64 {
let pa = sub3(p, a);
let ba = sub3(b, a);
let h = clamp(dot3(pa, ba) / dot3(ba, ba).max(1e-30), 0.0, 1.0);
norm3(sub3(pa, scale3(ba, h)))
}
pub fn sdf_ellipsoid(p: [f64; 3], r: [f64; 3]) -> f64 {
let k0 = norm3([p[0] / r[0], p[1] / r[1], p[2] / r[2]]);
let k1 = norm3([
p[0] / (r[0] * r[0]),
p[1] / (r[1] * r[1]),
p[2] / (r[2] * r[2]),
]);
if k1 < 1e-30 {
return -r[0].min(r[1]).min(r[2]);
}
k0 * (k0 - 1.0) / k1
}