From d34196a6bd0daaac3b084daee4d054b754f20c7d Mon Sep 17 00:00:00 2001 From: Piotrek Date: Thu, 6 May 2021 12:43:03 +0200 Subject: [PATCH] World, WorldChunk, WorldBlock structure working --- src/app/mod.rs | 23 +++++++++++---------- src/app/world/block.rs | 15 +++++++++++--- src/app/world/chunk.rs | 28 ++++++++++++++++++++----- src/app/world/generator.rs | 42 +++++++++++++++----------------------- src/app/world/mod.rs | 39 +++++++++++++++++++++++++++-------- 5 files changed, 94 insertions(+), 53 deletions(-) diff --git a/src/app/mod.rs b/src/app/mod.rs index ec55d5d..8a035f0 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,12 +1,9 @@ -use winit::event::Event; -use noise::Perlin; - -use crate::renderer::{camera::CameraTransform, RenderSpace}; - -mod camera_controller; -use camera_controller::CameraController; - +mod camera_controller; mod world; +use cgmath::{SquareMatrix, Point3, InnerSpace}; +use winit::event::Event; +use crate::renderer::{camera::CameraTransform, RenderSpace}; +use camera_controller::CameraController; use world::World; pub enum GameState { @@ -21,11 +18,15 @@ pub struct App { impl App { pub fn new(renderer: &mut dyn RenderSpace) -> Self { - Self { + let mut app = Self { camera_controller: CameraController::new(), world: World::new("default".to_string()) - } - //instance.world_gen.generate(renderer, &Perlin::new()); + }; + + let block = app.world.gen_block(&Point3{x:0,y:0,z:0}); + + + app } pub fn input(&mut self, event: &Event<()>) { diff --git a/src/app/world/block.rs b/src/app/world/block.rs index 066f711..e4a1559 100644 --- a/src/app/world/block.rs +++ b/src/app/world/block.rs @@ -1,12 +1,21 @@ +use cgmath::Point3; + +pub const SIZE: usize = 32; + #[derive(Clone)] pub struct WorldBlock { - pub data: [u8;32*32*32] + pub materials: [u8;(SIZE*SIZE*SIZE) as usize] } impl WorldBlock { pub fn new() -> Self { - let data = [0_u8; 32*32*32]; - Self { data } + Self { + materials: [0_u8; (SIZE*SIZE*SIZE) as usize] + } + } + + pub fn set(&mut self, voxel_pos: Point3, value: u8) { + self.materials[voxel_pos.x + SIZE * (voxel_pos.y + SIZE * voxel_pos.z)] = value; } } \ No newline at end of file diff --git a/src/app/world/chunk.rs b/src/app/world/chunk.rs index 9384944..a550ecd 100644 --- a/src/app/world/chunk.rs +++ b/src/app/world/chunk.rs @@ -1,14 +1,32 @@ use cgmath::Point3; use crate::app::world::WorldBlock; +pub const SIZE: u32 = 32; + + pub struct WorldChunk { - pos: Point3, - blocks: Box<[WorldBlock]> + nodes: Box<[u32]>, + blocks: Vec } impl WorldChunk { - pub fn new(pos: Point3) -> Self { - let blocks = vec![WorldBlock::new(); 16*16*16].into_boxed_slice(); - Self { pos, blocks } + pub fn new() -> Self { + Self { + nodes: vec![0_u32; (SIZE*SIZE*SIZE) as usize].into_boxed_slice(), + blocks: Vec::new() + } + } + + pub fn get_block(&mut self, block_pos: &Point3) -> &mut WorldBlock { + // Get block index + let index = block_pos.x + SIZE * (block_pos.y + SIZE * block_pos.z); + let mut value = self.nodes[index as usize]; + // Allocate new block + if value == 0 { + value = (self.blocks.len() + 1) as u32; + self.blocks.push(WorldBlock::new()); + } + // Return block reference + &mut self.blocks[(value-1) as usize] } } \ No newline at end of file diff --git a/src/app/world/generator.rs b/src/app/world/generator.rs index 969b239..c6703f2 100644 --- a/src/app/world/generator.rs +++ b/src/app/world/generator.rs @@ -2,8 +2,7 @@ use cgmath::Point3; use noise::{Perlin, NoiseFn}; use rand::{Rng, prelude::ThreadRng}; -use crate::renderer::RenderSpace; -use crate::renderer::buffers::BLOCK_SIZE; +use crate::app::world::{block, block::WorldBlock}; const SCALE: f64 = 150.0; @@ -14,22 +13,18 @@ pub struct WorldGen { impl WorldGen { - pub fn new() -> Self { - Self{} - } - /* * Generate height map for given block position */ - fn gen_height_map(x: usize, z: usize, rand: &mut ThreadRng, noise: &Perlin) -> ([[usize;BLOCK_SIZE]; BLOCK_SIZE], usize) { - let x = x * BLOCK_SIZE; - let z = z * BLOCK_SIZE; + fn gen_height_map(x: usize, z: usize, rand: &mut ThreadRng, noise: &Perlin) -> ([[usize;block::SIZE]; block::SIZE], usize) { + let x = x * block::SIZE; + let z = z * block::SIZE; // Generate map let mut max: usize = 0; - let mut map = [[0_usize; BLOCK_SIZE]; BLOCK_SIZE]; - for lx in 0..BLOCK_SIZE { - for lz in 0..BLOCK_SIZE { + let mut map = [[0_usize; block::SIZE]; block::SIZE]; + for lx in 0..block::SIZE { + for lz in 0..block::SIZE { let value = (noise.get([(x + lx) as f64 / SCALE, (z + lz) as f64 /SCALE]) + 1.0) / 2.0; let mut h = (value * 30.0) as usize; h += (rand.gen::() * 2.0) as usize; @@ -42,30 +37,28 @@ impl WorldGen { } /* - * Generate world + * Generate block */ - pub fn generate(&mut self, renderer: &mut dyn RenderSpace, noise: &Perlin) { + pub fn generate(block: &mut WorldBlock) { let mut rng = rand::thread_rng(); + let mut noise = Perlin::new(); let mut dirty: Vec = Vec::new(); for bx in 0..16 { for bz in 0..16 { // Generate height map - let (map, max) = WorldGen::gen_height_map(bx, bz, &mut rng, noise); - let bh = (max / BLOCK_SIZE) + 1; + let (map, max) = WorldGen::gen_height_map(bx, bz, &mut rng, &noise); + let bh = (max / block::SIZE) + 1; // Generate blocks for by in 0..bh { - // Get - let b = renderer.block_get(Point3{x:bx, y:by, z:bz}); - dirty.push(b.id); // Fill - for x in 0..BLOCK_SIZE { - for z in 0..BLOCK_SIZE { + for x in 0..block::SIZE { + for z in 0..block::SIZE { // TODO let h = map[x][z]; for y in 0..h { - b.set(Point3{x, y, z}, 2); + block.set(Point3{x, y, z}, 2); } } } @@ -73,9 +66,6 @@ impl WorldGen { } } - - for id in dirty { - renderer.block_dirty(id); - } + // loop end } } \ No newline at end of file diff --git a/src/app/world/mod.rs b/src/app/world/mod.rs index 8d3d83a..43fccaa 100644 --- a/src/app/world/mod.rs +++ b/src/app/world/mod.rs @@ -1,26 +1,49 @@ mod generator; -use generator::WorldGen; mod chunk; -use chunk::WorldChunk; mod block; +use cgmath::Point3; +use std::collections::HashMap; +use generator::WorldGen; +use chunk::WorldChunk; use block::WorldBlock; pub struct World { name: String, - chunks: Vec // Loaded chunks + chunks: HashMap, WorldChunk> } impl World { pub fn new(name: String) -> Self { - Self { name, chunks: Vec::new() } + Self { + name, + chunks: HashMap::new() + } } - fn load(&mut self) { - + pub fn gen_block(&mut self, block_pos: &Point3) -> &WorldBlock { + // Split world space to chunk and block space + let ch_pos = block_pos / chunk::SIZE; + let bl_pos = block_pos % chunk::SIZE; + // Create chunk if does not exist + if let None = self.chunks.get_mut(&ch_pos) { + self.chunks.insert(block_pos.clone(), WorldChunk::new()); + } + // Generate block for chunk + let chunk = self.chunks.get_mut(block_pos).unwrap(); + let block = chunk.get_block(&bl_pos); + WorldGen::generate(block); + block } - fn save(&mut self) { - + pub fn get_block(&mut self, block_pos: &Point3) -> Option<&WorldBlock> { + // Split world space to chunk and block space + let ch_pos = block_pos / chunk::SIZE; + let bl_pos = block_pos % chunk::SIZE; + // Return block if exists + if let Some(chunk) = self.chunks.get_mut(&ch_pos) { + return Some(chunk.get_block(&bl_pos)); + } + None } } \ No newline at end of file