Implement basic culling

This commit is contained in:
Thinkofname 2016-03-21 16:36:50 +00:00
parent ce1c286801
commit 99caa01032
2 changed files with 127 additions and 53 deletions

View File

@ -104,7 +104,14 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, 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<RwLock<render::TextureManager>>, 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<RwLock<render::TextureManager>>, 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<Direction> {
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),

View File

@ -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::<VarInt, u64>::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::<VarInt, u64>::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),