diff options
Diffstat (limited to 'src/perlin.rs')
-rw-r--r-- | src/perlin.rs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/perlin.rs b/src/perlin.rs index 393582b..0b29f48 100644 --- a/src/perlin.rs +++ b/src/perlin.rs @@ -1,7 +1,53 @@ +use std::eprintln; + use crate::vec3::{Vec3, Point3}; const POINT_COUNT: usize = 256; +// Mix-in images are necessarily monochrome, so each data entry is a pixel. +pub struct MixInImage { + width: usize, + height: usize, + data: Vec<f64>, +} + +impl MixInImage { + pub fn from_bmp(bmp_data: &Vec<u8>) -> Self { + let data_position = u32::from_le_bytes([ + bmp_data[0x0A], + bmp_data[0x0B], + bmp_data[0x0C], + bmp_data[0x0D], + ]); + // assuming windows BITMAPINFOHEADER, these are i32 + let width = i32::from_le_bytes([ + bmp_data[0x12], + bmp_data[0x13], + bmp_data[0x14], + bmp_data[0x15], + ]) as usize; + let height = i32::from_le_bytes([ + bmp_data[0x16], + bmp_data[0x17], + bmp_data[0x18], + bmp_data[0x19], + ]) as usize; + // assuming 3 channels, all of which are equal + let data = bmp_data[(data_position as usize)..bmp_data.len()].iter().skip(2).step_by(3).map(|x| *x as f64 / 255.0).collect(); + Self { + width, + height, + data, + } + } + + pub fn get(&self, point: &Point3) -> &f64 { + let disc_x = ((point.x * self.width as f64) % self.width as f64) as usize; + let disc_y = ((point.y * self.height as f64) % self.height as f64) as usize; + self.data.get((disc_y * self.width) + disc_x).unwrap() + } +} + pub struct Perlin { ranvec: Vec<Vec3>, perm_x: Vec<usize>, @@ -50,6 +96,25 @@ impl Perlin { accum.abs() } + + pub fn turb_dsw_mixin(&self, point: &Point3, depth: u32, factor: f64, mixin: &MixInImage, mixin_factor: f64, mixin_strength: f64) -> f64 { + let mut accum = 0.0; + let mut temp_point = point.clone(); + let mut mixin_point = point.clone(); + let mut weight = 1.0; + + for _ in 0..depth { + accum += weight * (1.0 - mixin_strength) * self.noise(&temp_point); + temp_point *= 2.0; + let diff = temp_point.xy_diff(&|p: &Vec3| -> f64 {weight * self.noise(p)}); + temp_point += &diff * factor; + mixin_point += &diff * mixin_factor; + accum += weight * mixin_strength * mixin.get(&mixin_point); + weight *= 0.5; + } + accum.abs() + } + pub fn noise(&self, point: &Point3) -> f64 { let u = point.x - point.x.floor(); let v = point.y - point.y.floor(); |