use crate::compiled::real::{Real, Vec3R};
use glam::{Vec2, Vec3};
#[inline(always)]
pub fn sdf_torus_r<R: Real>(p: Vec3R<R>, major_radius: f32, minor_radius: f32) -> R {
let qx = (p.x * p.x + p.z * p.z).sqrt() - R::splat(major_radius);
(qx * qx + p.y * p.y).sqrt() - R::splat(minor_radius)
}
#[inline(always)]
pub fn sdf_torus(point: Vec3, major_radius: f32, minor_radius: f32) -> f32 {
sdf_torus_r::<f32>(point.into(), major_radius, minor_radius)
}
#[inline(always)]
pub fn sdf_torus_capped(point: Vec3, major_radius: f32, minor_radius: f32, angle: f32) -> f32 {
let sc = Vec2::new(alice_det_math::sin(angle), alice_det_math::cos(angle));
let p_xz = Vec2::new(point.x.abs(), point.z);
let k = if sc.y * p_xz.x > sc.x * p_xz.y {
p_xz.dot(sc)
} else {
p_xz.length()
};
let q = Vec2::new(
((2.0 * major_radius) * -k + (major_radius * major_radius + p_xz.length_squared())).sqrt(),
point.y,
);
q.length() - minor_radius
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_torus_center() {
let d = sdf_torus(Vec3::ZERO, 2.0, 0.5);
assert!((d - 1.5).abs() < 0.0001);
}
#[test]
fn test_torus_tube_center() {
let d = sdf_torus(Vec3::new(2.0, 0.0, 0.0), 2.0, 0.5);
assert!((d + 0.5).abs() < 0.0001);
}
#[test]
fn test_torus_surface_outer() {
let d = sdf_torus(Vec3::new(2.5, 0.0, 0.0), 2.0, 0.5);
assert!(d.abs() < 0.0001);
}
#[test]
fn test_torus_surface_inner() {
let d = sdf_torus(Vec3::new(1.5, 0.0, 0.0), 2.0, 0.5);
assert!(d.abs() < 0.0001);
}
#[test]
fn test_torus_surface_top() {
let d = sdf_torus(Vec3::new(2.0, 0.5, 0.0), 2.0, 0.5);
assert!(d.abs() < 0.0001);
}
}