use glam::Vec3;
pub const GDF_CUBE: [Vec3; 3] = [
Vec3::new(1.0, 0.0, 0.0),
Vec3::new(0.0, 1.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
];
const INV_SQRT3: f32 = 0.577_350_26;
pub const GDF_OCTAHEDRON: [Vec3; 4] = [
Vec3::new(INV_SQRT3, INV_SQRT3, INV_SQRT3),
Vec3::new(-INV_SQRT3, INV_SQRT3, INV_SQRT3),
Vec3::new(INV_SQRT3, -INV_SQRT3, INV_SQRT3),
Vec3::new(INV_SQRT3, INV_SQRT3, -INV_SQRT3),
];
const ICO_A: f32 = 0.525_731_1;
const ICO_B: f32 = 0.850_650_8;
pub const GDF_ICOSAHEDRON: [Vec3; 6] = [
Vec3::new(0.0, ICO_A, ICO_B),
Vec3::new(0.0, ICO_A, -ICO_B),
Vec3::new(ICO_A, ICO_B, 0.0),
Vec3::new(ICO_A, -ICO_B, 0.0),
Vec3::new(ICO_B, 0.0, ICO_A),
Vec3::new(-ICO_B, 0.0, ICO_A),
];
pub const GDF_DODECAHEDRON: [Vec3; 6] = [
Vec3::new(0.0, ICO_B, ICO_A),
Vec3::new(0.0, ICO_B, -ICO_A),
Vec3::new(ICO_B, ICO_A, 0.0),
Vec3::new(-ICO_B, ICO_A, 0.0),
Vec3::new(ICO_A, 0.0, ICO_B),
Vec3::new(ICO_A, 0.0, -ICO_B),
];
#[inline(always)]
pub fn gdf_eval(p: Vec3, normals: &[Vec3], radius: f32) -> f32 {
let mut d = f32::NEG_INFINITY;
for n in normals {
d = d.max(p.dot(*n).abs());
}
d - radius
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gdf_vectors_normalized() {
for n in &GDF_CUBE {
assert!((n.length() - 1.0).abs() < 1e-6);
}
for n in &GDF_OCTAHEDRON {
assert!((n.length() - 1.0).abs() < 1e-6);
}
for n in &GDF_ICOSAHEDRON {
assert!((n.length() - 1.0).abs() < 1e-6, "ICO norm: {}", n.length());
}
for n in &GDF_DODECAHEDRON {
assert!(
(n.length() - 1.0).abs() < 1e-6,
"DODEC norm: {}",
n.length()
);
}
}
}