diff --git a/shaders/world.vert b/shaders/world.vert index 955ca12..de3d2e7 100644 --- a/shaders/world.vert +++ b/shaders/world.vert @@ -13,7 +13,7 @@ in uint tex_index; out vec2 v_uv; out vec3 v_normal; flat out uint v_tex_index; -uniform vec2 position_offset; +uniform vec3 position_offset; uniform mat4 perspective; uniform mat4 view; @@ -21,5 +21,5 @@ void main() { v_normal = normal; v_tex_index = tex_index; v_uv = uv; - gl_Position = perspective * view * (vec4(position, 1.0) + vec4(position_offset.x, 0., position_offset.y, 0.)); + gl_Position = perspective * view * vec4(position + position_offset, 1.); } diff --git a/src/camera.rs b/src/camera.rs index 501f720..97efee5 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -49,7 +49,7 @@ fn update_perspective_matrix( mut vm_camera: ViewMut ) { //todo compute this on win resize! - const ASPECT_RATIO: f32 = 9. / 16.; + const ASPECT_RATIO: f32 = 16. / 9.; for camera in (&mut vm_camera).iter() { camera.perspective_matrix = Mat4::perspective_rh_gl( camera.fov, diff --git a/src/settings.rs b/src/settings.rs index df9cd49..2ad524c 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -8,7 +8,7 @@ pub struct GameSettings { impl Default for GameSettings { fn default() -> Self { Self { - render_distance: 5 + render_distance: 2 } } } diff --git a/src/world/block.rs b/src/world/block.rs index 3ac2026..ced61a8 100644 --- a/src/world/block.rs +++ b/src/world/block.rs @@ -1,6 +1,6 @@ use strum::EnumIter; -#[derive(Clone, Copy, Debug, EnumIter)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter)] #[repr(u8)] pub enum Block { Air, diff --git a/src/world/loading.rs b/src/world/loading.rs index 6a8b9e5..571c3bb 100644 --- a/src/world/loading.rs +++ b/src/world/loading.rs @@ -153,8 +153,8 @@ fn process_completed_tasks( }; //check if chunk still wants it - if matches!(chunk.desired_state, DesiredChunkState::Loaded | DesiredChunkState::Rendered) { - log::warn!("block data discarded: state undesirable"); + if !matches!(chunk.desired_state, DesiredChunkState::Loaded | DesiredChunkState::Rendered) { + log::warn!("block data discarded: state undesirable: {:?}", chunk.desired_state); return } @@ -175,7 +175,7 @@ fn process_completed_tasks( //check if chunk still wants it if chunk.desired_state != DesiredChunkState::Rendered { - log::warn!("mesh discarded: state undesirable"); + log::warn!("mesh discarded: state undesirable: {:?}", chunk.desired_state); return } diff --git a/src/world/mesh.rs b/src/world/mesh.rs index 6fdcecd..fb5686f 100644 --- a/src/world/mesh.rs +++ b/src/world/mesh.rs @@ -1,5 +1,6 @@ use strum::{EnumIter, IntoEnumIterator}; -use glam::{Vec3A, vec3a}; +use glam::{Vec3A, vec3a, IVec3, ivec3}; +use super::{render::ChunkVertex, chunk::CHUNK_SIZE, block::Block}; pub mod data; use data::MeshGenData; @@ -38,6 +39,95 @@ const UV_COORDS: [[f32; 2]; 4] = [ [1., 1.], ]; -pub fn generate_mesh(data: MeshGenData) { - +#[derive(Default)] +struct MeshBuilder { + vertex_buffer: Vec, + index_buffer: Vec, + idx_counter: u32, +} +impl MeshBuilder { + pub fn new() -> Self { + Self::default() + } + + pub fn add_face(&mut self, face: CubeFace, coord: IVec3, texture: u8) { + let coord = coord.as_vec3a(); + let face_index = face as usize; + + //Push vertexes + let norm = CUBE_FACE_NORMALS[face_index]; + let vert = CUBE_FACE_VERTICES[face_index]; + self.vertex_buffer.reserve(4); + for i in 0..4 { + self.vertex_buffer.push(ChunkVertex { + position: (coord + vert[i]).to_array(), + normal: norm.to_array(), + uv: UV_COORDS[i], + tex_index: texture + }); + } + + //Push indices + self.index_buffer.extend_from_slice(&CUBE_FACE_INDICES.map(|x| x + self.idx_counter)); + self.idx_counter += 4; + } + + pub fn finish(self) -> (Vec, Vec) { + (self.vertex_buffer, self.index_buffer) + } +} + +pub fn generate_mesh(data: MeshGenData) -> (Vec, Vec) { + let get_block = |pos: IVec3| -> Block { + if pos.x < 0 { + data.block_data_neg_x[(CHUNK_SIZE as i32 + pos.x) as usize][pos.y as usize][pos.z as usize] + } else if pos.x >= CHUNK_SIZE as i32 { + data.block_data_pos_x[pos.x as usize - CHUNK_SIZE][pos.y as usize][pos.z as usize] + } else if pos.y < 0 { + data.block_data_neg_y[pos.x as usize][(CHUNK_SIZE as i32 + pos.y) as usize][pos.z as usize] + } else if pos.y >= CHUNK_SIZE as i32 { + data.block_data_pos_y[pos.x as usize][pos.y as usize - CHUNK_SIZE][pos.z as usize] + } else if pos.z < 0 { + data.block_data_neg_z[pos.x as usize][pos.y as usize][(CHUNK_SIZE as i32 + pos.z) as usize] + } else if pos.z >= CHUNK_SIZE as i32 { + data.block_data_pos_z[pos.x as usize][pos.y as usize][pos.z as usize - CHUNK_SIZE] + } else { + data.block_data[pos.x as usize][pos.y as usize][pos.z as usize] + } + }; + + let mut builder = MeshBuilder::new(); + + for x in 0..CHUNK_SIZE { + for y in 0..CHUNK_SIZE { + for z in 0..CHUNK_SIZE { + let coord = ivec3(x as i32, y as i32, z as i32); + let block = get_block(coord); + if block == Block::Air { + continue + } + for face in CubeFace::iter() { + let facing = CUBE_FACE_NORMALS[face as usize].as_ivec3(); + let facing_coord = coord + facing; + let show = { + get_block(facing_coord) == Block::Air + }; + if show { + // let texures = descriptor.render.unwrap().1; + // let block_texture = match face { + // CubeFace::Top => texures.top, + // CubeFace::Front => texures.front, + // CubeFace::Left => texures.left, + // CubeFace::Right => texures.right, + // CubeFace::Back => texures.back, + // CubeFace::Bottom => texures.bottom, + // }; + builder.add_face(face, coord, 0); + } + } + } + } + } + + builder.finish() } diff --git a/src/world/tasks.rs b/src/world/tasks.rs index 2047d80..9b921bc 100644 --- a/src/world/tasks.rs +++ b/src/world/tasks.rs @@ -4,7 +4,7 @@ use shipyard::Unique; use super::{ chunk::BlockData, render::ChunkVertex, - mesh::data::MeshGenData, + mesh::{generate_mesh, data::MeshGenData}, worldgen::generate_world, }; @@ -45,7 +45,8 @@ impl ChunkTaskManager { rayon::spawn(move || { let _ = sender.send(match task { ChunkTask::GenerateMesh { position, data } => { - todo!() + let (vertices, indexes) = generate_mesh(data); + ChunkTaskResponse::GeneratedMesh { position, vertices, indexes } }, ChunkTask::LoadChunk { position, seed } => { let chunk_data = generate_world(position, seed);