|
|
|
@ -14,8 +14,14 @@ pub struct WorldGenPlugin; |
|
|
|
|
|
|
|
|
|
impl Plugin for WorldGenPlugin { |
|
|
|
|
fn build(&self, app: &mut App) { |
|
|
|
|
app.init_resource::<ExistingChunks>() |
|
|
|
|
.add_systems(Update, (create_chunks_around_camera, generate_terrain)); |
|
|
|
|
app.init_resource::<ExistingChunks>().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<ExistingChunks>, |
|
|
|
|
camera: Single<&Transform, With<ControlledCamera>>, |
|
|
|
|
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::<Vec<_>>(); |
|
|
|
|
|
|
|
|
|
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<Res<TerrainBlocks>>, |
|
|
|
|