From 97f45812244b4eef889279be0bcec22e7b4b56f8 Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:04:26 +0200 Subject: [PATCH] save (works) --- .vscode/launch.json | 45 ++++++++++++++ Cargo.lock | 46 ++++++++++++++ Cargo.toml | 4 +- src/graphics.rs | 5 +- src/main.rs | 3 +- src/state.rs | 148 +++++++++++++++++++++----------------------- 6 files changed, 171 insertions(+), 80 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2ea7828 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. + // Pointez pour afficher la description des attributs existants. + // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'forestiles'", + "cargo": { + "args": [ + "build", + "--bin=forestiles", + "--package=forestiles" + ], + "filter": { + "name": "forestiles", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'forestiles'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=forestiles", + "--package=forestiles" + ], + "filter": { + "name": "forestiles", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 97c67ab..1761901 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -473,6 +473,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "delaunator" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab46e386c7a38300a0d93b0f3e484bc2ee0aded66c47b14762ec9ab383934fa" +dependencies = [ + "robust", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -580,8 +589,10 @@ dependencies = [ "env_logger", "log", "nalgebra", + "noise", "pollster", "rand", + "voronoice", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1004,6 +1015,17 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "noise" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da45c8333f2e152fc665d78a380be060eb84fad8ca4c9f7ac8ca29216cff0cc" +dependencies = [ + "num-traits", + "rand", + "rand_xorshift", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1283,6 +1305,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "range-alloc" version = "0.1.3" @@ -1369,6 +1400,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "robust" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1706,6 +1743,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "voronoice" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23acc5e2a7645f62ff9d7d11b46c15819fb1132fc87352a35bb4a9dee3b27d80" +dependencies = [ + "delaunator", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index a05c3ea..7231f96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,10 @@ wgpu = "22.1" cfg-if = "1" pollster = "0.3" bytemuck = { version = "1.17", features = [ "derive" ] } -rand = "0.8" +rand = { version = "0.8", features = ["small_rng"] } nalgebra = "0.33" +voronoice = "0.2" +noise = "0.9" [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" diff --git a/src/graphics.rs b/src/graphics.rs index d4b6101..487fa7e 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -93,13 +93,13 @@ impl<'a> Graphics<'a> { let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(&state.vertices), + contents: &[bytemuck::cast_slice::(&state.vertices), &[0; 1024]].concat(), usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, }); let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Index Buffer"), - contents: bytemuck::cast_slice(&state.indices), + contents: &[bytemuck::cast_slice::(&state.indices), &[0; 1024]].concat(), usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, }); @@ -265,6 +265,7 @@ impl<'a> Graphics<'a> { rpass.set_vertex_buffer(0, self.vertex_buf.slice(..)); rpass.set_index_buffer(self.index_buf.slice(..), wgpu::IndexFormat::Uint32); rpass.draw_indexed(0..self.state.indices.len() as u32, 0, 0..1); + // rpass.draw(0..self.state.vertices.len() as u32, 0..1); } self.queue.submit(Some(encoder.finish())); diff --git a/src/main.rs b/src/main.rs index e7de5e5..f5a3c43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,8 @@ pub fn main() { #[cfg(not(target_arch = "wasm32"))] { - pollster::block_on(Graphics::init(&window, State::new())).run(event_loop); + let state = State::new(); + pollster::block_on(Graphics::init(&window, state)).run(event_loop); } #[cfg(target_arch = "wasm32")] { diff --git a/src/state.rs b/src/state.rs index 38cf218..d918e02 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,6 +1,7 @@ use std::time::Instant; -use nalgebra::Point2; +use noise::{Fbm, NoiseFn, Perlin}; use rand::prelude::*; +use voronoice::{BoundingBox, Point, Voronoi, VoronoiBuilder, VoronoiCell}; use winit::event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent}; use crate::graphics::{Uniforms, Vertex}; @@ -17,6 +18,8 @@ enum CellKind { impl CellKind { const VARIANTS: u8 = 3; fn color(&self) -> [f32; 4] { + // let mut rng = thread_rng(); + // [rng.gen(), rng.gen(), rng.gen(), 1.] match self { Self::Void => [0.; 4], Self::Sea => [0., 0., 1., 1.], @@ -35,43 +38,64 @@ impl From for CellKind { } } -struct Cell { - pos: Point2, - kind: CellKind +struct CellData { + kind: CellKind, + cell: usize, + z: f32 } -impl Cell { - const RADIUS: f32 = 1.; - fn new(pos: Point2, kind: CellKind) -> Self { +impl CellData { + fn new(kind: CellKind, cell: usize, z: f32) -> Self { Self { - pos, - kind + kind, + cell, + z } } } struct Map { - cells: [Cell; Self::SIZE] + voronoi: Voronoi, + cells_data: Vec, + seed: u32 } impl Map { - const HEIGHT: usize = 10; - const WIDTH: usize = 10; - const SIZE: usize = 10; - fn new() -> Self { - Self { - cells: std::array::from_fn(|_| { - let mut rng = thread_rng(); - Cell::new( - Point2::new(rng.gen_range(-1.0..1.), rng.gen_range(-1.0..1.)), - rng.gen_range(0..CellKind::VARIANTS).into() - ) - }) + const HEIGHT: f32 = 2.; + const WIDTH: f32 = 2.; + const SIZE: usize = 1_00; + fn new(seed: u32) -> Self { + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed as u64); + let mut sites = Vec::with_capacity(Self::SIZE); + for _ in 0..Self::SIZE { + sites.push(Point { x:rng.gen_range(-Self::WIDTH/2.0..Self::WIDTH/2.0) as f64, y:rng.gen_range(-Self::HEIGHT/2.0..Self::HEIGHT/2.0) as f64 }) + } + let voronoi = VoronoiBuilder::default() + .set_sites(sites) + .set_bounding_box(BoundingBox::new_centered(Self::WIDTH as f64, Self::HEIGHT as f64)) + .set_lloyd_relaxation_iterations(5) + .build() + .unwrap(); + let mut cells_data = Vec::with_capacity(Self::SIZE); + let z_noise = Fbm::::new(seed); + for i in 0..Self::SIZE { + let c = voronoi.cell(i); + let site = c.site_position(); + let z = ( + 0.3 // Arbitrary value + + ((z_noise.get([site.x, site.y])+1.)/2.) // Noise + [0; 1] + - ((site.x.powi(2)+site.y.powi(2)).sqrt()*0.5) // Distance - [0; sqrt(2)] * 0.5 + ).clamp(0., 1.); + let k = if z <= 0.5 { + CellKind::Sea + } else { + CellKind::Grass + }; + cells_data.push(CellData::new(k, i, z as f32)); + } + Self { + voronoi, + cells_data, + seed } - - // "sgssv - // ggsvg - // gsvvs - // vgsgs - // ssggs".into() } } @@ -89,7 +113,7 @@ impl State { indices: vec![], uniforms: Uniforms::default(), start: Instant::now(), - map: Map::new() + map: Map::new(0) }; s.update(); s @@ -98,21 +122,15 @@ impl State { match event { Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => { if let state = ElementState::Pressed { - self.uniforms.camera[2] += match button { - MouseButton::Left => 0.1, - MouseButton::Right => -0.1, - _ => 0. + match button { + MouseButton::Left => self.map = Map::new(self.map.seed + 1), + MouseButton::Right => self.map = Map::new(self.map.seed - 1), + _ => {} }; } }, - // Event::WindowEvent { event: WindowEvent::MouseWheel { delta, ..}, ..} => { - // self.uniforms.camera[2] -= match delta { - // MouseScrollDelta::PixelDelta(pos) => pos.y as f32, - // MouseScrollDelta::LineDelta(_, y) => y - // }; - // }, Event::DeviceEvent { event: DeviceEvent::MouseWheel { delta }, ..} => { - self.uniforms.camera[2] += match delta { + self.uniforms.camera[2] -= match delta { MouseScrollDelta::PixelDelta(pos) => pos.y as f32, MouseScrollDelta::LineDelta(_, y) => y }; @@ -121,43 +139,21 @@ impl State { } } pub fn update(&mut self) { - self.vertices = Vec::with_capacity(self.map.cells.len()*6); - self.indices = Vec::with_capacity(self.map.cells.len()*12); - - for c in self.map.cells.iter() { - let x = x as f32; - let y = y as f32; - let i = self.vertices.len(); - let color = c.kind.color(); - let center = [(0.5+x+((y%2.)*0.5)) * (SQRT_3*Cell::RADIUS), -(0.5+y)*(1.5*Cell::RADIUS)]; - // self.vertices.push(Vertex { pos: [center[0], center[1], 0.], color }); - // self.vertices.push(Vertex { pos: [center[0]+0.1, center[1]+0.1, 0.], color }); - // self.vertices.push(Vertex { pos: [center[0]-0.1, center[1]+0.1, 0.], color }); - self.vertices.push(Vertex { pos: [center[0], center[1]+Cell::RADIUS, 0.], color: color.clone() }); - self.vertices.push(Vertex { pos: [center[0]-(0.5*SQRT_3*Cell::RADIUS), center[1]+(0.5*Cell::RADIUS), 0.], color: color.clone() }); - self.vertices.push(Vertex { pos: [center[0]+(0.5*SQRT_3*Cell::RADIUS), center[1]+(0.5*Cell::RADIUS), 0.], color: color.clone() }); - self.vertices.push(Vertex { pos: [center[0]-(0.5*SQRT_3*Cell::RADIUS), center[1]-(0.5*Cell::RADIUS), 0.], color: color.clone() }); - self.vertices.push(Vertex { pos: [center[0]+(0.5*SQRT_3*Cell::RADIUS), center[1]-(0.5*Cell::RADIUS), 0.], color: color.clone() }); - self.vertices.push(Vertex { pos: [center[0], center[1]-Cell::RADIUS, 0.], color: color.clone() }); + self.vertices = Vec::new(); + self.indices = Vec::new(); - self.indices.push(i as u32); - self.indices.push((i+1) as u32); - self.indices.push((i+2) as u32); - - self.indices.push((i+1) as u32); - self.indices.push((i+3) as u32); - self.indices.push((i+2) as u32); - - self.indices.push((i+3) as u32); - self.indices.push((i+4) as u32); - self.indices.push((i+2) as u32); - - self.indices.push((i+3) as u32); - self.indices.push((i+5) as u32); - self.indices.push((i+4) as u32); + for (c, data) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()) { + let color = data.kind.color(); + let vs = c.iter_vertices().collect::>(); + let i = self.vertices.len() as u32; + for v in vs.iter() { + self.vertices.push(Vertex { pos: [v.x as f32, v.y as f32, data.z], color }); + } + for v in 1..(vs.len()-1) as u32 { + self.indices.push(i); + self.indices.push(i+v); + self.indices.push(i+v+1); + } } - - // dbg!(&self.vertices, &self.indices, &self.uniforms); - // dbg!(self.vertices.len(), self.indices.len(), &self.uniforms); } } \ No newline at end of file