diff --git a/src/main.rs b/src/main.rs index bdf4459..2a95ef7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,9 @@ mod aabb; mod camera; -mod chunk; mod geometry; mod npc; -mod quad; mod render_context; +mod renderable; mod state; mod text_renderer; mod texture; diff --git a/src/renderable.rs b/src/renderable.rs new file mode 100644 index 0000000..addae07 --- /dev/null +++ b/src/renderable.rs @@ -0,0 +1,10 @@ +use std::time::Duration; + +use wgpu::RenderPass; + +use crate::{camera::Camera, render_context::RenderContext, view::View}; + +pub trait Renderable { + fn update(&mut self, render_context: &RenderContext, dt: Duration, camera: &Camera); + fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize; +} diff --git a/src/state/mod.rs b/src/state/mod.rs index acbc1c9..18338db 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -20,8 +20,8 @@ pub const PRIMITIVE_STATE: wgpu::PrimitiveState = wgpu::PrimitiveState { strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: None, - polygon_mode: wgpu::PolygonMode::Fill, clamp_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, conservative: false, }; @@ -47,6 +47,7 @@ impl State { }) .await .unwrap(); + println!("Using {:?}", adapter.get_info().backend); let (render_device, queue) = adapter .request_device( diff --git a/src/state/world_state.rs b/src/state/world_state.rs index 6ef7905..38f1232 100644 --- a/src/state/world_state.rs +++ b/src/state/world_state.rs @@ -13,11 +13,12 @@ use winit::{ use crate::{ camera::{Camera, Projection}, render_context::RenderContext, + renderable::Renderable, texture::{Texture, TextureManager}, time::Time, vertex::{BlockVertex, Vertex}, view::View, - world::World, + world::world::World, }; pub struct WorldState { @@ -428,7 +429,7 @@ impl WorldState { pub fn update(&mut self, dt: Duration, render_context: &RenderContext) { self.update_position(dt); - self.world.update(dt, render_context, &self.camera); + self.world.update(render_context, dt, &self.camera); self.view .update_view_projection(&self.camera, &self.projection); diff --git a/src/world/block.rs b/src/world/block.rs new file mode 100644 index 0000000..ccd9aaf --- /dev/null +++ b/src/world/block.rs @@ -0,0 +1,41 @@ +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum BlockType { + Cobblestone = 1, + Dirt = 2, + Stone = 3, + Grass = 4, + Bedrock = 5, + Sand = 6, + Gravel = 7, + Water = 8, +} + +impl BlockType { + #[rustfmt::skip] + pub const fn texture_indices(self) -> (usize, usize, usize, usize, usize, usize) { + match self { + BlockType::Cobblestone => ( 0, 0, 0, 0, 0, 0), + BlockType::Dirt => ( 1, 1, 1, 1, 1, 1), + BlockType::Stone => ( 2, 2, 2, 2, 2, 2), + BlockType::Grass => ( 4, 4, 4, 4, 2, 3), + BlockType::Bedrock => ( 5, 5, 5, 5, 5, 5), + BlockType::Sand => ( 6, 6, 6, 6, 6, 6), + BlockType::Gravel => ( 7, 7, 7, 7, 7, 7), + BlockType::Water => ( 8, 8, 8, 8, 8, 8), // up to 71 + } + } + + pub const fn is_transparent(self) -> bool { + matches!(self, BlockType::Water) + } +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub struct Block { + pub block_type: BlockType, +} diff --git a/src/chunk.rs b/src/world/chunk.rs similarity index 87% rename from src/chunk.rs rename to src/world/chunk.rs index f3c6f5a..deeea0a 100644 --- a/src/chunk.rs +++ b/src/world/chunk.rs @@ -1,81 +1,31 @@ -use std::{collections::VecDeque, usize}; +use std::collections::VecDeque; use crate::{ aabb::Aabb, geometry::{Geometry, GeometryBuffers}, - quad::Quad, vertex::BlockVertex, view::View, + world::{ + block::{Block, BlockType}, + face_flags::*, + quad::Quad, + }, }; use ahash::{AHashMap, AHashSet}; use cgmath::{Point3, Vector3}; use noise::utils::{NoiseMapBuilder, PlaneMapBuilder}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; - use serde::{ de::{SeqAccess, Visitor}, - ser::{SerializeSeq, Serializer}, - Deserialize, Serialize, + ser::SerializeSeq, + Deserialize, Serialize, Serializer, }; -use serde_repr::{Deserialize_repr, Serialize_repr}; - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)] -#[repr(u8)] -pub enum BlockType { - Cobblestone = 1, - Dirt = 2, - Stone = 3, - Grass = 4, - Bedrock = 5, - Sand = 6, - Gravel = 7, - Water = 8, -} - -impl BlockType { - #[rustfmt::skip] - pub const fn texture_indices(self) -> (usize, usize, usize, usize, usize, usize) { - match self { - BlockType::Cobblestone => ( 0, 0, 0, 0, 0, 0), - BlockType::Dirt => ( 1, 1, 1, 1, 1, 1), - BlockType::Stone => ( 2, 2, 2, 2, 2, 2), - BlockType::Grass => ( 4, 4, 4, 4, 2, 3), - BlockType::Bedrock => ( 5, 5, 5, 5, 5, 5), - BlockType::Sand => ( 6, 6, 6, 6, 6, 6), - BlockType::Gravel => ( 7, 7, 7, 7, 7, 7), - BlockType::Water => ( 8, 8, 8, 8, 8, 8), // up to 71 - } - } - - pub const fn is_transparent(self) -> bool { - matches!(self, BlockType::Water) - } -} - -pub type FaceFlags = usize; -pub const FACE_NONE: FaceFlags = 0; -pub const FACE_LEFT: FaceFlags = 1; -pub const FACE_RIGHT: FaceFlags = 2; -pub const FACE_BOTTOM: FaceFlags = 4; -pub const FACE_TOP: FaceFlags = 8; -pub const FACE_BACK: FaceFlags = 16; -pub const FACE_FRONT: FaceFlags = 32; -pub const FACE_ALL: FaceFlags = - FACE_LEFT | FACE_RIGHT | FACE_BOTTOM | FACE_TOP | FACE_BACK | FACE_FRONT; - -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct Block { - pub block_type: BlockType, -} pub const CHUNK_SIZE: usize = 32; pub const CHUNK_ISIZE: isize = CHUNK_SIZE as isize; -type ChunkBlocks = [[[Option; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE]; - pub struct Chunk { - pub blocks: ChunkBlocks, + pub blocks: [[[Option; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE], pub buffers: Option>, } @@ -88,23 +38,6 @@ impl Default for Chunk { } } -impl Serialize for Chunk { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(Some(CHUNK_SIZE.pow(3)))?; - for layer in self.blocks.iter() { - for row in layer { - for block in row { - seq.serialize_element(block)?; - } - } - } - seq.end() - } -} - struct ChunkVisitor; impl<'de> Visitor<'de> for ChunkVisitor { @@ -131,6 +64,23 @@ impl<'de> Visitor<'de> for ChunkVisitor { } } +impl Serialize for Chunk { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(CHUNK_SIZE.pow(3)))?; + for layer in self.blocks.iter() { + for row in layer { + for block in row { + seq.serialize_element(block)?; + } + } + } + seq.end() + } +} + impl<'de> Deserialize<'de> for Chunk { fn deserialize(deserializer: D) -> Result where diff --git a/src/world/face_flags.rs b/src/world/face_flags.rs new file mode 100644 index 0000000..82a3845 --- /dev/null +++ b/src/world/face_flags.rs @@ -0,0 +1,10 @@ +pub type FaceFlags = usize; +pub const FACE_NONE: FaceFlags = 0; +pub const FACE_LEFT: FaceFlags = 1; +pub const FACE_RIGHT: FaceFlags = 2; +pub const FACE_BOTTOM: FaceFlags = 4; +pub const FACE_TOP: FaceFlags = 8; +pub const FACE_BACK: FaceFlags = 16; +pub const FACE_FRONT: FaceFlags = 32; +pub const FACE_ALL: FaceFlags = + FACE_LEFT | FACE_RIGHT | FACE_BOTTOM | FACE_TOP | FACE_BACK | FACE_FRONT; diff --git a/src/world/mod.rs b/src/world/mod.rs new file mode 100644 index 0000000..791948d --- /dev/null +++ b/src/world/mod.rs @@ -0,0 +1,5 @@ +pub mod block; +pub mod chunk; +pub mod face_flags; +pub mod quad; +pub mod world; diff --git a/src/quad.rs b/src/world/quad.rs similarity index 98% rename from src/quad.rs rename to src/world/quad.rs index 8803e5c..88c719c 100644 --- a/src/quad.rs +++ b/src/world/quad.rs @@ -1,12 +1,9 @@ use cgmath::{Point3, Vector3, Zero}; use crate::{ - chunk::{ - BlockType, FaceFlags, FACE_ALL, FACE_BACK, FACE_BOTTOM, FACE_FRONT, FACE_LEFT, FACE_RIGHT, - FACE_TOP, - }, geometry::Geometry, vertex::BlockVertex, + world::{block::BlockType, face_flags::*}, }; #[derive(Debug)] diff --git a/src/world.rs b/src/world/world.rs similarity index 97% rename from src/world.rs rename to src/world/world.rs index 6874c54..f1695a4 100644 --- a/src/world.rs +++ b/src/world/world.rs @@ -2,11 +2,15 @@ use std::{collections::VecDeque, time::Duration}; use crate::{ camera::Camera, - chunk::{Block, BlockType, Chunk, CHUNK_ISIZE}, geometry::GeometryBuffers, npc::Npc, render_context::RenderContext, + renderable::Renderable, view::View, + world::{ + block::{Block, BlockType}, + chunk::{Chunk, CHUNK_ISIZE}, + }, }; use ahash::AHashMap; use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector3}; @@ -31,34 +35,8 @@ pub const WORLD_HEIGHT: isize = 16 * 16 / CHUNK_ISIZE; const DEBUG_IO: bool = false; -impl World { - pub fn new() -> Self { - let chunks = AHashMap::new(); - let npc = Npc::load(); - - let chunk_database = sled::Config::new() - .path("chunks") - .mode(sled::Mode::HighThroughput) - .use_compression(true) - .open() - .unwrap(); - - Self { - chunks, - npc, - - chunk_database, - chunk_load_queue: VecDeque::new(), - chunk_save_queue: VecDeque::new(), - chunk_generate_queue: VecDeque::new(), - - highlighted: None, - - unload_timer: Duration::new(0, 0), - } - } - - pub fn update(&mut self, dt: Duration, render_context: &RenderContext, camera: &Camera) { +impl Renderable for World { + fn update(&mut self, render_context: &RenderContext, dt: Duration, camera: &Camera) { if let Some(position) = self.chunk_load_queue.pop_front() { let chunk = self.chunks.entry(position).or_default(); match chunk.load(position, &self.chunk_database) { @@ -144,7 +122,7 @@ impl World { } } - pub fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize { + fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize { let mut triangle_count = 0; for (position, chunk) in &self.chunks { @@ -166,6 +144,34 @@ impl World { triangle_count } +} + +impl World { + pub fn new() -> Self { + let chunks = AHashMap::new(); + let npc = Npc::load(); + + let chunk_database = sled::Config::new() + .path("chunks") + .mode(sled::Mode::HighThroughput) + .use_compression(true) + .open() + .unwrap(); + + Self { + chunks, + npc, + + chunk_database, + chunk_load_queue: VecDeque::new(), + chunk_save_queue: VecDeque::new(), + chunk_generate_queue: VecDeque::new(), + + highlighted: None, + + unload_timer: Duration::new(0, 0), + } + } pub fn enqueue_chunk_save(&mut self, position: Point3, unload: bool) { if let Some((_, unload_)) = self