diff options
author | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-05-15 19:36:28 +0200 |
---|---|---|
committer | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-05-15 19:36:28 +0200 |
commit | 654b4ec6fa67de3c19fed8d32850cc9d30c83190 (patch) | |
tree | 7a2c18e8a963c4e26953d7d0863481ecb6a05fe6 /src/gfx | |
parent | 6f887d475d32f32ebdd1f914f5067031b12d025d (diff) | |
download | mt_client-654b4ec6fa67de3c19fed8d32850cc9d30c83190.tar.xz |
Cull faces to neighbor blocks
Diffstat (limited to 'src/gfx')
-rw-r--r-- | src/gfx/map.rs | 67 | ||||
-rw-r--r-- | src/gfx/map/mesh.rs | 44 |
2 files changed, 80 insertions, 31 deletions
diff --git a/src/gfx/map.rs b/src/gfx/map.rs index 5a714a2..42fff6c 100644 --- a/src/gfx/map.rs +++ b/src/gfx/map.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, ops::{Deref, DerefMut}, - sync::{Arc, Mutex}, + sync::{Arc, Mutex, RwLock}, }; use wgpu::util::DeviceExt; @@ -55,10 +55,11 @@ pub struct MapRender { pipeline: wgpu::RenderPipeline, atlas: wgpu::BindGroup, model: wgpu::BindGroupLayout, - blocks: HashMap<[i16; 3], BlockModel>, + blocks: Arc<RwLock<HashMap<Point3<i16>, Arc<MapBlock>>>>, + block_models: HashMap<Point3<i16>, BlockModel>, meshgen_info: Arc<MeshgenInfo>, meshgen_threads: Vec<std::thread::JoinHandle<()>>, - meshgen_channel: crossbeam_channel::Sender<(Point3<i16>, Box<MapBlock>)>, + meshgen_channel: crossbeam_channel::Sender<Point3<i16>>, queue_consume: MeshQueue, queue_produce: Arc<Mutex<MeshQueue>>, } @@ -139,7 +140,7 @@ impl MapRender { let mut blend = Vec::new(); - for (index, (&pos, model)) in self.blocks.iter().enumerate() { + for (index, (&pos, model)) in self.block_models.iter().enumerate() { if model.mesh.is_none() && model.mesh_blend.is_none() { continue; } @@ -186,7 +187,7 @@ impl MapRender { &mut self.queue_consume, ); for (pos, data) in self.queue_consume.drain() { - self.blocks.insert( + self.block_models.insert( pos.into(), BlockModel { mesh: BlockMesh::new(state, &data.vertices), @@ -203,9 +204,16 @@ impl MapRender { } } + // TODO: move this to a map thread pub fn add_block(&self, pos: Point3<i16>, block: Box<MapBlock>) { - // FIXME: received mapblocks are propagated twice: network -> gfx -> meshgen - self.meshgen_channel.send((pos, block)).ok(); + self.blocks.write().unwrap().insert(pos, Arc::new(*block)); + + self.meshgen_channel.send(pos).ok(); + + // TODO: make this smarter (less rebuilds pls) + for off in FACE_DIR { + self.meshgen_channel.send(pos + Vector3::from(off)).ok(); + } } pub fn new(state: &mut State, media: &MediaMgr, mut nodes: HashMap<u16, NodeDef>) -> Self { @@ -368,20 +376,48 @@ impl MapRender { let mut meshgen_threads = Vec::new(); let (meshgen_tx, meshgen_rx) = crossbeam_channel::unbounded(); + let blocks = Arc::new(RwLock::new(HashMap::<Point3<i16>, Arc<MapBlock>>::new())); + // TODO: make this configurable for _ in 0..2 { let input = meshgen_rx.clone(); let output = meshgen_queue.clone(); let info = meshgen_info.clone(); let config = Default::default(); + let blocks = blocks.clone(); meshgen_threads.push(std::thread::spawn(move || { let mut buffer_cap = 0; let info = info.deref(); - while let Ok((pos, block)) = input.recv() { + while let Ok(pos) = input.recv() { let mut data = MeshData::new(buffer_cap); - create_mesh(info, &config, pos, block, &mut data); + + let blocks = blocks.read().unwrap(); + + let block = match blocks.get(&pos) { + Some(x) => x.clone(), + None => continue, + }; + + let nbors: [_; 6] = std::array::from_fn(|i| { + blocks.get(&(pos + Vector3::from(FACE_DIR[i]))).cloned() + }); + + drop(blocks); + + create_mesh( + info, + &config, + pos, + block.deref(), + std::array::from_fn(|i| nbors[i].as_deref()), + &mut data, + ); + + drop(block); + drop(nbors); + buffer_cap = data.cap(); output.lock().unwrap().insert(pos, data); } @@ -392,7 +428,8 @@ impl MapRender { pipeline, atlas: atlas_bind_group, model: model_bind_group_layout, - blocks: HashMap::new(), + blocks, + block_models: HashMap::new(), meshgen_info, meshgen_threads, meshgen_channel: meshgen_tx, @@ -453,3 +490,13 @@ const CUBE: [[([f32; 3], [f32; 2]); 6]; 6] = [ ([-0.5, 0.5, -0.5], [ 0.0, 1.0]), ], ]; + +#[rustfmt::skip] +const FACE_DIR: [[i16; 3]; 6] = [ + [ 0, 1, 0], + [ 0, -1, 0], + [ 1, 0, 0], + [-1, 0, 0], + [ 0, 0, 1], + [ 0, 0, -1], +]; diff --git a/src/gfx/map/mesh.rs b/src/gfx/map/mesh.rs index 51bf9f6..e504be4 100644 --- a/src/gfx/map/mesh.rs +++ b/src/gfx/map/mesh.rs @@ -1,4 +1,4 @@ -use super::{LeavesMode, MapRenderSettings, MeshgenInfo, Vertex, CUBE}; +use super::{LeavesMode, MapRenderSettings, MeshgenInfo, Vertex, CUBE, FACE_DIR}; use cgmath::Point3; use mt_net::MapBlock; @@ -25,7 +25,8 @@ pub(super) fn create_mesh( mkinfo: &MeshgenInfo, settings: &MapRenderSettings, pos: Point3<i16>, - block: Box<MapBlock>, + block: &MapBlock, + nbors: [Option<&MapBlock>; 6], buffer: &mut MeshData, ) { for (index, content) in block.param_0.iter().enumerate() { @@ -64,15 +65,26 @@ pub(super) fn create_mesh( let pos: [i16; 3] = array(|i| ((index >> (4 * i)) & 0xf) as i16); for (f, face) in CUBE.iter().enumerate() { - let dir = FACE_DIR[f]; - let npos: [i16; 3] = array(|i| dir[i] + pos[i]); - if npos.iter().all(|x| (0..16).contains(x)) { - let nindex = npos[0] | (npos[1] << 4) | (npos[2] << 8); - - if let Some(ndef) = &mkinfo.nodes[block.param_0[nindex as usize] as usize] { - if ndef.draw_type == DrawType::Cube { - continue; - } + let c = [1, 1, 0, 0, 2, 2][f]; + + let mut nblk = block; + let mut npos = pos; + npos[c] += FACE_DIR[f][c]; + + if !(0..16).contains(&npos[c]) { + nblk = match nbors[f].as_ref() { + Some(x) => x, + None => continue, + }; + + npos[c] = (npos[c] + 16) % 16; + } + + let nidx = npos[0] | (npos[1] << 4) | (npos[2] << 8); + + if let Some(ndef) = &mkinfo.nodes[nblk.param_0[nidx as usize] as usize] { + if ndef.draw_type == DrawType::Cube { + continue; } } @@ -94,13 +106,3 @@ pub(super) fn create_mesh( } } } - -#[rustfmt::skip] -const FACE_DIR: [[i16; 3]; 6] = [ - [ 0, 1, 0], - [ 0, -1, 0], - [ 1, 0, 0], - [-1, 0, 0], - [ 0, 0, 1], - [ 0, 0, -1], -]; |