use alice_sdf::SdfNode;
use glam::Vec3;
use std::sync::Arc;
const DEFAULT_WALL_THICKNESS: f32 = 3.0;
const DEFAULT_BOTTOM_THICKNESS: f32 = 3.0;
const DEFAULT_HANDLE_MAJOR_R: f32 = 15.0;
const DEFAULT_HANDLE_MINOR_R: f32 = 3.0;
#[must_use]
pub fn mug_sdf(dia: f32, height: f32) -> SdfNode {
let outer_r = dia * 0.5;
let inner_r = outer_r - DEFAULT_WALL_THICKNESS;
let half_h = height * 0.5;
let hollow_z_offset = DEFAULT_BOTTOM_THICKNESS * 0.5;
let hollow_half_h = (height - DEFAULT_BOTTOM_THICKNESS).mul_add(0.5, 1.0);
let outer = Arc::new(SdfNode::Cylinder {
radius: outer_r,
half_height: half_h,
});
let hollow_raw = Arc::new(SdfNode::Cylinder {
radius: inner_r,
half_height: hollow_half_h,
});
let hollow = Arc::new(SdfNode::Translate {
child: hollow_raw,
offset: Vec3::new(0.0, 0.0, hollow_z_offset),
});
let hollow_body = SdfNode::Subtraction {
a: outer,
b: hollow,
};
let handle_raw = Arc::new(SdfNode::Torus {
major_radius: DEFAULT_HANDLE_MAJOR_R,
minor_radius: DEFAULT_HANDLE_MINOR_R,
});
let handle_rotated = Arc::new(SdfNode::Rotate {
child: handle_raw,
rotation: crate::angle::quat_from_rotation_x(std::f32::consts::FRAC_PI_2),
});
let handle = SdfNode::Translate {
child: handle_rotated,
offset: Vec3::new(outer_r + DEFAULT_HANDLE_MINOR_R, 0.0, 0.0),
};
SdfNode::Union {
a: Arc::new(hollow_body),
b: Arc::new(handle),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mug_sdf_returns_union_of_subtract_and_translate_handle() {
let node = mug_sdf(50.0, 100.0);
match &node {
SdfNode::Union { a, b } => {
assert!(matches!(**a, SdfNode::Subtraction { .. }));
assert!(matches!(**b, SdfNode::Translate { .. }));
}
_ => panic!("Expected Union at top level"),
}
}
#[test]
fn mug_sdf_various_dimensions_do_not_panic() {
let _ = mug_sdf(50.0, 100.0);
let _ = mug_sdf(80.0, 120.0);
let _ = mug_sdf(30.0, 80.0);
let _ = mug_sdf(20.0, 40.0);
}
}