Cache most recent chunk access in terrain meshing

This commit is contained in:
Imbris 2019-09-29 01:53:22 -04:00 committed by Imbris
parent ff82e77ec9
commit 89a1c45ac7
2 changed files with 40 additions and 12 deletions

View File

@ -161,6 +161,27 @@ impl<V: RectRasterableVol> VolGrid2d<V> {
}
}
impl<V: RectRasterableVol + ReadVol> VolGrid2d<V> {
// Note: this may be invalidated by mutations of the chunks hashmap
#[inline(always)]
pub fn get_vox_cached<'a>(
&'a self,
pos: Vec3<i32>,
cache: &'a mut Option<(Vec2<i32>, Arc<V>)>,
) -> Result<&V::Vox, VolGrid2dError<V>> {
let ck = Self::chunk_key(pos);
let chunk = if cache.as_ref().map(|(key, _)| *key == ck).unwrap_or(false) {
&cache.as_ref().unwrap().1
} else {
let chunk = self.chunks.get(&ck).ok_or(VolGrid2dError::NoSuchChunk)?;
*cache = Some((ck, chunk.clone()));
chunk
};
let co = Self::chunk_offs(pos);
chunk.get(co).map_err(VolGrid2dError::ChunkError)
}
}
pub struct ChunkIter<'a, V: RectRasterableVol> {
iter: hash_map::Iter<'a, Vec2<i32>, Arc<V>>,
}

View File

@ -41,6 +41,8 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
max: bounds.max + sunlight,
};
let mut get_cache = None;
let mut voids = HashMap::new();
let mut rays = vec![outer.size().d; outer.size().product() as usize];
for x in 0..outer.size().w {
@ -48,7 +50,7 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
let mut outside = true;
for z in (0..outer.size().d).rev() {
let block = vol
.get(outer.min + Vec3::new(x, y, z))
.get_vox_cached(outer.min + Vec3::new(x, y, z), &mut get_cache)
.ok()
.copied()
.unwrap_or(Block::empty());
@ -138,6 +140,8 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
let mut opaque_mesh = Mesh::new();
let mut fluid_mesh = Mesh::new();
let mut get_cache = None;
let light = calc_light(range, self);
for x in range.min.x + 1..range.max.x - 1 {
@ -155,23 +159,25 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
}
let get_color = |pos| {
self.get(pos)
.ok()
.filter(|vox| vox.is_opaque())
.and_then(|vox| vox.get_color())
.map(|col| Rgba::from_opaque(col))
.unwrap_or(Rgba::zero())
macro_rules! get_color {
($pos:expr) => {
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 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(
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,
- 1
);
}
}
@ -193,11 +199,12 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
for i in 0..3 {
for j in 0..3 {
colors[2][j][i] = get_color(pos + Vec3::new(i as i32, j as i32, 2) - 1);
colors[2][j][i] =
get_color!(pos + Vec3::new(i as i32, j as i32, 2) - 1);
}
}
let block = self.get(pos).ok();
let block = self.get_vox_cached(pos, &mut get_cache).ok();
// Create mesh polygons
if block.map(|vox| vox.is_opaque()).unwrap_or(false) {