From fc2055b65f8dece92ae35117f847bbe2ce5d271e Mon Sep 17 00:00:00 2001 From: Andy Killorin <37423245+Speedy6451@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:54:06 -0500 Subject: [PATCH] extracted noise and sampler modules --- front/index.js | 4 +- pirates/src/lib.rs | 111 +++-------------------------------------- pirates/src/noise.rs | 68 +++++++++++++++++++++++++ pirates/src/sampler.rs | 40 +++++++++++++++ 4 files changed, 116 insertions(+), 107 deletions(-) create mode 100644 pirates/src/noise.rs create mode 100644 pirates/src/sampler.rs diff --git a/front/index.js b/front/index.js index 8e7e3c0..947d1e6 100644 --- a/front/index.js +++ b/front/index.js @@ -1,8 +1,8 @@ var ctx; var image; var memory; -const width = 256; -const height = 224; +const width = 160; +const height = 144; function blit_frame() { ctx.putImageData(image, 0, 0); diff --git a/pirates/src/lib.rs b/pirates/src/lib.rs index 2743d9a..16bb6a7 100644 --- a/pirates/src/lib.rs +++ b/pirates/src/lib.rs @@ -14,6 +14,9 @@ use libm::{self, Libm}; extern crate nalgebra as na; use nalgebra::{Vector2}; +mod sampler; +mod noise; + extern { fn blit_frame(); fn blit_text(text: *const u8, len: u32, x: i32, y: i32, size: u8); @@ -28,8 +31,8 @@ fn draw_text(text: &str, x: i32, y: i32, size: u8) { } } -const WIDTH: usize = 256; -const HEIGHT: usize = 224; +const WIDTH: usize = 160; +const HEIGHT: usize = 144; #[no_mangle] static mut BUFFER: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; @@ -77,7 +80,7 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { let offset = Vector2::new(64120.0, 7320.0); let point = point + offset; let mut n = 0.0; - n += (sample_map_inter(point / 64.0, &MAP)-0.5)* 0.6; + n += (sampler::sample_map_inter(point / 64.0, &MAP)-0.5)* 0.6; n += noise::noise(point / 64.0, rand) / 1.0; n += noise::noise(point / 32.0, rand) / 2.0; n += noise::noise(point / 16.0, rand) / 4.0; @@ -102,38 +105,6 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { //draw_text("hi from rust", 0,100,30); } -fn sample_map_inter(point: Vector2, map: &[u8]) -> f32 { - let x = libm::floorf(point.x) as usize % MAP_WIDTH; - let y = libm::floorf(point.y) as usize % MAP_HEIGHT; - let p0 = Vector2::new(libm::floorf(point.x), libm::floorf(point.y)); - let p1 = p0 + Vector2::new(1.0, 0.0); - let p2 = p0 + Vector2::new(0.0, 1.0); - let p3 = p0 + Vector2::new(1.0, 1.0); - - let tx = point.x - libm::floorf(point.x); - let ty = point.y - libm::floorf(point.y); - - let top = (1.0 - tx) * sample_map(p0, map) as f32 + tx * sample_map(p1, map) as f32; - let bot = (1.0 - tx) * sample_map(p2, map) as f32 + tx * sample_map(p3, map) as f32; - - (1.0-ty) * top + ty * bot -} - -fn sample_map(point: Vector2, map: &[u8]) -> u8 { - const MARGIN: usize = 3; - let x = libm::floorf(point.x) as usize % (MAP_WIDTH + MARGIN); - let y = libm::floorf(point.y) as usize % (MAP_HEIGHT + MARGIN); - - if x >= MAP_WIDTH || y >= MAP_HEIGHT { - if x-y > 12 { - return 1; - } - return 0; - } - - map[y*MAP_WIDTH + x] - -} #[cfg(test)] mod tests { @@ -146,73 +117,3 @@ mod tests { } } -mod noise { - use libm::Libm; - use nalgebra::Vector2; - - pub type PerlinBuf = [u32; 512]; - - pub fn generate(seed: u32) -> PerlinBuf { - let mut rand = seed; - let mut data: PerlinBuf = [0; 512]; - for item in data.iter_mut() { - rand = xorshift(rand); - *item = rand; - } - - data - } - - fn xorshift(state: u32) -> u32 { - // impl from wikipedia - let mut state = state; - state ^= state << 13; - state ^= state >> 17; - state ^= state << 5; - state - } - - fn fade(t: f32) -> f32 { - t*t*t*(t*(t*6.0-15.0)+10.0) - } - - fn lerp(a: f32, b:f32, d:f32) -> f32 { - a * (1.0-d) + b * d - } - - fn grad(p: Vector2, b: PerlinBuf) -> Vector2 { - const width: usize = 16; - - - let x = p.x as usize % width; - let y = p.y as usize % width; - - let one = b[x*width + y] as f32; - let two = b[(x*width + y + 1)%512] as f32; - - Vector2::new(one, two).normalize() - } - - pub fn noise(p: Vector2, b: PerlinBuf) -> f32 { - let p0 = Vector2::new(libm::floorf(p.x), libm::floorf(p.y)); - let p1 = p0 + Vector2::new(1.0, 0.0); - let p2 = p0 + Vector2::new(0.0, 1.0); - let p3 = p0 + Vector2::new(1.0, 1.0); - - let g0 = grad(p0, b); - let g1 = grad(p1, b); - let g2 = grad(p2, b); - let g3 = grad(p3, b); - - let tx = p.x - p0.x; - let ftx = fade(tx); - let ty = p.y - p0.y; - let fty = fade(ty); - - let p0p1 = (1.0 - ftx) * g0.dot(&(p-p0)) + ftx * g1.dot(&(p-p1)); - let p2p3 = (1.0 - ftx) * g2.dot(&(p-p2)) + ftx * g3.dot(&(p-p3)); - - - (1.0 - fty) * p0p1 + fty * p2p3 - } -} diff --git a/pirates/src/noise.rs b/pirates/src/noise.rs new file mode 100644 index 0000000..99e45c4 --- /dev/null +++ b/pirates/src/noise.rs @@ -0,0 +1,68 @@ +use libm::Libm; +use nalgebra::Vector2; + +pub type PerlinBuf = [u32; 512]; + +pub fn generate(seed: u32) -> PerlinBuf { + let mut rand = seed; + let mut data: PerlinBuf = [0; 512]; + for item in data.iter_mut() { + rand = xorshift(rand); + *item = rand; + } + + data +} + +fn xorshift(state: u32) -> u32 { + // impl from wikipedia + let mut state = state; + state ^= state << 13; + state ^= state >> 17; + state ^= state << 5; + state +} + +fn fade(t: f32) -> f32 { + t*t*t*(t*(t*6.0-15.0)+10.0) +} + +fn lerp(a: f32, b:f32, d:f32) -> f32 { + a * (1.0-d) + b * d +} + +fn grad(p: Vector2, b: PerlinBuf) -> Vector2 { + const width: usize = 16; + + + let x = p.x as usize % width; + let y = p.y as usize % width; + + let one = b[x*width + y] as f32; + let two = b[(x*width + y + 1)%512] as f32; + + Vector2::new(one, two).normalize() +} + +pub fn noise(p: Vector2, b: PerlinBuf) -> f32 { + let p0 = Vector2::new(libm::floorf(p.x), libm::floorf(p.y)); + let p1 = p0 + Vector2::new(1.0, 0.0); + let p2 = p0 + Vector2::new(0.0, 1.0); + let p3 = p0 + Vector2::new(1.0, 1.0); + + let g0 = grad(p0, b); + let g1 = grad(p1, b); + let g2 = grad(p2, b); + let g3 = grad(p3, b); + + let tx = p.x - p0.x; + let ftx = fade(tx); + let ty = p.y - p0.y; + let fty = fade(ty); + + let p0p1 = (1.0 - ftx) * g0.dot(&(p-p0)) + ftx * g1.dot(&(p-p1)); + let p2p3 = (1.0 - ftx) * g2.dot(&(p-p2)) + ftx * g3.dot(&(p-p3)); + + + (1.0 - fty) * p0p1 + fty * p2p3 +} diff --git a/pirates/src/sampler.rs b/pirates/src/sampler.rs new file mode 100644 index 0000000..6449094 --- /dev/null +++ b/pirates/src/sampler.rs @@ -0,0 +1,40 @@ +use super::MAP_HEIGHT; + +use super::MAP_WIDTH; + +use libm::Libm; + +use nalgebra::Vector2; + +pub(crate) fn sample_map_inter(point: Vector2, map: &[u8]) -> f32 { + let x = libm::floorf(point.x) as usize % MAP_WIDTH; + let y = libm::floorf(point.y) as usize % MAP_HEIGHT; + let p0 = Vector2::new(libm::floorf(point.x), libm::floorf(point.y)); + let p1 = p0 + Vector2::new(1.0, 0.0); + let p2 = p0 + Vector2::new(0.0, 1.0); + let p3 = p0 + Vector2::new(1.0, 1.0); + + let tx = point.x - libm::floorf(point.x); + let ty = point.y - libm::floorf(point.y); + + let top = (1.0 - tx) * sample_map(p0, map) as f32 + tx * sample_map(p1, map) as f32; + let bot = (1.0 - tx) * sample_map(p2, map) as f32 + tx * sample_map(p3, map) as f32; + + (1.0-ty) * top + ty * bot +} + +pub(crate) fn sample_map(point: Vector2, map: &[u8]) -> u8 { + const MARGIN: usize = 3; + let x = libm::floorf(point.x) as usize % (MAP_WIDTH + MARGIN); + let y = libm::floorf(point.y) as usize % (MAP_HEIGHT + MARGIN); + + if x >= MAP_WIDTH || y >= MAP_HEIGHT { + if x-y > 12 { + return 1; + } + return 0; + } + + map[y*MAP_WIDTH + x] + +}