From c761688f81d6e70e0cda576d94c1987c3bd020c6 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 22 Jan 2023 01:51:23 +0100 Subject: [PATCH] chunk marking/loading!! --- src/main.rs | 13 +++++------ src/prefabs.rs | 4 ++-- src/rendering.rs | 4 ++-- src/world.rs | 13 +++++++---- src/world/chunk.rs | 14 +++++++++++- src/world/loading.rs | 54 +++++++++++++++++++++++++++++++++----------- 6 files changed, 72 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index b538ec9..daf797d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,9 +21,9 @@ pub(crate) mod prefabs; pub(crate) mod transform; pub(crate) mod settings; -use rendering::{Rederer, RenderTarget, BackgroundColor, clear_background}; +use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background}; use player::spawn_player; -use world::{ChunkStorage, loading::load_world_around_player}; +use world::{ChunkStorage, ChunkMeshStorage, loading::load_world_around_player}; use prefabs::load_prefabs; use settings::GameSettings; @@ -56,14 +56,13 @@ fn main() { let world = World::new(); //Add systems and uniques, Init and load things - world.add_unique_non_send_sync( - Rederer::init(&event_loop) - ); - load_prefabs(&world); + world.add_unique_non_send_sync(Renderer::init(&event_loop)); world.add_unique(ChunkStorage::new()); + world.add_unique_non_send_sync(ChunkMeshStorage::new()); world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); world.add_unique(DeltaTime(Duration::default())); world.add_unique(GameSettings::default()); + load_prefabs(&world); //Register workloads world.add_workload(startup); @@ -102,7 +101,7 @@ fn main() { //Start rendering (maybe use custom views for this?) let mut target = { - let renderer = world.borrow::>>().unwrap(); + let renderer = world.borrow::>>().unwrap(); renderer.display.draw() }; target.clear_color_and_depth((0., 0., 0., 1.), 1.); diff --git a/src/prefabs.rs b/src/prefabs.rs index f4c0532..b77108e 100644 --- a/src/prefabs.rs +++ b/src/prefabs.rs @@ -1,7 +1,7 @@ use shipyard::{World, NonSendSync, UniqueView, Unique}; use glium::{texture::SrgbTexture2dArray, Program}; use strum::EnumIter; -use crate::rendering::Rederer; +use crate::rendering::Renderer; mod texture; mod shaders; @@ -57,7 +57,7 @@ pub struct BlockTexturesPrefab(SrgbTexture2dArray); pub struct ChunkShaderPrefab(Program); pub fn load_prefabs(world: &World) { - let renderer = world.borrow::>>().unwrap(); + let renderer = world.borrow::>>().unwrap(); world.add_unique_non_send_sync(BlockTexturesPrefab( load_texture2darray_prefab::( "./assets/blocks/".into(), diff --git a/src/rendering.rs b/src/rendering.rs index c00f500..ae07223 100644 --- a/src/rendering.rs +++ b/src/rendering.rs @@ -16,10 +16,10 @@ pub struct RenderTarget(pub glium::Frame); pub struct BackgroundColor(pub Vec3); #[derive(Unique)] -pub struct Rederer { +pub struct Renderer { pub display: Display } -impl Rederer { +impl Renderer { pub fn init(event_loop: &EventLoop<()>) -> Self { log::info!("initializing display"); let wb = WindowBuilder::new() diff --git a/src/world.rs b/src/world.rs index e22fafa..72d19e0 100644 --- a/src/world.rs +++ b/src/world.rs @@ -58,6 +58,7 @@ impl<'a> ChunksNeighbors<'a> { } #[derive(Default, Unique)] +#[track(Modification)] pub struct ChunkStorage { pub chunks: HashMap } @@ -101,9 +102,11 @@ impl ChunkStorage { } } + +#[derive(Default, Unique)] pub struct ChunkMeshStorage { - meshes: HashMap>, - index: u64, + meshes: HashMap>, + index: usize, } impl ChunkMeshStorage { pub fn new() -> Self { @@ -112,17 +115,17 @@ impl ChunkMeshStorage { index: 0, } } - pub fn insert(&mut self, mesh: ChunkMesh) -> u64 { + pub fn insert(&mut self, mesh: ChunkMesh) -> usize { let index = self.index; self.meshes.insert_unique_unchecked(index, mesh); self.index += 1; index } - pub fn update(&mut self, key: u64, mesh: ChunkMesh) -> Result<()> { + pub fn update(&mut self, key: usize, mesh: ChunkMesh) -> Result<()> { *self.meshes.get_mut(&key).context("Chunk doesn't exist")? = mesh; Ok(()) } - pub fn remove(&mut self, key: u64) -> Result<()> { + pub fn remove(&mut self, key: usize) -> Result<()> { self.meshes.remove(&key).context("Chunk doesn't exist")?; Ok(()) } diff --git a/src/world/chunk.rs b/src/world/chunk.rs index c08bd9d..f99989c 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -21,9 +21,10 @@ pub struct ChunkMesh { pub index_buffer: IndexBuffer, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum ChunkState { ToUnload, //desired only + #[default] Nothing, Loading, //current only Loaded, @@ -39,3 +40,14 @@ pub struct Chunk { pub current_state: ChunkState, pub desired_state: ChunkState, } +impl Chunk { + pub fn new(position: IVec3) -> Self { + Self { + position, + block_data: None, + mesh_index: None, + current_state: Default::default(), + desired_state: Default::default(), + } + } +} diff --git a/src/world/loading.rs b/src/world/loading.rs index 46942ee..27c20cd 100644 --- a/src/world/loading.rs +++ b/src/world/loading.rs @@ -1,31 +1,32 @@ use glam::ivec3; -use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload}; +use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync}; use crate::{player::LocalPlayer, transform::Transform, settings::GameSettings}; -use super::{ChunkStorage, chunk::{ChunkState, CHUNK_SIZE}}; +use super::{ChunkStorage, chunk::{Chunk, ChunkState, CHUNK_SIZE}, ChunkMeshStorage}; pub fn load_world_around_player() -> Workload { ( - mark_chunks, + update_chunks_if_player_moved, + unload_marked_chunks ).into_workload() } -pub fn mark_chunks( +pub fn update_chunks_if_player_moved( v_settings: UniqueView, v_local_player: View, v_transform: View, mut vm_world: UniqueViewMut, ) { - //Read game settings - let load_distance = (v_settings.render_distance + 1) as i32; - - //Check if a player moved + //Check if the player actually moved let Some((_, transform)) = (&v_local_player, v_transform.inserted_or_modified()).iter().next() else { return }; + //Read game settings + let load_distance = (v_settings.render_distance + 1) as i32; + //If it did, get it's position and current chunk - let position = transform.0.to_scale_rotation_translation().2; - let at_chunk = position.as_ivec3() / CHUNK_SIZE as i32; + let player_position = transform.0.to_scale_rotation_translation().2; + let player_at_chunk = player_position.as_ivec3() / CHUNK_SIZE as i32; //Then, mark *ALL* chunks with ToUnload for (_, chunk) in &mut vm_world.chunks { @@ -37,19 +38,46 @@ pub fn mark_chunks( for y in -load_distance..=load_distance { for z in -load_distance..=load_distance { let chunk_pos_offset = ivec3(x, y, z); + let chunk_pos = player_at_chunk + chunk_pos_offset; let is_border = { chunk_pos_offset.x.abs() == load_distance || chunk_pos_offset.y.abs() == load_distance || chunk_pos_offset.z.abs() == load_distance }; + //If chunk doesn't exist create it + let chunk = match vm_world.chunks.get_mut(&chunk_pos) { + Some(chunk) => chunk, + None => { + let chunk = Chunk::new(chunk_pos); + vm_world.chunks.insert_unique_unchecked(chunk_pos, chunk); + vm_world.chunks.get_mut(&chunk_pos).unwrap() + } + }; let desired = match is_border { true => ChunkState::Loaded, false => ChunkState::Rendered, }; + chunk.desired_state = desired; } } } - - //TODO - todo!() +} + +fn unload_marked_chunks( + mut vm_world: UniqueViewMut, + mut vm_meshes: NonSendSync> +) { + if !vm_world.is_modified() { + return + } + vm_world.chunks.retain(|_, chunk| { + if chunk.desired_state == ChunkState::ToUnload { + if let Some(mesh_index) = chunk.mesh_index { + vm_meshes.remove(mesh_index).unwrap(); + } + false + } else { + true + } + }) }