diff --git a/Cargo.lock b/Cargo.lock index c166bf4..ed30955 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -652,6 +652,8 @@ dependencies = [ "log", "mars", "pollster", + "rand", + "rand_chacha", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -669,6 +671,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -990,7 +1003,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom", + "getrandom 0.3.4", "libc", ] @@ -1659,6 +1672,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "presser" version = "0.3.1" @@ -1719,6 +1741,36 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + [[package]] name = "range-alloc" version = "0.1.5" @@ -2222,6 +2274,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "wasip2" version = "1.0.3+wasi-0.2.9" diff --git a/Cargo.toml b/Cargo.toml index 0073a97..a21b8d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ console_error_panic_hook = "0.1.7" bytemuck = { version = "1.25.0", features = [ "derive" ]} image = { version = "0.24", default-features = false, features = ["png", "jpeg"]} mars = { path = "../Mars" } +rand = "0.8" +rand_chacha = "0.3" [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" diff --git a/src/app.rs b/src/app.rs index 0907c8e..d2e35ba 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,6 +2,8 @@ use std::collections::HashMap; // Credit of most code to https://sotrh.github.io/learn-wgpu/ since I'm not familiar with wgpu use crate::render::Renderer; use crate::world::{SimpleObject, World}; +use crate::permutation_array; +use crate::noise2d; use glam::{Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4}; use std::sync::Arc; #[cfg(target_arch = "wasm32")] @@ -16,6 +18,8 @@ use winit::{ keyboard::{KeyCode, PhysicalKey}, window::Window, }; +use crate::noise2d::Noise2D; +use crate::permutation_array::PermutationArray; struct Controller { buttons: HashMap, @@ -38,9 +42,12 @@ pub struct AppState { controller: Controller, window: Arc, clients: Vec, + chunks: Vec<(i32, i32)>, + Permutation: PermutationArray, } -const BLOCKS: i32 = 1; +const BLOCKS: i32 = 100; + impl AppState { // We don't need this to be async right now, @@ -48,6 +55,9 @@ impl AppState { pub async fn new(window: Arc) -> Result> { let mut world = World::new(); world.add_renderer(Renderer::new(&window).await?); + let mut Permutation: PermutationArray = PermutationArray::new(); + Permutation.generate_permutation_array(0); + let mut chunks = Vec::new(); let mut clients = Vec::new(); { let file = world @@ -65,35 +75,39 @@ impl AppState { //let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png")); //let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png")); //let mat = renderer.new_material(color,normal,roughness); - for x in -BLOCKS..BLOCKS { - for y in -BLOCKS..BLOCKS { - let block = block.hard_clone(); - world.add_object(block.clone()); - { - let mut model = block.0.borrow_mut(); - model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( - Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0), - ) - * Mat4::from_rotation_z((x * y) as f32 / 1.23); - model.model.as_mut().unwrap().instance.color = Vec4::new( - 0.3, - (x + BLOCKS) as f32 / BLOCKS as f32, - (y + BLOCKS) as f32 / BLOCKS as f32, - 1.0, - ); - } - clients.push(block) - } - } + // for x in -BLOCKS..BLOCKS { + // for y in -BLOCKS..BLOCKS { + // let block = block.hard_clone(); + // world.add_object(block.clone()); + // { + // let mut model = block.0.borrow_mut(); + // model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( + // Vec3::new(-x as f32 * 1.0, Noise2D::fractal_noise(x as f64 * 0.1, y as f64*0.1, 5, 10.0, 0.05, &Permutation).round() as i64 as f32, -y as f32 * 1.0), + // ) + // * Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/); + // model.model.as_mut().unwrap().instance.color = Vec4::new( + // 0.3, + // (x + BLOCKS) as f32 / BLOCKS as f32, + // (y + BLOCKS) as f32 / BLOCKS as f32, + // 1.0, + // ); + // } + // clients.push(block) + // } + // } } Ok(Self { world, clients, controller: Controller::new(), window, + chunks, + Permutation }) } + + pub fn bounds(&self) -> (u32, u32) { let size = self.window.inner_size(); (size.width, size.height) @@ -152,6 +166,42 @@ impl App { proxy, } } + + pub fn GenerateChunk(ChunkX: i32, ChunkY: i32, size: i32, state: &mut AppState){ + if(state.chunks.contains(&(ChunkX, ChunkY))){ + return; + } + let file = state.world + .renderer + .as_mut() + .unwrap() + .load_from_gltf(include_bytes!("assets/cube.glb")); + let block = file.first_object().unwrap(); + + for x in 0..size { + for y in 0..size { + let worldPosX = ChunkX * size + x; + let worldPosY = ChunkY * size + y; + let block = block.hard_clone(); + state.world.add_object(block.clone()); + { + let mut model = block.0.borrow_mut(); + model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( + Vec3::new(worldPosX as f32 * 1.0, Noise2D::fractal_noise(worldPosX as f64 * 0.25, worldPosY as f64*0.25, 10, 20.0, 0.05, &state.Permutation).round() as i64 as f32, worldPosY as f32 * 1.0), + ) + * Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/); + model.model.as_mut().unwrap().instance.color = Vec4::new( + 0.3, + (x + size) as f32 / size as f32, + (y + size) as f32 / size as f32, + 1.0, + ); + } + state.clients.push(block); + } + } + state.chunks.push((ChunkX, ChunkY)); + } } impl ApplicationHandler for App { @@ -261,13 +311,28 @@ impl ApplicationHandler for App { movement.y -= 1.0; } + let PosX = state.world.renderer.as_ref().unwrap().eye.frame.translation.x; + let Posy = state.world.renderer.as_ref().unwrap().eye.frame.translation.z; + + let WorldPosX = (PosX / 16.0).floor() as i32; + let WorldPosY = (Posy / 16.0).floor() as i32; + let startX = WorldPosX - 5; + let endX = WorldPosX + 5; + let startY = WorldPosY - 5; + let endY = WorldPosY + 5; + + for x in startX..endX { + for y in startY..endY { + App::GenerateChunk(x, y, 16, state); + } + } state .world .renderer .as_mut() .unwrap() .eye - .control(movement * 0.1); + .control(movement * 0.5); match state.world.renderer.as_mut().unwrap().render(&state.window) { Ok(_) => {} Err(e) => { @@ -285,7 +350,7 @@ impl ApplicationHandler for App { .unwrap() .instance .transform *= Mat4::from_rotation_translation( - Quat::from_euler(EulerRot::XYZ, 0.001, -0.001, 0.001), + Quat::from_euler(EulerRot::XYZ,0.00,0.00,0.00 /*0.001, -0.001, 0.001*/), Vec3::new(0.0, 0.0, 0.0), ); } @@ -308,6 +373,9 @@ impl ApplicationHandler for App { _ => {} } } + + + } pub fn run() -> anyhow::Result<()> { diff --git a/src/lib.rs b/src/lib.rs index 6c22f2e..3275aa0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,6 @@ pub mod app; pub mod render; pub mod web; -pub mod world; \ No newline at end of file +pub mod world; +pub mod permutation_array; +pub mod noise2d; \ No newline at end of file diff --git a/src/noise2d.rs b/src/noise2d.rs new file mode 100644 index 0000000..f473026 --- /dev/null +++ b/src/noise2d.rs @@ -0,0 +1,97 @@ +use crate::permutation_array; +use crate::permutation_array::PermutationArray; + +#[derive(Debug, Clone, Copy)] +pub struct Vector2d { + pub x: f64, + pub y: f64, +} + +impl Vector2d { + pub fn new(x: f64, y: f64) -> Self { + Self { x, y } + } + + pub fn dot(&self, other: Vector2d) -> f64 { + self.x * other.x + self.y * other.y + } +} + +pub struct Noise2D; + +impl Noise2D { + pub fn gen_gradient_vector(p: i32) -> Vector2d { + match p & 3 { + 0 => Vector2d::new(1.0, 1.0), + 1 => Vector2d::new(-1.0, 1.0), + 2 => Vector2d::new(-1.0, -1.0), + _ => Vector2d::new(1.0, -1.0), + } + } + + fn fade(t: f64) -> f64 { + t * t * t * (t * (t * 6.0 - 15.0) + 10.0) + } + + fn lerp(t: f64, x: f64, y: f64) -> f64 { + x + t * (y - x) + } + + pub fn noise_2d(x: f64, y: f64, permutation: &[i32; 512]) -> f64 { + let x_floor = x.floor(); + let y_floor = y.floor(); + + let x_grid = (x_floor as i32) & 255; + let y_grid = (y_floor as i32) & 255; + + let xd = x - x_floor; + let yd = y - y_floor; + + let tr = Vector2d::new(xd - 1.0, yd - 1.0); + let tl = Vector2d::new(xd, yd - 1.0); + let br = Vector2d::new(xd - 1.0, yd); + let bl = Vector2d::new(xd, yd); + + let x_idx = x_grid as usize; + let y_idx = y_grid as usize; + + let value_tr = permutation[permutation[x_idx + 1] as usize + y_idx + 1]; + let value_tl = permutation[permutation[x_idx] as usize + y_idx + 1]; + let value_br = permutation[permutation[x_idx + 1] as usize + y_idx]; + let value_bl = permutation[permutation[x_idx] as usize + y_idx]; + + let d_tr = tr.dot(Self::gen_gradient_vector(value_tr)); + let d_tl = tl.dot(Self::gen_gradient_vector(value_tl)); + let d_br = br.dot(Self::gen_gradient_vector(value_br)); + let d_bl = bl.dot(Self::gen_gradient_vector(value_bl)); + + let u = Self::fade(xd); + let v = Self::fade(yd); + + Self::lerp( + u, + Self::lerp(v, d_bl, d_tl), + Self::lerp(v, d_br, d_tr), + ) + } + + pub fn fractal_noise( + x: f64, + y: f64, + octaves: i32, + mut amplitude: f64, + mut frequency: f64, + permutation: &PermutationArray, + ) -> f64 { + let mut fractal_noise = 0.0; + + for _ in 0..octaves { + let layer = amplitude * Self::noise_2d(x * frequency, y * frequency, permutation.get_permutation()); + fractal_noise += layer; + amplitude *= 0.5; + frequency *= 2.0; + } + + fractal_noise + } +} \ No newline at end of file diff --git a/src/permutation_array.rs b/src/permutation_array.rs new file mode 100644 index 0000000..96e23a8 --- /dev/null +++ b/src/permutation_array.rs @@ -0,0 +1,39 @@ +use rand::{Rng, SeedableRng}; +use rand_chacha::ChaCha8Rng; + +//i translated the Terrain4J Noise2D to Rust so i can mess around with the cubes +pub struct PermutationArray { + permutation: [i32; 512], +} + +impl PermutationArray { + pub fn new() -> Self { + Self { + permutation: [0; 512], + } + } + + pub fn get_permutation(&self) -> &[i32; 512] { + &self.permutation + } + + pub fn generate_permutation_array(&mut self, seed: i64) { + let mut seed_bytes = [0u8; 32]; + seed_bytes[0..8].copy_from_slice(&(seed as u64).to_le_bytes()); + let mut rnd = ChaCha8Rng::from_seed(seed_bytes); + + self.permutation = [0; 512]; + for i in 0..256 { + self.permutation[i] = i as i32; + } + + for p in (1..256).rev() { + let index = rnd.gen_range(0..=p); + self.permutation.swap(p, index); + } + + for i in 0..256 { + self.permutation[i + 256] = self.permutation[i]; + } + } +} \ No newline at end of file