diff --git a/Cargo.toml b/Cargo.toml index 13d6df1..a3273a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,5 @@ hashbrown = "0.13" noise = "0.8" rayon = "1.6" shipyard = { version = "0.6", features = ["thread_local"] } +nohash-hasher = "0.2.0" +anyhow = "1.0" diff --git a/src/main.rs b/src/main.rs index b27a5c0..b538ec9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ pub(crate) mod settings; use rendering::{Rederer, RenderTarget, BackgroundColor, clear_background}; use player::spawn_player; -use world::{GameWorld, loading::load_world_around_player}; +use world::{ChunkStorage, loading::load_world_around_player}; use prefabs::load_prefabs; use settings::GameSettings; @@ -60,9 +60,7 @@ fn main() { Rederer::init(&event_loop) ); load_prefabs(&world); - world.add_unique_non_send_sync( - GameWorld::new() - ); + world.add_unique(ChunkStorage::new()); world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); world.add_unique(DeltaTime(Duration::default())); world.add_unique(GameSettings::default()); diff --git a/src/world.rs b/src/world.rs index b2608c7..e22fafa 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,14 +1,17 @@ +use nohash_hasher::BuildNoHashHasher; use shipyard::Unique; use glam::{IVec3, ivec3}; use hashbrown::HashMap; +use anyhow::{Result, Context}; pub mod chunk; pub mod block; pub mod render; pub mod tasks; pub mod loading; +pub mod mesh; -use chunk::Chunk; +use chunk::{Chunk, ChunkMesh}; //TODO separate world struct for render data // because this is not send-sync @@ -55,10 +58,10 @@ impl<'a> ChunksNeighbors<'a> { } #[derive(Default, Unique)] -pub struct GameWorld { +pub struct ChunkStorage { pub chunks: HashMap } -impl GameWorld { +impl ChunkStorage { pub fn new() -> Self { Self::default() } @@ -97,3 +100,30 @@ impl GameWorld { }) } } + +pub struct ChunkMeshStorage { + meshes: HashMap>, + index: u64, +} +impl ChunkMeshStorage { + pub fn new() -> Self { + Self { + meshes: HashMap::with_capacity_and_hasher(250, BuildNoHashHasher::default()), + index: 0, + } + } + pub fn insert(&mut self, mesh: ChunkMesh) -> u64 { + 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<()> { + *self.meshes.get_mut(&key).context("Chunk doesn't exist")? = mesh; + Ok(()) + } + pub fn remove(&mut self, key: u64) -> Result<()> { + self.meshes.remove(&key).context("Chunk doesn't exist")?; + Ok(()) + } +} diff --git a/src/world/chunk.rs b/src/world/chunk.rs index 3cb1978..c08bd9d 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -28,13 +28,14 @@ pub enum ChunkState { Loading, //current only Loaded, Meshing, //current only - Rendered + Rendered, + RecalculatingMesh //current only } pub struct Chunk { pub position: IVec3, pub block_data: Option, - pub mesh: Option, + pub mesh_index: Option, pub current_state: ChunkState, pub desired_state: ChunkState, } diff --git a/src/world/loading.rs b/src/world/loading.rs index bb42a57..57c0cde 100644 --- a/src/world/loading.rs +++ b/src/world/loading.rs @@ -1,7 +1,7 @@ use glam::ivec3; -use shipyard::{View, UniqueView, UniqueViewMut, NonSendSync, IntoIter, Workload, IntoWorkload}; +use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload}; use crate::{player::LocalPlayer, transform::Transform, settings::GameSettings}; -use super::{GameWorld, chunk::{ChunkState, CHUNK_SIZE}}; +use super::{ChunkStorage, chunk::{ChunkState, CHUNK_SIZE}}; pub fn load_world_around_player() -> Workload { ( @@ -13,7 +13,7 @@ pub fn mark_chunks( v_settings: UniqueView, v_local_player: View, v_transform: View, - mut vm_world: NonSendSync>, + mut vm_world: UniqueViewMut, ) { //Read game settings let load_distance = (v_settings.render_distance + 1) as i32;