From 99caa0103267fa166021e4c3b86a7c4cca519699 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Mon, 21 Mar 2016 16:36:50 +0000 Subject: [PATCH] Implement basic culling --- src/chunk_builder.rs | 67 +++++++++++++++++++++---- src/world/mod.rs | 113 ++++++++++++++++++++++++++----------------- 2 files changed, 127 insertions(+), 53 deletions(-) diff --git a/src/chunk_builder.rs b/src/chunk_builder.rs index 509f0bf..130206e 100644 --- a/src/chunk_builder.rs +++ b/src/chunk_builder.rs @@ -104,7 +104,14 @@ fn build_func(id: usize, textures: Arc>, work_rec continue; } - for verts in &PRECOMPUTED_VERTS { + for dir in Direction::all() { + + let offset = dir.get_offset(); + let other = snapshot.get_block(x + offset.0, y + offset.1, z + offset.2); + if other.renderable() { + continue; + } + let stone = render::Renderer::get_texture(&textures, rng.choose(&[ "minecraft:blocks/lava_flow", "minecraft:blocks/stone", @@ -112,7 +119,7 @@ fn build_func(id: usize, textures: Arc>, work_rec "minecraft:blocks/sand", ]).unwrap()); solid_count += 6; - for vert in verts { + for vert in dir.get_verts() { let mut vert = vert.clone(); // TODO vert.r = 255; @@ -152,38 +159,80 @@ fn build_func(id: usize, textures: Arc>, work_rec } } -const PRECOMPUTED_VERTS: [[BlockVertex; 4]; 6] = [ - [ // Up +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + Up, + Down, + North, + South, + West, + East, +} + +impl Direction { + pub fn all() -> Vec { + vec![ + Direction::Up, Direction::Down, + Direction::North, Direction::South, + Direction::West, Direction::East, + ] + } + + pub fn get_verts(&self) -> &'static [BlockVertex; 4] { + match *self { + Direction::Up => PRECOMPUTED_VERTS[0], + Direction::Down => PRECOMPUTED_VERTS[1], + Direction::North => PRECOMPUTED_VERTS[2], + Direction::South => PRECOMPUTED_VERTS[3], + Direction::West => PRECOMPUTED_VERTS[4], + Direction::East => PRECOMPUTED_VERTS[5], + } + } + + pub fn get_offset(&self) -> (i32, i32, i32) { + match *self { + Direction::Up => (0, 1, 0), + Direction::Down => (0, -1, 0), + Direction::North => (0, 0, -1), + Direction::South => (0, 0, 1), + Direction::West => (-1, 0, 0), + Direction::East => (1, 0, 0), + } + } +} + +const PRECOMPUTED_VERTS: [&'static [BlockVertex; 4]; 6] = [ + &[ // Up BlockVertex::base(0.0, 1.0, 0.0, 0, 0), BlockVertex::base(1.0, 1.0, 0.0, 1, 0), BlockVertex::base(0.0, 1.0, 1.0, 0, 1), BlockVertex::base(1.0, 1.0, 1.0, 1, 1), ], - [ // Down + &[ // Down BlockVertex::base(0.0, 0.0, 0.0, 0, 1), BlockVertex::base(0.0, 0.0, 1.0, 0, 0), BlockVertex::base(1.0, 0.0, 0.0, 1, 1), BlockVertex::base(1.0, 0.0, 1.0, 1, 0), ], - [ // North + &[ // North BlockVertex::base(0.0, 0.0, 0.0, 1, 1), BlockVertex::base(1.0, 0.0, 0.0, 0, 1), BlockVertex::base(0.0, 1.0, 0.0, 1, 0), BlockVertex::base(1.0, 1.0, 0.0, 0, 0), ], - [ // South + &[ // South BlockVertex::base(0.0, 0.0, 1.0, 0, 1), BlockVertex::base(0.0, 1.0, 1.0, 0, 0), BlockVertex::base(1.0, 0.0, 1.0, 1, 1), BlockVertex::base(1.0, 1.0, 1.0, 1, 0), ], - [ // West + &[ // West BlockVertex::base(0.0, 0.0, 0.0, 0, 1), BlockVertex::base(0.0, 1.0, 0.0, 0, 0), BlockVertex::base(0.0, 0.0, 1.0, 1, 1), BlockVertex::base(0.0, 1.0, 1.0, 1, 0), ], - [ // East + &[ // East BlockVertex::base(1.0, 0.0, 0.0, 1, 1), BlockVertex::base(1.0, 0.0, 1.0, 0, 1), BlockVertex::base(1.0, 1.0, 0.0, 1, 0), diff --git a/src/world/mod.rs b/src/world/mod.rs index b251bdb..078dc35 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -43,7 +43,7 @@ impl World { pub fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { match self.chunks.get(&CPos(x >> 4, z >> 4)) { Some(ref chunk) => chunk.get_block(x & 0xF, y, z & 0xF), - None => block::AIR.base(), + None => block::MISSING.base(), } } @@ -158,57 +158,82 @@ impl World { let mut data = Cursor::new(data); let cpos = CPos(x, z); - let chunk = if new { - self.chunks.insert(cpos, Chunk::new(cpos)); - self.chunks.get_mut(&cpos).unwrap() - } else { - if !self.chunks.contains_key(&cpos) { - return Ok(()); - } - self.chunks.get_mut(&cpos).unwrap() - }; + { + let chunk = if new { + self.chunks.insert(cpos, Chunk::new(cpos)); + self.chunks.get_mut(&cpos).unwrap() + } else { + if !self.chunks.contains_key(&cpos) { + return Ok(()); + } + self.chunks.get_mut(&cpos).unwrap() + }; + for i in 0 .. 16 { + if mask & (1 << i) == 0 { + continue; + } + if chunk.sections[i].is_none() { + chunk.sections[i] = Some(Section::new(i as u8)); + } + let section = chunk.sections[i as usize].as_mut().unwrap(); + section.dirty = true; + + let bit_size = try!(data.read_u8()); + let mut block_map = HashMap::new(); + if bit_size <= 8 { + let count = try!(VarInt::read_from(&mut data)).0; + for i in 0 .. count { + let id = try!(VarInt::read_from(&mut data)).0; + block_map.insert(i as usize, id); + } + } + + let bits = try!(LenPrefixed::::read_from(&mut data)).data; + let m = bit::Map::from_raw(bits, bit_size as usize); + + for i in 0 .. 4096 { + let val = m.get(i); + let block_id = block_map.get(&val).map(|v| *v as usize).unwrap_or(val); + let block = block::get_block_by_vanilla_id(block_id); + let i = i as i32; + section.set_block( + i & 0xF, + i >> 8, + (i >> 4) & 0xF, + block + ); + } + + try!(data.read_exact(&mut section.block_light.data)); + try!(data.read_exact(&mut section.sky_light.data)); + } + } for i in 0 .. 16 { if mask & (1 << i) == 0 { continue; } - if chunk.sections[i].is_none() { - chunk.sections[i] = Some(Section::new(i as u8)); + for pos in [ + (-1, 0, 0), (1, 0, 0), + (0, -1, 0), (0, 1, 0), + (0, 0, -1), (0, 0, 1)].into_iter() { + self.flag_section_dirty(x + pos.0, i as i32 + pos.1, z + pos.2); } - let section = chunk.sections[i as usize].as_mut().unwrap(); - - let bit_size = try!(data.read_u8()); - let mut block_map = HashMap::new(); - if bit_size <= 8 { - let count = try!(VarInt::read_from(&mut data)).0; - for i in 0 .. count { - let id = try!(VarInt::read_from(&mut data)).0; - block_map.insert(i as usize, id); - } - } - - let bits = try!(LenPrefixed::::read_from(&mut data)).data; - let m = bit::Map::from_raw(bits, bit_size as usize); - - for i in 0 .. 4096 { - let val = m.get(i); - let block_id = block_map.get(&val).map(|v| *v as usize).unwrap_or(val); - let block = block::get_block_by_vanilla_id(block_id); - let i = i as i32; - section.set_block( - i & 0xF, - i >> 8, - (i >> 4) & 0xF, - block - ); - } - - try!(data.read_exact(&mut section.block_light.data)); - try!(data.read_exact(&mut section.sky_light.data)); } - Ok(()) } + + fn flag_section_dirty(&mut self, x: i32, y: i32, z: i32) { + if y < 0 || y > 15 { + return; + } + let cpos = CPos(x, z); + if let Some(chunk) = self.chunks.get_mut(&cpos) { + if let Some(sec) = chunk.sections[y as usize].as_mut() { + sec.dirty = true; + } + } + } } pub struct Snapshot { @@ -308,7 +333,7 @@ impl Chunk { fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { let s_idx = y >> 4; if s_idx < 0 || s_idx > 15 { - return block::AIR.base(); + return block::MISSING.base(); } match self.sections[s_idx as usize].as_ref() { Some(sec) => sec.get_block(x, y & 0xF, z),