use crate::compiled::real::{Real, Vec3R};
use glam::Vec3;
#[inline(always)]
pub fn sdf_box3d_r<R: Real>(p: Vec3R<R>, half_extents: Vec3) -> R {
let q = p.abs() - Vec3R::splat(half_extents);
q.max(Vec3R::zero()).length() + q.x.max(q.y.max(q.z)).min(R::zero())
}
#[inline(always)]
pub fn sdf_box3d(point: Vec3, half_extents: Vec3) -> f32 {
sdf_box3d_r::<f32>(point.into(), half_extents)
}
#[inline(always)]
pub fn sdf_box3d_at(point: Vec3, center: Vec3, half_extents: Vec3) -> f32 {
sdf_box3d(point - center, half_extents)
}
#[inline(always)]
pub fn sdf_rounded_box3d(point: Vec3, half_extents: Vec3, radius: f32) -> f32 {
sdf_box3d(point, half_extents - Vec3::splat(radius)) - radius
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_box_origin() {
let d = sdf_box3d(Vec3::ZERO, Vec3::new(1.0, 1.0, 1.0));
assert!((d + 1.0).abs() < 0.0001); }
#[test]
fn test_box_surface() {
let d = sdf_box3d(Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 1.0, 1.0));
assert!(d.abs() < 0.0001);
}
#[test]
fn test_box_outside() {
let d = sdf_box3d(Vec3::new(2.0, 0.0, 0.0), Vec3::new(1.0, 1.0, 1.0));
assert!((d - 1.0).abs() < 0.0001);
}
#[test]
fn test_box_corner() {
let d = sdf_box3d(Vec3::new(2.0, 2.0, 2.0), Vec3::new(1.0, 1.0, 1.0));
let expected = (3.0_f32).sqrt(); assert!((d - expected).abs() < 0.0001);
}
#[test]
fn test_box_inside() {
let d = sdf_box3d(Vec3::new(0.5, 0.0, 0.0), Vec3::new(1.0, 1.0, 1.0));
assert!((d + 0.5).abs() < 0.0001);
}
#[test]
fn test_rounded_box() {
let d = sdf_rounded_box3d(Vec3::ZERO, Vec3::new(1.0, 1.0, 1.0), 0.1);
assert!(d < 0.0);
}
}