diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 3bd1d13..2fc44d9 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -81,8 +81,8 @@ impl ApplicationHandler for App { 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 worldgen_config: shared::generator::WorldGenConfig = + serde_json::from_str(&config_str).expect("Failed to parse worldgen config"); let seed = 4_813_530; @@ -90,10 +90,18 @@ impl ApplicationHandler for App { 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()); + 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"); + 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 index 14e860b..8ec1a6a 100644 --- a/crates/client/src/meshing.rs +++ b/crates/client/src/meshing.rs @@ -1,7 +1,11 @@ -use shared::world::{BlockId, CHUNK_SIZE, Chunk}; use renderer::mesh::Vertex; +use shared::world::{BlockId, CHUNK_SIZE, Chunk}; -#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)] +#[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::too_many_lines +)] pub fn generate_mesh(chunk: &Chunk) -> (Vec, Vec) { let mut vertices = Vec::new(); let mut indices = Vec::new(); @@ -22,69 +26,180 @@ pub fn generate_mesh(chunk: &Chunk) -> (Vec, Vec) { 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] }); + 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, + 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]); + 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]); + 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]); + 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]); + 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.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 +} diff --git a/crates/renderer/src/renderer.rs b/crates/renderer/src/renderer.rs index 184196a..60dcb17 100644 --- a/crates/renderer/src/renderer.rs +++ b/crates/renderer/src/renderer.rs @@ -1,6 +1,6 @@ use crate::create_gpu_buffer; -use crate::{error::RendererError, mesh::Vertex}; use crate::sync::SyncPrimitives; +use crate::{error::RendererError, mesh::Vertex}; use ash::{Device, Instance, khr, vk}; use gpu_allocator::vulkan::{Allocation, Allocator}; @@ -299,7 +299,8 @@ impl Renderer { mvp_bytes, ); - self.device.cmd_draw_indexed(cmd, self.index_count, 1, 0, 0, 0); + self.device + .cmd_draw_indexed(cmd, self.index_count, 1, 0, 0, 0); } } @@ -339,26 +340,34 @@ impl Renderer { } /// Replaces the currently rendering mesh with a new set of vertices and indices. - /// + /// /// # Errors /// Returns a `RendererError` if new Vulkan buffers cannot be allocated or created. #[allow(clippy::cast_possible_truncation)] - pub fn update_mesh(&mut self, vertices: &[Vertex], indices: &[u32]) -> Result<(), RendererError> { + pub fn update_mesh( + &mut self, + vertices: &[Vertex], + indices: &[u32], + ) -> Result<(), RendererError> { unsafe { let _ = self.device.device_wait_idle(); - let _ = self.allocator.free(std::ptr::read(&raw const self.vertex_allocation)); + let _ = self + .allocator + .free(std::ptr::read(&raw const self.vertex_allocation)); self.device.destroy_buffer(self.vertex_buffer, None); - let _ = self.allocator.free(std::ptr::read(&raw const self.index_allocation)); + let _ = self + .allocator + .free(std::ptr::read(&raw const self.index_allocation)); self.device.destroy_buffer(self.index_buffer, None); } let (v_buf, v_alloc) = create_gpu_buffer( - &self.device, - &mut self.allocator, - bytemuck::cast_slice(vertices), - vk::BufferUsageFlags::VERTEX_BUFFER, + &self.device, + &mut self.allocator, + bytemuck::cast_slice(vertices), + vk::BufferUsageFlags::VERTEX_BUFFER, "Chunk Vertex Buffer", )?; diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index ac61c9f..eb44c6e 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -8,24 +8,29 @@ pub mod world_server; use std::fs; -use shared::{generator::{VoxelGenerator, WorldGenConfig}, world::ChunkPos}; +use shared::{ + generator::{VoxelGenerator, WorldGenConfig}, + world::ChunkPos, +}; use tracing::{debug, info}; fn main() { tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("debug")) + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("debug")), ) .init(); info!("Starting Project Catalyst server"); #[allow(clippy::expect_used)] - let config_str = fs::read_to_string("assets/data/worldgen/default.json").expect("Failed to read worldgen config"); + let config_str = fs::read_to_string("assets/data/worldgen/default.json") + .expect("Failed to read worldgen config"); #[allow(clippy::expect_used)] - let worldgen_config: WorldGenConfig = serde_json::from_str(&config_str).expect("Failed to parse worldgen config"); + let worldgen_config: WorldGenConfig = + serde_json::from_str(&config_str).expect("Failed to parse worldgen config"); info!("Successfully loaded world configuration"); debug!("Base height: {}", worldgen_config.base_height); @@ -42,5 +47,8 @@ fn main() { let spawn_chunk = world.get_chunk(ChunkPos::new(0, 0, 0)); - tracing::info!("Spawn chunk generated. Block at (0,0,0) is {}", spawn_chunk.get(0, 0, 0).0); -} \ No newline at end of file + tracing::info!( + "Spawn chunk generated. Block at (0,0,0) is {}", + spawn_chunk.get(0, 0, 0).0 + ); +} diff --git a/crates/server/src/world_server.rs b/crates/server/src/world_server.rs index 2d7d8a3..e02c9de 100644 --- a/crates/server/src/world_server.rs +++ b/crates/server/src/world_server.rs @@ -1,6 +1,9 @@ //! Authoritative chunk storage and generation logic for the server. -use shared::{generator::VoxelGenerator, world::{Chunk, ChunkPos}}; +use shared::{ + generator::VoxelGenerator, + world::{Chunk, ChunkPos}, +}; use std::collections::HashMap; /// The server's authoritative representation of the world. @@ -21,8 +24,8 @@ impl ServerWorld { /// Retrieves a reference to the chunk at the given position, generating it if necessary. pub fn get_chunk(&mut self, pos: ChunkPos) -> &Chunk { - self.chunks.entry(pos).or_insert_with(|| { - self.generator.generate_chunk(pos) - }) + self.chunks + .entry(pos) + .or_insert_with(|| self.generator.generate_chunk(pos)) } -} \ No newline at end of file +} diff --git a/crates/shared/src/generator.rs b/crates/shared/src/generator.rs index 64aa381..6fb5edc 100644 --- a/crates/shared/src/generator.rs +++ b/crates/shared/src/generator.rs @@ -39,10 +39,14 @@ impl VoxelGenerator { /// Generates a complete voxel chunk for the specified position. #[must_use] - #[allow(clippy::cast_precision_loss, clippy::cast_possible_wrap, clippy::cast_possible_truncation)] + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_wrap, + clippy::cast_possible_truncation + )] pub fn generate_chunk(&self, pos: ChunkPos) -> Chunk { let mut chunk = Chunk::default(); - + for x in 0..CHUNK_SIZE { for z in 0..CHUNK_SIZE { let global_x = (pos.x * CHUNK_SIZE as i32) + x as i32; @@ -78,4 +82,4 @@ impl VoxelGenerator { } chunk } -} \ No newline at end of file +} diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index aa1d3e3..5b535ce 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -3,5 +3,5 @@ //! This crate contains data structures and constants that are used by both //! the client and the server. +pub mod generator; pub mod world; -pub mod generator; \ No newline at end of file diff --git a/crates/shared/src/world.rs b/crates/shared/src/world.rs index cf1a500..a5a268d 100644 --- a/crates/shared/src/world.rs +++ b/crates/shared/src/world.rs @@ -11,7 +11,19 @@ pub const CHUNK_VOLUME: usize = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE; /// A unique identifier representing a type of block in the world. #[repr(transparent)] #[derive( - Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Pod, Zeroable, + Copy, + Clone, + Debug, + Default, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + Pod, + Zeroable, )] pub struct BlockId(pub u16); @@ -72,4 +84,4 @@ impl ChunkPos { pub fn new(x: i32, y: i32, z: i32) -> Self { Self { x, y, z } } -} \ No newline at end of file +}