fixed freeze when loading chunks

Commit fe1a520c9015 · mgecumshooter · 2026-10-20 00:54 +0300

Changeset
fe1a520c9015c8486637fe62d733ae2443c07e80
Parents
10:d3e02c9e4e27

View source at this commit

Comments

No comments yet.

Log in to comment

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();
 	    }
 	}