This commit is contained in:
griffi-gh 2023-01-16 23:27:14 +01:00
parent 09d08264d5
commit 2637838be9
4 changed files with 43 additions and 26 deletions

View file

@ -36,10 +36,12 @@ impl World {
pub fn update_loaded_chunks(&mut self, around_position: Vec2, options: &GameOptions, display: &Display) { pub fn update_loaded_chunks(&mut self, around_position: Vec2, options: &GameOptions, display: &Display) {
let render_dist = options.render_distance as i32 + 1; let render_dist = options.render_distance as i32 + 1;
let inside_chunk = (around_position / CHUNK_SIZE as f32).as_ivec2(); let inside_chunk = (around_position / CHUNK_SIZE as f32).as_ivec2();
//Mark all chunks for unload //Mark all chunks for unload
for (_, chunk) in &mut self.chunks { for (_, chunk) in &mut self.chunks {
chunk.desired = ChunkState::Unload; chunk.desired = ChunkState::Unload;
} }
//Load new/update chunks in range //Load new/update chunks in range
for x in -render_dist..=render_dist { for x in -render_dist..=render_dist {
for z in -render_dist..=render_dist { for z in -render_dist..=render_dist {
@ -54,34 +56,47 @@ impl World {
} else { } else {
chunk.desired = ChunkState::Rendered; chunk.desired = ChunkState::Rendered;
} }
if matches!(chunk.state, ChunkState::Nothing) {
self.thread.queue_load(position);
}
if matches!(chunk.state, ChunkState::Loaded) && matches!(chunk.desired, ChunkState::Rendered) {
fn all_some<'a>(x: [Option<&'a Chunk>; 4]) -> Option<[&'a Chunk; 4]> {
Some([x[0]?, x[1]?, x[2]?, x[3]?])
}
if let Some(neighbors) = all_some(self.chunk_neighbors(chunk.position)) {
if {
neighbors[0].block_data.is_some() &&
neighbors[1].block_data.is_some() &&
neighbors[2].block_data.is_some() &&
neighbors[3].block_data.is_some()
} {
self.thread.queue_mesh(chunk, neighbors);
} }
} }
//State up/downgrades are handled here! }
self.chunks.retain(|&position, chunk| { }
}
//Handle Unload
self.chunks.retain(|_, chunk| !matches!(chunk.desired, ChunkState::Unload));
//State downgrades
for (_, chunk) in &mut self.chunks {
match chunk.desired { match chunk.desired {
// Any => Unload downgrade
ChunkState::Unload => {
return false
},
// Any => Nothing downgrade // Any => Nothing downgrade
ChunkState::Nothing => { ChunkState::Nothing => {
chunk.block_data = None; chunk.block_data = None;
chunk.vertex_buffer = None; chunk.mesh = None;
chunk.state = ChunkState::Nothing; chunk.state = ChunkState::Nothing;
}, },
// Nothing => Loading => Loaded upgrade
ChunkState::Loaded if matches!(chunk.state, ChunkState::Nothing) => {
self.thread.queue_load(position);
},
//Render => Loaded downgrade //Render => Loaded downgrade
ChunkState::Loaded if matches!(chunk.state, ChunkState::Rendering | ChunkState::Rendered) => { ChunkState::Loaded if matches!(chunk.state, ChunkState::Rendering | ChunkState::Rendered) => {
chunk.vertex_buffer = None; chunk.mesh = None;
chunk.state = ChunkState::Loaded; chunk.state = ChunkState::Loaded;
}, },
_ => () _ => ()
} }
true }
});
//Apply changes from threads //Apply changes from threads
self.thread.apply_tasks(&mut self.chunks, display); self.thread.apply_tasks(&mut self.chunks, display);
} }

View file

@ -1,5 +1,5 @@
use glam::IVec2; use glam::IVec2;
use glium::VertexBuffer; use glium::{VertexBuffer, IndexBuffer};
use crate::game::{ use crate::game::{
blocks::Block, blocks::Block,
shaders::chunk::Vertex as ChunkVertex shaders::chunk::Vertex as ChunkVertex
@ -18,12 +18,11 @@ pub enum ChunkState {
} }
pub type ChunkData = [[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE]; pub type ChunkData = [[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE];
pub type ChunkMesh = VertexBuffer<ChunkVertex>;
pub struct Chunk { pub struct Chunk {
pub position: IVec2, pub position: IVec2,
pub block_data: Option<ChunkData>, pub block_data: Option<ChunkData>,
pub vertex_buffer: Option<(bool, ChunkMesh)>, pub mesh: Option<(bool, VertexBuffer<ChunkVertex>, IndexBuffer<u16>)>,
pub state: ChunkState, pub state: ChunkState,
pub desired: ChunkState, pub desired: ChunkState,
} }
@ -32,7 +31,7 @@ impl Chunk {
Self { Self {
position, position,
block_data: None, block_data: None,
vertex_buffer: None, mesh: None,
state: ChunkState::Nothing, state: ChunkState::Nothing,
desired: ChunkState::Nothing, desired: ChunkState::Nothing,
} }

View file

@ -1,5 +1,5 @@
use glam::IVec2; use glam::IVec2;
use glium::{Display, VertexBuffer}; use glium::{Display, VertexBuffer, IndexBuffer, index::PrimitiveType};
use std::{ use std::{
thread::{self, JoinHandle}, thread::{self, JoinHandle},
collections::HashMap, collections::HashMap,
@ -17,7 +17,7 @@ pub struct WorldThreading {
//Options are needed here to take ownership, //Options are needed here to take ownership,
//None values should never appear here! //None values should never appear here!
pub load_tasks: HashMap<IVec2, Option<JoinHandle<ChunkData>>>, pub load_tasks: HashMap<IVec2, Option<JoinHandle<ChunkData>>>,
pub mesh_tasks: HashMap<IVec2, Option<JoinHandle<Vec<ChunkVertex>>>>, pub mesh_tasks: HashMap<IVec2, Option<JoinHandle<(Vec<ChunkVertex>, Vec<u16>)>>>,
} }
impl WorldThreading { impl WorldThreading {
pub fn new() -> Self { pub fn new() -> Self {
@ -93,11 +93,12 @@ impl WorldThreading {
} }
log::info!("mesh: done {}", position); log::info!("mesh: done {}", position);
let handle = mem::take(handle).unwrap(); let handle = mem::take(handle).unwrap();
let data = handle.join().unwrap(); let (shape, index) = handle.join().unwrap();
let chunk = chunks.get_mut(position).unwrap(); let chunk = chunks.get_mut(position).unwrap();
chunk.vertex_buffer = Some(( chunk.mesh = Some((
true, true,
VertexBuffer::immutable(display, &data).expect("Failed to build VertexBuffer") VertexBuffer::immutable(display, &shape).expect("Failed to build VertexBuffer"),
IndexBuffer::immutable(display, PrimitiveType::TrianglesList, &index).expect("Failed to build IndexBuffer")
)); ));
chunk.state = ChunkState::Rendered; chunk.state = ChunkState::Rendered;
false false

View file

@ -1,7 +1,9 @@
use glam::IVec2; use glam::IVec2;
use crate::game::world::chunk::{Chunk, ChunkData}; use crate::game::world::chunk::ChunkData;
use crate::game::shaders::chunk::Vertex as ChunkVertex; use crate::game::shaders::chunk::Vertex as ChunkVertex;
pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkData; 4]) -> Vec<ChunkVertex> { pub fn generate_mesh(position: IVec2, chunk_data: ChunkData, neighbors: [ChunkData; 4]) -> (Vec<ChunkVertex>, Vec<u16>) {
vec![] let vertex = Vec::new();
let index = Vec::new();
(vertex, index)
} }