diff --git a/assets/shader/outline.fsh.glsl b/assets/shader/outline.fsh.glsl new file mode 100644 index 0000000..d625f6e --- /dev/null +++ b/assets/shader/outline.fsh.glsl @@ -0,0 +1,8 @@ +#version 100 +precision mediump float; + +void main() { + + gl_FragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); + +} \ No newline at end of file diff --git a/assets/shader/outline.vsh.glsl b/assets/shader/outline.vsh.glsl new file mode 100644 index 0000000..606a3cd --- /dev/null +++ b/assets/shader/outline.vsh.glsl @@ -0,0 +1,21 @@ +#version 100 +precision mediump float; + +attribute vec3 pos; +uniform vec3 wpos; + +uniform mat4 view; +uniform mat4 proj; + + +void main() { + mat4 drawProj = mat4( + vec4(-1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, -1.0, 0.0), + vec4(-wpos.x, wpos.y, -wpos.z, 1.0) + ); + gl_Position = proj * view * drawProj * vec4(pos, 1.0); + gl_Position.z -= 0.0001; + +} \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index 7fddf5f..e5e1be8 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,28 +1,32 @@ -use std::vec; +use std::{collections::HashMap, vec}; use crate::{ - tools::{WPos, Sides}, graphics::DrawType, systems::{WorldGenerator, BlockType}, + systems::{BlockType, WorldGenerator, DrawType}, + tools::{Sides, WPos}, }; -use self::{world::World}; +use self::{world::{GetBlock, World}, block::Block}; pub mod block; pub mod chunk; pub mod world; - pub struct Game { - worlds: Vec, - types: Vec>, + pub worlds: HashMap, + pub types: Vec>, type_names: Vec, + w_gens: Vec, + w_gens_names: Vec, } impl Game { pub fn new() -> Self { let mut g = Game { - worlds: vec![], + worlds: HashMap::new(), types: vec![], type_names: vec![], + w_gens: vec![], + w_gens_names: vec![], }; g.add_type(Box::new(Air { id: "air".to_string(), @@ -30,47 +34,121 @@ impl Game { g } + pub fn add_gen(&mut self, gen: WorldGenerator, name: String) -> usize{ + self.w_gens.push(gen); + self.w_gens_names.push(name.clone()); + self.w_gens.len()-1 + } + pub fn get_type(&self, id: usize) -> Option<&Box> { self.types.get(id) } - pub fn find_type(&self, id: String) -> Option<(usize, &Box)> { - let index = self.type_names.iter().position(|r| r.eq(&id)); - if let Some(i) = index { - return Some((i, &self.types[i])); - } - None + pub fn find_type(&self, id: String) -> Option { + self.type_names.iter().position(|r| r.eq(&id)) } pub fn do_tick(&mut self, instant: bool) -> usize { let mut num = 0; - for w in 0..self.worlds.len() { - num += self.worlds[w].do_tick(instant, &self.types); + for (w_id, w) in self.worlds.iter_mut() { + num += w.do_tick(instant, &self.types); } num } pub fn do_tex_tick(&mut self) { - for w in 0..self.worlds.len() { - self.worlds[w].do_tex_tick(&self.types); + for (w_id, w) in self.worlds.iter_mut() { + w.do_tex_tick(&self.types); } } pub fn add_type(&mut self, mut block_type: Box) -> usize { self.type_names.push(block_type.get_id().to_string()); let index = self.types.len(); block_type.set_index(index); - self.types.push(block_type); + self.types.push(block_type); index } - pub fn add_world(&mut self) -> usize { - self.worlds.push(World::new()); - self.worlds.len() - 1 + pub fn add_world(&mut self, wordl_id: usize) -> usize { + self.worlds.insert(wordl_id, World::new()); + wordl_id } pub fn get_world(&mut self, id: usize) -> Option<&mut World> { - self.worlds.get_mut(id) + self.worlds.get_mut(&id) } pub fn get_world_im(&self, id: usize) -> Option<&World> { - self.worlds.get(id) + self.worlds.get(&id) + } + pub fn get_block(&mut self, world: usize, pos: &WPos) -> GetBlock<&mut Block> { + if let Some(w) = self.worlds.get_mut(&world) { + w.get_block(pos); + } + return GetBlock::None; + } + pub fn get_block_im(&self, world: usize, pos: &WPos) -> GetBlock<&Block> { + if let Some(w) = self.worlds.get(&world) { + w.get_block_im(pos); + } + return GetBlock::None; + } + pub fn load_chunk(&mut self, world: usize, chunk_x: i32, chunk_z: i32) -> bool { + let mut built = false; + if let Some(w) = self.worlds.get_mut(&world){ + if w.add_chunk(chunk_x, chunk_z){ + if let Some(gen) = self.w_gens.get_mut(w.gen){ + gen(self, world, chunk_x, chunk_z); + built = true; + } + } + } + if built{self.worlds.get_mut(&world).unwrap().rebuild_chunk_tex(chunk_x, chunk_z);} + built + } + + pub fn load_chunk_around_point( + &mut self, + world: usize, + chunk_x: i32, + chunk_z: i32, + width: i32, + ) { + if let Some(w) = self.worlds.get_mut(&world){ + if !w.chunks.contains_key(&(chunk_x, chunk_z)) { + self.load_chunk(world, chunk_x, chunk_z); + return; + } + for dist in 1..=width { + for side_w in 0..=dist { + if side_w * side_w + dist * dist > width * width { + continue; + } + if self.load_chunk(world, chunk_x + dist, chunk_z + side_w) { + return; + } + if self.load_chunk(world, chunk_x + dist, chunk_z - side_w) { + return; + } + if self.load_chunk(world, chunk_x - dist, chunk_z + side_w) { + return; + } + if self.load_chunk(world, chunk_x - dist, chunk_z - side_w) { + return; + } + if self.load_chunk(world, chunk_x + side_w, chunk_z + dist) { + return; + } + if self.load_chunk(world, chunk_x - side_w, chunk_z + dist) { + return; + } + if self.load_chunk(world, chunk_x + side_w, chunk_z - dist) { + return; + } + if self.load_chunk(world, chunk_x - side_w, chunk_z - dist) { + return; + } + } + } + } + } } @@ -82,10 +160,4 @@ impl BlockType for Air { fn get_id(&self) -> String { self.id.to_string() } - fn is_sided(&self) -> bool { - false - } - fn texture(&self) -> &DrawType { - &DrawType::None() - } } diff --git a/src/game/block.rs b/src/game/block.rs index 12f52d3..5e79bfb 100644 --- a/src/game/block.rs +++ b/src/game/block.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; -use crate::{graphics::{Draw, DrawType}, tools::PrimitiveData}; - -use super::{WPos, world::World}; +use crate::{tools::PrimitiveData}; #[derive(Debug)] pub struct Block { diff --git a/src/game/chunk.rs b/src/game/chunk.rs index 0997b1e..1aaf6de 100644 --- a/src/game/chunk.rs +++ b/src/game/chunk.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use gl_matrix::common::Vec3; use crate::tools::Sides; @@ -14,7 +15,9 @@ pub enum Instances { #[derive(Debug)] pub struct Chunk { pub blocks: HashMap<(u8, u8, u8), Block>, //[[[Block; 16]; 256]; 16], - pub instances: HashMap, + //pub instances: HashMap, + pub instances: HashMap>>, + pub single: HashMap>, } impl Chunk { @@ -23,6 +26,7 @@ impl Chunk { #[rustfmt::skip] blocks: HashMap::new(), instances: HashMap::new(), + single: HashMap::new(), } } @@ -41,101 +45,78 @@ impl Chunk { self.blocks.remove(&(inner_x, pos[1] as u8, inner_z)); } - pub fn remove_pos(&mut self, block_type: usize, pos: &WPos) { - if let Some(data) = self.instances.get_mut(&block_type) { - match data { - Instances::Single(d) => { - d.retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); - if d.len() == 0 { - self.instances.remove(&block_type); - } - } - Instances::Sided(d) => { - for i in 0..6 { - d[i].retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); - } - if d[0].len() == 0 - && d[1].len() == 0 - && d[2].len() == 0 - && d[3].len() == 0 - && d[4].len() == 0 - && d[5].len() == 0 - { - self.instances.remove(&block_type); - } - } - } - } - } - - pub fn remove_all_pos(&mut self, pos: &WPos) { - let mut rem_inst: Vec = vec![]; + pub fn remove_instanced(&mut self, pos: &WPos) { + let mut remove_type: Vec = vec![]; for (block_type, data) in &mut self.instances { - match data { - Instances::Single(d) => { - d.retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); - if d.len() == 0 { - rem_inst.push(*block_type); - } - } - Instances::Sided(d) => { - for i in 0..6 { - d[i].retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); - } - if d[0].len() == 0 - && d[1].len() == 0 - && d[2].len() == 0 - && d[3].len() == 0 - && d[4].len() == 0 - && d[5].len() == 0 - { - rem_inst.push(*block_type); - } + let mut not_empty = false; + for i in 0..data.len() { + data[i].retain(|f| { + pos[0] as f32 != f[0] || pos[1] as f32 != f[1] || pos[2] as f32 != f[2] + }); + if data[i].len() > 0 { + not_empty = true; } } + if !not_empty { + remove_type.push(*block_type); + } } - for b_t in rem_inst.iter() { - self.instances.remove(&b_t); + for block_type in remove_type{ + self.instances.remove(&block_type); + } + } + pub fn remove_single(&mut self, pos: &WPos) { + let mut remove_type: Vec = vec![]; + for (block_type, data) in &mut self.single { + data.retain(|f| { + pos[0] as f32 != f[0] || pos[1] as f32 != f[1] || pos[2] as f32 != f[2] + }); + + if data.len() == 0 { + remove_type.push(*block_type); + } + } + for block_type in remove_type{ + self.single.remove(&block_type); } } - pub fn add_tex_pos(&mut self, block_type: usize, pos: &WPos) { - if let Some(inst) = self.instances.get_mut(&block_type) { - if let Instances::Single(vec) = inst { - if !vec.contains(&pos) { - vec.push(pos.clone()); - } - } else { - panic!("Wrong side Type") + pub fn remove_pos(&mut self, pos: &WPos) { + self.remove_instanced(pos); + self.remove_single(pos); + } + + pub fn set_single(&mut self, block_type: usize, pos: &WPos) { + self.remove_instanced(pos); + if !self.single.contains_key(&block_type){ + self.single.insert(block_type, vec![]); + } + if let Some(data) = self.single.get_mut(&block_type) { + let fpos: Vec3 = [pos[0] as f32, pos[1] as f32, pos[2] as f32]; + if !data.contains(&fpos) { + data.push(fpos.clone()); } - } else { - self.instances - .insert(block_type, Instances::Single(vec![pos.clone()])); } } - pub fn add_tex_pos_sided(&mut self, block_type: usize, pos: &WPos, sides: Sides) { - if let Some(inst) = self.instances.get_mut(&block_type) { - if let Instances::Sided(vec) = inst { - for i in 0..6 { - if sides[i] { - if !vec[i].contains(&pos) { - vec[i].push(pos.clone()); - } - } else { - vec[i].retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); + pub fn set_instanced(&mut self, block_type: usize, pos: &WPos, states: Vec) { + self.remove_single(pos); + if !self.instances.contains_key(&block_type){ + self.instances.insert(block_type, vec![]); + } + if let Some(data) = self.instances.get_mut(&block_type) { + let fpos: Vec3 = [pos[0] as f32, pos[1] as f32, pos[2] as f32]; + for i in 0..states.len() { + if i >= data.len(){data.push(vec![]);} + if states[i] { + if !data[i].contains(&fpos) { + data[i].push(fpos.clone()); } - } - } else { - panic!("Wrong side Type") - } - } else { - let mut new_arr: [Vec<[i32; 3]>; 6] = [vec![], vec![], vec![], vec![], vec![], vec![]]; - for i in 0..6 { - if sides[i] { - new_arr[i].push(pos.clone()); + } else { + data[i].retain(|f| { + pos[0] as f32 != f[0] || pos[1] as f32 != f[1] || pos[2] as f32 != f[2] + }); } } - self.instances.insert(block_type, Instances::Sided(new_arr)); } } } diff --git a/src/game/world.rs b/src/game/world.rs index 4f7c3e5..08e1b5f 100644 --- a/src/game/world.rs +++ b/src/game/world.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; - -use crate::{graphics::Draw, systems::WorldGenerator}; +use crate::systems::Draw; use super::{block::Block, chunk::Chunk, BlockType, Sides, WPos}; @@ -18,7 +17,7 @@ pub struct World { i_updates: Vec, t_updates: Vec, - gen: Box, + pub gen: usize, } impl World { @@ -28,14 +27,10 @@ impl World { updates: vec![], i_updates: vec![], t_updates: vec![], - gen: Box::new(|_world: &mut World, _chunk_x: i32, _chunk_z: i32| {}), + gen: 0, } } - pub fn set_gen(&mut self, gen: Box) { - self.gen = gen; - } - pub fn get_block(&mut self, pos: &WPos) -> GetBlock<&mut Block> { if pos[1] < 0 || pos[1] > 256 { return GetBlock::None; @@ -78,55 +73,16 @@ impl World { } } - pub fn load_chunk_around_point( - &mut self, - //gen: &Box, - chunk_x: i32, - chunk_z: i32, - width: i32, - ) { - if !self.chunks.contains_key(&(chunk_x, chunk_z)) { - self.load_chunk(chunk_x, chunk_z); - return; - } - for w in 1..=width { - for side_w in 0..=w { - if side_w * side_w + w * w > width * width { - continue; - } - if self.load_chunk(chunk_x + w, chunk_z + side_w) { - return; - } - if self.load_chunk(chunk_x + w, chunk_z - side_w) { - return; - } - if self.load_chunk(chunk_x - w, chunk_z + side_w) { - return; - } - if self.load_chunk(chunk_x - w, chunk_z - side_w) { - return; - } - if self.load_chunk(chunk_x + side_w, chunk_z + w) { - return; - } - if self.load_chunk(chunk_x - side_w, chunk_z + w) { - return; - } - if self.load_chunk(chunk_x + side_w, chunk_z - w) { - return; - } - if self.load_chunk(chunk_x - side_w, chunk_z - w) { - return; - } - } - } - } - - pub fn load_chunk(&mut self, chunk_x: i32, chunk_z: i32) -> bool { + pub fn add_chunk(&mut self, chunk_x: i32, chunk_z: i32) -> bool { if !self.chunks.contains_key(&(chunk_x, chunk_z)) { self.chunks .insert((chunk_x, chunk_z), Chunk::new(chunk_x, chunk_z)); - self.gen.as_mut()(self, chunk_x, chunk_z); + return true; + } + return false; + } + pub fn rebuild_chunk_tex(&mut self, chunk_x: i32, chunk_z: i32) -> bool{ + if self.chunks.contains_key(&(chunk_x, chunk_z)) { for x in chunk_x * 16 - 1..=chunk_x * 16 + 16 { for z in chunk_z * 16 - 1..=chunk_z * 16 + 16 { for y in 0..256 { @@ -135,14 +91,6 @@ impl World { } } return true; - /*for x in 0..16 { - for y in 0..256 { - self.update_texture(&[chunk_x * 16 + x, y, chunk_z * 16 - 1]); - self.update_texture(&[chunk_x * 16 + x, y, chunk_z * 16 + 16]); - self.update_texture(&[chunk_x * 16 - 1, y, chunk_z * 16 + x]); - self.update_texture(&[chunk_x * 16 + 16, y, chunk_z * 16 + x]); - } - }*/ } false } @@ -210,20 +158,11 @@ impl World { } } - pub fn delete_block( - &mut self, - pos: &WPos, - update: Sides, - ) { + pub fn delete_block(&mut self, pos: &WPos, update: Sides) { self.delete_block_tex(pos, update, true); } - pub fn delete_block_tex( - &mut self, - pos: &WPos, - update: Sides, - update_tex_surr: bool, - ) { + pub fn delete_block_tex(&mut self, pos: &WPos, update: Sides, update_tex_surr: bool) { if pos[1] < 0 { return; } @@ -325,33 +264,25 @@ impl World { if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { match draw { - Draw::Sides(s) => { - if block_type.is_sided() { - chunk.add_tex_pos_sided(block_type_num, &pos, s); - } else { - chunk.add_tex_pos(block_type_num, &pos); - } + Draw::Instanced(s) => { + chunk.set_instanced(block_type_num, &pos, s); } - Draw::All() => { - if block_type.is_sided() { - chunk.add_tex_pos_sided(block_type_num, &pos, Sides::all(true)); - } else { - chunk.add_tex_pos(block_type_num, &pos); - } + Draw::Single() => { + chunk.set_single(block_type_num, &pos); } Draw::None() => { - chunk.remove_pos(block_type_num, &pos); + chunk.remove_pos(&pos); } } } - }else{ + } else { if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { - chunk.remove_all_pos(&pos) + chunk.remove_pos(&pos) } } - }else{ + } else { if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { - chunk.remove_all_pos(&pos) + chunk.remove_pos(&pos) } } } diff --git a/src/graphics.rs b/src/graphics.rs index 987a4b5..d1311dc 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -2,29 +2,20 @@ use std::collections::HashMap; use miniquad::*; -use crate::tools::Sides; +use crate::tools::Vertex; + + #[derive(Debug)] -pub enum Draw { - All(), //single Model - None(), - Sides(Sides), -} - -pub enum DrawType { - All(Texture), //single Model - None(), - Sides(Sides), -} - pub struct Graphics { pub textures: HashMap, pub pipelines: HashMap, + pub models: HashMap } impl Graphics { pub fn new() -> Self { - Graphics { textures: HashMap::new(), pipelines: HashMap::new() } + Graphics { textures: HashMap::new(), pipelines: HashMap::new(), models: HashMap::new() } } pub fn load_texture(&mut self, ctx: &mut Context, bytes: &[u8], id: String) -> Texture { let decoder = png::Decoder::new(bytes); @@ -37,7 +28,7 @@ impl Graphics { bytes, TextureParams { format: TextureFormat::RGBA8, - wrap: TextureWrap::Clamp, + wrap: TextureWrap::Repeat, filter: FilterMode::Nearest, width: info.width, height: info.height, @@ -50,9 +41,14 @@ impl Graphics { text } - pub fn addPipeline(&mut self, pipeline: Pipeline, id:String) { + pub fn add_pipeline(&mut self, pipeline: Pipeline, id:String) { self.pipelines.insert(id, pipeline); } + pub fn add_model(&mut self, ctx: &mut Context, vertices: Vec, indices: Vec, id:String){ + let vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &vertices); + let index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &indices); + self.models.insert(id, (vertex_buffer, index_buffer)); + } } diff --git a/src/jucraft.rs b/src/jucraft.rs index 31273b8..45029e1 100644 --- a/src/jucraft.rs +++ b/src/jucraft.rs @@ -1,7 +1,7 @@ use crate::{ - game::{world::World, *}, + game::*, graphics::*, - tools::Sides, + tools::*, }; use default_solid_block::DefaultSolidBlock; @@ -10,7 +10,7 @@ use miniquad::*; mod default_solid_block; pub mod default_solid_shader; -pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics, default_world: usize) { +pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics) { graphics.load_texture( ctx, include_bytes!(concat!("../assets/break/empty_overlay.png")), @@ -86,40 +86,102 @@ pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics, def include_bytes!(concat!("../assets/blocks/grass_bottom.png")), "grass_bottom".to_string(), ); - let stone = game.add_type(Box::new(DefaultSolidBlock { - id: "stone".to_string(), - texture: DrawType::All(stone_tex), - })); - let dirt = game.add_type(Box::new(DefaultSolidBlock { - id: "dirt".to_string(), - texture: DrawType::All(dirt_tex), - })); - let cobblestone = game.add_type(Box::new(DefaultSolidBlock { - id: "cobblestone".to_string(), - texture: DrawType::All(cobble_tex), - })); - let grassblock = game.add_type(Box::new(DefaultSolidBlock { - id: "grassblock".to_string(), - texture: DrawType::Sides(Sides { + + #[rustfmt::skip] + let vertices = vec![ + Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 1.0]}, + Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 1.0]}, + Vertex{pos:[0.0, 1.0, 1.0], uv:[0.0, 0.0]}, + Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]}, + + Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]}, + Vertex{pos:[0.0, 0.0, 1.0], uv:[1.0, 1.0]}, + Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 0.0]}, + Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 0.0]}, + + Vertex{pos:[1.0, 0.0, 0.0], uv:[0.0, 1.0]}, + Vertex{pos:[0.0, 0.0, 0.0], uv:[1.0, 1.0]}, + Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]}, + Vertex{pos:[0.0, 1.0, 0.0], uv:[1.0, 0.0]}, + + Vertex{pos:[1.0, 0.0, 1.0], uv:[0.0, 1.0]}, + Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]}, + Vertex{pos:[1.0, 1.0, 1.0], uv:[0.0, 0.0]}, + Vertex{pos:[1.0, 1.0, 0.0], uv:[1.0, 0.0]}, + + Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 1.0]}, + Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 1.0]}, + Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]}, + Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]}, + + Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]}, + Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]}, + Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 0.0]}, + Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 0.0]} + ]; + + let indices = vec![ + 16, 17, 18, // top + 19, 18, 17, + + 20, 21, 22, // bottom + 23, 22, 21, + + 12, 13, 14, // left + 15, 14, 13, + + 4, 5, 6, //right + 7, 6, 5, + + 8, 9, 10, // front + 11, 10, 9, + + 0, 1, 2, // back + 3, 2, 1, + ]; + + graphics.add_model(ctx, vertices, indices, "block".to_string()); + + + let stone = game.add_type(Box::new(DefaultSolidBlock::new( + "stone".to_string(), + Sides::all(stone_tex), + ))); + let dirt = game.add_type(Box::new(DefaultSolidBlock::new( + "dirt".to_string(), + Sides::all(dirt_tex), + ))); + let cobblestone = game.add_type(Box::new(DefaultSolidBlock::new( + "cobblestone".to_string(), + Sides::all(cobble_tex), + ))); + let grassblock = game.add_type(Box::new(DefaultSolidBlock::new( + "grassblock".to_string(), + Sides { top: grass_top, bottom: grass_bottom, left: grass_side, right: grass_side, front: grass_side, back: grass_side, - }), - })); + }, + ))); - if let Some(world) = game.get_world(default_world) { - world.set_gen(Box::new(|world: &mut World, chunk_x: i32, chunk_z: i32| { + game.add_gen( + |game: &mut Game, world: usize, chunk_x: i32, chunk_z: i32| { + let stone = game.find_type("stone".to_string()).unwrap(); + let grassblock = game.find_type("grassblock".to_string()).unwrap(); + let w = game.get_world(world).unwrap(); for x in chunk_x * 16..chunk_x * 16 + 16 { for z in chunk_z * 16..chunk_z * 16 + 16 { for y in 0..63 { - world.set_block_tex(&[x, y, z], 1, Sides::all(false), false, false); + w.set_block_tex(&[x, y, z], stone, Sides::all(false), false, false); } - world.set_block_tex(&[x, 63, z], 4, Sides::all(false), false, false); + w.set_block_tex(&[x, 63, z], grassblock, Sides::all(false), false, false); } } - })); - } + }, + "flat".to_string(), + ); + } diff --git a/src/jucraft/default_solid_block.rs b/src/jucraft/default_solid_block.rs index 94bcd85..268a043 100644 --- a/src/jucraft/default_solid_block.rs +++ b/src/jucraft/default_solid_block.rs @@ -1,20 +1,39 @@ - use gl_matrix::common::*; +use miniquad::*; use crate::{ - game::{block::*, world::*}, - graphics::*, - tools::*, systems::BlockType, + game::{block::*, chunk::Chunk, world::*}, + graphics::Graphics, + systems::{BlockType, Draw}, + tools::*, }; +/// Requieres Block Model and break textures pub struct DefaultSolidBlock { pub id: String, - pub texture: DrawType, + pub texture: Sides, + bindings: Option, +} +impl DefaultSolidBlock { + pub fn new(id: String, texture: Sides) -> Self { + Self { + id, + texture, + bindings: None, + } + } } impl BlockType for DefaultSolidBlock { fn get_id(&self) -> String { self.id.to_string() } + fn init(&mut self, ctx: &mut Context, graphics: &Graphics, instanzeBuf: Buffer) { + self.bindings = Some(Bindings { + vertex_buffers: vec![graphics.models["block"].0, instanzeBuf], + index_buffer: graphics.models["block"].1, + images: vec![graphics.textures["d-1"], self.texture.top], + }); + } fn create( &self, world: &mut World, @@ -28,11 +47,12 @@ impl BlockType for DefaultSolidBlock { } } } - fn render( - &self, - world: &mut World, - block: WPos, - ) -> Draw { + fn render(&self, world: &mut World, block: WPos) -> Draw { + if let GetBlock::Some(b) = world.get_block(&block){ + if b.destroy > 0{ + return Draw::Single() + } + } let mut sides = Sides::all(true); sides.top = match world.get_block(&[block[0], block[1] + 1, block[2]]) { GetBlock::Some(bt) => !bt.solid, @@ -67,20 +87,55 @@ impl BlockType for DefaultSolidBlock { if sides.are_all(false) { Draw::None() } else { - Draw::Sides(sides) + Draw::Instanced(sides.vec()) } } - fn texture(&self) -> &DrawType { - &self.texture + fn render_instanced(&self, ctx: &mut Context, graphics: &Graphics, positions: &Vec, state: usize) { + if let Some(bindings) = &self.bindings { + ctx.apply_bindings(&Bindings { + vertex_buffers: bindings.vertex_buffers.clone(), + index_buffer: bindings.index_buffer, + images: vec![ graphics.textures["d-1"], self.texture[state]], + }); + bindings.vertex_buffers[1].update(ctx, &positions); + ctx.draw(6 * state as i32, 6, positions.len() as i32); + } + } + fn render_single(&self, ctx: &mut Context, graphics: &Graphics, world: &World, positions: &Vec) { + if let Some(bindings) = &self.bindings { + for pos in positions { + let breaking = if let GetBlock::Some(block) = world.get_block_im(&[pos[0] as i32, pos[1] as i32, pos[2] as i32]){ + block.destroy + }else{ + 0 + }; + for state in 0..6{ + ctx.apply_bindings(&Bindings { + vertex_buffers: bindings.vertex_buffers.clone(), + index_buffer: bindings.index_buffer, + images: vec![match breaking { + 1 => graphics.textures["d0"], + 2 => graphics.textures["d1"], + 3 => graphics.textures["d2"], + 4 => graphics.textures["d3"], + 5 => graphics.textures["d4"], + 6 => graphics.textures["d5"], + 7 => graphics.textures["d6"], + 8 => graphics.textures["d7"], + _ => graphics.textures["d-1"], + }, self.texture[state]], + }); + bindings.vertex_buffers[1].update(ctx, pos); + ctx.draw(6 * state as i32, 6, 1); + } + } + } } - fn is_sided(&self) -> bool { - true - } fn collision(&self, _world: &World, _block: WPos) -> Vec<(Vec3, Vec3)> { - vec![([0.,0.,0.], [1.,1.,1.])] + vec![([0., 0., 0.], [1., 1., 1.])] } fn interaction(&self, _world: &World, _block: &Block, _pos: WPos) -> Vec<(Vec3, Vec3)> { - vec![([0.,0.,0.], [1.,1.,1.])] + vec![([0., 0., 0.], [1., 1., 1.])] } } diff --git a/src/player.rs b/src/player.rs index 04c6066..5822899 100644 --- a/src/player.rs +++ b/src/player.rs @@ -22,6 +22,7 @@ pub struct Player { // retundant pub speed: f32, pub on_gound: bool, + pub looking_at: Option<(Side, WPos)> } impl Player { @@ -38,6 +39,7 @@ impl Player { speed: 0., on_gound: false, + looking_at: None } } pub fn update(&mut self, game: &mut Game, s_move: &Sides, delta: f32) { @@ -187,6 +189,15 @@ impl Player { if self.pos[1] < -50. { self.pos[1] = 256. + 128.; } + + + let start = date::now(); + + self.looking_at = self.looking_at(&game, 6., 0.1); + + + //println!("pos trace time: {}µs", (date::now() - start) * 1000000.); + } pub fn is_clipped(&self, game: &mut Game) -> Option<(Vec3, Vec3)> { @@ -237,17 +248,24 @@ impl Player { None } - pub fn right_click(&self, game: &mut Game) {} - pub fn left_click(&self, game: &mut Game) { + pub fn right_click(&self, game: &mut Game) { - let start = date::now(); - if let Some((_, pos)) = self.looking_at(&game, 6., 0.1) { + } + pub fn left_click(&self, game: &mut Game) { + if let Some((_, pos)) = self.looking_at { if let Some(world) = game.get_world(self.world) { - world.delete_block(&pos, Sides::all(true)); + if let GetBlock::Some(block) = world.get_block(&pos) { + block.destroy += 1; + if block.destroy > 8 { + world.delete_block(&pos, Sides::all(true)); + } else { + world.update_texture(&pos); + } + } + // } } - println!("pos trace time: {}µs", (date::now() - start) * 1000000.); } pub fn looking_at(&self, game: &Game, dist: f32, offset: f32) -> Option<(Side, WPos)> { @@ -261,37 +279,34 @@ impl Player { ]; let mut curr_dist = offset; - let mut c_x:i32 = i32::max_value(); - let mut c_y:i32 = i32::max_value(); - let mut c_z:i32 = i32::max_value(); + let mut x: i32 = (start[0] + curr_dist * dirc[0]) as i32; + let mut y: i32 = (start[1] + curr_dist * dirc[1]) as i32; + let mut z: i32 = (start[2] + curr_dist * dirc[2]) as i32; while curr_dist < dist { - let x = (start[0] + dirc[0] * curr_dist).floor() as i32; - let y = (start[1] + dirc[1] * curr_dist).floor() as i32; - let z = (start[2] + dirc[2] * curr_dist).floor() as i32; - if x != c_x || y != c_y || z != c_z { - c_x = x; - c_y = y; - c_z = z; - if let GetBlock::Some(block) = world.get_block_im(&[x, y, z]) { - if let Some(b_t) = game.get_type(block.block_type) { - let boxes: Vec<([f32; 3], [f32; 3])> = - b_t.interaction(&world, block, [x, y, z]); - for (pos, size) in boxes { - if let Some((b_dist, side)) = block_collision( - start, - [x as f32 + pos[0], y as f32 + pos[1], z as f32 + pos[2]], - dirc, - size, - ) { - if b_dist < dist { - return Some((side, [x, y, z])); - } + if let GetBlock::Some(block) = world.get_block_im(&[x, y, z]) { + if let Some(b_t) = game.get_type(block.block_type) { + let boxes: Vec<([f32; 3], [f32; 3])> = + b_t.interaction(&world, block, [x, y, z]); + for (pos, size) in boxes { + if let Some((b_dist, side)) = block_collision( + start, + [x as f32 + pos[0], y as f32 + pos[1], z as f32 + pos[2]], + dirc, + size, + ) { + if b_dist < dist { + return Some((side, [x, y, z])); } } } } } - curr_dist += 0.05; + let cords = next_cord([x, y, z], start, dirc); + //println!("{:?}", cords); + x = cords.0[0]; + y = cords.0[1]; + z = cords.0[2]; + curr_dist = cords.1.abs(); } } diff --git a/src/render_helper.rs b/src/render_helper.rs index a2d60c7..56d9f99 100644 --- a/src/render_helper.rs +++ b/src/render_helper.rs @@ -1,13 +1,16 @@ use std::f64::consts::PI; -use gl_matrix::*; -use miniquad::*; +use gl_matrix::{common::*, *}; +use miniquad::{*, gl::glDrawArrays}; +pub mod outline; pub mod post; pub struct RenderHelper { post_processing_pipeline: Pipeline, post_processing_bind: Bindings, + outline_bind: Bindings, + outline_pipline: Pipeline, offscreen_pass: RenderPass, post_enabled: bool, } @@ -67,11 +70,65 @@ impl RenderHelper { post_shader, ); + let shader_outline = + Shader::new(ctx, outline::VERTEX, outline::FRAGMENT, outline::meta()).unwrap(); + + let outline_vertices: Vec = vec![ + [-0.001, -0.001, -0.001], //0 + [-0.001, -0.001, 1.001], //1 + [-0.001, 1.001, -0.001], //2 + [-0.001, 1.001, 1.001], //3 + [1.001, -0.001, -0.001], //4 + [1.001, -0.001, 1.001], //5 + [1.001, 1.001, -0.001], //6 + [1.001, 1.001, 1.001], //7 + ]; + let outline_vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &outline_vertices); + + let outline_indices = vec![ + 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7, + ]; + + let outline_index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &outline_indices); + + + let outline_bind = Bindings{ + vertex_buffers: vec![outline_vertex_buffer], + index_buffer: outline_index_buffer, + images: vec![], + }; + + let outline_pipline = Pipeline::with_params( + ctx, + &[BufferLayout::default()], + &[VertexAttribute::with_buffer("pos", VertexFormat::Float3, 0)], + shader_outline, + PipelineParams { + depth_test: Comparison::LessOrEqual, + depth_write: true, + primitive_type: PrimitiveType::Lines, + color_blend: Some(BlendState::new( + Equation::Add, + BlendFactor::One, + BlendFactor::OneMinusValue(BlendValue::SourceAlpha), + )), + alpha_blend: Some(BlendState::new( + Equation::Add, + BlendFactor::One, + BlendFactor::Zero, + )), + + ..Default::default() + }, + ); + Self { post_processing_pipeline, post_processing_bind, offscreen_pass, post_enabled: false, + outline_bind, + outline_pipline } } @@ -113,6 +170,13 @@ impl RenderHelper { } } + pub fn draw_outline(&self, ctx: &mut Context, uniforms:&outline::Uniforms){ + ctx.apply_pipeline(&self.outline_pipline); + ctx.apply_bindings(&self.outline_bind); + ctx.apply_uniforms(uniforms); + ctx.draw(0,24,1); + } + pub fn do_post_begin_ui(&self, ctx: &mut Context) { ctx.end_render_pass(); if self.post_enabled { @@ -121,7 +185,7 @@ impl RenderHelper { ctx.apply_pipeline(&self.post_processing_pipeline); ctx.apply_bindings(&self.post_processing_bind); - let invert = ((t).sin()/2.0 + 0.5) as f32; + let invert = ((t).sin() / 2.0 + 0.5) as f32; ctx.apply_uniforms(&post::Uniforms { wobble: [1., ((t * 6.0) % (2.0 * PI)) as f32], invert: [invert, invert, invert], diff --git a/src/render_helper/outline.rs b/src/render_helper/outline.rs new file mode 100644 index 0000000..e125563 --- /dev/null +++ b/src/render_helper/outline.rs @@ -0,0 +1,26 @@ +use gl_matrix::common::*; +use miniquad::*; + +pub const VERTEX: &str = include_str!(concat!("../../assets/shader/outline.vsh.glsl")); + +pub const FRAGMENT: &str = include_str!(concat!("../../assets/shader/outline.fsh.glsl")); + +pub fn meta() -> ShaderMeta { + ShaderMeta { + images: vec![], + uniforms: UniformBlockLayout { + uniforms: vec![ + UniformDesc::new("view", UniformType::Mat4), + UniformDesc::new("proj", UniformType::Mat4), + UniformDesc::new("wpos", UniformType::Float3), + ], + }, + } +} + +#[repr(C)] +pub struct Uniforms { + pub view: Mat4, + pub proj: Mat4, + pub wpos: Vec3, +} diff --git a/src/stage.rs b/src/stage.rs index d423913..0812e36 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -1,14 +1,21 @@ - -use gl_matrix::{mat4, common::*}; +use gl_matrix::{common::*, mat4}; use miniquad::*; -use crate::{game::{Game, chunk::*, world::World}, graphics::{Graphics, DrawType}, jucraft::{*, self}, render_helper::RenderHelper, tools::*, player::Player}; +use crate::{ + game::{chunk::*, world::World, Game}, + graphics::Graphics, + jucraft::{self, *}, + player::Player, + render_helper::{RenderHelper, outline}, + systems::DrawType, + tools::*, +}; const MAX_INSTANT_TICKS: i32 = 50; pub struct Stage { - game: Game, - graphics: Graphics, + pub game: Game, + pub graphics: Graphics, render_helper: RenderHelper, @@ -17,11 +24,9 @@ pub struct Stage { last_frame: f64, pipeline: Pipeline, - bindings: Bindings, - fullscreen: bool, - player: Player, + pub player: Player, mouse_grab: bool, s_move: Sides, @@ -29,118 +34,74 @@ pub struct Stage { y: i32, z: i32, - t_fp:f64, + t_fp: f64, } impl Stage { pub fn new(ctx: &mut Context) -> Stage { let mut game = Game::new(); let mut graphics = Graphics::new(); - let world = game.add_world(); + let world = game.add_world(0); - let mut player = Player::new( - [0.,0.], - [16.*10.,64.,16.*10.], - ); + let mut player = Player::new([0., 0.], [16. * 10., 64., 16. * 10.]); - + jucraft::register(ctx, &mut game, &mut graphics); - jucraft::register(ctx,&mut game, &mut graphics, world); - player.world = world; let post = RenderHelper::new(ctx); - #[rustfmt::skip] - let vertices = vec![ - Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 1.0]}, - Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 1.0]}, - Vertex{pos:[0.0, 1.0, 1.0], uv:[0.0, 0.0]}, - Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]}, - - Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]}, - Vertex{pos:[0.0, 0.0, 1.0], uv:[1.0, 1.0]}, - Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 0.0]}, - Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 0.0]}, - - Vertex{pos:[1.0, 0.0, 0.0], uv:[0.0, 1.0]}, - Vertex{pos:[0.0, 0.0, 0.0], uv:[1.0, 1.0]}, - Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]}, - Vertex{pos:[0.0, 1.0, 0.0], uv:[1.0, 0.0]}, - - Vertex{pos:[1.0, 0.0, 1.0], uv:[0.0, 1.0]}, - Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]}, - Vertex{pos:[1.0, 1.0, 1.0], uv:[0.0, 0.0]}, - Vertex{pos:[1.0, 1.0, 0.0], uv:[1.0, 0.0]}, - - Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 1.0]}, - Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 1.0]}, - Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]}, - Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]}, - - Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]}, - Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]}, - Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 0.0]}, - Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 0.0]} - ]; - let vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &vertices); - - let indices = vec![ - 16, 17, 18, // top - 19, 18, 17, - - 20, 21, 22, // bottom - 23, 22, 21, - - 12, 13, 14, // left - 15, 14, 13, - - 4, 5, 6, //right - 7, 6, 5, - - 8, 9, 10, // front - 11, 10, 9, - - 0, 1, 2, // back - 3, 2, 1, - ]; - let index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &indices); - let positions_vertex_buffer = Buffer::stream( ctx, BufferType::VertexBuffer, - 16*16*256 * std::mem::size_of::(), + 16 * 16 * 256 * std::mem::size_of::(), ); - let bindings = Bindings { - vertex_buffers: vec![vertex_buffer, positions_vertex_buffer], - index_buffer: index_buffer, - images: vec![graphics.textures["stone"], graphics.textures["d-1"]], - }; + for t in game.types.iter_mut() { + t.as_mut().init(ctx, &graphics, positions_vertex_buffer); + } - let shader = Shader::new(ctx, default_solid_shader::VERTEX, default_solid_shader::FRAGMENT, default_solid_shader::meta()).unwrap(); + let shader = Shader::new( + ctx, + default_solid_shader::VERTEX, + default_solid_shader::FRAGMENT, + default_solid_shader::meta(), + ) + .unwrap(); let pipeline = Pipeline::with_params( ctx, - &[BufferLayout::default(), BufferLayout { - step_func: VertexStep::PerInstance, - ..Default::default() - }], &[ - VertexAttribute::with_buffer("pos", VertexFormat::Float3,0), - VertexAttribute::with_buffer("uv", VertexFormat::Float2,0), - VertexAttribute::with_buffer("wpos", VertexFormat::Int3, 1), + BufferLayout::default(), + BufferLayout { + step_func: VertexStep::PerInstance, + ..Default::default() + }, + ], + &[ + VertexAttribute::with_buffer("pos", VertexFormat::Float3, 0), + VertexAttribute::with_buffer("uv", VertexFormat::Float2, 0), + VertexAttribute::with_buffer("wpos", VertexFormat::Float3, 1), ], shader, - PipelineParams { - depth_test: Comparison::LessOrEqual, + PipelineParams { + depth_test: Comparison::LessOrEqual, depth_write: true, cull_face: CullFace::Back, front_face_order: FrontFaceOrder::CounterClockwise, - color_blend: Some(BlendState::new(Equation::Add, BlendFactor::One, BlendFactor::OneMinusValue(BlendValue::SourceAlpha))), - alpha_blend: Some(BlendState::new(Equation::Add, BlendFactor::One, BlendFactor::Zero)), + color_blend: Some(BlendState::new( + Equation::Add, + BlendFactor::One, + BlendFactor::OneMinusValue(BlendValue::SourceAlpha), + )), + alpha_blend: Some(BlendState::new( + Equation::Add, + BlendFactor::One, + BlendFactor::Zero, + )), + ..Default::default() - } + }, ); println!("created"); @@ -153,12 +114,11 @@ impl Stage { last_frame: date::now(), render_helper: post, pipeline, - bindings, - fullscreen: false, + fullscreen: false, player, - + mouse_grab: false, s_move: Sides::all(false), x: 2, @@ -184,23 +144,27 @@ impl EventHandler for Stage { } l_a = self.game.do_tick(true); count += 1; - } + } if self.last_tick < t - 1. / 20. { self.last_tick += 1. / 20.; self.game.do_tick(false); - //eprintln!("fps: {}|{}", 1. / self.delta, self.t_fp); - if let Some(world) = self.game.get_world(0) { - world.load_chunk_around_point( (self.player.pos[0] as i32).div_euclid(16), (self.player.pos[2] as i32).div_euclid(16), 10); - } + eprintln!("fps: {}|{}", 1. / self.delta, self.t_fp); + self.game.load_chunk_around_point( + self.player.world, + (self.player.pos[0] as i32).div_euclid(16), + (self.player.pos[2] as i32).div_euclid(16), + 10, + ); + if self.last_tick < t - 5. { self.last_tick = t - 1. / 20.; } } self.game.do_tex_tick(); - self.player.update(&mut self.game, &self.s_move, self.delta as f32); - + self.player + .update(&mut self.game, &self.s_move, self.delta as f32); } fn draw(&mut self, ctx: &mut Context) { @@ -209,11 +173,16 @@ impl EventHandler for Stage { let t = date::now(); ctx.apply_pipeline(&self.pipeline); - ctx.apply_bindings(&self.bindings); - let (w,h) = ctx.screen_size(); + let (w, h) = ctx.screen_size(); let mut proj_matrix = mat4::create(); - mat4::perspective(&mut proj_matrix, 90.0f32.to_radians(), w as f32 / h as f32, 0.1, Some(10000.0)); + mat4::perspective( + &mut proj_matrix, + 90.0f32.to_radians(), + w as f32 / h as f32, + 0.1, + Some(10000.0), + ); let mut cammat = mat4::create(); let mut cammat1 = mat4::create(); @@ -221,59 +190,67 @@ impl EventHandler for Stage { mat4::identity(&mut cammat); mat4::rotate_x(&mut cammat1, &cammat, -(self.player.rot[0] / 180. * PI)); mat4::rotate_y(&mut cammat, &cammat1, self.player.rot[1] / 180. * PI); - mat4::translate(&mut cammat1, &cammat, &[self.player.pos[0], -self.player.pos[1]- self.player.eyes, self.player.pos[2]]); + mat4::translate( + &mut cammat1, + &cammat, + &[ + self.player.pos[0], + -self.player.pos[1] - self.player.eyes, + self.player.pos[2], + ], + ); let mut view_matrix = mat4::create(); - mat4::look_at(&mut view_matrix, &[0., 0., 0.], &[0., 0., 0.], &[0., 0., 0.]); + mat4::look_at( + &mut view_matrix, + &[0., 0., 0.], + &[0., 0., 0.], + &[0., 0., 0.], + ); mat4::multiply(&mut cammat, &cammat1, &view_matrix); - + ctx.apply_uniforms(&default_solid_shader::Uniforms { proj: proj_matrix, view: cammat, - fog: [140.0, 160.0] + fog: [140.0, 160.0], }); - if let Some(world) = self.game.get_world_im(self.player.world){ - for (_,chunk) in &world.chunks { - for (b_type, inst) in &chunk.instances{ - if let Some(b_t) = self.game.get_type(*b_type){ - let tex = b_t.texture(); - if let DrawType::All(ttt) = tex { - self.bindings.images[0] = *ttt; - ctx.apply_bindings(&self.bindings); - } - match inst { - Instances::Single(c) => { - if c.len() > 0{ - self.bindings.vertex_buffers[1].update(ctx, &c); - ctx.draw(0, 36, c.len() as i32); - } - }, - Instances::Sided(s) => { - for i in 0..6 { - let len = s[i].len() as i32; - if len > 0{ - if let DrawType::Sides(ttt) = tex { - self.bindings.images[0] = ttt[i]; - ctx.apply_bindings(&self.bindings); - } - self.bindings.vertex_buffers[1].update(ctx, &s[i]); - ctx.draw(6 * i as i32, 6, len); - } - } - }, + if let Some(world) = self.game.get_world_im(self.player.world) { + for (_, chunk) in &world.chunks { + for (b_type, inst) in &chunk.instances { + if let Some(b_t) = self.game.get_type(*b_type) { + for (state, positions) in inst.iter().enumerate() { + if positions.len() > 0 { + b_t.render_instanced(ctx, &self.graphics, positions, state); + } + } + } + } + for (b_type, inst) in &chunk.single { + if let Some(b_t) = self.game.get_type(*b_type) { + if inst.len() > 0 { + b_t.render_single(ctx, &self.graphics, world, inst); } } - } } } + if let Some(looking_at) = &self.player.looking_at{ + self.render_helper.draw_outline(ctx, &outline::Uniforms{ + view: cammat, + proj: proj_matrix, + wpos: [looking_at.1[0] as f32, looking_at.1[1] as f32, looking_at.1[2] as f32], + }); + } + + + self.render_helper.do_post_begin_ui(ctx); let end = date::now(); - self.t_fp = self.t_fp *0.9 + 0.1/(end-t); + self.t_fp = self.t_fp * 0.9 + 0.1 / (end - t); // TODO: render 2D UI @@ -284,30 +261,35 @@ impl EventHandler for Stage { self.render_helper.resize(ctx, width, height); } - fn key_down_event(&mut self, _ctx: &mut Context, keycode: KeyCode, _keymods: KeyMods,_repeatt: bool) { - if keycode == KeyCode::Space{ + fn key_down_event( + &mut self, + _ctx: &mut Context, + keycode: KeyCode, + _keymods: KeyMods, + _repeatt: bool, + ) { + if keycode == KeyCode::Space { self.s_move.top = true; - }else if keycode == KeyCode::LeftShift{ + } else if keycode == KeyCode::LeftShift { self.s_move.bottom = true; - }else if keycode == KeyCode::W{ + } else if keycode == KeyCode::W { self.s_move.front = true; - }else if keycode == KeyCode::A{ + } else if keycode == KeyCode::A { self.s_move.left = true; - }else if keycode == KeyCode::S{ + } else if keycode == KeyCode::S { self.s_move.back = true; - }else if keycode == KeyCode::D{ + } else if keycode == KeyCode::D { self.s_move.right = true; } } fn key_up_event(&mut self, ctx: &mut Context, keycode: KeyCode, _keymods: KeyMods) { - if keycode == KeyCode::F11 { if self.fullscreen { ctx.set_fullscreen(false); - ctx.set_window_size(900* 16 / 9, 900); + ctx.set_window_size(900 * 16 / 9, 900); self.fullscreen = false; - }else { + } else { ctx.set_fullscreen(true); self.fullscreen = true; } @@ -317,27 +299,25 @@ impl EventHandler for Stage { ctx.show_mouse(true); self.mouse_grab = false; } - }else if keycode == KeyCode::Escape { + } else if keycode == KeyCode::Escape { ctx.set_cursor_grab(false); ctx.show_mouse(true); self.mouse_grab = false; - - }else if keycode == KeyCode::Space{ + } else if keycode == KeyCode::Space { self.s_move.top = false; - }else if keycode == KeyCode::LeftShift{ + } else if keycode == KeyCode::LeftShift { self.s_move.bottom = false; - }else if keycode == KeyCode::W{ + } else if keycode == KeyCode::W { self.s_move.front = false; - }else if keycode == KeyCode::A{ + } else if keycode == KeyCode::A { self.s_move.left = false; - }else if keycode == KeyCode::S{ + } else if keycode == KeyCode::S { self.s_move.back = false; - }else if keycode == KeyCode::D{ + } else if keycode == KeyCode::D { self.s_move.right = false; - }else if keycode == KeyCode::F{ + } else if keycode == KeyCode::F { self.player.flying = !self.player.flying; } - } fn window_minimized_event(&mut self, ctx: &mut Context) { @@ -346,7 +326,13 @@ impl EventHandler for Stage { self.mouse_grab = false; } - fn mouse_button_down_event(&mut self,ctx: &mut Context, button: MouseButton,_x: f32,_y: f32) { + fn mouse_button_down_event( + &mut self, + ctx: &mut Context, + button: MouseButton, + _x: f32, + _y: f32, + ) { if button == MouseButton::Left { if !self.mouse_grab { ctx.set_cursor_grab(true); @@ -364,7 +350,5 @@ impl EventHandler for Stage { } } - fn touch_event(&mut self, ctx: &mut Context, phase: TouchPhase, _id: u64, x: f32, y: f32) { - - } + fn touch_event(&mut self, ctx: &mut Context, phase: TouchPhase, _id: u64, x: f32, y: f32) {} } diff --git a/src/systems.rs b/src/systems.rs index 414d050..40284cf 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -1,25 +1,41 @@ use gl_matrix::common::*; +use miniquad::*; -use crate::{game::{world::World, block::Block, Game}, tools::WPos, graphics::{Draw, DrawType}}; +use crate::{game::{world::World, block::Block, Game, chunk::Chunk}, tools::{WPos, Sides}, graphics::Graphics}; +pub type WorldGenerator = fn(game: &mut Game, world: usize, chunk_x: i32, chunk_z:i32); -/*pub trait WorldGenerator { - fn get_id(&self) -> String; - fn generate_chunk(&self, world: &mut World, chunk_x: i32, chunk_z:i32); -}*/ +#[derive(Debug)] +pub enum Draw { + None(), + Instanced(Vec), + Single() +} -pub type WorldGenerator = fn(world: &mut World, chunk_x: i32, chunk_z:i32); +pub enum DrawType { + All(Texture), //single Model + None(), + Sides(Sides), +} pub trait BlockType { fn get_id(&self) -> String; - fn is_sided(&self) -> bool; + //fn is_sided(&self) -> bool; - fn set_index(&mut self, _id: usize) {} + fn set_index(&mut self, id: usize){} + + fn init(&mut self, ctx: &mut Context, graphics: &Graphics, instanzeBuf: Buffer) {} + fn create(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} fn update(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} - fn render(&self, _world: &mut World, _block: WPos) -> Draw { Draw::None() } + + fn render(&self, _world: &mut World, _block: WPos) -> Draw { Draw::None() } + fn render_instanced(&self, ctx: &mut Context, graphics: &Graphics, positions: &Vec, state: usize) {} + fn render_single(&self, ctx: &mut Context, graphics: &Graphics, world: &World, positions: &Vec) {} + //fn texture(&self) -> &DrawType; + fn collision(&self, _world: &World, _block: WPos) -> Vec<(Vec3, Vec3)> { vec![] } fn interaction(&self, _world: &World, _block: &Block, _pos: WPos) -> Vec<(Vec3, Vec3)> { vec![] } - fn texture(&self) -> &DrawType; + } \ No newline at end of file diff --git a/src/tools.rs b/src/tools.rs index 2aa76ef..8de4a90 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -42,6 +42,16 @@ impl Sides { && self.front == v && self.back == v } + pub fn vec(&self) -> Vec { + vec![ + self.top, + self.bottom, + self.left, + self.right, + self.front, + self.back, + ] + } } impl Index for Sides { @@ -110,12 +120,12 @@ pub fn block_collision( let x = pos1[0] + d_z * direction[0]; let y = pos1[1] + d_z * direction[1]; if x > pos2[0] && x < pos2[0] + size2[0] && y > pos2[1] && y < pos2[1] + size2[1] { - out = Some((d_z, Side::Back)); + out = Some((d_z, Side::Back)); dist = d_z; } } - if d_b_x > 0. && dist > d_b_x{ + if d_b_x > 0. && dist > d_b_x { let y = pos1[1] + d_x * direction[1]; let z = pos1[2] + d_x * direction[2]; if y > pos2[1] && y < pos2[1] + size2[1] && z > pos2[2] && z < pos2[2] + size2[2] { @@ -141,6 +151,31 @@ pub fn block_collision( out } +pub fn to_unit(n: f32) -> i32 { + if n >= 0. { + 1 + } else { + -1 + } +} + +pub fn next_cord(n_pos: WPos, pos: Vec3, direction: Vec3) -> (WPos, f32) { + let x_dir = to_unit(direction[0]); + let y_dir = to_unit(direction[1]); + let z_dir = to_unit(direction[2]); + let d_x = (n_pos[0] as f32 + x_dir as f32 - pos[0]) / direction[0]; + let d_y = (n_pos[1] as f32 + y_dir as f32 - pos[1]) / direction[1]; + let d_z = (n_pos[2] as f32 + z_dir as f32 - pos[2]) / direction[2]; + + if d_x < d_y && d_x < d_z { + return ([n_pos[0] + x_dir, n_pos[1], n_pos[2]], d_x); + } + if d_y < d_x && d_y < d_z { + return ([n_pos[0], n_pos[1] + y_dir, n_pos[2]], d_y); + } + return ([n_pos[0], n_pos[1], n_pos[2] + z_dir], d_z); +} + #[derive(Debug)] pub enum PrimitiveData { String(String),