WIP: World rewrite #2
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
use ndarray::{s, Array3};
 | 
			
		||||
use wgpu::naga::FastHashSet;
 | 
			
		||||
 | 
			
		||||
use crate::math;
 | 
			
		||||
 | 
			
		||||
use super::{GenerationSettings, Voxel};
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +14,9 @@ pub struct ChunkSettings {
 | 
			
		|||
#[derive(Debug)]
 | 
			
		||||
pub struct Chunk {
 | 
			
		||||
    settings: ChunkSettings,
 | 
			
		||||
    genned_blocks: FastHashSet<(usize, usize, usize)>,
 | 
			
		||||
    noise: Vec<f32>,
 | 
			
		||||
    blocks: Vec<Vec<Voxel>>,
 | 
			
		||||
    blocks: Array3<Voxel>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Chunk {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,13 +46,21 @@ impl Chunk {
 | 
			
		|||
        .generate()
 | 
			
		||||
        .0;
 | 
			
		||||
 | 
			
		||||
        let num_blocks = dims.x * dims.y * dims.z;
 | 
			
		||||
        let blocks = vec![vec![]; num_blocks as usize];
 | 
			
		||||
        let genned_blocks = FastHashSet::default();
 | 
			
		||||
 | 
			
		||||
        let shape = chunk_settings.dimensions * chunk_settings.block_dimensions;
 | 
			
		||||
        let num_voxels = shape.x * shape.y * shape.z;
 | 
			
		||||
        let blocks = Array3::from_shape_vec(
 | 
			
		||||
            (shape.x as usize, shape.y as usize, shape.z as usize),
 | 
			
		||||
            vec![Voxel::Empty; num_voxels as usize],
 | 
			
		||||
        )
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            settings: chunk_settings,
 | 
			
		||||
            noise,
 | 
			
		||||
            blocks,
 | 
			
		||||
            genned_blocks,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,57 +69,84 @@ impl Chunk {
 | 
			
		|||
        region_start: glam::UVec3,
 | 
			
		||||
        region_dims: glam::UVec3,
 | 
			
		||||
    ) -> Vec<Voxel> {
 | 
			
		||||
        let mut voxels = vec![];
 | 
			
		||||
 | 
			
		||||
        let start = region_start;
 | 
			
		||||
        let end = region_start + region_dims;
 | 
			
		||||
        let dims = self.settings.dimensions * self.settings.block_dimensions;
 | 
			
		||||
        assert!(end.x <= dims.x && end.y <= dims.y && end.z <= dims.z);
 | 
			
		||||
 | 
			
		||||
        for z in (start.z)..(end.z) {
 | 
			
		||||
            for y in (start.y)..(end.y) {
 | 
			
		||||
                for x in (start.x)..(end.x) {
 | 
			
		||||
                    voxels.push(self.get_voxel(glam::uvec3(x, y, z)));
 | 
			
		||||
        // Check that all the blocks needed are generated and generated them if needed
 | 
			
		||||
        // TODO: Don't hardcode this division!!
 | 
			
		||||
        let start_block = start / 8;
 | 
			
		||||
        let end_block = end / 8;
 | 
			
		||||
        for z in start_block.z..(end_block.z) {
 | 
			
		||||
            for y in (start_block.y)..(end_block.y) {
 | 
			
		||||
                for x in (start_block.x)..(end_block.x) {
 | 
			
		||||
                    if !self
 | 
			
		||||
                        .genned_blocks
 | 
			
		||||
                        .contains(&(x as usize, y as usize, z as usize))
 | 
			
		||||
                    {
 | 
			
		||||
                        self.gen_block(glam::uvec3(x, y, z));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        voxels
 | 
			
		||||
        //
 | 
			
		||||
        let region = self
 | 
			
		||||
            .blocks
 | 
			
		||||
            .slice(s![
 | 
			
		||||
                (start.x as usize)..(end.x as usize),
 | 
			
		||||
                (start.y as usize)..(end.y as usize),
 | 
			
		||||
                (start.z as usize)..(end.z as usize)
 | 
			
		||||
            ])
 | 
			
		||||
            .to_owned()
 | 
			
		||||
            .into_raw_vec();
 | 
			
		||||
        // dbg!(®ion);
 | 
			
		||||
        region
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_voxel(&mut self, pos: glam::UVec3) -> Voxel {
 | 
			
		||||
        let dims = self.settings.dimensions * self.settings.block_dimensions;
 | 
			
		||||
        debug_assert!(pos.x < dims.x && pos.y < dims.y && pos.z < dims.z);
 | 
			
		||||
    // pub fn get_voxel(&mut self, pos: glam::UVec3) -> Voxel {
 | 
			
		||||
    //     let dims = self.settings.dimensions * self.settings.block_dimensions;
 | 
			
		||||
    //     debug_assert!(pos.x < dims.x && pos.y < dims.y && pos.z < dims.z);
 | 
			
		||||
 | 
			
		||||
        let block_pos = pos / self.settings.block_dimensions;
 | 
			
		||||
        let block_idx = math::to_1d_index(block_pos, self.settings.dimensions);
 | 
			
		||||
        let mut block = &self.blocks[block_idx];
 | 
			
		||||
        if block.is_empty() {
 | 
			
		||||
            self.gen_block(block_pos, block_idx);
 | 
			
		||||
            block = &self.blocks[block_idx]
 | 
			
		||||
        }
 | 
			
		||||
    //     let block_pos = pos / self.settings.block_dimensions;
 | 
			
		||||
    //     let block_idx = math::to_1d_index(block_pos, self.settings.dimensions);
 | 
			
		||||
    //     let mut block = &self.blocks[block_idx];
 | 
			
		||||
    //     if block.is_empty() {
 | 
			
		||||
    //         self.gen_block(block_pos, block_idx);
 | 
			
		||||
    //         block = &self.blocks[block_idx]
 | 
			
		||||
    //     }
 | 
			
		||||
 | 
			
		||||
        let local_pos = pos % self.settings.block_dimensions;
 | 
			
		||||
        let local_idx = math::to_1d_index(local_pos, self.settings.block_dimensions);
 | 
			
		||||
        block[local_idx]
 | 
			
		||||
    }
 | 
			
		||||
    //     let local_pos = pos % self.settings.block_dimensions;
 | 
			
		||||
    //     let local_idx = math::to_1d_index(local_pos, self.settings.block_dimensions);
 | 
			
		||||
    //     block[local_idx]
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    pub fn get_block(&mut self, pos: glam::UVec3) -> Vec<Voxel> {
 | 
			
		||||
        let dims = self.settings.dimensions;
 | 
			
		||||
        assert!(pos.x < dims.x && pos.y < dims.y && pos.z < dims.z);
 | 
			
		||||
 | 
			
		||||
        let block_idx = math::to_1d_index(pos, dims);
 | 
			
		||||
        let mut block = &self.blocks[block_idx];
 | 
			
		||||
        if block.is_empty() {
 | 
			
		||||
            self.gen_block(pos, block_idx);
 | 
			
		||||
            block = &self.blocks[block_idx]
 | 
			
		||||
        let gen_key = &(pos.x as usize, pos.y as usize, pos.z as usize);
 | 
			
		||||
        if !self.genned_blocks.contains(gen_key) {
 | 
			
		||||
            self.gen_block(pos);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        block.to_owned()
 | 
			
		||||
        let block_dims = self.settings.block_dimensions;
 | 
			
		||||
        let start = pos * block_dims;
 | 
			
		||||
        let end = start + block_dims;
 | 
			
		||||
        let region = self
 | 
			
		||||
            .blocks
 | 
			
		||||
            .slice(s![
 | 
			
		||||
                (start.x as usize)..(end.x as usize),
 | 
			
		||||
                (start.y as usize)..(end.y as usize),
 | 
			
		||||
                (start.z as usize)..(end.z as usize)
 | 
			
		||||
            ])
 | 
			
		||||
            .to_owned()
 | 
			
		||||
            .into_raw_vec();
 | 
			
		||||
        region
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn gen_block(&mut self, block_pos: glam::UVec3, block_idx: usize) {
 | 
			
		||||
        let block = &mut self.blocks[block_idx];
 | 
			
		||||
    pub fn gen_block(&mut self, block_pos: glam::UVec3) {
 | 
			
		||||
        let noise_dims = self.settings.dimensions + glam::uvec3(1, 1, 1);
 | 
			
		||||
 | 
			
		||||
        // Extract relevant noise values from the chunk
 | 
			
		||||
| 
						 | 
				
			
			@ -126,32 +165,46 @@ impl Chunk {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // If all the corners are negative, then all the interpolated values
 | 
			
		||||
        // will be negative too. In that case we can just fill with empty.
 | 
			
		||||
        if block_sign == -8.0 {
 | 
			
		||||
            block.resize(512, Voxel::Empty);
 | 
			
		||||
        } else {
 | 
			
		||||
        // will be negative too. The chunk voxels are initialised as empty already
 | 
			
		||||
        // so we only need to modify them if we have at least one positive corner
 | 
			
		||||
        if block_sign != -8.0 {
 | 
			
		||||
            let mut vals = [0.0f32; 512];
 | 
			
		||||
            math::tri_lerp_block(&noise_vals, &[8, 8, 8], &mut vals);
 | 
			
		||||
 | 
			
		||||
            let block_dims = self.settings.block_dimensions;
 | 
			
		||||
            let start = block_pos * block_dims;
 | 
			
		||||
            let end = start + block_dims;
 | 
			
		||||
            let mut block = self.blocks.slice_mut(s![
 | 
			
		||||
                (start.x as usize)..(end.x as usize),
 | 
			
		||||
                (start.y as usize)..(end.y as usize),
 | 
			
		||||
                (start.z as usize)..(end.z as usize)
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            // TODO: Better voxel colours
 | 
			
		||||
            let mut idx = 0;
 | 
			
		||||
            for z in 0..8 {
 | 
			
		||||
                for y in 0..8 {
 | 
			
		||||
                    for x in 0..8 {
 | 
			
		||||
                        let val = vals[idx];
 | 
			
		||||
                        idx += 1;
 | 
			
		||||
            let mut val_idx = 0;
 | 
			
		||||
            for z in 0..block_dims.z {
 | 
			
		||||
                for y in 0..block_dims.y {
 | 
			
		||||
                    for x in 0..block_dims.x {
 | 
			
		||||
                        let val = vals[val_idx];
 | 
			
		||||
                        val_idx += 1;
 | 
			
		||||
 | 
			
		||||
                        if val > 0.0 {
 | 
			
		||||
                            let r = ((x + 1) * 32 - 1) as u8;
 | 
			
		||||
                            let g = ((y + 1) * 32 - 1) as u8;
 | 
			
		||||
                            let b = ((z + 1) * 32 - 1) as u8;
 | 
			
		||||
                            block.push(Voxel::Color(r, g, b));
 | 
			
		||||
                        } else {
 | 
			
		||||
                            block.push(Voxel::Empty);
 | 
			
		||||
                            let block_idx = [z as usize, y as usize, x as usize];
 | 
			
		||||
                            block[block_idx] = Voxel::Color(r, g, b);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let key = (
 | 
			
		||||
            block_pos.x as usize,
 | 
			
		||||
            block_pos.y as usize,
 | 
			
		||||
            block_pos.z as usize,
 | 
			
		||||
        );
 | 
			
		||||
        self.genned_blocks.insert(key);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue