use crate::{ mesh::{vol, Meshable}, render::{self, FluidPipeline, Mesh, TerrainPipeline}, }; use common::{ terrain::{Block, BlockKind}, vol::{ReadVol, RectRasterableVol, Vox}, volumes::{dyna::Dyna, vol_grid_2d::VolGrid2d}, }; use hashbrown::{HashMap, HashSet}; use std::fmt::Debug; use vek::*; type TerrainVertex = ::Vertex; type FluidVertex = ::Vertex; const DIRS: [Vec2; 4] = [ Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: 1 }, Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: -1 }, ]; const DIRS_3D: [Vec3; 6] = [ Vec3 { x: 1, y: 0, z: 0 }, Vec3 { x: 0, y: 1, z: 0 }, Vec3 { x: 0, y: 0, z: 1 }, Vec3 { x: -1, y: 0, z: 0 }, Vec3 { x: 0, y: -1, z: 0 }, Vec3 { x: 0, y: 0, z: -1 }, ]; fn calc_light + ReadVol + Debug>( bounds: Aabb, vol: &VolGrid2d, ) -> impl Fn(Vec3) -> f32 { let sunlight = 24; let outer = Aabb { min: bounds.min - sunlight, max: bounds.max + sunlight, }; let mut voids = HashMap::new(); let mut rays = vec![outer.size().d; outer.size().product() as usize]; for x in 0..outer.size().w { for y in 0..outer.size().h { let mut outside = true; for z in (0..outer.size().d).rev() { if vol .get(outer.min + Vec3::new(x, y, z)) .map(|vox| vox.is_air()) .unwrap_or(true) { if !outside { voids.insert(Vec3::new(x, y, z), None); } } else if outside { rays[(outer.size().w * y + x) as usize] = z; outside = false; } } } } let mut opens = HashSet::new(); for (pos, l) in &mut voids { for dir in &DIRS { let col = Vec2::::from(*pos) + dir; if pos.z > *rays .get(((outer.size().w * col.y) + col.x) as usize) .unwrap_or(&0) { *l = Some(sunlight - 1); opens.insert(*pos); } } } while opens.len() > 0 { let mut new_opens = HashSet::new(); for open in &opens { let parent_l = voids[open].unwrap_or(0); for dir in &DIRS_3D { let other = *open + *dir; if !opens.contains(&other) { if let Some(l) = voids.get_mut(&other) { if l.unwrap_or(0) < parent_l - 1 { new_opens.insert(other); } *l = Some(parent_l - 1); } } } } opens = new_opens; } move |wpos| { let pos = wpos - outer.min; rays.get(((outer.size().w * pos.y) + pos.x) as usize) .and_then(|ray| if pos.z > *ray { Some(1.0) } else { None }) .or_else(|| { if let Some(Some(l)) = voids.get(&pos) { Some(*l as f32 / sunlight as f32) } else { None } }) .unwrap_or(0.0) } } fn block_shadow_density(kind: BlockKind) -> (f32, f32) { // (density, cap) match kind { BlockKind::Normal => (0.085, 0.3), BlockKind::Dense => (0.3, 0.0), BlockKind::Water => (0.15, 0.0), kind if kind.is_air() => (0.0, 0.0), _ => (1.0, 0.0), } } impl + ReadVol + Debug> Meshable for VolGrid2d { type Pipeline = TerrainPipeline; type TranslucentPipeline = FluidPipeline; type Supplement = Aabb; fn generate_mesh( &self, range: Self::Supplement, ) -> (Mesh, Mesh) { let mut opaque_mesh = Mesh::new(); let mut fluid_mesh = Mesh::new(); let mut light = calc_light(range, self); for x in range.min.x + 1..range.max.x - 1 { for y in range.min.y + 1..range.max.y - 1 { for z in (range.min.z..range.max.z).rev() { let pos = Vec3::new(x, y, z); let offs = (pos - (range.min + 1) * Vec3::new(1, 1, 0)).map(|e| e as f32); let block = self.get(pos).ok(); // Create mesh polygons if let Some(col) = block .filter(|vox| vox.is_opaque()) .and_then(|vox| vox.get_color()) { let col = col.map(|e| e as f32 / 255.0); vol::push_vox_verts( &mut opaque_mesh, self, pos, offs, col, |pos, norm, col, ao, light| { TerrainVertex::new(pos, norm, col, light * ao) }, false, &{ let mut ls = [[[0.0; 3]; 3]; 3]; for x in 0..3 { for y in 0..3 { for z in 0..3 { ls[x][y][z] = light( pos + Vec3::new(x as i32, y as i32, z as i32) - 1, ); } } } ls }, |vox| !vox.is_opaque(), |vox| vox.is_opaque(), ); } else if let Some(col) = block .filter(|vox| vox.is_fluid()) .and_then(|vox| vox.get_color()) { let col = col.map(|e| e as f32 / 255.0); vol::push_vox_verts( &mut fluid_mesh, self, pos, offs, col, |pos, norm, col, ao, light| { FluidVertex::new(pos, norm, col, light * ao, 0.3) }, false, &{ let mut ls = [[[0.0; 3]; 3]; 3]; for x in 0..3 { for y in 0..3 { for z in 0..3 { ls[x][y][z] = light( pos + Vec3::new(x as i32, y as i32, z as i32) - 1, ); } } } ls }, |vox| vox.is_air(), |vox| vox.is_opaque(), ); } } } } (opaque_mesh, fluid_mesh) } } /* impl + ReadVol + Debug> Meshable for VolGrid3d { type Pipeline = TerrainPipeline; type Supplement = Aabb; fn generate_mesh(&self, range: Self::Supplement) -> Mesh { let mut mesh = Mesh::new(); let mut last_chunk_pos = self.pos_key(range.min); let mut last_chunk = self.get_key(last_chunk_pos); let size = range.max - range.min; for x in 1..size.x - 1 { for y in 1..size.y - 1 { for z in 1..size.z - 1 { let pos = Vec3::new(x, y, z); let new_chunk_pos = self.pos_key(range.min + pos); if last_chunk_pos != new_chunk_pos { last_chunk = self.get_key(new_chunk_pos); last_chunk_pos = new_chunk_pos; } let offs = pos.map(|e| e as f32 - 1.0); if let Some(chunk) = last_chunk { let chunk_pos = Self::chunk_offs(range.min + pos); if let Some(col) = chunk.get(chunk_pos).ok().and_then(|vox| vox.get_color()) { let col = col.map(|e| e as f32 / 255.0); vol::push_vox_verts( &mut mesh, self, range.min + pos, offs, col, TerrainVertex::new, false, ); } } else { if let Some(col) = self .get(range.min + pos) .ok() .and_then(|vox| vox.get_color()) { let col = col.map(|e| e as f32 / 255.0); vol::push_vox_verts( &mut mesh, self, range.min + pos, offs, col, TerrainVertex::new, false, ); } } } } } mesh } } */