use glam::Vec3;
const TETRA_NORMALS: [Vec3; 4] = [
Vec3::new(0.577_350_26, 0.577_350_26, 0.577_350_26),
Vec3::new(-0.577_350_26, -0.577_350_26, 0.577_350_26),
Vec3::new(-0.577_350_26, 0.577_350_26, -0.577_350_26),
Vec3::new(0.577_350_26, -0.577_350_26, -0.577_350_26),
];
#[inline(always)]
pub fn sdf_tetrahedron(p: Vec3, size: f32) -> f32 {
let mut d = f32::NEG_INFINITY;
for n in &TETRA_NORMALS {
d = d.max(p.dot(*n));
}
d - size
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tetrahedron_origin() {
let d = sdf_tetrahedron(Vec3::ZERO, 1.0);
assert!(d < 0.0, "Origin should be inside, got {}", d);
}
#[test]
fn test_tetrahedron_surface() {
let n = Vec3::new(1.0, 1.0, 1.0).normalize();
let d = sdf_tetrahedron(n * 1.0, 1.0);
assert!(
d.abs() < 0.01,
"Face center should be on surface, got {}",
d
);
}
#[test]
fn test_tetrahedron_outside() {
let d = sdf_tetrahedron(Vec3::new(3.0, 0.0, 0.0), 1.0);
assert!(d > 0.0, "Far point should be outside, got {}", d);
}
#[test]
fn test_tetrahedron_symmetry() {
let size = 1.0;
let p = Vec3::new(0.5, 0.3, 0.2);
let d1 = sdf_tetrahedron(p, size);
let d2 = sdf_tetrahedron(Vec3::new(-p.x, -p.y, p.z), size);
assert!(d1.is_finite() && d2.is_finite());
}
}