Merge branch 'imbris/mesh-speed' into 'master'

Cache most recent chunk access in terrain meshing

See merge request veloren/veloren!522
This commit is contained in:
Joshua Barretto 2019-10-01 08:23:25 +00:00
commit 9ef7036024
2 changed files with 71 additions and 10 deletions

View File

@ -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,6 +159,56 @@ impl<V: RectRasterableVol> VolGrid2d<V> {
iter: self.chunks.iter(),
}
}
pub fn cached<'a>(&'a self) -> CachedVolGrid2d<'a, V> {
CachedVolGrid2d::new(self)
}
}
pub struct CachedVolGrid2d<'a, V: RectRasterableVol> {
vol_grid_2d: &'a VolGrid2d<V>,
cache: Option<(Vec2<i32>, Arc<V>)>,
}
impl<'a, V: RectRasterableVol> CachedVolGrid2d<'a, V> {
pub fn new(vol_grid_2d: &'a VolGrid2d<V>) -> 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(&mut self, pos: Vec3<i32>) -> Result<&V::Vox, VolGrid2dError<V>> {
let ck = VolGrid2d::<V>::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
.vol_grid_2d
.chunks
.get(&ck)
.ok_or(VolGrid2dError::NoSuchChunk)?;
self.cache = Some((ck, chunk.clone()));
chunk
};
let co = VolGrid2d::<V>::chunk_offs(pos);
chunk.get(co).map_err(VolGrid2dError::ChunkError)
}
}
impl<'a, V: RectRasterableVol> Deref for CachedVolGrid2d<'a, V> {
type Target = VolGrid2d<V>;
fn deref(&self) -> &Self::Target {
self.vol_grid_2d
}
}
pub struct ChunkIter<'a, V: RectRasterableVol> {

View File

@ -41,13 +41,15 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
max: bounds.max + sunlight,
};
let mut vol_cached = vol.cached();
let mut voids = HashMap::new();
let mut rays = vec![outer.size().d; outer.size().product() as usize];
for x in 0..outer.size().w {
for y in 0..outer.size().h {
let mut outside = true;
for z in (0..outer.size().d).rev() {
let block = vol
let block = vol_cached
.get(outer.min + Vec3::new(x, y, z))
.ok()
.copied()
@ -140,6 +142,8 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
let light = calc_light(range, self);
let mut vol_cached = self.cached();
for x in range.min.x + 1..range.max.x - 1 {
for y in range.min.y + 1..range.max.y - 1 {
let mut lights = [[[0.0; 3]; 3]; 3];
@ -155,9 +159,8 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
}
let get_color = |pos| {
self.get(pos)
.ok()
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))
@ -169,9 +172,13 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
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,
vol_cached
.get(
Vec3::new(x, y, range.min.z)
+ Vec3::new(i as i32, j as i32, k as i32)
- 1,
)
.ok(),
);
}
}
@ -193,11 +200,15 @@ 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(
vol_cached
.get(pos + Vec3::new(i as i32, j as i32, 2) - 1)
.ok(),
);
}
}
let block = self.get(pos).ok();
let block = vol_cached.get(pos).ok();
// Create mesh polygons
if block.map(|vox| vox.is_opaque()).unwrap_or(false) {