chunk marking/loading!!

This commit is contained in:
griffi-gh 2023-01-22 01:51:23 +01:00
parent 0a528d8ccf
commit c761688f81
6 changed files with 72 additions and 30 deletions

View file

@ -21,9 +21,9 @@ pub(crate) mod prefabs;
pub(crate) mod transform; pub(crate) mod transform;
pub(crate) mod settings; pub(crate) mod settings;
use rendering::{Rederer, RenderTarget, BackgroundColor, clear_background}; use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background};
use player::spawn_player; 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 prefabs::load_prefabs;
use settings::GameSettings; use settings::GameSettings;
@ -56,14 +56,13 @@ fn main() {
let world = World::new(); let world = World::new();
//Add systems and uniques, Init and load things //Add systems and uniques, Init and load things
world.add_unique_non_send_sync( world.add_unique_non_send_sync(Renderer::init(&event_loop));
Rederer::init(&event_loop)
);
load_prefabs(&world);
world.add_unique(ChunkStorage::new()); 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(BackgroundColor(vec3(0.5, 0.5, 1.)));
world.add_unique(DeltaTime(Duration::default())); world.add_unique(DeltaTime(Duration::default()));
world.add_unique(GameSettings::default()); world.add_unique(GameSettings::default());
load_prefabs(&world);
//Register workloads //Register workloads
world.add_workload(startup); world.add_workload(startup);
@ -102,7 +101,7 @@ fn main() {
//Start rendering (maybe use custom views for this?) //Start rendering (maybe use custom views for this?)
let mut target = { let mut target = {
let renderer = world.borrow::<NonSendSync<UniqueView<Rederer>>>().unwrap(); let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.draw() renderer.display.draw()
}; };
target.clear_color_and_depth((0., 0., 0., 1.), 1.); target.clear_color_and_depth((0., 0., 0., 1.), 1.);

View file

@ -1,7 +1,7 @@
use shipyard::{World, NonSendSync, UniqueView, Unique}; use shipyard::{World, NonSendSync, UniqueView, Unique};
use glium::{texture::SrgbTexture2dArray, Program}; use glium::{texture::SrgbTexture2dArray, Program};
use strum::EnumIter; use strum::EnumIter;
use crate::rendering::Rederer; use crate::rendering::Renderer;
mod texture; mod texture;
mod shaders; mod shaders;
@ -57,7 +57,7 @@ pub struct BlockTexturesPrefab(SrgbTexture2dArray);
pub struct ChunkShaderPrefab(Program); pub struct ChunkShaderPrefab(Program);
pub fn load_prefabs(world: &World) { pub fn load_prefabs(world: &World) {
let renderer = world.borrow::<NonSendSync<UniqueView<Rederer>>>().unwrap(); let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
world.add_unique_non_send_sync(BlockTexturesPrefab( world.add_unique_non_send_sync(BlockTexturesPrefab(
load_texture2darray_prefab::<BlockTextures, _>( load_texture2darray_prefab::<BlockTextures, _>(
"./assets/blocks/".into(), "./assets/blocks/".into(),

View file

@ -16,10 +16,10 @@ pub struct RenderTarget(pub glium::Frame);
pub struct BackgroundColor(pub Vec3); pub struct BackgroundColor(pub Vec3);
#[derive(Unique)] #[derive(Unique)]
pub struct Rederer { pub struct Renderer {
pub display: Display pub display: Display
} }
impl Rederer { impl Renderer {
pub fn init(event_loop: &EventLoop<()>) -> Self { pub fn init(event_loop: &EventLoop<()>) -> Self {
log::info!("initializing display"); log::info!("initializing display");
let wb = WindowBuilder::new() let wb = WindowBuilder::new()

View file

@ -58,6 +58,7 @@ impl<'a> ChunksNeighbors<'a> {
} }
#[derive(Default, Unique)] #[derive(Default, Unique)]
#[track(Modification)]
pub struct ChunkStorage { pub struct ChunkStorage {
pub chunks: HashMap<IVec3, Chunk> pub chunks: HashMap<IVec3, Chunk>
} }
@ -101,9 +102,11 @@ impl ChunkStorage {
} }
} }
#[derive(Default, Unique)]
pub struct ChunkMeshStorage { pub struct ChunkMeshStorage {
meshes: HashMap<u64, ChunkMesh, BuildNoHashHasher<u64>>, meshes: HashMap<usize, ChunkMesh, BuildNoHashHasher<usize>>,
index: u64, index: usize,
} }
impl ChunkMeshStorage { impl ChunkMeshStorage {
pub fn new() -> Self { pub fn new() -> Self {
@ -112,17 +115,17 @@ impl ChunkMeshStorage {
index: 0, index: 0,
} }
} }
pub fn insert(&mut self, mesh: ChunkMesh) -> u64 { pub fn insert(&mut self, mesh: ChunkMesh) -> usize {
let index = self.index; let index = self.index;
self.meshes.insert_unique_unchecked(index, mesh); self.meshes.insert_unique_unchecked(index, mesh);
self.index += 1; self.index += 1;
index 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; *self.meshes.get_mut(&key).context("Chunk doesn't exist")? = mesh;
Ok(()) 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")?; self.meshes.remove(&key).context("Chunk doesn't exist")?;
Ok(()) Ok(())
} }

View file

@ -21,9 +21,10 @@ pub struct ChunkMesh {
pub index_buffer: IndexBuffer<u32>, pub index_buffer: IndexBuffer<u32>,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum ChunkState { pub enum ChunkState {
ToUnload, //desired only ToUnload, //desired only
#[default]
Nothing, Nothing,
Loading, //current only Loading, //current only
Loaded, Loaded,
@ -39,3 +40,14 @@ pub struct Chunk {
pub current_state: ChunkState, pub current_state: ChunkState,
pub desired_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(),
}
}
}

View file

@ -1,31 +1,32 @@
use glam::ivec3; 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 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 { pub fn load_world_around_player() -> Workload {
( (
mark_chunks, update_chunks_if_player_moved,
unload_marked_chunks
).into_workload() ).into_workload()
} }
pub fn mark_chunks( pub fn update_chunks_if_player_moved(
v_settings: UniqueView<GameSettings>, v_settings: UniqueView<GameSettings>,
v_local_player: View<LocalPlayer>, v_local_player: View<LocalPlayer>,
v_transform: View<Transform>, v_transform: View<Transform>,
mut vm_world: UniqueViewMut<ChunkStorage>, mut vm_world: UniqueViewMut<ChunkStorage>,
) { ) {
//Read game settings //Check if the player actually moved
let load_distance = (v_settings.render_distance + 1) as i32;
//Check if a player moved
let Some((_, transform)) = (&v_local_player, v_transform.inserted_or_modified()).iter().next() else { let Some((_, transform)) = (&v_local_player, v_transform.inserted_or_modified()).iter().next() else {
return return
}; };
//Read game settings
let load_distance = (v_settings.render_distance + 1) as i32;
//If it did, get it's position and current chunk //If it did, get it's position and current chunk
let position = transform.0.to_scale_rotation_translation().2; let player_position = transform.0.to_scale_rotation_translation().2;
let at_chunk = position.as_ivec3() / CHUNK_SIZE as i32; let player_at_chunk = player_position.as_ivec3() / CHUNK_SIZE as i32;
//Then, mark *ALL* chunks with ToUnload //Then, mark *ALL* chunks with ToUnload
for (_, chunk) in &mut vm_world.chunks { for (_, chunk) in &mut vm_world.chunks {
@ -37,19 +38,46 @@ pub fn mark_chunks(
for y in -load_distance..=load_distance { for y in -load_distance..=load_distance {
for z in -load_distance..=load_distance { for z in -load_distance..=load_distance {
let chunk_pos_offset = ivec3(x, y, z); let chunk_pos_offset = ivec3(x, y, z);
let chunk_pos = player_at_chunk + chunk_pos_offset;
let is_border = { let is_border = {
chunk_pos_offset.x.abs() == load_distance || chunk_pos_offset.x.abs() == load_distance ||
chunk_pos_offset.y.abs() == load_distance || chunk_pos_offset.y.abs() == load_distance ||
chunk_pos_offset.z.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 { let desired = match is_border {
true => ChunkState::Loaded, true => ChunkState::Loaded,
false => ChunkState::Rendered, false => ChunkState::Rendered,
}; };
chunk.desired_state = desired;
}
} }
} }
} }
//TODO fn unload_marked_chunks(
todo!() mut vm_world: UniqueViewMut<ChunkStorage>,
mut vm_meshes: NonSendSync<UniqueViewMut<ChunkMeshStorage>>
) {
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
}
})
} }