diff --git a/common/src/volumes/vol_grid_2d.rs b/common/src/volumes/vol_grid_2d.rs index 4432fc80a5..03ecec38af 100644 --- a/common/src/volumes/vol_grid_2d.rs +++ b/common/src/volumes/vol_grid_2d.rs @@ -26,7 +26,7 @@ impl VolGrid2d { #[inline(always)] pub fn chunk_key>>(pos: P) -> Vec2 { pos.into() - .map2(V::RECT_SIZE, |e, sz: u32| e >> (sz - 1).count_ones()) + .map2(V::RECT_SIZE, |e, sz: u32| e.div_euclid(sz as i32)) } #[inline(always)] diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 8ce523ab31..345d6d79b3 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -630,13 +630,25 @@ impl Terrain { // be meshed span!(guard, "Add chunks with modified blocks to mesh todo list"); // TODO: would be useful if modified blocks were grouped by chunk - for pos in scene_data + for (&pos, &block) in scene_data .state .terrain_changes() .modified_blocks .iter() - .map(|(p, _)| *p) { + // TODO: Be cleverer about this to avoid remeshing all neighbours. There are a few things that can create + // an 'effect at a distance'. These are as follows: + // - A glowing block is added or removed, thereby causing a lighting recalculation proportional to its glow + // radius. + // - An opaque block that was blocking sunlight from entering a cavity is removed (or added) thereby + // changing the way that sunlight propagates into the cavity. + // + // We can and should be cleverer about this, but it's non-trivial. For now, just conservatively assume that + // the lighting in all neighbouring chunks is invalidated. Thankfully, this doesn't need to happen often + // because block modification is unusual in Veloren. + // let block_effect_radius = block.get_glow().unwrap_or(0).max(1); + let block_effect_radius = crate::mesh::terrain::MAX_LIGHT_DIST; + // Handle block changes on chunk borders // Remesh all neighbours because we have complex lighting now // TODO: if lighting is on the server this can be updated to only remesh when @@ -644,7 +656,7 @@ impl Terrain { // change was on the border for x in -1..2 { for y in -1..2 { - let neighbour_pos = pos + Vec3::new(x, y, 0); + let neighbour_pos = pos + Vec3::new(x, y, 0) * block_effect_radius; let neighbour_chunk_pos = scene_data.state.terrain().pos_key(neighbour_pos); // Only remesh if this chunk has all its neighbors