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;
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<()>) {
+12 -3
View File
@@ -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<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 crate::app::world::WorldBlock;
pub const SIZE: u32 = 32;
pub struct WorldChunk {
pos: Point3<u32>,
blocks: Box<[WorldBlock]>
nodes: Box<[u32]>,
blocks: Vec<WorldBlock>
}
impl WorldChunk {
pub fn new(pos: Point3<u32>) -> 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<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 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::<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 noise = Perlin::new();
let mut dirty: Vec<usize> = 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
}
}
+31 -8
View File
@@ -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<WorldChunk> // Loaded chunks
chunks: HashMap<Point3<u32>, 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<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
}
}