use super::{seed_expan, Sampler}; use rand::RngCore; use vek::*; #[derive(Clone, Copy)] pub struct RandomField { seed: u32, } impl RandomField { pub const fn new(seed: u32) -> Self { Self { seed } } pub fn chance(&self, pos: Vec3, chance: f32) -> bool { self.get_f32(pos) < chance } pub fn get_f32(&self, pos: Vec3) -> f32 { (self.get(pos) % (1 << 16)) as f32 / ((1 << 16) as f32) } pub fn choose<'a, T>(&self, pos: Vec3, slice: &'a [T]) -> Option<&'a T> { if slice.is_empty() { return None; } let i = self.get(pos) as usize; slice.get(i % slice.len()) } } impl Sampler<'static> for RandomField { type Index = Vec3; type Sample = u32; fn get(&self, pos: Self::Index) -> Self::Sample { let pos = pos.map(|e| u32::from_le_bytes(e.to_le_bytes())); let mut a = self.seed; a = (a ^ 61) ^ (a >> 16); a = a.wrapping_add(a << 3); a ^= pos.x; a ^= a >> 4; a = a.wrapping_mul(0x27d4eb2d); a ^= a >> 15; a ^= pos.y; a = (a ^ 61) ^ (a >> 16); a = a.wrapping_add(a << 3); a ^= a >> 4; a ^= pos.z; a = a.wrapping_mul(0x27d4eb2d); a ^= a >> 15; a } } pub struct RandomPerm { seed: u32, } impl RandomPerm { pub const fn new(seed: u32) -> Self { Self { seed } } pub fn chance(&self, perm: u32, chance: f32) -> bool { (self.get(perm) % (1 << 16)) as f32 / ((1 << 16) as f32) < chance } } impl Sampler<'static> for RandomPerm { type Index = u32; type Sample = u32; fn get(&self, perm: Self::Index) -> Self::Sample { seed_expan::diffuse_mult(&[self.seed, perm]) } } // `RandomPerm` is not high-quality but it is at least fast and deterministic. impl RngCore for RandomPerm { fn next_u32(&mut self) -> u32 { self.seed = self.get(self.seed) ^ 0xA7535839; self.seed } fn next_u64(&mut self) -> u64 { let a = self.next_u32(); let b = self.next_u32(); (a as u64) << 32 | b as u64 } fn fill_bytes(&mut self, dest: &mut [u8]) { dest.iter_mut() .for_each(|b| *b = (self.next_u32() & 0xFF) as u8); } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { self.fill_bytes(dest); Ok(()) } }