fix: panic in terrain meshing

This commit is contained in:
Imbris 2020-01-17 23:05:26 -05:00
parent 5666f18ded
commit b3cdde3ce9
3 changed files with 46 additions and 42 deletions

View File

@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Made shadows and lights use interpolated positions
- Changed "Create Character" button position
- Made clouds bigger, more performant and prettier
- Terrain meshing optimized further
### Removed

View File

@ -243,7 +243,10 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
for x in 0..range.size().w {
for y in 0..range.size().h {
for z in -1..range.size().d + 1 {
let block = *volume.get(range.min + Vec3::new(x, y, z)).unwrap();
let block = volume
.get(range.min + Vec3::new(x, y, z))
.map(|b| *b)
.unwrap_or(Block::empty());
if block.is_opaque() {
lowest_opaque = lowest_opaque.min(z);
highest_opaque = highest_opaque.max(z);

View File

@ -16,7 +16,7 @@ use common::{
};
use crossbeam::channel;
use dot_vox::DotVoxData;
use hashbrown::{hash_map::Entry, HashMap};
use hashbrown::HashMap;
use std::{f32, fmt::Debug, i32, marker::PhantomData, time::Duration};
use treeculler::{BVol, Frustum, AABB};
use vek::*;
@ -837,60 +837,60 @@ impl<V: RectRasterableVol> Terrain<V> {
.map(|(p, _)| *p)
{
let chunk_pos = client.state().terrain().pos_key(pos);
let new_mesh_state = ChunkMeshState {
pos: chunk_pos,
started_tick: current_tick,
active_worker: None,
};
// Only mesh if this chunk has all its neighbors
// If it does have all its neighbors either it should have already been meshed or is in
// mesh_todo
match self.mesh_todo.entry(chunk_pos) {
Entry::Occupied(mut entry) => {
entry.insert(new_mesh_state);
}
Entry::Vacant(entry) => {
if self.chunks.contains_key(&chunk_pos) {
entry.insert(new_mesh_state);
}
let mut neighbours = true;
for i in -1..2 {
for j in -1..2 {
neighbours &= client
.state()
.terrain()
.get_key(chunk_pos + Vec2::new(i, j))
.is_some();
}
}
if neighbours {
self.mesh_todo.insert(
chunk_pos,
ChunkMeshState {
pos: chunk_pos,
started_tick: current_tick,
active_worker: None,
},
);
}
// 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 lighting
// changes in that neighbouring chunk or if the block 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_chunk_pos = client.state().terrain().pos_key(neighbour_pos);
if neighbour_chunk_pos != chunk_pos {
let new_mesh_state = ChunkMeshState {
pos: neighbour_chunk_pos,
started_tick: current_tick,
active_worker: None,
};
// Only mesh if this chunk has all its neighbors
match self.mesh_todo.entry(neighbour_chunk_pos) {
Entry::Occupied(mut entry) => {
entry.insert(new_mesh_state);
}
Entry::Vacant(entry) => {
if self.chunks.contains_key(&neighbour_chunk_pos) {
entry.insert(new_mesh_state);
}
// Only remesh if this chunk has all its neighbors
let mut neighbours = true;
for i in -1..2 {
for j in -1..2 {
neighbours &= client
.state()
.terrain()
.get_key(neighbour_chunk_pos + Vec2::new(i, j))
.is_some();
}
}
if neighbours {
self.mesh_todo.insert(
neighbour_chunk_pos,
ChunkMeshState {
pos: neighbour_chunk_pos,
started_tick: current_tick,
active_worker: None,
},
);
}
}
// TODO: Remesh all neighbours because we have complex lighting now
/*self.mesh_todo.insert(
neighbour_chunk_pos,
ChunkMeshState {
pos: chunk_pos + Vec2::new(x, y),
started_tick: current_tick,
active_worker: None,
},
);
*/
}
}
}