summaryrefslogtreecommitdiff
path: root/src/perlin.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/perlin.rs')
-rw-r--r--src/perlin.rs65
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();