World, WorldChunk, WorldBlock structure working
This commit is contained in:
+12
-11
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user