diff options
Diffstat (limited to 'src/render')
-rw-r--r-- | src/render/composite.rs | 31 | ||||
-rw-r--r-- | src/render/mod.rs | 102 | ||||
-rw-r--r-- | src/render/models.rs | 12 |
3 files changed, 126 insertions, 19 deletions
diff --git a/src/render/composite.rs b/src/render/composite.rs index 7409478..99950f1 100644 --- a/src/render/composite.rs +++ b/src/render/composite.rs @@ -1,8 +1,5 @@ use image::ImageBuffer; use image::Rgba; - -use crate::SEG_SIZE; - pub const REGION_SIZE: usize = 16 * 8; pub const CHUNK_HEIGHT: usize = 320; pub const CHUNK_SIZE: usize = 16; @@ -28,21 +25,21 @@ pub fn image_buffer_blit( } } -pub fn isometric_coord_mapping(x: i32, y: i32, z: i32) -> (u32, u32) { - // const BASE_X: i32 = 1016; - const BASE_X: i32 = (SEG_SIZE as i32 * 8) - 8; - const BASE_Y: i32 = 2040; +// pub fn isometric_coord_mapping(x: i32, y: i32, z: i32) -> (u32, u32) { +// // const BASE_X: i32 = 1016; +// const BASE_X: i32 = (SEG_SIZE as i32 * 8) - 8; +// const BASE_Y: i32 = 2040; - const XDIFF: (i32, i32) = (-8, 4); - const ZDIFF: (i32, i32) = (8, 4); - const YDIFF: (i32, i32) = (0, -8); +// const XDIFF: (i32, i32) = (-8, 4); +// const ZDIFF: (i32, i32) = (8, 4); +// const YDIFF: (i32, i32) = (0, -8); - let diff = ( - XDIFF.0 * x + YDIFF.0 * y + ZDIFF.0 * z, - XDIFF.1 * x + YDIFF.1 * y + ZDIFF.1 * z, - ); +// let diff = ( +// XDIFF.0 * x + YDIFF.0 * y + ZDIFF.0 * z, +// XDIFF.1 * x + YDIFF.1 * y + ZDIFF.1 * z, +// ); - let coords = (BASE_X + diff.0, BASE_Y + diff.1); +// let coords = (BASE_X + diff.0, BASE_Y + diff.1); - (coords.0 as u32, coords.1 as u32) -} +// (coords.0 as u32, coords.1 as u32) +// } diff --git a/src/render/mod.rs b/src/render/mod.rs index cd9856e..293e566 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,3 +1,101 @@ -pub mod processing; -pub mod models; +use std::time::Instant; + +use chashmap::{CHashMap, ReadGuard}; +use image::ImageBuffer; +use log::info; + +use crate::{ + dimension::Dimension, + render::{ + composite::image_buffer_blit, + models::{block_properties, processed_block_texture}, + }, +}; + +use self::processing::Texture; pub mod composite; +pub mod models; +pub mod processing; + +const SEG_SIZE: isize = 128; +const BLOCK_NAMESPACE_LEN: usize = "minecraft:".len(); + +pub struct Renderer { + dimension: Dimension, + textures: CHashMap<String, Texture>, +} +impl Renderer { + pub fn new(dimension: Dimension) -> Self { + Self { + dimension, + textures: Default::default(), + } + } + pub fn load_texture(&self, name: &str) -> ReadGuard<'_, std::string::String, Texture> { + match self.textures.contains_key(name) { + true => self.textures.get(name).unwrap(), + false => { + self.textures + .insert(name.to_owned(), processed_block_texture(name)); + self.load_texture(name) + } + } + } + + pub fn render_segment(&self, sx: isize, sy: isize) -> Texture { + let start_time = Instant::now(); + + let solid = |x: isize, y: isize, z: isize| { + self.dimension + .block(x, y, z) + .map(|b| block_properties(&b.name()[BLOCK_NAMESPACE_LEN..])) + .unwrap_or((true, true)) + }; + + let mut view: Texture = + ImageBuffer::new(16 * (SEG_SIZE + 1) as u32, 16 * (SEG_SIZE + 1) as u32); + + let mut visible = Vec::<((isize, isize, isize), (isize, isize, isize))>::new(); + + for ix in (sx * SEG_SIZE)..((sx + 1) * SEG_SIZE) { + for iy in (sy * (SEG_SIZE * 2))..((sy + 1) * (SEG_SIZE * 2)) { + for off in 0..=1 { + let mut y = 319; + let mut x = -ix + iy; + let mut z = ix + iy + off; + loop { + let (solid, has_texture) = solid(x, y, z); + if has_texture { + visible.push(((x, y, z), (ix, iy, off))); + } + if solid { + break; + } + y -= 1; + x -= 1; + z -= 1; + } + } + } + } + info!("{} visible blocks", visible.len()); + visible.sort_by_cached_key(|((x, y, z), _)| x + y + z); + + info!("compositing textures"); + for ((x, y, z), (ix, iy, off)) in visible { + let name = match self.dimension.block(x, y, z) { + Some(block) => block.name().to_owned(), + None => "minecraft:debug".to_owned(), + }; + let name = &name[BLOCK_NAMESPACE_LEN..]; + let texture = &self.load_texture(name); + let ix = ix * 16 + off * 8; + let iy = iy * 8 + off * 4; + image_buffer_blit(&mut view, texture, (ix as u32, iy as u32)); + } + + let end_time = Instant::now(); + info!("segment rendered in {:?}", end_time - start_time); + view + } +} diff --git a/src/render/models.rs b/src/render/models.rs index 24e7817..4a8673d 100644 --- a/src/render/models.rs +++ b/src/render/models.rs @@ -37,3 +37,15 @@ pub fn processed_block_texture(name: &str) -> ImageBuffer<Rgba<u8>, Vec<u8>> { } } } + +pub fn block_properties(name: &str) -> (bool, bool) { + match name { + "air" | "cave_air" => (false, false), + + "oak_leaves" | "birch_leaves" | "acacia_leaves" | "jungle_leaves" | "dark_oak_leaves" + | "spruce_leaves" => (false, true), + "water" => (false, true), + + _ => (true, true), + } +} |