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 - Made shadows and lights use interpolated positions
- Changed "Create Character" button position - Changed "Create Character" button position
- Made clouds bigger, more performant and prettier - Made clouds bigger, more performant and prettier
- Terrain meshing optimized further
### Removed ### Removed

View File

@ -243,7 +243,10 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
for x in 0..range.size().w { for x in 0..range.size().w {
for y in 0..range.size().h { for y in 0..range.size().h {
for z in -1..range.size().d + 1 { 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() { if block.is_opaque() {
lowest_opaque = lowest_opaque.min(z); lowest_opaque = lowest_opaque.min(z);
highest_opaque = highest_opaque.max(z); highest_opaque = highest_opaque.max(z);

View File

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