// SPDX-License-Identifier: AGPL-3.0-only use renderer::mesh::Vertex; use shared::world::{BlockId, CHUNK_SIZE, Chunk}; #[expect( clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::too_many_lines )] pub fn generate_mesh(chunk: &Chunk) -> (Vec, Vec) { let mut vertices = Vec::new(); let mut indices = Vec::new(); for x in 0..CHUNK_SIZE { for y in 0..CHUNK_SIZE { for z in 0..CHUNK_SIZE { let block = chunk.get(x, y, z); if block == BlockId::AIR { continue; } let fx = x as f32; let fy = y as f32; let fz = z as f32; if y == CHUNK_SIZE - 1 || chunk.get(x, y + 1, z) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.2, 0.8, 0.2], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2], }); vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.2, 0.8, 0.2], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } if y == 0 || chunk.get(x, y - 1, z) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1], }); vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.1, 0.4, 0.1], }); vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1], }); vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.1, 0.4, 0.1], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } if x == CHUNK_SIZE - 1 || chunk.get(x + 1, y, z) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } if x == 0 || chunk.get(x - 1, y, z) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.15, 0.6, 0.15], }); vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.15, 0.6, 0.15], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } if z == CHUNK_SIZE - 1 || chunk.get(x, y, z + 1) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz + 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz + 0.5], color: [0.18, 0.7, 0.18], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } if z == 0 || chunk.get(x, y, z - 1) == BlockId::AIR { let base_idx = vertices.len() as u32; vertices.push(Vertex { position: [fx + 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx - 0.5, fy - 0.5, fz - 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx - 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18], }); vertices.push(Vertex { position: [fx + 0.5, fy + 0.5, fz - 0.5], color: [0.18, 0.7, 0.18], }); indices.extend_from_slice(&[ base_idx, base_idx + 1, base_idx + 2, base_idx + 2, base_idx + 3, base_idx, ]); } } } } (vertices, indices) }