World, WorldChunk, WorldBlock structure working

This commit is contained in:
Piotrek
2021-05-06 12:43:03 +02:00
parent c04a1aea11
commit d34196a6bd
5 changed files with 94 additions and 53 deletions
+12 -11
View File
@@ -1,12 +1,9 @@
use winit::event::Event; mod camera_controller;
use noise::Perlin;
use crate::renderer::{camera::CameraTransform, RenderSpace};
mod camera_controller;
use camera_controller::CameraController;
mod world; mod world;
use cgmath::{SquareMatrix, Point3, InnerSpace};
use winit::event::Event;
use crate::renderer::{camera::CameraTransform, RenderSpace};
use camera_controller::CameraController;
use world::World; use world::World;
pub enum GameState { pub enum GameState {
@@ -21,11 +18,15 @@ pub struct App {
impl App { impl App {
pub fn new(renderer: &mut dyn RenderSpace) -> Self { pub fn new(renderer: &mut dyn RenderSpace) -> Self {
Self { let mut app = Self {
camera_controller: CameraController::new(), camera_controller: CameraController::new(),
world: World::new("default".to_string()) 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<()>) { pub fn input(&mut self, event: &Event<()>) {
+12 -3
View File
@@ -1,12 +1,21 @@
use cgmath::Point3;
pub const SIZE: usize = 32;
#[derive(Clone)] #[derive(Clone)]
pub struct WorldBlock { pub struct WorldBlock {
pub data: [u8;32*32*32] pub materials: [u8;(SIZE*SIZE*SIZE) as usize]
} }
impl WorldBlock { impl WorldBlock {
pub fn new() -> Self { pub fn new() -> Self {
let data = [0_u8; 32*32*32]; Self {
Self { data } materials: [0_u8; (SIZE*SIZE*SIZE) as usize]
}
}
pub fn set(&mut self, voxel_pos: Point3<usize>, value: u8) {
self.materials[voxel_pos.x + SIZE * (voxel_pos.y + SIZE * voxel_pos.z)] = value;
} }
} }
+23 -5
View File
@@ -1,14 +1,32 @@
use cgmath::Point3; use cgmath::Point3;
use crate::app::world::WorldBlock; use crate::app::world::WorldBlock;
pub const SIZE: u32 = 32;
pub struct WorldChunk { pub struct WorldChunk {
pos: Point3<u32>, nodes: Box<[u32]>,
blocks: Box<[WorldBlock]> blocks: Vec<WorldBlock>
} }
impl WorldChunk { impl WorldChunk {
pub fn new(pos: Point3<u32>) -> Self { pub fn new() -> Self {
let blocks = vec![WorldBlock::new(); 16*16*16].into_boxed_slice(); Self {
Self { pos, blocks } nodes: vec![0_u32; (SIZE*SIZE*SIZE) as usize].into_boxed_slice(),
blocks: Vec::new()
}
}
pub fn get_block(&mut self, block_pos: &Point3<u32>) -> &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]
} }
} }
+16 -26
View File
@@ -2,8 +2,7 @@ use cgmath::Point3;
use noise::{Perlin, NoiseFn}; use noise::{Perlin, NoiseFn};
use rand::{Rng, prelude::ThreadRng}; use rand::{Rng, prelude::ThreadRng};
use crate::renderer::RenderSpace; use crate::app::world::{block, block::WorldBlock};
use crate::renderer::buffers::BLOCK_SIZE;
const SCALE: f64 = 150.0; const SCALE: f64 = 150.0;
@@ -14,22 +13,18 @@ pub struct WorldGen {
impl WorldGen { impl WorldGen {
pub fn new() -> Self {
Self{}
}
/* /*
* Generate height map for given block position * 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) { 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 x = x * block::SIZE;
let z = z * BLOCK_SIZE; let z = z * block::SIZE;
// Generate map // Generate map
let mut max: usize = 0; let mut max: usize = 0;
let mut map = [[0_usize; BLOCK_SIZE]; BLOCK_SIZE]; let mut map = [[0_usize; block::SIZE]; block::SIZE];
for lx in 0..BLOCK_SIZE { for lx in 0..block::SIZE {
for lz 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 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; let mut h = (value * 30.0) as usize;
h += (rand.gen::<f32>() * 2.0) as usize; h += (rand.gen::<f32>() * 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 rng = rand::thread_rng();
let mut noise = Perlin::new();
let mut dirty: Vec<usize> = Vec::new(); let mut dirty: Vec<usize> = Vec::new();
for bx in 0..16 { for bx in 0..16 {
for bz in 0..16 { for bz in 0..16 {
// Generate height map // Generate height map
let (map, max) = WorldGen::gen_height_map(bx, bz, &mut rng, noise); let (map, max) = WorldGen::gen_height_map(bx, bz, &mut rng, &noise);
let bh = (max / BLOCK_SIZE) + 1; let bh = (max / block::SIZE) + 1;
// Generate blocks // Generate blocks
for by in 0..bh { for by in 0..bh {
// Get
let b = renderer.block_get(Point3{x:bx, y:by, z:bz});
dirty.push(b.id);
// Fill // Fill
for x in 0..BLOCK_SIZE { for x in 0..block::SIZE {
for z in 0..BLOCK_SIZE { for z in 0..block::SIZE {
// TODO // TODO
let h = map[x][z]; let h = map[x][z];
for y in 0..h { 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 {
} }
} }
// loop end
for id in dirty {
renderer.block_dirty(id);
}
} }
} }
+31 -8
View File
@@ -1,26 +1,49 @@
mod generator; mod generator;
use generator::WorldGen;
mod chunk; mod chunk;
use chunk::WorldChunk;
mod block; mod block;
use cgmath::Point3;
use std::collections::HashMap;
use generator::WorldGen;
use chunk::WorldChunk;
use block::WorldBlock; use block::WorldBlock;
pub struct World { pub struct World {
name: String, name: String,
chunks: Vec<WorldChunk> // Loaded chunks chunks: HashMap<Point3<u32>, WorldChunk>
} }
impl World { impl World {
pub fn new(name: String) -> Self { 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<u32>) -> &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<u32>) -> 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
} }
} }