From 542708b4390fe66ec3e6273dc4c4bae71bbaa906 Mon Sep 17 00:00:00 2001 From: Niklas Korz Date: Mon, 31 Mar 2025 19:59:39 +0200 Subject: [PATCH] Use poisson disk distribution for point generation --- Cargo.lock | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/main.rs | 50 +++++++------- 3 files changed, 217 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2efb3ee..a04c334 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -169,6 +178,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + [[package]] name = "arrayref" version = "0.3.9" @@ -292,6 +307,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "base64" version = "0.21.7" @@ -791,7 +812,7 @@ dependencies = [ "glam", "itertools", "rand 0.8.5", - "rand_distr", + "rand_distr 0.4.3", "serde", "smallvec", ] @@ -1472,6 +1493,12 @@ dependencies = [ "libloading", ] +[[package]] +name = "cmov" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1dc960ba75d543267db9254da8ec1cb318a037beb3f8d2497520e410096fab" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1817,6 +1844,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" +[[package]] +name = "divrem" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82" + [[package]] name = "dlib" version = "0.5.2" @@ -1826,6 +1859,12 @@ dependencies = [ "libloading", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "document-features" version = "0.2.11" @@ -1853,6 +1892,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elapsed" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f4e5af126dafd0741c2ad62d47f68b28602550102e5f0dd45c8a97fc8b49c29" + [[package]] name = "encase" version = "0.10.0" @@ -1885,6 +1930,26 @@ dependencies = [ "syn", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1947,6 +2012,18 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fast_poisson" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda9fa8fbe71e6c34b9874bf98905916436c506cbcd64394c43129be0a238592" +dependencies = [ + "kiddo", + "rand 0.9.0", + "rand_distr 0.5.1", + "rand_xoshiro", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1962,6 +2039,19 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fixed" +version = "1.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707070ccf8c4173548210893a0186e29c266901b71ed20cd9e2ca0193dfe95c3" +dependencies = [ + "az", + "bytemuck", + "half", + "num-traits", + "typenum", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2129,6 +2219,19 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "generator" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.58.0", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -2360,6 +2463,16 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "half" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -2461,6 +2574,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" +[[package]] +name = "init_with" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0175f63815ce00183bf755155ad0cb48c65226c5d17a724e369c25418d2b7699" + [[package]] name = "inotify" version = "0.11.0" @@ -2574,6 +2693,32 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "kiddo" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e580022eee0bcd05b8c1c43d3512e79bfa001ccf88ef3dcfd1a3ac74b4e390" +dependencies = [ + "aligned-vec", + "array-init", + "az", + "cmov", + "divrem", + "doc-comment", + "elapsed", + "fixed", + "generator", + "init_with", + "itertools", + "log", + "num-traits", + "ordered-float", + "sorted-vec", + "tracing", + "tracing-subscriber", + "ubyte", +] + [[package]] name = "ktx2" version = "0.3.0" @@ -2909,6 +3054,7 @@ version = "0.1.0" dependencies = [ "bevy", "bevy_vello", + "fast_poisson", "noise", "rand 0.9.0", "voronator", @@ -3244,6 +3390,15 @@ dependencies = [ "libredox", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -3561,6 +3716,16 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.0", +] + [[package]] name = "rand_xorshift" version = "0.3.0" @@ -3570,6 +3735,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", +] + [[package]] name = "range-alloc" version = "0.1.4" @@ -3985,6 +4159,12 @@ dependencies = [ "serde", ] +[[package]] +name = "sorted-vec" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d372029cb5195f9ab4e4b9aef550787dce78b124fcaee8d82519925defcd6f0d" + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -4323,6 +4503,18 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ubyte" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" + [[package]] name = "unicode-bidi" version = "0.3.18" diff --git a/Cargo.toml b/Cargo.toml index 4d10ee4..1c87de2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ opt-level = 3 [dependencies] bevy = "0.15.3" bevy_vello = "0.7.1" +fast_poisson = "1.0.2" noise = "0.9.0" rand = "0.9.0" voronator = "0.2.1" diff --git a/src/main.rs b/src/main.rs index 912a7a9..d03fe54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,13 +4,11 @@ use bevy_vello::{ prelude::*, vello::kurbo::{PathEl, Point}, }; +use fast_poisson::Poisson2D; use noise::{NoiseFn, Simplex}; -use rand::Rng; -use std::ops::DerefMut; +use std::{ops::DerefMut, time::SystemTime}; use voronator::VoronoiDiagram; -const JITTER: f64 = 0.5; - fn main() { App::new() .add_plugins(DefaultPlugins) @@ -28,34 +26,27 @@ fn setup_vector_graphics(mut commands: Commands) { fn draw_map(mut query_scene: Single<(&mut Transform, &mut VelloScene)>) { let (transform, scene) = query_scene.deref_mut(); scene.reset(); - transform.scale = Vec3::ONE * 30.0; - let grid_size_x = 40; - let grid_max_x = grid_size_x / 2; - let grid_min_x = -grid_max_x; + let grid_size_x = 20.0; + let grid_size_y = 10.0; - let grid_size_y = 20; - let grid_max_y = grid_size_y / 2; - let grid_min_y = -grid_max_y; - - let mut rng = rand::rng(); - let mut points = Vec::new(); - for x in grid_min_x..=grid_max_x { - for y in grid_min_y..=grid_max_y { - points.push(( - (x as f64) + rng.random_range(-JITTER..=JITTER), - (y as f64) + rng.random_range(-JITTER..=JITTER), - )); - } - } + let points: Vec<_> = Poisson2D::new() + .with_dimensions([grid_size_x, grid_size_y], 0.2) + .iter() + .map(|[x, y]| (x, y)) + .collect(); let diagram = VoronoiDiagram::::from_tuple( - &(grid_min_x as f64, grid_min_y as f64), - &(grid_max_x as f64, grid_max_y as f64), + &(0.0, 0.0), + &(grid_size_x, grid_size_y), &points, ) .unwrap(); - let noise = Simplex::new(rng.random()); + let seed = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() as u32; + let noise = Simplex::new(seed); for cell in diagram.cells() { let mut first = true; let mut path = Vec::new(); @@ -73,8 +64,8 @@ fn draw_map(mut query_scene: Single<(&mut Transform, &mut VelloScene)>) { } } - let nx = (center.x + grid_max_x as f64) / (grid_size_x as f64) - 0.5; - let ny = (center.y + grid_max_y as f64) / (grid_size_y as f64) - 0.5; + let nx = center.x / (grid_size_x as f64) - 0.5; + let ny = center.y / (grid_size_y as f64) - 0.5; let elevation = (1.0 + noise.get([nx / 0.5, ny / 0.5])) / 2.0; let d = 2.0 * nx.abs().max(ny.abs()); @@ -93,4 +84,9 @@ fn draw_map(mut query_scene: Single<(&mut Transform, &mut VelloScene)>) { &kurbo::BezPath::from_vec(path), ); } + + let scale = 60.0; + transform.scale = Vec3::ONE * scale; + transform.translation = + Vec3::new(-(grid_size_x as f32 / 2.0), grid_size_y as f32 / 2.0, 0.0) * scale; }