mgecumshooter/esotera
Merge pull request 'fixed freeze when loading chunks' (#6) from mgecumshooter into master
Commit cb4950c03d8e · mgecumshooter · 2026-10-20 06:24 +0200
Merge pull request 'fixed freeze when loading chunks' (#6) from mgecumshooter into master Reviewed-on: https://codeberg.org/mgecumshooter/esotera/pulls/6
Comments
No comments yet.
Diff
diff --git a/src/chunk/mod.rs b/src/chunk/mod.rs
--- a/src/chunk/mod.rs
+++ b/src/chunk/mod.rs
@@ -30,12 +30,12 @@
let mut s = Self {
chunk_pos: pos,
voxels: [Voxel::Air; CHUNK_SIZE*CHUNK_SIZE*CHUNK_SIZE],
- dirty: false,
+ dirty: true,
mesh: None
};
- for x in 0..31 {
- for z in 0..31 {
- let y = x + z;
+ for x in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ let y = (x + z).min(CHUNK_SIZE - 1);
let i = x + (y * CHUNK_SIZE) + (z * CHUNK_SIZE * CHUNK_SIZE);
s.voxels[i] = Voxel::Stone;
}
@@ -43,6 +43,238 @@
s
}
+ pub fn generate_mesh(&mut self, rl: &RaylibThread) {
+ let mut vertices: Vec<Vector3> = Vec::new();
+ let mut normals: Vec<Vector3> = Vec::new();
+ let mut indices: Vec<u16> = Vec::new();
+
+ let mut vertex_offset: i32 = 0;
+ for x in 0..CHUNK_SIZE {
+ for y in 0..CHUNK_SIZE {
+ for z in 0..CHUNK_SIZE {
+ if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
+ continue;
+ }
+ if !self.is_exposed(x, y, z) {
+ continue;
+ }
+
+
+ // first side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, -1f32));
+
+ // second side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(-1f32, 0f32, 0f32));
+
+ // third side
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, -1f32, 0f32));
+
+ // fourth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 1f32, 0f32));
+
+ // fifth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32 + VOXEL_SIZE as f32, z as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(1f32, 0f32, 0f32));
+
+ // sixth side
+ vertices.push(
+ Vector3::
+ new(x as f32+VOXEL_SIZE as f32, y as f32+VOXEL_SIZE as f32, z as f32+VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32 + VOXEL_SIZE as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32 + VOXEL_SIZE as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ vertices.push(
+ Vector3::
+ new(x as f32, y as f32, z as f32 + VOXEL_SIZE as f32)
+ );
+ push_quad_normal(&mut normals, Vector3::new(0f32, 0f32, 1f32));
+
+
+ indices.push(0 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(2 as u16 + vertex_offset as u16);
+ indices.push(1 as u16 + vertex_offset as u16);
+ indices.push(3 as u16 + vertex_offset as u16);
+
+ indices.push(4 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(5 as u16 + vertex_offset as u16);
+ indices.push(6 as u16 + vertex_offset as u16);
+ indices.push(7 as u16 + vertex_offset as u16);
+
+ indices.push(8 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(10 as u16 + vertex_offset as u16);
+ indices.push(9 as u16 + vertex_offset as u16);
+ indices.push(11 as u16 + vertex_offset as u16);
+
+ indices.push(12 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(13 as u16 + vertex_offset as u16);
+ indices.push(14 as u16 + vertex_offset as u16);
+ indices.push(15 as u16 + vertex_offset as u16);
+
+ indices.push(16 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(18 as u16 + vertex_offset as u16);
+ indices.push(17 as u16 + vertex_offset as u16);
+ indices.push(19 as u16 + vertex_offset as u16);
+
+ indices.push(20 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(21 as u16 + vertex_offset as u16);
+ indices.push(22 as u16 + vertex_offset as u16);
+ indices.push(23 as u16 + vertex_offset as u16);
+
+
+
+ vertex_offset += 24;
+
+ }
+ }
+ }
+
+ let vertex_count = vertices.len();
+ let index_count = indices.len();
+ let normals_count = normals.len();
+
+ if vertex_count == 0 {
+ self.mesh = None;
+ return;
+ }
+
+ unsafe {
+ let v_size = vertex_count * std::mem::size_of::<Vector3>();
+ let i_size = index_count * std::mem::size_of::<u16>();
+ let n_size = normals_count * std::mem::size_of::<Vector3>();
+
+ let v_ptr = rlb::ffi::MemAlloc(v_size as u32) as *mut Vector3;
+ let i_ptr = rlb::ffi::MemAlloc(i_size as u32) as *mut u16;
+ let n_ptr = rlb::ffi::MemAlloc(n_size as u32) as *mut Vector3;
+
+ std::ptr::copy_nonoverlapping(vertices.as_ptr(), v_ptr, vertex_count);
+ std::ptr::copy_nonoverlapping(indices.as_ptr(), i_ptr, index_count);
+ std::ptr::copy_nonoverlapping(normals.as_ptr(), n_ptr, normals_count);
+
+ let raw_mesh = rlb::ffi::Mesh {
+ vertexCount: vertex_count as i32,
+ triangleCount: (index_count / 3) as i32,
+ vertices: v_ptr as *mut std::ffi::c_float,
+ indices: i_ptr,
+ normals: n_ptr as *mut std::ffi::c_float,
+ texcoords: std::ptr::null_mut(),
+ texcoords2: std::ptr::null_mut(),
+ colors: std::ptr::null_mut(),
+ tangents: std::ptr::null_mut(),
+ animVertices: std::ptr::null_mut(),
+ animNormals: std::ptr::null_mut(),
+ boneCount: 0,
+ boneIndices: std::ptr::null_mut(),
+ boneWeights: std::ptr::null_mut(),
+ vaoId: 0,
+ vboId: std::ptr::null_mut(),
+ };
+
+ let mut mesh = Mesh::from_raw(raw_mesh);
+
+ mesh.upload(false);
+
+ self.mesh = Some(mesh);
+ }
+
+ }
+
// returns voxel by chunk coordinates
pub fn get_voxel(&self, x: usize, y: usize, z: usize) -> Option<&Voxel> {
if x >= CHUNK_SIZE || y >= CHUNK_SIZE || z >= CHUNK_SIZE {
@@ -187,7 +419,7 @@
return Some(Self{
chunk_pos: pos,
voxels,
- dirty: false,
+ dirty: true,
mesh: None,
});
}
@@ -195,3 +427,11 @@
None
}
}
+
+
+fn push_quad_normal(normals: &mut Vec<Vector3>, n: Vector3) {
+ for _ in 0..4 {
+ normals.push(n);
+ }
+}
+
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,13 +40,19 @@
let mut rend_tex = rl.load_render_texture
(&rl_thd, rl.get_render_width() as u32, rl.get_render_height() as u32).unwrap();
+ let mut chunk_material = rl.load_material_default(&rl_thd);
+ unsafe {
+ *chunk_material.shader_mut() = shader.make_weak();
+ }
+ // chunk_material.set_shader(&shader);
+
// chunks
// let test_chunk = Chunk::new(Vector3::zero());
// let test2 = [&test_chunk];
- let mut world = World::new(2);
+ let mut world = World::new(5);
let mut plr = Player::new(
Vector3::new(0f32, 10f32, 0f32),
@@ -58,7 +64,8 @@
// main game loop
while !rl.window_should_close() {
- world.update_around_player(plr.get_eye_pos());
+ world.load_around_player(plr.get_eye_pos());
+ world.update_chunks(&rl_thd);
let active_chunks: Vec<&Chunk> = world.chunks.values().collect();
plr.update(&rl, &active_chunks);
@@ -75,12 +82,19 @@
tx.clear_background(Color::new(30, 30, 30, 255));
tx.draw_mode3D(cam, |mut d3, _| {
d3.draw_grid(100, 1f32);
- d3.draw_shader_mode(&mut shader, |mut shd| {
- // test_chunk.draw(&mut shd);
- for chunk in world.chunks.values() {
- chunk.draw(&mut shd);
+ for chunk in world.chunks.values() {
+ if let Some(ref mesh) = chunk.mesh {
+ d3.draw_mesh(mesh,
+ chunk_material.clone(),
+ Matrix::translate(
+ chunk.chunk_pos.x * CHUNK_SIZE as f32,
+ chunk.chunk_pos.y * CHUNK_SIZE as f32,
+ chunk.chunk_pos.z * CHUNK_SIZE as f32,
+ )
+ );
}
- });
+ // chunk.draw(&mut shd);
+ }
});
});
d.draw_shader_mode(&mut post_shader, |mut shd| {
diff --git a/src/world/mod.rs b/src/world/mod.rs
--- a/src/world/mod.rs
+++ b/src/world/mod.rs
@@ -15,7 +15,23 @@
}
}
- pub fn update_around_player(&mut self, player_pos: Vector3) {
+ pub fn update_chunks(&mut self, rl: &RaylibThread) {
+ const CHUNK_PER_FRAME: usize = 2;
+ let mut processed = 0;
+
+ for (_, mut chunk) in &mut self.chunks {
+ if processed >= CHUNK_PER_FRAME {
+ break;
+ }
+ if chunk.dirty {
+ chunk.generate_mesh(rl);
+ chunk.dirty = false;
+ processed += 1;
+ }
+ }
+ }
+
+ pub fn load_around_player(&mut self, player_pos: Vector3) {
let p_chunk_x = (player_pos.x / CHUNK_SIZE as f32).floor() as i32;
let p_chunk_y = (player_pos.y / CHUNK_SIZE as f32).floor() as i32;
let p_chunk_z = (player_pos.z / CHUNK_SIZE as f32).floor() as i32;
@@ -56,7 +72,7 @@
}
}
for coords in to_unload {
- if let Some(chunk) = self.chunks.remove(&coords) {
+ if let Some(mut chunk) = self.chunks.remove(&coords) {
chunk.save();
}
}