mgecumshooter/esotera
added chunk split meshing
Commit 493d4080cf84 · mgecumshooter · 2026-10-22 13:12 +0300
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
@@ -10,13 +10,13 @@
use crate::voxel::*;
// constants
-pub const CHUNK_SIZE: usize = 16;
+pub const CHUNK_SIZE: usize = 32;
pub struct Chunk {
pub chunk_pos: Vector3,
pub voxels: [Voxel; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
pub dirty: bool,
- pub mesh: Option<Mesh>,
+ pub meshes: Vec<Mesh>,
} // pending: add events stack
impl Chunk {
@@ -26,7 +26,7 @@
chunk_pos: pos,
voxels: [Voxel::from_kind(VoxelKind::Air); CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE],
dirty: true,
- mesh: None,
+ meshes: Vec::new(),
};
for x in 0..CHUNK_SIZE {
for z in 0..CHUNK_SIZE {
@@ -113,6 +113,64 @@
cos_angle.acos() <= half_fov + angular_margin
}
+
+ fn flush_mesh_buffer(&mut self,
+ vertices: &mut Vec<Vector3>,
+ normals: &mut Vec<Vector3>,
+ indices: &mut Vec<u16>,
+ colors: &mut Vec<u8>,
+ ) {
+ let vertex_count = vertices.len();
+ let index_count = indices.len();
+
+ if vertex_count == 0 {
+ 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 = vertex_count * std::mem::size_of::<Vector3>();
+ let c_size = colors.len();
+
+ 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;
+ let c_ptr = rlb::ffi::MemAlloc(c_size as u32) as *mut u8;
+
+ 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, vertex_count);
+ std::ptr::copy_nonoverlapping(colors.as_ptr(), c_ptr, colors.len());
+
+ 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: c_ptr,
+ 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.meshes.push(mesh);
+ }
+ vertices.clear();
+ indices.clear();
+ normals.clear();
+ colors.clear();
+ }
pub fn generate_mesh(&mut self) {
let mut vertices: Vec<Vector3> = Vec::new();
@@ -120,7 +178,10 @@
let mut indices: Vec<u16> = Vec::new();
let mut colors: Vec<u8> = Vec::new();
+ const MAX_VERTICES_PER_MESH: i32 = 65536 - 24;
+
let mut vertex_offset: i32 = 0;
+
for x in 0..CHUNK_SIZE {
for y in 0..CHUNK_SIZE {
for z in 0..CHUNK_SIZE {
@@ -129,18 +190,24 @@
if v.kind == VoxelKind::Air {
continue;
}
- v
+ *v
}
None => continue,
};
- // if let Some(Voxel::Air) = self.get_voxel(x, y, z) {
- // continue;
- // }
if !self.is_exposed(x, y, z) {
continue;
}
+ if vertex_offset + 24 > MAX_VERTICES_PER_MESH {
+ self.flush_mesh_buffer(&mut vertices,
+ &mut normals,
+ &mut indices,
+ &mut colors
+ );
+ vertex_offset = 0;
+ }
+
// first side
vertices.push(Vector3::new(x as f32, y as f32, z as f32));
vertices.push(Vector3::new(
@@ -315,57 +382,7 @@
}
}
}
-
- 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 c_size = colors.len();
-
- 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;
- let c_ptr = rlb::ffi::MemAlloc(c_size as u32) as *mut u8;
-
- 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);
- std::ptr::copy_nonoverlapping(colors.as_ptr(), c_ptr, colors.len());
-
- 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: c_ptr,
- 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);
- }
+ self.flush_mesh_buffer(&mut vertices, &mut normals, &mut indices, &mut colors);
}
// returns voxel by chunk coordinates
@@ -501,7 +518,7 @@
chunk_pos: pos,
voxels,
dirty: true,
- mesh: None,
+ meshes: Vec::new(),
});
}
}
@@ -523,3 +540,4 @@
colors.push(c.3);
}
}
+
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -54,7 +54,7 @@
*chunk_material.shader_mut() = shader.make_weak();
}
- let mut world = World::new(6);
+ let mut world = World::new(5);
let mut plr = Player::new(
Vector3::new(0f32, 50f32, 0f32),
@@ -91,17 +91,26 @@
if !chunk.is_visible(&cam) {
continue;
}
- 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,
- ),
- );
- }
+ for mesh in &chunk.meshes {
+ 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,
+ ),
+ );
+ }
+ // 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);
}
});
diff --git a/src/voxel/mod.rs b/src/voxel/mod.rs
--- a/src/voxel/mod.rs
+++ b/src/voxel/mod.rs
@@ -23,7 +23,7 @@
let color = match kind {
VoxelKind::Air => VoxelColor(0, 0, 0, 0),
VoxelKind::Stone => VoxelColor(128, 128, 128, 255),
- VoxelKind::Dirt => VoxelColor(96, 136, 67, 255),
+ VoxelKind::Dirt => VoxelColor(106, 180, 77, 255),
VoxelKind::Wood => VoxelColor(161, 60, 0, 255),
};
Self { kind, color }