From 3bc500c7273c06ac42342cacbbd1558e52f3166a Mon Sep 17 00:00:00 2001 From: Andy Killorin <37423245+Speedy6451@users.noreply.github.com> Date: Sat, 26 Aug 2023 19:52:33 -0500 Subject: [PATCH] noise (this is iter 4) --- front/index.js | 4 +- pirates/Cargo.lock | 103 ++++++++++++++++++++++++++++++++++++++++++++ pirates/Cargo.toml | 6 +++ pirates/src/lib.rs | 105 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 210 insertions(+), 8 deletions(-) diff --git a/front/index.js b/front/index.js index 2d55c6b..1637704 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 = 80; +const height = 60; function blit_frame() { ctx.putImageData(image, 0, 0); diff --git a/pirates/Cargo.lock b/pirates/Cargo.lock index c82e24d..4556b25 100644 --- a/pirates/Cargo.lock +++ b/pirates/Cargo.lock @@ -2,6 +2,109 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "nalgebra" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" +dependencies = [ + "approx", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "pirates" version = "0.1.0" +dependencies = [ + "libm", + "nalgebra", +] + +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" diff --git a/pirates/Cargo.toml b/pirates/Cargo.toml index d865f45..2fddb0e 100644 --- a/pirates/Cargo.toml +++ b/pirates/Cargo.toml @@ -11,3 +11,9 @@ opt-level = 's' crate-type = ["cdylib"] [dependencies] +libm = "0.2.7" + +[dependencies.nalgebra] +version = "0.32.3" +default-features = false +features = ["libm"] diff --git a/pirates/src/lib.rs b/pirates/src/lib.rs index 008a9e3..a17b5f5 100644 --- a/pirates/src/lib.rs +++ b/pirates/src/lib.rs @@ -1,12 +1,16 @@ #![no_std] -use core::sync::atomic::{AtomicU32, Ordering}; - #[panic_handler] fn handle_panic(_: &core::panic::PanicInfo) -> ! { loop {} } + +use core::sync::atomic::{AtomicU32, Ordering}; +use libm::{self, Libm}; +extern crate nalgebra as na; +use nalgebra::{Vector2}; + extern { fn blit_frame(); fn blit_text(text: *const u8, len: u32, x: i32, y: i32, size: u8); @@ -21,14 +25,16 @@ fn draw_text(text: &str, x: i32, y: i32, size: u8) { } } -const WIDTH: usize = 256; -const HEIGHT: usize = 224; +const WIDTH: usize = 80; +const HEIGHT: usize = 60; #[no_mangle] static mut BUFFER: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; static FRAME: AtomicU32 = AtomicU32::new(0); +static mut RAND: noise::PerlinBuf = [0; 512]; + #[no_mangle] pub unsafe extern fn frame_entry() { // calling from multiple threads is ub @@ -37,14 +43,30 @@ pub unsafe extern fn frame_entry() { fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) { let frame = FRAME.fetch_add(1, Ordering::Relaxed); + + if frame == 1 { + unsafe { + RAND = noise::generate(); + } + } + let rand = unsafe { + RAND + }; + for y in 0..HEIGHT { for x in 0..WIDTH { - buffer[y*WIDTH + x] = frame.wrapping_add((x^y) as u32) | 0xFF000000; + let point = Vector2::new((x+frame as usize) as f32,y as f32)*100.0; + let mut n = noise::noise(point / 600.0, rand) * 2.0; + n += noise::noise(point / 300.0, rand) * 1.0; + n += noise::noise(point / 150.0, rand) * 0.5; + n += noise::noise(point / 75.0, rand) * 0.25; + n += noise::noise(point / 37.5, rand) * 0.125; + buffer[y*WIDTH + x] = (((n*0.5+0.5)*256.0) as u32) << 16| 0xFF005000; } } unsafe { blit_frame(); } - draw_text("hi from rust", 0,100,1); + draw_text("hi from rust", 0,100,3); } #[cfg(test)] @@ -57,3 +79,74 @@ mod tests { assert_eq!(result, 64); } } + +mod noise { + use libm::Libm; + use nalgebra::Vector2; + + pub type PerlinBuf = [u32; 512]; + + pub fn generate() -> PerlinBuf { + let mut rand = 42424242; + 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 + 256] 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 + } +}