diff --git a/common/src/volumes/vol_grid_2d.rs b/common/src/volumes/vol_grid_2d.rs index 9713888b95..0086bd4ee4 100644 --- a/common/src/volumes/vol_grid_2d.rs +++ b/common/src/volumes/vol_grid_2d.rs @@ -3,7 +3,7 @@ use crate::{ volumes::dyna::DynaError, }; use hashbrown::{hash_map, HashMap}; -use std::{fmt::Debug, sync::Arc}; +use std::{fmt::Debug, ops::Deref, sync::Arc}; use vek::*; #[derive(Debug, Clone)] @@ -159,29 +159,58 @@ impl VolGrid2d { iter: self.chunks.iter(), } } + + pub fn cached<'a>(&'a self) -> CachedVolGrid2d<'a, V> { + CachedVolGrid2d::new(self) + } } -impl VolGrid2d { +pub struct CachedVolGrid2d<'a, V: RectRasterableVol> { + vol_grid_2d: &'a VolGrid2d, + cache: Option<(Vec2, Arc)>, +} +impl<'a, V: RectRasterableVol> CachedVolGrid2d<'a, V> { + pub fn new(vol_grid_2d: &'a VolGrid2d) -> Self { + Self { + vol_grid_2d, + cache: None, + } + } +} +impl<'a, V: RectRasterableVol + ReadVol> CachedVolGrid2d<'a, V> { // Note: this may be invalidated by mutations of the chunks hashmap #[inline(always)] - pub fn get_vox_cached<'a>( - &'a self, - pos: Vec3, - cache: &'a mut Option<(Vec2, Arc)>, - ) -> Result<&V::Vox, VolGrid2dError> { - let ck = Self::chunk_key(pos); - let chunk = if cache.as_ref().map(|(key, _)| *key == ck).unwrap_or(false) { - &cache.as_ref().unwrap().1 + pub fn get(&mut self, pos: Vec3) -> Result<&V::Vox, VolGrid2dError> { + let ck = VolGrid2d::::chunk_key(pos); + let chunk = if self + .cache + .as_ref() + .map(|(key, _)| *key == ck) + .unwrap_or(false) + { + &self.cache.as_ref().unwrap().1 } else { - let chunk = self.chunks.get(&ck).ok_or(VolGrid2dError::NoSuchChunk)?; - *cache = Some((ck, chunk.clone())); + let chunk = self + .vol_grid_2d + .chunks + .get(&ck) + .ok_or(VolGrid2dError::NoSuchChunk)?; + self.cache = Some((ck, chunk.clone())); chunk }; - let co = Self::chunk_offs(pos); + let co = VolGrid2d::::chunk_offs(pos); chunk.get(co).map_err(VolGrid2dError::ChunkError) } } +impl<'a, V: RectRasterableVol> Deref for CachedVolGrid2d<'a, V> { + type Target = VolGrid2d; + + fn deref(&self) -> &Self::Target { + self.vol_grid_2d + } +} + pub struct ChunkIter<'a, V: RectRasterableVol> { iter: hash_map::Iter<'a, Vec2, Arc>, } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 9a50c2a394..8f1975b7a2 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -41,7 +41,7 @@ fn calc_light + ReadVol + Debug>( max: bounds.max + sunlight, }; - let mut get_cache = None; + let mut vol_cached = vol.cached(); let mut voids = HashMap::new(); let mut rays = vec![outer.size().d; outer.size().product() as usize]; @@ -49,8 +49,8 @@ fn calc_light + ReadVol + Debug>( for y in 0..outer.size().h { let mut outside = true; for z in (0..outer.size().d).rev() { - let block = vol - .get_vox_cached(outer.min + Vec3::new(x, y, z), &mut get_cache) + let block = vol_cached + .get(outer.min + Vec3::new(x, y, z)) .ok() .copied() .unwrap_or(Block::empty()); @@ -140,10 +140,10 @@ impl + ReadVol + Debug> Meshable + ReadVol + Debug> Meshable { - self.get_vox_cached($pos, &mut get_cache) - .ok() - .filter(|vox| vox.is_opaque()) - .and_then(|vox| vox.get_color()) - .map(|col| Rgba::from_opaque(col)) - .unwrap_or(Rgba::zero()) - }; + let get_color = |maybe_block: Option<&Block>| { + maybe_block + .filter(|vox| vox.is_opaque()) + .and_then(|vox| vox.get_color()) + .map(|col| Rgba::from_opaque(col)) + .unwrap_or(Rgba::zero()) }; let mut colors = [[[Rgba::zero(); 3]; 3]; 3]; for i in 0..3 { for j in 0..3 { for k in 0..3 { - colors[k][j][i] = get_color!( - Vec3::new(x, y, range.min.z) - + Vec3::new(i as i32, j as i32, k as i32) - - 1 + colors[k][j][i] = get_color( + vol_cached + .get( + Vec3::new(x, y, range.min.z) + + Vec3::new(i as i32, j as i32, k as i32) + - 1, + ) + .ok(), ); } } @@ -199,12 +200,15 @@ impl + ReadVol + Debug> Meshable