save (works)

This commit is contained in:
Arkitu 2024-08-23 18:04:26 +02:00
parent 549bd261b8
commit 97f4581224
6 changed files with 171 additions and 80 deletions

45
.vscode/launch.json vendored Normal file
View File

@ -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}"
}
]
}

46
Cargo.lock generated
View File

@ -473,6 +473,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "delaunator"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab46e386c7a38300a0d93b0f3e484bc2ee0aded66c47b14762ec9ab383934fa"
dependencies = [
"robust",
]
[[package]] [[package]]
name = "dispatch" name = "dispatch"
version = "0.2.0" version = "0.2.0"
@ -580,8 +589,10 @@ dependencies = [
"env_logger", "env_logger",
"log", "log",
"nalgebra", "nalgebra",
"noise",
"pollster", "pollster",
"rand", "rand",
"voronoice",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures", "wasm-bindgen-futures",
"web-sys", "web-sys",
@ -1004,6 +1015,17 @@ dependencies = [
"jni-sys", "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]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.6" version = "0.4.6"
@ -1283,6 +1305,15 @@ dependencies = [
"getrandom", "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]] [[package]]
name = "range-alloc" name = "range-alloc"
version = "0.1.3" version = "0.1.3"
@ -1369,6 +1400,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "robust"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "1.1.0" version = "1.1.0"
@ -1706,6 +1743,15 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "voronoice"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23acc5e2a7645f62ff9d7d11b46c15819fb1132fc87352a35bb4a9dee3b27d80"
dependencies = [
"delaunator",
]
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.5.0" version = "2.5.0"

View File

@ -11,8 +11,10 @@ wgpu = "22.1"
cfg-if = "1" cfg-if = "1"
pollster = "0.3" pollster = "0.3"
bytemuck = { version = "1.17", features = [ "derive" ] } bytemuck = { version = "1.17", features = [ "derive" ] }
rand = "0.8" rand = { version = "0.8", features = ["small_rng"] }
nalgebra = "0.33" nalgebra = "0.33"
voronoice = "0.2"
noise = "0.9"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6" console_error_panic_hook = "0.1.6"

View File

@ -93,13 +93,13 @@ impl<'a> Graphics<'a> {
let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"), label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(&state.vertices), contents: &[bytemuck::cast_slice::<Vertex, _>(&state.vertices), &[0; 1024]].concat(),
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
}); });
let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"), label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&state.indices), contents: &[bytemuck::cast_slice::<u32, _>(&state.indices), &[0; 1024]].concat(),
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, 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_vertex_buffer(0, self.vertex_buf.slice(..));
rpass.set_index_buffer(self.index_buf.slice(..), wgpu::IndexFormat::Uint32); 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_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())); self.queue.submit(Some(encoder.finish()));

View File

@ -20,7 +20,8 @@ pub fn main() {
#[cfg(not(target_arch = "wasm32"))] #[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")] #[cfg(target_arch = "wasm32")]
{ {

View File

@ -1,6 +1,7 @@
use std::time::Instant; use std::time::Instant;
use nalgebra::Point2; use noise::{Fbm, NoiseFn, Perlin};
use rand::prelude::*; use rand::prelude::*;
use voronoice::{BoundingBox, Point, Voronoi, VoronoiBuilder, VoronoiCell};
use winit::event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent}; use winit::event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent};
use crate::graphics::{Uniforms, Vertex}; use crate::graphics::{Uniforms, Vertex};
@ -17,6 +18,8 @@ enum CellKind {
impl CellKind { impl CellKind {
const VARIANTS: u8 = 3; const VARIANTS: u8 = 3;
fn color(&self) -> [f32; 4] { fn color(&self) -> [f32; 4] {
// let mut rng = thread_rng();
// [rng.gen(), rng.gen(), rng.gen(), 1.]
match self { match self {
Self::Void => [0.; 4], Self::Void => [0.; 4],
Self::Sea => [0., 0., 1., 1.], Self::Sea => [0., 0., 1., 1.],
@ -35,43 +38,64 @@ impl From<u8> for CellKind {
} }
} }
struct Cell { struct CellData {
pos: Point2<f32>, kind: CellKind,
kind: CellKind cell: usize,
z: f32
} }
impl Cell { impl CellData {
const RADIUS: f32 = 1.; fn new(kind: CellKind, cell: usize, z: f32) -> Self {
fn new(pos: Point2<f32>, kind: CellKind) -> Self {
Self { Self {
pos, kind,
kind cell,
z
} }
} }
} }
struct Map { struct Map {
cells: [Cell; Self::SIZE] voronoi: Voronoi,
cells_data: Vec<CellData>,
seed: u32
} }
impl Map { impl Map {
const HEIGHT: usize = 10; const HEIGHT: f32 = 2.;
const WIDTH: usize = 10; const WIDTH: f32 = 2.;
const SIZE: usize = 10; const SIZE: usize = 1_00;
fn new() -> Self { fn new(seed: u32) -> Self {
Self { let mut rng = rand::rngs::SmallRng::seed_from_u64(seed as u64);
cells: std::array::from_fn(|_| { let mut sites = Vec::with_capacity(Self::SIZE);
let mut rng = thread_rng(); for _ in 0..Self::SIZE {
Cell::new( 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 })
Point2::new(rng.gen_range(-1.0..1.), rng.gen_range(-1.0..1.)), }
rng.gen_range(0..CellKind::VARIANTS).into() 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::<Perlin>::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![], indices: vec![],
uniforms: Uniforms::default(), uniforms: Uniforms::default(),
start: Instant::now(), start: Instant::now(),
map: Map::new() map: Map::new(0)
}; };
s.update(); s.update();
s s
@ -98,21 +122,15 @@ impl State {
match event { match event {
Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => { Event::WindowEvent { event: WindowEvent::MouseInput { state, button, ..}, ..} => {
if let state = ElementState::Pressed { if let state = ElementState::Pressed {
self.uniforms.camera[2] += match button { match button {
MouseButton::Left => 0.1, MouseButton::Left => self.map = Map::new(self.map.seed + 1),
MouseButton::Right => -0.1, MouseButton::Right => self.map = Map::new(self.map.seed - 1),
_ => 0. _ => {}
}; };
} }
}, },
// 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 }, ..} => { 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::PixelDelta(pos) => pos.y as f32,
MouseScrollDelta::LineDelta(_, y) => y MouseScrollDelta::LineDelta(_, y) => y
}; };
@ -121,43 +139,21 @@ impl State {
} }
} }
pub fn update(&mut self) { pub fn update(&mut self) {
self.vertices = Vec::with_capacity(self.map.cells.len()*6); self.vertices = Vec::new();
self.indices = Vec::with_capacity(self.map.cells.len()*12); self.indices = Vec::new();
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.indices.push(i as u32); for (c, data) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()) {
self.indices.push((i+1) as u32); let color = data.kind.color();
self.indices.push((i+2) as u32); let vs = c.iter_vertices().collect::<Vec<_>>();
let i = self.vertices.len() as u32;
self.indices.push((i+1) as u32); for v in vs.iter() {
self.indices.push((i+3) as u32); self.vertices.push(Vertex { pos: [v.x as f32, v.y as f32, data.z], color });
self.indices.push((i+2) as u32); }
for v in 1..(vs.len()-1) as u32 {
self.indices.push((i+3) as u32); self.indices.push(i);
self.indices.push((i+4) as u32); self.indices.push(i+v);
self.indices.push((i+2) as u32); self.indices.push(i+v+1);
}
self.indices.push((i+3) as u32);
self.indices.push((i+5) as u32);
self.indices.push((i+4) as u32);
} }
// dbg!(&self.vertices, &self.indices, &self.uniforms);
// dbg!(self.vertices.len(), self.indices.len(), &self.uniforms);
} }
} }