diff --git a/src/lib.rs b/src/lib.rs index bed4ac6..272a676 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(iter_array_chunks)] use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, prelude::*, diff --git a/src/map.rs b/src/map.rs index ad49046..4f7334a 100644 --- a/src/map.rs +++ b/src/map.rs @@ -30,7 +30,7 @@ impl bevy::prelude::Plugin for Plugin { app.add_plugins(cells::Plugin) .add_systems(Startup, setup) .add_systems(PreUpdate, picking_backend.in_set(PickSet::Backend)) - .add_systems(Update, update_map_mesh) + .add_systems(Update, update_chunk_mesh) .insert_resource(ClearColor(Color::srgb(0., 0., 1.))) .insert_resource(Seed(thread_rng().gen())); } @@ -186,29 +186,7 @@ fn setup( indices[chs[2]].push((t[2] % CELLS_PER_CHUNK) as u32); } } - let mut cells_entities = Vec::with_capacity(cells.len()); - for cell in cells { - let kind = cell.kind; - // let id = cell.voronoi_id; - let mut cmd = cmds.spawn(cell); - // if let Some(ch) = hybrid_cells.get(&id) { - // cmd.insert(GhostCell(*ch)); - // } - match kind { - CellKind::Grass | CellKind::Forest => { - cmd.insert(( - Wealth(0), - Regeneration { - last_update: Duration::ZERO, - full_growth_duration: kind.regen_full_growth_duration(), - }, - )); - } - _ => {} - } - cmd.observe(self::cells::on_click); - cells_entities.push(cmd.id()); - } + // indices.extend(voronoi.triangulation().triangles.iter().map(|t| *t as u32)); // for (c, cd) in voronoi.iter_cells().zip(cells.iter_mut()) { @@ -232,7 +210,12 @@ fn setup( // cd.vertices.extend_from_slice(&[i, i + v, i + v + 1]); // } // } - for (poss, indices) in poss.into_iter().zip(indices.into_iter()) { + let mut cells_entities = Vec::with_capacity(cells.len()); + for ((poss, indices), ch_cells) in poss + .into_iter() + .zip(indices.into_iter()) + .zip(cells.chunks_exact(CELLS_PER_CHUNK)) + { let colors = vec![[0.; 4]; poss.len()]; let mut mesh = Mesh::new( PrimitiveTopology::TriangleList, @@ -262,7 +245,31 @@ fn setup( MeshColors(colors), MeshNeedsUpdate(true), MapMarker, - )); + )) + .with_children(|parent| { + for cell in ch_cells { + let kind = cell.kind; + // let id = cell.voronoi_id; + let mut cmd = parent.spawn(cell.clone()); + // if let Some(ch) = hybrid_cells.get(&id) { + // cmd.insert(GhostCell(*ch)); + // } + match kind { + CellKind::Grass | CellKind::Forest => { + cmd.insert(( + Wealth(0), + Regeneration { + last_update: Duration::ZERO, + full_growth_duration: kind.regen_full_growth_duration(), + }, + )); + } + _ => {} + } + cmd.observe(self::cells::on_click); + cells_entities.push(cmd.id()); + } + }); } cmds.insert_resource(Voronoi(voronoi)); @@ -270,31 +277,33 @@ fn setup( } // TODO: update this to take chunks into account -fn update_map_mesh( +fn update_chunk_mesh( cells: Query<(&Cell, Option<&Wealth>)>, - mut map: Query<(&Mesh3d, &mut MeshColors, &mut MeshNeedsUpdate), With>, + mut chunks: Query<(&Mesh3d, &mut MeshColors, &mut MeshNeedsUpdate, &Children), With>, mut meshes: ResMut>, ) { - let (mesh, mut cols, mut needs_update) = map.single_mut(); - if needs_update.0 { - if let Some(mesh) = meshes.get_mut(mesh) { - let mut modified = false; - // let mut rng = thread_rng(); - for (cell, wealth) in cells.iter() { - // let col: [f32; 4] = [rng.gen(), rng.gen(), rng.gen(), 1.]; - let col = cell.color(wealth.map(|w| w.0).unwrap_or_default()); - modified = modified || cols.0[cell.voronoi_id] != col; - cols.0[cell.voronoi_id] = col; - // for id in cell.vertices.iter() { - // modified = modified || cols.0[*id] != col; - // cols.0[*id] = col.clone(); - // } - } - if modified { - mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, cols.0.clone()); + for (mesh, mut cols, mut needs_update, children) in chunks.iter_mut() { + if needs_update.0 { + if let Some(mesh) = meshes.get_mut(mesh) { + let mut modified = false; + // let mut rng = thread_rng(); + for child in children.iter() { + let (cell, wealth) = cells.get(*child).unwrap(); + // let col: [f32; 4] = [rng.gen(), rng.gen(), rng.gen(), 1.]; + let col = cell.color(wealth.map(|w| w.0).unwrap_or_default()); + modified = modified || cols.0[cell.voronoi_id % CELLS_PER_CHUNK] != col; + cols.0[cell.voronoi_id % CELLS_PER_CHUNK] = col; + // for id in cell.vertices.iter() { + // modified = modified || cols.0[*id] != col; + // cols.0[*id] = col.clone(); + // } + } + if modified { + mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, cols.0.clone()); + } } + needs_update.0 = false; } - needs_update.0 = false; } } diff --git a/src/map/cells.rs b/src/map/cells.rs index 0ff5cba..34245ce 100644 --- a/src/map/cells.rs +++ b/src/map/cells.rs @@ -52,7 +52,7 @@ impl CellKind { } } -#[derive(Debug, Component)] +#[derive(Debug, Component, Clone)] pub struct Cell { pub kind: CellKind, pub voronoi_id: usize, @@ -111,12 +111,11 @@ pub struct Regeneration { const STEP: u8 = u8::MAX / 4; pub fn cells_regeneration( - mut cells: Query<(&mut Regeneration, &mut Wealth)>, - mut map_needs_update: Query<&mut MeshNeedsUpdate, With>, + mut cells: Query<(&mut Regeneration, &mut Wealth, &Parent)>, + mut chunks: Query<&mut MeshNeedsUpdate, With>, gt: Res, ) { - let mut map_needs_update = map_needs_update.single_mut(); - for (mut regen, mut wealth) in cells.iter_mut() { + for (mut regen, mut wealth, parent) in cells.iter_mut() { while gt.current - regen.last_update > regen.full_growth_duration / u8::MAX as u32 { regen.last_update = gt .current @@ -124,7 +123,7 @@ pub fn cells_regeneration( wealth.0 = wealth.0.saturating_add(1); // Not update map each time for optimization if wealth.0 % STEP == 0 { - map_needs_update.0 = true; + chunks.get_mut(parent.get()).unwrap().0 = true; } } } diff --git a/src/map/picking.rs b/src/map/picking.rs index 3f01d7e..39020e1 100644 --- a/src/map/picking.rs +++ b/src/map/picking.rs @@ -15,14 +15,14 @@ pub fn picking_backend( cam: Query<(&Transform, Entity), With>, window: Query<&Window, With>, pointers: Query<(&PointerId, &PointerLocation)>, - map: Query<&Transform, With>, + // map: Query<&Transform, With>, voronoi: Res, cells_entities: Res, mut output: EventWriter, ) { let (cam, cam_id) = cam.single(); let window = window.single(); - let map_pos = map.single(); + let map_pos = Transform::default(); let mut last_cell = 0; for (id, l) in pointers.iter() { if let Some(mut pos) = l.location().map(|l| l.position) {