should be all working now

This commit is contained in:
griffi-gh 2023-01-17 15:08:19 +01:00
parent 2637838be9
commit 096db79b12
5 changed files with 40 additions and 36 deletions

View file

@ -10,3 +10,4 @@ log = "0.4"
env_logger = "0.10" env_logger = "0.10"
strum = { version = "0.24", features = ["derive"] } strum = { version = "0.24", features = ["derive"] }
glam = { version = "0.22", features = ["debug-glam-assert", "mint", "fast-math"] } glam = { version = "0.22", features = ["debug-glam-assert", "mint", "fast-math"] }
hashbrown = "0.13"

View file

@ -1,6 +1,6 @@
use glam::{Vec2, IVec2}; use glam::{Vec2, IVec2};
use glium::Display; use glium::Display;
use std::collections::HashMap; use hashbrown::HashMap;
use crate::game::options::GameOptions; use crate::game::options::GameOptions;
mod chunk; mod chunk;
@ -50,16 +50,20 @@ impl World {
if !self.chunks.contains_key(&position) { if !self.chunks.contains_key(&position) {
self.chunks.insert(position, Chunk::new(position)); self.chunks.insert(position, Chunk::new(position));
} }
{
//we only need mutable reference here:
let chunk = self.chunks.get_mut(&position).unwrap(); let chunk = self.chunks.get_mut(&position).unwrap();
if x == 0 || z == 0 || x == render_dist || z == render_dist { if x == 0 || z == 0 || x == render_dist || z == render_dist {
chunk.desired = ChunkState::Loaded; chunk.desired = ChunkState::Loaded;
} 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) { //borrow chunk immutably
let chunk = self.chunks.get(&position).unwrap();
if matches!(chunk.state, ChunkState::Nothing) && matches!(chunk.desired, ChunkState::Loaded | ChunkState::Rendered) {
self.thread.queue_load(position);
} else if matches!(chunk.state, ChunkState::Loaded) && matches!(chunk.desired, ChunkState::Rendered) {
fn all_some<'a>(x: [Option<&'a Chunk>; 4]) -> Option<[&'a Chunk; 4]> { fn all_some<'a>(x: [Option<&'a Chunk>; 4]) -> Option<[&'a Chunk; 4]> {
Some([x[0]?, x[1]?, x[2]?, x[3]?]) Some([x[0]?, x[1]?, x[2]?, x[3]?])
} }
@ -70,33 +74,43 @@ impl World {
neighbors[2].block_data.is_some() && neighbors[2].block_data.is_some() &&
neighbors[3].block_data.is_some() neighbors[3].block_data.is_some()
} { } {
self.thread.queue_mesh(chunk, neighbors); self.thread.queue_mesh(
position,
chunk.block_data.clone().unwrap(),
[
neighbors[0].block_data.clone().unwrap(),
neighbors[1].block_data.clone().unwrap(),
neighbors[2].block_data.clone().unwrap(),
neighbors[3].block_data.clone().unwrap(),
]
);
} }
} }
} }
} }
} }
//Handle Unload //Unloads and state downgrades
self.chunks.retain(|_, chunk| !matches!(chunk.desired, ChunkState::Unload)); self.chunks.retain(|_, chunk| {
//State downgrades
for (_, chunk) in &mut self.chunks {
match chunk.desired { match chunk.desired {
// Chunk unload
ChunkState::Unload => false,
// Any => Nothing downgrade // Any => Nothing downgrade
ChunkState::Nothing => { ChunkState::Nothing => {
chunk.block_data = None; chunk.block_data = None;
chunk.mesh = None; chunk.mesh = None;
chunk.state = ChunkState::Nothing; chunk.state = ChunkState::Nothing;
true
}, },
//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.mesh = None; chunk.mesh = None;
chunk.state = ChunkState::Loaded; chunk.state = ChunkState::Loaded;
true
}, },
_ => () _ => 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

@ -17,7 +17,7 @@ pub enum ChunkState {
Rendered, Rendered,
} }
pub type ChunkData = [[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE]; pub type ChunkData = Box<[[[Block; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE]>;
pub struct Chunk { pub struct Chunk {
pub position: IVec2, pub position: IVec2,

View file

@ -1,10 +1,7 @@
use glam::IVec2; use glam::IVec2;
use glium::{Display, VertexBuffer, IndexBuffer, index::PrimitiveType}; use glium::{Display, VertexBuffer, IndexBuffer, index::PrimitiveType};
use std::{ use std::{mem, thread::{self, JoinHandle}};
thread::{self, JoinHandle}, use hashbrown::HashMap;
collections::HashMap,
mem
};
use super::chunk::{Chunk, ChunkData, ChunkState}; use super::chunk::{Chunk, ChunkData, ChunkState};
use crate::game::shaders::chunk::Vertex as ChunkVertex; use crate::game::shaders::chunk::Vertex as ChunkVertex;
@ -38,20 +35,12 @@ impl WorldThreading {
log::warn!("load: discarded {}, reason: new task started", position); log::warn!("load: discarded {}, reason: new task started", position);
} }
} }
pub fn queue_mesh(&mut self, chunk: &Chunk, neighbors: [&Chunk; 4]) { pub fn queue_mesh(&mut self, position: IVec2, chunk: ChunkData, neighbor_data: [ChunkData; 4]) {
let position = chunk.position;
let data = chunk.block_data.expect("Chunk has no mesh!");
let neighbor_data = [
neighbors[0].block_data.expect("Chunk has no mesh!"),
neighbors[1].block_data.expect("Chunk has no mesh!"),
neighbors[2].block_data.expect("Chunk has no mesh!"),
neighbors[3].block_data.expect("Chunk has no mesh!"),
];
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
mesh_gen::generate_mesh(position, data, neighbor_data) mesh_gen::generate_mesh(position, chunk, neighbor_data)
}); });
if self.mesh_tasks.insert(chunk.position, Some(handle)).is_some() { if self.mesh_tasks.insert(position, Some(handle)).is_some() {
log::warn!("mesh: discarded {}, reason: new task started", chunk.position); log::warn!("mesh: discarded {}, reason: new task started", position);
} }
} }
pub fn apply_tasks(&mut self, chunks: &mut HashMap<IVec2, Chunk>, display: &Display) { pub fn apply_tasks(&mut self, chunks: &mut HashMap<IVec2, Chunk>, display: &Display) {

View file

@ -4,5 +4,5 @@ use crate::game::{
}; };
pub fn generate_chunk() -> ChunkData { pub fn generate_chunk() -> ChunkData {
[[[Block::Stone; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE] Box::new([[[Block::Stone; CHUNK_SIZE]; CHUNK_HEIGHT]; CHUNK_SIZE])
} }