use num::Float;
pub trait VoxelData {
type Density: Density;
fn density(&self) -> Self::Density;
}
impl<F: Density> VoxelData for F {
type Density = Self;
fn density(&self) -> Self::Density {
*self
}
}
pub trait Density: Default + Clone + Copy + Float {
fn inside(&self, threshold: &Self) -> bool {
self > threshold
}
const EPSILON: Self;
const HALF: Self;
const ZERO: Self;
fn interpolate(a: Self, b: Self, threshold: Self) -> Self {
if (b - a).abs() > Self::EPSILON {
(threshold - a) / (b - a)
} else {
Self::HALF
}
}
fn diff(&self, other: Self) -> Self {
*self - other
}
fn gradients_to_normal(x_gradient: Self, y_gradient: Self, z_gradient: Self) -> [Self; 3] {
let norm =
(x_gradient * x_gradient + y_gradient * y_gradient + z_gradient * z_gradient).sqrt();
if norm > Self::EPSILON {
[-x_gradient / norm, -y_gradient / norm, -z_gradient / norm]
} else {
[Self::ZERO, Self::ZERO, Self::ZERO]
}
}
}
macro_rules! float_impl_density {
($T:ident) => {
impl Density for $T {
const EPSILON: Self = $T::EPSILON;
const HALF: Self = 0.5;
const ZERO: Self = 0.0;
}
};
}
float_impl_density!(f32);
float_impl_density!(f64);