Skip to content

Commit bbf0a7e

Browse files
committed
Improve encapsulation of worldgen short-circuiting
1 parent c7b1bfe commit bbf0a7e

File tree

1 file changed

+44
-30
lines changed

1 file changed

+44
-30
lines changed

common/src/worldgen.rs

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -212,33 +212,6 @@ impl ChunkParams {
212212

213213
/// Generate voxels making up the chunk
214214
pub fn generate_voxels(&self) -> VoxelData {
215-
// Determine whether this chunk might contain a boundary between solid and void
216-
let mut me_min = self.env.max_elevations[0];
217-
let mut me_max = self.env.max_elevations[0];
218-
for &me in &self.env.max_elevations[1..] {
219-
me_min = me_min.min(me);
220-
me_max = me_max.max(me);
221-
}
222-
// Maximum difference between elevations at the center of a chunk and any other point in the chunk
223-
// TODO: Compute what this actually is, current value is a guess! Real one must be > 0.6
224-
// empirically.
225-
const ELEVATION_MARGIN: f32 = 0.7;
226-
let center_elevation = self
227-
.surface
228-
.distance_to_chunk(self.chunk, &na::Vector3::repeat(0.5));
229-
if (center_elevation - ELEVATION_MARGIN > me_max / TERRAIN_SMOOTHNESS)
230-
&& !(self.is_road || self.is_road_support)
231-
{
232-
// The whole chunk is above ground and not part of the road
233-
return VoxelData::Solid(Material::Void);
234-
}
235-
236-
if (center_elevation + ELEVATION_MARGIN < me_min / TERRAIN_SMOOTHNESS) && !self.is_road {
237-
// The whole chunk is underground
238-
// TODO: More accurate VoxelData
239-
return VoxelData::Solid(Material::Dirt);
240-
}
241-
242215
let mut voxels = VoxelData::Solid(Material::Void);
243216
let mut rng = rand_pcg::Pcg64Mcg::seed_from_u64(hash(self.node_spice, self.chunk as u64));
244217

@@ -252,9 +225,7 @@ impl ChunkParams {
252225

253226
// TODO: Don't generate detailed data for solid chunks with no neighboring voids
254227

255-
if self.dimension > 4 && matches!(voxels, VoxelData::Dense(_)) {
256-
self.generate_trees(&mut voxels, &mut rng);
257-
}
228+
self.generate_trees(&mut voxels, &mut rng);
258229

259230
margins::initialize_margins(self.dimension, &mut voxels);
260231
voxels
@@ -263,6 +234,33 @@ impl ChunkParams {
263234
/// Performs all terrain generation that can be done one voxel at a time and with
264235
/// only the containing chunk's surrounding nodes' envirofactors.
265236
fn generate_terrain(&self, voxels: &mut VoxelData, rng: &mut Pcg64Mcg) {
237+
// Determine whether this chunk might contain a boundary between solid and void
238+
let mut me_min = self.env.max_elevations[0];
239+
let mut me_max = self.env.max_elevations[0];
240+
for &me in &self.env.max_elevations[1..] {
241+
me_min = me_min.min(me);
242+
me_max = me_max.max(me);
243+
}
244+
// Maximum difference between elevations at the center of a chunk and any other point in the chunk
245+
// TODO: Compute what this actually is, current value is a guess! Real one must be > 0.6
246+
// empirically.
247+
const ELEVATION_MARGIN: f32 = 0.7;
248+
let center_elevation = self
249+
.surface
250+
.distance_to_chunk(self.chunk, &na::Vector3::repeat(0.5));
251+
if center_elevation - ELEVATION_MARGIN > me_max / TERRAIN_SMOOTHNESS {
252+
// The whole chunk is above ground
253+
*voxels = VoxelData::Solid(Material::Void);
254+
return;
255+
}
256+
if center_elevation + ELEVATION_MARGIN < me_min / TERRAIN_SMOOTHNESS {
257+
// The whole chunk is underground
258+
*voxels = VoxelData::Solid(Material::Dirt);
259+
return;
260+
}
261+
262+
// Otherwise, the chunk might contain a solid/void boundary, so the full terrain generation
263+
// code should run.
266264
let normal = Normal::new(0.0, 0.03).unwrap();
267265

268266
for (x, y, z) in VoxelCoords::new(self.dimension) {
@@ -346,6 +344,12 @@ impl ChunkParams {
346344

347345
/// Fills the half-plane below the road with wooden supports.
348346
fn generate_road_support(&self, voxels: &mut VoxelData) {
347+
if voxels.is_solid() && voxels.get(0) != Material::Void {
348+
// There is guaranteed no void to fill with the road supports, so
349+
// nothing to do here.
350+
return;
351+
}
352+
349353
let plane = -Plane::from(Side::B);
350354

351355
for (x, y, z) in VoxelCoords::new(self.dimension) {
@@ -395,6 +399,16 @@ impl ChunkParams {
395399
/// and a block of leaves. The leaf block is on the opposite face of the
396400
/// wood block as the ground block.
397401
fn generate_trees(&self, voxels: &mut VoxelData, rng: &mut Pcg64Mcg) {
402+
if voxels.is_solid() {
403+
// No trees can be generated unless there's both land and air.
404+
return;
405+
}
406+
407+
if self.dimension <= 4 {
408+
// The tree generation algorithm can crash when the chunk size is too small.
409+
return;
410+
}
411+
398412
// margins are added to keep voxels outside the chunk from being read/written
399413
let random_position = Uniform::new(1, self.dimension - 1).unwrap();
400414

0 commit comments

Comments
 (0)