use rand::distributions::{Distribution, Uniform}; use rand::Rng; use crate::Point3; pub struct Perlin { ranfloat: Vec, perm_x: Vec, perm_y: Vec, perm_z: Vec, } impl Perlin { const POINT_COUNT: usize = 256; pub fn new() -> Self { let range = Uniform::from(0.0..1.0); let mut rng = rand::thread_rng(); let mut ranfloat = Vec::with_capacity(Perlin::POINT_COUNT); (0..Perlin::POINT_COUNT).for_each(|_i|ranfloat.push(range.sample(&mut rng))); Perlin { ranfloat, perm_x: Perlin::perlin_generate_perm(), perm_y: Perlin::perlin_generate_perm(), perm_z: Perlin::perlin_generate_perm(), } } pub fn noise(&self, point: &Point3) -> f64 { let i = ((4.0 * point.x()) as i32) & 255; let j = ((4.0 * point.y()) as i32) & 255; let k= ((4.0 * point.z()) as i32) & 255; let idx = self.perm_x[i as usize] ^ self.perm_y[j as usize] ^ self.perm_z[k as usize]; self.ranfloat[idx] } fn perlin_generate_perm() -> Vec { let mut p = Vec::with_capacity(Perlin::POINT_COUNT); (0..Perlin::POINT_COUNT).for_each(|i| p.push(i)); let mut rng = rand::thread_rng(); (1..Perlin::POINT_COUNT).rev().for_each(|idx| { let target = rng.gen_range(0..=idx); p.swap(idx, target); }); p } }