diff --git a/src/bloxel/worldgen/mod.rs b/src/bloxel/worldgen/mod.rs index 895beb7..a9a14bf 100644 --- a/src/bloxel/worldgen/mod.rs +++ b/src/bloxel/worldgen/mod.rs @@ -14,8 +14,14 @@ 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)); + app.init_resource::().add_systems( + Update, + ( + create_chunks_around_camera, + destroy_chunks_away_from_camera, + generate_terrain, + ), + ); } } @@ -60,6 +66,42 @@ fn create_chunks_around_camera( } } +fn destroy_chunks_away_from_camera( + mut commands: Commands, + mut octree: ResMut, + camera: Single<&Transform, With>, + chunk_map: Single<&ChunkMap>, +) { + let block_pos = camera.translation.as_ivec3().into(); + let (chunk_pos, _) = ChunkPos::from_block_pos(block_pos); + + let distance = |node: OctreeNode| -> i32 { + let (min, max) = node.region().into(); + let a = (chunk_pos - min).length_squared(); + let b = (chunk_pos - max).length_squared(); + a.max(b) + }; + + let to_destroy = octree + .find(|node, exist| (exist != Existing::None).then(|| distance(node))) + .take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > 16 * 16) + .map(|(chunk_pos, _, _)| chunk_pos) + .collect::>(); + + for chunk_pos in to_destroy { + let chunk = *chunk_map.get(&chunk_pos).unwrap(); + commands.entity(chunk).despawn_recursive(); + octree.update(chunk_pos, |_, children, parent| { + let children = children.map(|a| a.as_slice()).unwrap_or_default(); + *parent = if children.iter().all(|c| *c == Existing::None) { + Existing::None + } else { + Existing::Some + } + }); + } +} + fn generate_terrain( mut commands: Commands, terrain_blocks: Option>,