From 6ed434d98a9e54b64d8d9643cc5d349d642690ab Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 9 Oct 2021 13:19:28 +0100 Subject: [PATCH] Nicer lake borders --- world/examples/settlement_viewer.rs | 7 ++- world/src/column/mod.rs | 93 ++++++++++++++++++++++------- world/src/index.rs | 2 + world/src/layer/mod.rs | 2 +- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/world/examples/settlement_viewer.rs b/world/examples/settlement_viewer.rs index d2c311827b..d397a2dd06 100644 --- a/world/examples/settlement_viewer.rs +++ b/world/examples/settlement_viewer.rs @@ -17,7 +17,12 @@ fn main() { let mut focus = Vec2::::zero(); let mut zoom = 1.0; let colors = &**index.colors().read(); - let index = IndexRef { colors, index }; + let features = &**index.features().read(); + let index = IndexRef { + colors, + features, + index, + }; while win.is_open() { let mut buf = vec![0; W * H]; diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 4fa873f159..2d77fb8cf8 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -414,7 +414,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { downhill_chunk.river.river_kind, Some(RiverKind::Lake { .. }) )) - && (river_chunk.water_alt > downhill_chunk.water_alt + 8.0) + && (river_chunk.water_alt > downhill_chunk.water_alt + 0.0) } /// Determine the altitude of a river based on the altitude of the @@ -452,7 +452,14 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { // they do not result in artifacts, even in edge cases. The exact configuration // of this code is the product of hundreds of hours of testing and // refinement and I ask that you do not take that effort lightly. - let (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level) = neighbor_river_data.iter().copied().fold( + let ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ) = neighbor_river_data.iter().copied().fold( ( WeightedSum::default().with_max(base_sea_level), false, @@ -461,7 +468,18 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { None, WeightedSum::default().with_max(base_sea_level), ), - |(mut river_water_level, mut in_river, mut lake_water_level, mut lake_dist, water_dist, mut unbounded_water_level), (river_chunk_idx, river_chunk, river, dist_info)| match (river.river_kind, dist_info) { + |( + mut river_water_level, + mut in_river, + lake_water_level, + mut lake_dist, + water_dist, + mut unbounded_water_level, + ), + (river_chunk_idx, river_chunk, river, dist_info)| match ( + river.river_kind, + dist_info, + ) { ( Some(kind), Some((_, _, river_width, (river_t, (river_pos, _), downhill_chunk))), @@ -480,7 +498,8 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { match kind { RiverKind::River { .. } => { - // Alt of river water *is* the alt of land (ignoring gorge, which gets applied later) + // Alt of river water *is* the alt of land (ignoring gorge, which gets + // applied later) let river_water_alt = river_water_alt( river_chunk.alt.max(river_chunk.water_alt), downhill_chunk.alt.max(downhill_chunk.water_alt), @@ -488,14 +507,15 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { is_waterfall(river_chunk_idx, river_chunk, downhill_chunk), ); - river_water_level = river_water_level - .with(river_water_alt, near_center); + river_water_level = + river_water_level.with(river_water_alt, near_center); if river_edge_dist <= 0.0 { in_river = true; } }, - // Slightly wider threshold is chosen in case the lake bounds are a bit wrong + // Slightly wider threshold is chosen in case the lake bounds are a bit + // wrong RiverKind::Lake { .. } | RiverKind::Ocean => { let lake_water_alt = if matches!(kind, RiverKind::Ocean) { base_sea_level @@ -509,32 +529,63 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { }; if river_edge_dist > 0.0 && river_width > lake_width * 0.99 { - let unbounded_water_alt = lake_water_alt - ((river_edge_dist - 8.0).max(0.0) / 5.0).powf(2.0); + let unbounded_water_alt = lake_water_alt + - ((river_edge_dist - 8.0).max(0.0) / 5.0).powf(2.0); unbounded_water_level = unbounded_water_level - .with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0)) - .with_max(unbounded_water_alt); + .with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0)); + //.with_max(unbounded_water_alt); } - river_water_level = river_water_level - .with(lake_water_alt, near_center); + river_water_level = river_water_level.with(lake_water_alt, near_center); lake_dist = lake_dist.min(river_edge_dist); - // Lake border prevents a lake failing to propagate its altitude to nearby rivers - if river_edge_dist <= 0.0 { - lake_water_level = lake_water_level - // Make sure the closest lake is prioritised - .with(lake_water_alt, near_center + 0.1 / (1.0 + river_edge_dist)); + // Lake border prevents a lake failing to propagate its altitude to + // nearby rivers + let off = 0.0; + let len = 3.0; + if river_edge_dist <= off { + // lake_water_level = lake_water_level + // // Make sure the closest lake is prioritised + // .with(lake_water_alt, near_center + 0.1 / (1.0 + + // river_edge_dist)); // .with_min(lake_water_alt); + // + river_water_level = river_water_level.with_min( + lake_water_alt + + ((((river_dist - river_width * 0.5) as f32 + len - off) + .max(0.0)) + / len) + .powf(1.5) + * 32.0, + ); } }, }; let river_edge_dist_unclamped = (river_dist - river_width * 0.5) as f32; - let water_dist = Some(water_dist.unwrap_or(river_edge_dist_unclamped).min(river_edge_dist_unclamped)); + let water_dist = Some( + water_dist + .unwrap_or(river_edge_dist_unclamped) + .min(river_edge_dist_unclamped), + ); - (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level) + ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ) }, - (_, _) => (river_water_level, in_river, lake_water_level, lake_dist, water_dist, unbounded_water_level), + (_, _) => ( + river_water_level, + in_river, + lake_water_level, + lake_dist, + water_dist, + unbounded_water_level, + ), }, ); let unbounded_water_level = unbounded_water_level.eval_or(base_sea_level); @@ -679,7 +730,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { ) .with_min(min_alt.unwrap_or(riverbed_alt).min(riverbed_alt)) } else { - const GORGE: f32 = 0.5; + const GORGE: f32 = 0.25; const BANK_SCALE: f32 = 24.0; // Weighting of this riverbank on nearby terrain (higher when closer to // the river). This 'pulls' the riverbank diff --git a/world/src/index.rs b/world/src/index.rs index 0edef3eaf7..1e69f6f310 100644 --- a/world/src/index.rs +++ b/world/src/index.rs @@ -84,6 +84,8 @@ impl Index { pub fn colors(&self) -> AssetHandle> { self.colors } + pub fn features(&self) -> AssetHandle> { self.features } + pub fn get_site_prices(&self, site_id: SiteId) -> Option { self.sites .recreate_id(site_id) diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index b026959b28..8cb9f87efd 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -701,7 +701,7 @@ pub fn apply_caverns_to(canvas: &mut Canvas, dynamic_rng: &mut R) { let warp_amp = Vec3::new(12.0, 12.0, 12.0); let wposf_warped = wposf.map(|e| e as f32) + Vec3::new( - FastNoise::new(seed + 0).get(wposf * warp_freq) as f32, + FastNoise::new(seed).get(wposf * warp_freq) as f32, FastNoise::new(seed + 1).get(wposf * warp_freq) as f32, FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, ) * warp_amp