mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-26 08:48:50 -06:00
chunk marking/loading!!
This commit is contained in:
parent
0a528d8ccf
commit
c761688f81
13
src/main.rs
13
src/main.rs
|
@ -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.);
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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()
|
||||||
|
|
13
src/world.rs
13
src/world.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
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
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue