use crate::{
core::worley::*,
math::vectors::*,
noise_fns::{NoiseFn, Seedable},
permutationtable::PermutationTable,
};
use alloc::rc::Rc;
#[derive(Clone)]
pub struct Worley {
pub distance_function: Rc<DistanceFunction>,
pub return_type: ReturnType,
pub frequency: f64,
seed: u32,
perm_table: PermutationTable,
}
type DistanceFunction = dyn Fn(&[f64], &[f64]) -> f64;
impl Worley {
pub const DEFAULT_SEED: u32 = 0;
pub const DEFAULT_FREQUENCY: f64 = 1.0;
pub fn new(seed: u32) -> Self {
Self {
perm_table: PermutationTable::new(seed),
seed,
distance_function: Rc::new(distance_functions::euclidean),
return_type: ReturnType::Value,
frequency: Self::DEFAULT_FREQUENCY,
}
}
pub fn set_distance_function<F>(self, function: F) -> Self
where
F: Fn(&[f64], &[f64]) -> f64 + 'static,
{
Self {
distance_function: Rc::new(function),
..self
}
}
pub fn set_return_type(self, return_type: ReturnType) -> Self {
Self {
return_type,
..self
}
}
pub fn set_frequency(self, frequency: f64) -> Self {
Self { frequency, ..self }
}
}
impl Default for Worley {
fn default() -> Self {
Self::new(0)
}
}
impl Seedable for Worley {
fn set_seed(self, seed: u32) -> Self {
if self.seed == seed {
return self;
}
Self {
perm_table: PermutationTable::new(seed),
seed,
..self
}
}
fn seed(&self) -> u32 {
self.seed
}
}
impl NoiseFn<f64, 2> for Worley {
fn get(&self, point: [f64; 2]) -> f64 {
worley_2d(
&self.perm_table,
&*self.distance_function,
self.return_type,
Vector2::from(point) * self.frequency,
)
}
}
impl NoiseFn<f64, 3> for Worley {
fn get(&self, point: [f64; 3]) -> f64 {
worley_3d(
&self.perm_table,
&*self.distance_function,
self.return_type,
Vector3::from(point) * self.frequency,
)
}
}
#[allow(clippy::cognitive_complexity)]
impl NoiseFn<f64, 4> for Worley {
fn get(&self, point: [f64; 4]) -> f64 {
worley_4d(
&self.perm_table,
&*self.distance_function,
self.return_type,
Vector4::from(point) * self.frequency,
)
}
}