diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index f892266..d5bdb02 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -14,3 +14,5 @@ winit = "0.30.13" renderer = { path = "../renderer" } raw-window-handle = "0.6.2" ash-window = "0.13.0" +serde_json = "1.0.149" +shared = { version = "0.1.0", path = "../shared" } diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 8826c3b..3bd1d13 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -2,6 +2,7 @@ //! //! This crate handles window creation, input processing, and drives the //! renderer to display the game world. +mod meshing; use anyhow::{Context, Result}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; @@ -75,6 +76,24 @@ impl ApplicationHandler for App { self.window = Some(window); self.renderer = Some(renderer); + + #[allow(clippy::expect_used)] + let config_str = std::fs::read_to_string("assets/data/worldgen/default.json") + .expect("Failed to read worldgen config"); + #[allow(clippy::expect_used)] + let worldgen_config: shared::generator::WorldGenConfig = serde_json::from_str(&config_str) + .expect("Failed to parse worldgen config"); + + let seed = 4_813_530; + + let generator = shared::generator::VoxelGenerator::new(worldgen_config, seed); + let chunk = generator.generate_chunk(shared::world::ChunkPos::new(0, 0, 0)); + + let (vertices, indices) = meshing::generate_mesh(&chunk); + tracing::info!("Generated Mesh with {} vertices and {} indices!", vertices.len(), indices.len()); + + #[allow(clippy::expect_used)] + self.renderer.as_mut().expect("Renderer initialized").update_mesh(&vertices, &indices).expect("Failed to upload terrain to GPU"); } fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { diff --git a/crates/client/src/meshing.rs b/crates/client/src/meshing.rs new file mode 100644 index 0000000..14e860b --- /dev/null +++ b/crates/client/src/meshing.rs @@ -0,0 +1,90 @@ +use shared::world::{BlockId, CHUNK_SIZE, Chunk}; +use renderer::mesh::Vertex; + +#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)] +pub fn generate_mesh(chunk: &Chunk) -> (Vec, Vec) { + let mut vertices = Vec::new(); + let mut indices = Vec::new(); + + for x in 0..CHUNK_SIZE { + for y in 0..CHUNK_SIZE { + for z in 0..CHUNK_SIZE { + let block = chunk.get(x, y, z); + + if block == BlockId::AIR { + continue; + } + + let fx = x as f32; + let fy = y as f32; + let fz = z as f32; + + if y == CHUNK_SIZE - 1 || chunk.get(x, y + 1, z) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2] }); + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2] }); + + indices.extend_from_slice(&[ + base_idx, base_idx + 1, base_idx + 2, + base_idx + 2, base_idx + 3, base_idx, + ]); + } + + if y == 0 || chunk.get(x, y - 1, z) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1] }); + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1] }); + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1] }); + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1] }); + indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]); + } + + if x == CHUNK_SIZE - 1 || chunk.get(x + 1, y, z) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] }); + indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]); + } + + if x == 0 || chunk.get(x - 1, y, z) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15] }); + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15] }); + indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]); + } + + if z == CHUNK_SIZE - 1 || chunk.get(x, y, z + 1) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18] }); + indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]); + } + + if z == 0 || chunk.get(x, y, z - 1) == BlockId::AIR { + let base_idx = vertices.len() as u32; + + vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] }); + vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18] }); + indices.extend_from_slice(&[base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx]); + } + } + } + } + + (vertices, indices) +} \ No newline at end of file