use crate::{
math::vectors::*,
noise_fns::{MultiFractal, NoiseFn, Seedable},
};
use alloc::vec::Vec;
#[derive(Clone, Debug)]
pub struct BasicMulti<T> {
pub octaves: usize,
pub frequency: f64,
pub lacunarity: f64,
pub persistence: f64,
seed: u32,
sources: Vec<T>,
}
impl<T> BasicMulti<T>
where
T: Default + Seedable,
{
pub const DEFAULT_SEED: u32 = 0;
pub const DEFAULT_OCTAVES: usize = 6;
pub const DEFAULT_FREQUENCY: f64 = 2.0;
pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0;
pub const DEFAULT_PERSISTENCE: f64 = 0.5;
pub const MAX_OCTAVES: usize = 32;
pub fn new(seed: u32) -> Self {
Self {
seed,
octaves: Self::DEFAULT_OCTAVES,
frequency: Self::DEFAULT_FREQUENCY,
lacunarity: Self::DEFAULT_LACUNARITY,
persistence: Self::DEFAULT_PERSISTENCE,
sources: super::build_sources(seed, Self::DEFAULT_OCTAVES),
}
}
pub fn set_sources(self, sources: Vec<T>) -> Self {
Self { sources, ..self }
}
}
impl<T> Default for BasicMulti<T>
where
T: Default + Seedable,
{
fn default() -> Self {
Self::new(Self::DEFAULT_SEED)
}
}
impl<T> MultiFractal for BasicMulti<T>
where
T: Default + Seedable,
{
fn set_octaves(self, mut octaves: usize) -> Self {
if self.octaves == octaves {
return self;
}
octaves = octaves.clamp(1, Self::MAX_OCTAVES);
Self {
octaves,
sources: super::build_sources(self.seed, octaves),
..self
}
}
fn set_frequency(self, frequency: f64) -> Self {
Self { frequency, ..self }
}
fn set_lacunarity(self, lacunarity: f64) -> Self {
Self { lacunarity, ..self }
}
fn set_persistence(self, persistence: f64) -> Self {
Self {
persistence,
..self
}
}
}
impl<T> Seedable for BasicMulti<T>
where
T: Default + Seedable,
{
fn set_seed(self, seed: u32) -> Self {
if self.seed == seed {
return self;
}
Self {
seed,
sources: super::build_sources(seed, self.octaves),
..self
}
}
fn seed(&self) -> u32 {
self.seed
}
}
impl<T> NoiseFn<f64, 2> for BasicMulti<T>
where
T: NoiseFn<f64, 2>,
{
fn get(&self, point: [f64; 2]) -> f64 {
let mut point = Vector2::from(point);
point *= self.frequency;
let mut result = self.sources[0].get(point.into_array());
for x in 1..self.octaves {
point *= self.lacunarity;
let mut signal = self.sources[x].get(point.into_array());
signal *= self.persistence.powi(x as i32);
signal *= result;
result += signal;
}
result * 0.5
}
}
impl<T> NoiseFn<f64, 3> for BasicMulti<T>
where
T: NoiseFn<f64, 3>,
{
fn get(&self, point: [f64; 3]) -> f64 {
let mut point = Vector3::from(point);
point *= self.frequency;
let mut result = self.sources[0].get(point.into_array());
for x in 1..self.octaves {
point *= self.lacunarity;
let mut signal = self.sources[x].get(point.into_array());
signal *= self.persistence.powi(x as i32);
signal *= result;
result += signal;
}
result * 0.5
}
}
impl<T> NoiseFn<f64, 4> for BasicMulti<T>
where
T: NoiseFn<f64, 4>,
{
fn get(&self, point: [f64; 4]) -> f64 {
let mut point = Vector4::from(point);
point *= self.frequency;
let mut result = self.sources[0].get(point.into_array());
for x in 1..self.octaves {
point *= self.lacunarity;
let mut signal = self.sources[x].get(point.into_array());
signal *= self.persistence.powi(x as i32);
signal *= result;
result += signal;
}
result * 0.5
}
}