diff --git a/src/bloxel/mod.rs b/src/bloxel/mod.rs index 71602f9..c7ad92f 100644 --- a/src/bloxel/mod.rs +++ b/src/bloxel/mod.rs @@ -14,6 +14,7 @@ pub mod prelude { chunk::*, math::*, storage::{BloxelView, BloxelViewMut}, + worldgen::WorldGenPlugin, BloxelPlugin, }; } @@ -26,15 +27,13 @@ impl Plugin for BloxelPlugin { fn build(&self, app: &mut App) { app.add_systems( Update, - ( - set_transform_on_chunkpos_changed, - worldgen::create_chunks_around_camera, - worldgen::generate_terrain, - mesh::generate_chunk_mesh, - ), + (set_transform_on_chunkpos_changed, mesh::generate_chunk_mesh), ) .add_observer(add_chunks_to_chunkmap) .add_observer(remove_chunks_from_chunkmap); + + // Spawn default `ChunkMap` entity which all `Chunk`s get added to. + app.world_mut().spawn(ChunkMap::default()); } } diff --git a/src/bloxel/worldgen/mod.rs b/src/bloxel/worldgen/mod.rs index 2142c49..895beb7 100644 --- a/src/bloxel/worldgen/mod.rs +++ b/src/bloxel/worldgen/mod.rs @@ -2,53 +2,65 @@ use bevy::prelude::*; use rand::prelude::*; use crate::{ - bloxel::{prelude::*, storage::ChunkedOctree}, + bloxel::{ + prelude::*, + storage::{ChunkedOctree, OctreeNode}, + }, camera_controller::ControlledCamera, TerrainBlocks, }; -pub fn create_chunks_around_camera( +pub struct WorldGenPlugin; + +impl Plugin for WorldGenPlugin { + fn build(&self, app: &mut App) { + app.init_resource::() + .add_systems(Update, (create_chunks_around_camera, generate_terrain)); + } +} + +fn create_chunks_around_camera( mut commands: Commands, - mut octree: Local, + mut octree: ResMut, camera: Single<&Transform, With>, chunk_map: Single>, ) { let block_pos = camera.translation.as_ivec3().into(); let (chunk_pos, _) = ChunkPos::from_block_pos(block_pos); - let mut create_chunk = |octree: &mut GeneratedChunks, chunk_pos: ChunkPos| { + let mut create_chunk = |octree: &mut ExistingChunks, chunk_pos: ChunkPos| { commands.entity(*chunk_map).with_child((Chunk, chunk_pos)); - octree.update(chunk_pos, |_node, children, parent| { + octree.update(chunk_pos, |_, children, parent| { let children = children.map(|a| a.as_slice()).unwrap_or_default(); - *parent = if children.iter().all(|c| *c == Generated::All) { - Generated::All + *parent = if children.iter().all(|c| *c == Existing::All) { + Existing::All } else { - Generated::Some + Existing::Some } }); }; // Create chunk at camera's position, if it's not already. This is necessary because we // need to "seed" the octree with a region so we have something to begin the search from. - if octree.get(chunk_pos) == Generated::None { + if octree.get(chunk_pos) == Existing::None { create_chunk(&mut octree, chunk_pos); } - let to_generate = octree - .find(|node, generated| { - (generated != Generated::All).then(|| -node.region().distance_to_squared(chunk_pos)) + let to_create = octree + .find(|node, exist| { + (exist != Existing::All).then(|| -node.region().distance_to_squared(chunk_pos)) }) - .take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > -(16 * 16)) + .take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > -(12 * 12)) .map(|(chunk_pos, _, _)| chunk_pos) - .take(12) // Generate up to 12 chunks per system iteration. + .take(12) // Create up to 12 chunks per system iteration. .collect::>(); - for chunk_pos in to_generate { + for chunk_pos in to_create { create_chunk(&mut octree, chunk_pos); } } -pub fn generate_terrain( +fn generate_terrain( mut commands: Commands, terrain_blocks: Option>, chunks_without_data: Query<(Entity, &ChunkPos), (With, Without)>, @@ -80,12 +92,12 @@ pub fn generate_terrain( } } -#[derive(Deref, DerefMut)] -pub struct GeneratedChunks { - octree: ChunkedOctree, +#[derive(Resource, Deref, DerefMut)] +pub struct ExistingChunks { + octree: ChunkedOctree, } -impl Default for GeneratedChunks { +impl Default for ExistingChunks { fn default() -> Self { let octree = ChunkedOctree::new(5); Self { octree } @@ -93,7 +105,7 @@ impl Default for GeneratedChunks { } #[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub enum Generated { +pub enum Existing { #[default] None, Some, diff --git a/src/main.rs b/src/main.rs index 4feeeb2..2c54f06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ fn main() { DefaultPlugins.set(ImagePlugin::default_nearest()), CameraControllerPlugin, BloxelPlugin, + WorldGenPlugin, )) .add_systems( Startup, @@ -43,7 +44,6 @@ fn main() { setup_camera, setup_terrain_blocks, load_terrain_textures, - generate_sample_chunks, ), ) .add_systems(Update, check_terrain_textures) @@ -118,14 +118,6 @@ fn check_terrain_textures( } } -fn generate_sample_chunks(mut commands: Commands) { - commands.spawn(ChunkMap::default()).with_children(|map| { - // map.spawn((Chunk, ChunkPos::new(0, 0, 0))); - // map.spawn((Chunk, ChunkPos::new(1, 0, 0))); - // map.spawn((Chunk, ChunkPos::new(-1, 0, 0))); - }); -} - fn setup_sunlight(mut commands: Commands) { commands.spawn(( DirectionalLight {