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 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::<NonSendSync<UniqueView<Rederer>>>().unwrap();
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.draw()
};
target.clear_color_and_depth((0., 0., 0., 1.), 1.);

View file

@ -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::<NonSendSync<UniqueView<Rederer>>>().unwrap();
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
world.add_unique_non_send_sync(BlockTexturesPrefab(
load_texture2darray_prefab::<BlockTextures, _>(
"./assets/blocks/".into(),

View file

@ -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()

View file

@ -58,6 +58,7 @@ impl<'a> ChunksNeighbors<'a> {
}
#[derive(Default, Unique)]
#[track(Modification)]
pub struct ChunkStorage {
pub chunks: HashMap<IVec3, Chunk>
}
@ -101,9 +102,11 @@ impl ChunkStorage {
}
}
#[derive(Default, Unique)]
pub struct ChunkMeshStorage {
meshes: HashMap<u64, ChunkMesh, BuildNoHashHasher<u64>>,
index: u64,
meshes: HashMap<usize, ChunkMesh, BuildNoHashHasher<usize>>,
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(())
}

View file

@ -21,9 +21,10 @@ pub struct ChunkMesh {
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 {
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(),
}
}
}

View file

@ -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<GameSettings>,
v_local_player: View<LocalPlayer>,
v_transform: View<Transform>,
mut vm_world: UniqueViewMut<ChunkStorage>,
) {
//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<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
}
})
}