|
|
@ -10,6 +10,10 @@ use crate::{ |
|
|
|
TerrainBlocks, |
|
|
|
TerrainBlocks, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const LOAD_DISTANCE: usize = 12; |
|
|
|
|
|
|
|
const UNLOAD_DISTANCE: usize = 16; |
|
|
|
|
|
|
|
const CHUNKS_PER_ITERATION: usize = 12; |
|
|
|
|
|
|
|
|
|
|
|
pub struct WorldGenPlugin; |
|
|
|
pub struct WorldGenPlugin; |
|
|
|
|
|
|
|
|
|
|
|
impl Plugin for WorldGenPlugin { |
|
|
|
impl Plugin for WorldGenPlugin { |
|
|
@ -52,13 +56,14 @@ fn create_chunks_around_camera( |
|
|
|
create_chunk(&mut octree, chunk_pos); |
|
|
|
create_chunk(&mut octree, chunk_pos); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sqr_load_distance = (LOAD_DISTANCE * LOAD_DISTANCE) as i32; |
|
|
|
let to_create = octree |
|
|
|
let to_create = octree |
|
|
|
.find(|node, exist| { |
|
|
|
.find(|node, exist| { |
|
|
|
(exist != Existing::All).then(|| -node.region().distance_to_squared(chunk_pos)) |
|
|
|
(exist != Existing::All).then(|| -node.region().distance_to_squared(chunk_pos)) |
|
|
|
}) |
|
|
|
}) |
|
|
|
.take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > -(12 * 12)) |
|
|
|
.take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > -sqr_load_distance) |
|
|
|
.map(|(chunk_pos, _, _)| chunk_pos) |
|
|
|
.map(|(chunk_pos, _, _)| chunk_pos) |
|
|
|
.take(12) // Create up to 12 chunks per system iteration.
|
|
|
|
.take(CHUNKS_PER_ITERATION) // Create up to this many chunks per system iteration.
|
|
|
|
.collect::<Vec<_>>(); |
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
|
|
|
|
|
|
|
for chunk_pos in to_create { |
|
|
|
for chunk_pos in to_create { |
|
|
@ -82,9 +87,10 @@ fn destroy_chunks_away_from_camera( |
|
|
|
a.max(b) |
|
|
|
a.max(b) |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sqr_unload_distance = (UNLOAD_DISTANCE * UNLOAD_DISTANCE) as i32; |
|
|
|
let to_destroy = octree |
|
|
|
let to_destroy = octree |
|
|
|
.find(|node, exist| (exist != Existing::None).then(|| distance(node))) |
|
|
|
.find(|node, exist| (exist != Existing::None).then(|| distance(node))) |
|
|
|
.take_while(|(_, _, neg_sqr_distance)| *neg_sqr_distance > 16 * 16) |
|
|
|
.take_while(|(_, _, sqr_distance)| *sqr_distance > sqr_unload_distance) |
|
|
|
.map(|(chunk_pos, _, _)| chunk_pos) |
|
|
|
.map(|(chunk_pos, _, _)| chunk_pos) |
|
|
|
.collect::<Vec<_>>(); |
|
|
|
.collect::<Vec<_>>(); |
|
|
|
|
|
|
|
|
|
|
@ -111,6 +117,8 @@ fn generate_terrain( |
|
|
|
return; |
|
|
|
return; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let slices = [terrain.rock, terrain.dirt, terrain.grass, terrain.sand]; |
|
|
|
|
|
|
|
|
|
|
|
for (entity, chunk_pos) in chunks_without_data.iter() { |
|
|
|
for (entity, chunk_pos) in chunks_without_data.iter() { |
|
|
|
let mut data = ChunkData::new(terrain.air); |
|
|
|
let mut data = ChunkData::new(terrain.air); |
|
|
|
data.update(|relative, _| { |
|
|
|
data.update(|relative, _| { |
|
|
@ -125,7 +133,7 @@ fn generate_terrain( |
|
|
|
.sample3(float_pos); |
|
|
|
.sample3(float_pos); |
|
|
|
|
|
|
|
|
|
|
|
if sample > bias { |
|
|
|
if sample > bias { |
|
|
|
terrain.rock |
|
|
|
slices[relative.y as usize % slices.len()] |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
terrain.air |
|
|
|
terrain.air |
|
|
|
} |
|
|
|
} |
|
|
|