diff --git a/src/main.rs b/src/main.rs index 64230cb..e474530 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,8 +23,8 @@ pub(crate) mod settings; pub(crate) mod state; pub(crate) mod camera; -use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background, draw_world}; -use world::{ChunkStorage, ChunkMeshStorage, loading::update_loaded_world_around_player}; +use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background}; +use world::{ChunkStorage, ChunkMeshStorage, loading::update_loaded_world_around_player, render::draw_world}; use player::spawn_player; use prefabs::load_prefabs; use settings::GameSettings; diff --git a/src/rendering.rs b/src/rendering.rs index d20bde5..2bf0517 100644 --- a/src/rendering.rs +++ b/src/rendering.rs @@ -1,20 +1,6 @@ -use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter}; +use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut}; use glium::{ - Display, Surface, uniform, - DrawParameters, - uniforms::{ - Sampler, - SamplerBehavior, - MinifySamplerFilter, - MagnifySamplerFilter, - SamplerWrapFunction - }, - draw_parameters::{ - Depth, - DepthTest, - PolygonMode, - BackfaceCullingMode, - }, + Display, Surface, glutin::{ event_loop::EventLoop, window::WindowBuilder, @@ -22,18 +8,6 @@ use glium::{ }, }; use glam::Vec3; -use crate::{ - camera::Camera, - prefabs::{ - ChunkShaderPrefab, - BlockTexturesPrefab, - }, - world::{ - ChunkStorage, - ChunkMeshStorage, - chunk::CHUNK_SIZE, - }, -}; #[derive(Unique)] pub struct RenderTarget(pub glium::Frame); @@ -66,52 +40,3 @@ pub fn clear_background( ) { target.0.clear_color_srgb_and_depth((color.0.x, color.0.y, color.0.z, 1.), 1.); } - -pub fn draw_world( - mut target: NonSendSync>, - chunks: UniqueView, - meshes: NonSendSync>, - program: NonSendSync>, - texture: NonSendSync>, - camera: View, -) { - let camera = camera.iter().next().expect("No cameras in the scene"); - let draw_parameters = DrawParameters { - depth: Depth { - test: DepthTest::IfLess, - write: true, - ..Default::default() - }, - polygon_mode: PolygonMode::Fill, //Change to Line for wireframe - backface_culling: BackfaceCullingMode::CullCounterClockwise, - ..Default::default() - }; - let texture_sampler = Sampler(&texture.0, SamplerBehavior { - minify_filter: MinifySamplerFilter::Linear, - magnify_filter: MagnifySamplerFilter::Nearest, - max_anisotropy: 8, - wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), - ..Default::default() - }); - let view = camera.view_matrix.to_cols_array_2d(); - let perspective = camera.perspective_matrix.to_cols_array_2d(); - - for (&position, chunk) in &chunks.chunks { - if let Some(key) = chunk.mesh_index { - let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); - let world_position = (position.as_vec3() * CHUNK_SIZE as f32).to_array(); - target.0.draw( - &mesh.vertex_buffer, - &mesh.index_buffer, - &program.0, - &uniform! { - position_offset: world_position, - view: view, - perspective: perspective, - tex: texture_sampler - }, - &draw_parameters - ).unwrap(); - } - } -} diff --git a/src/world.rs b/src/world.rs index f194a3c..349dc79 100644 --- a/src/world.rs +++ b/src/world.rs @@ -11,14 +11,13 @@ pub mod tasks; pub mod loading; pub mod mesh; pub mod neighbors; +pub mod worldgen; use chunk::{Chunk, ChunkMesh}; //TODO separate world struct for render data // because this is not send-sync - - #[derive(Default, Unique)] #[track(Modification)] pub struct ChunkStorage { @@ -30,6 +29,10 @@ impl ChunkStorage { } } +#[derive(Unique)] +pub struct WorldInfo { + pub seed: u32, +} #[derive(Default, Unique)] pub struct ChunkMeshStorage { diff --git a/src/world/mesh.rs b/src/world/mesh.rs index e69de29..ae5a6cd 100644 --- a/src/world/mesh.rs +++ b/src/world/mesh.rs @@ -0,0 +1,2 @@ +pub mod data; +use data::MeshGenData; diff --git a/src/world/mesh/data.rs b/src/world/mesh/data.rs new file mode 100644 index 0000000..403d1d4 --- /dev/null +++ b/src/world/mesh/data.rs @@ -0,0 +1,34 @@ +use crate::world::{ + neighbors::AllChunkNeighbors, + chunk::BlockData +}; + +pub struct MeshGenData { + pub block_data: BlockData, + pub block_data_pos_z: BlockData, + pub block_data_neg_z: BlockData, + pub block_data_pos_y: BlockData, + pub block_data_neg_y: BlockData, + pub block_data_pos_x: BlockData, + pub block_data_neg_x: BlockData, +} +impl<'a> AllChunkNeighbors<'a> { + pub fn mesh_data(&self) -> Option { + let center_block_data = self.center.block_data.as_ref()?; + let front_block_data = self.front.block_data.as_ref()?; + let back_block_data = self.back.block_data.as_ref()?; + let top_block_data = self.top.block_data.as_ref()?; + let bottom_block_data = self.bottom.block_data.as_ref()?; + let right_block_data = self.right.block_data.as_ref()?; + let left_block_data = self.left.block_data.as_ref()?; + Some(MeshGenData { + block_data: center_block_data.blocks.clone(), + block_data_pos_z: front_block_data.blocks.clone(), + block_data_neg_z: back_block_data.blocks.clone(), + block_data_pos_y: top_block_data.blocks.clone(), + block_data_neg_y: bottom_block_data.blocks.clone(), + block_data_pos_x: right_block_data.blocks.clone(), + block_data_neg_x: left_block_data.blocks.clone(), + }) + } +} diff --git a/src/world/render.rs b/src/world/render.rs index 9ae11b1..23fbbda 100644 --- a/src/world/render.rs +++ b/src/world/render.rs @@ -1,4 +1,34 @@ -use glium::implement_vertex; +use shipyard::{NonSendSync, UniqueView, UniqueViewMut, View, IntoIter}; +use glium::{ + implement_vertex, uniform, + Surface, DrawParameters, + uniforms::{ + Sampler, + SamplerBehavior, + MinifySamplerFilter, + MagnifySamplerFilter, + SamplerWrapFunction + }, + draw_parameters::{ + Depth, + DepthTest, + PolygonMode, + BackfaceCullingMode, + } +}; +use crate::{ + camera::Camera, + rendering::RenderTarget, + prefabs::{ + ChunkShaderPrefab, + BlockTexturesPrefab, + }, + world::{ + ChunkStorage, + ChunkMeshStorage, + chunk::CHUNK_SIZE, + }, +}; #[derive(Clone, Copy)] pub struct ChunkVertex { @@ -8,3 +38,53 @@ pub struct ChunkVertex { pub tex_index: u8, } implement_vertex!(ChunkVertex, position, normal, uv, tex_index); + + +pub fn draw_world( + mut target: NonSendSync>, + chunks: UniqueView, + meshes: NonSendSync>, + program: NonSendSync>, + texture: NonSendSync>, + camera: View, +) { + let camera = camera.iter().next().expect("No cameras in the scene"); + let draw_parameters = DrawParameters { + depth: Depth { + test: DepthTest::IfLess, + write: true, + ..Default::default() + }, + polygon_mode: PolygonMode::Fill, //Change to Line for wireframe + backface_culling: BackfaceCullingMode::CullCounterClockwise, + ..Default::default() + }; + let texture_sampler = Sampler(&texture.0, SamplerBehavior { + minify_filter: MinifySamplerFilter::Linear, + magnify_filter: MagnifySamplerFilter::Nearest, + max_anisotropy: 8, + wrap_function: (SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp, SamplerWrapFunction::Clamp), + ..Default::default() + }); + let view = camera.view_matrix.to_cols_array_2d(); + let perspective = camera.perspective_matrix.to_cols_array_2d(); + + for (&position, chunk) in &chunks.chunks { + if let Some(key) = chunk.mesh_index { + let mesh = meshes.get(key).expect("Mesh index pointing to nothing"); + let world_position = (position.as_vec3() * CHUNK_SIZE as f32).to_array(); + target.0.draw( + &mesh.vertex_buffer, + &mesh.index_buffer, + &program.0, + &uniform! { + position_offset: world_position, + view: view, + perspective: perspective, + tex: texture_sampler + }, + &draw_parameters + ).unwrap(); + } + } +} diff --git a/src/world/tasks.rs b/src/world/tasks.rs index 828847b..e2f1263 100644 --- a/src/world/tasks.rs +++ b/src/world/tasks.rs @@ -2,19 +2,21 @@ use flume::{Sender, Receiver}; use glam::IVec3; use super::{ chunk::BlockData, - render::ChunkVertex + render::ChunkVertex, + mesh::data::MeshGenData, + worldgen::generate_world, }; pub enum ChunkTask { LoadChunk { + seed: u32, position: IVec3 }, GenerateMesh { position: IVec3, - + data: MeshGenData } } - pub enum ChunkTaskResponse { LoadedChunk { position: IVec3, @@ -36,7 +38,18 @@ impl ChunkTaskManager { channel: flume::bounded::(0), } } - pub fn spawn_task() { - + pub fn spawn_task(&self, task: ChunkTask) { + let sender = self.channel.0.clone(); + rayon::spawn(move || { + sender.send(match task { + ChunkTask::GenerateMesh { position, data } => { + todo!() + }, + ChunkTask::LoadChunk { position, seed } => { + let chunk_data = generate_world(position, seed); + ChunkTaskResponse::LoadedChunk { position, chunk_data } + } + }); + }); } } diff --git a/src/world/worldgen.rs b/src/world/worldgen.rs new file mode 100644 index 0000000..3a58dc7 --- /dev/null +++ b/src/world/worldgen.rs @@ -0,0 +1,12 @@ +use glam::IVec3; +use super::{ + chunk::{BlockData, CHUNK_SIZE}, + block::Block +}; + +pub fn generate_world(position: IVec3, seed: u32) -> BlockData { + let mut blocks = Box::new([[[Block::Air; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE]); + blocks[0][0][0] = Block::Stone; + //TODO actual world generation + blocks +}