use bevy::{prelude::*, winit::WinitSettings}; use bevy_vello::{ VelloPlugin, prelude::*, vello::kurbo::{PathEl, Point}, }; use fast_poisson::Poisson2D; use noise::{NoiseFn, Simplex}; use std::{ops::DerefMut, time::SystemTime}; use voronator::CentroidDiagram; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(VelloPlugin::default()) .insert_resource(WinitSettings::desktop_app()) .add_systems(Startup, setup_vector_graphics) .add_systems(PostStartup, draw_map) .run(); } fn setup_vector_graphics(mut commands: Commands) { commands.spawn((Camera2d, VelloView)); commands.spawn(VelloScene::new()); } fn draw_map(mut query_scene: Single<(&mut Transform, &mut VelloScene)>) { let (transform, scene) = query_scene.deref_mut(); scene.reset(); let grid_size_x = 120.0; let grid_size_y = 60.0; let points: Vec<_> = Poisson2D::new() .with_dimensions([grid_size_x, grid_size_y], 1.0) .iter() .map(|[x, y]| (x, y)) .collect(); // Barycentric dual mesh let mesh = CentroidDiagram::::from_tuple(&points).unwrap(); let seed = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs() as u32; let noise = Simplex::new(seed); for cell in &mesh.cells { let mut first = true; let mut path = Vec::new(); let mut center = Point::new(0.0, 0.0); let points = cell.points().len() as f64; for point in cell.points() { let point = Point::new(point.x, point.y); center.x += point.x / points; center.y += point.y / points; if first { first = false; path.push(PathEl::MoveTo(point)); } else { path.push(PathEl::LineTo(point)); } } 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()); let elevation = (1.0 + elevation - d) / 2.0; let color = if elevation < 0.5 { peniko::Color::from_rgb8(89, 89, 166) } else { peniko::Color::from_rgb8(128, 153, 102) }; scene.fill( peniko::Fill::NonZero, kurbo::Affine::default(), color, None, &kurbo::BezPath::from_vec(path), ); } let scale = 10.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; }