Nicer lake borders

This commit is contained in:
Joshua Barretto 2021-10-09 13:19:28 +01:00
parent 1473029204
commit e660aafed3
4 changed files with 81 additions and 23 deletions

View File

@ -17,7 +17,12 @@ fn main() {
let mut focus = Vec2::<f32>::zero(); let mut focus = Vec2::<f32>::zero();
let mut zoom = 1.0; let mut zoom = 1.0;
let colors = &**index.colors().read(); 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() { while win.is_open() {
let mut buf = vec![0; W * H]; let mut buf = vec![0; W * H];

View File

@ -414,7 +414,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
downhill_chunk.river.river_kind, downhill_chunk.river.river_kind,
Some(RiverKind::Lake { .. }) 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 /// 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 // 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 // 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. // 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), WeightedSum::default().with_max(base_sea_level),
false, false,
@ -461,7 +468,18 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
None, None,
WeightedSum::default().with_max(base_sea_level), 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(kind),
Some((_, _, river_width, (river_t, (river_pos, _), downhill_chunk))), Some((_, _, river_width, (river_t, (river_pos, _), downhill_chunk))),
@ -480,7 +498,8 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
match kind { match kind {
RiverKind::River { .. } => { 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( let river_water_alt = river_water_alt(
river_chunk.alt.max(river_chunk.water_alt), river_chunk.alt.max(river_chunk.water_alt),
downhill_chunk.alt.max(downhill_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), is_waterfall(river_chunk_idx, river_chunk, downhill_chunk),
); );
river_water_level = river_water_level river_water_level =
.with(river_water_alt, near_center); river_water_level.with(river_water_alt, near_center);
if river_edge_dist <= 0.0 { if river_edge_dist <= 0.0 {
in_river = true; 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 => { RiverKind::Lake { .. } | RiverKind::Ocean => {
let lake_water_alt = if matches!(kind, RiverKind::Ocean) { let lake_water_alt = if matches!(kind, RiverKind::Ocean) {
base_sea_level 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 { 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 unbounded_water_level = unbounded_water_level
.with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0)) .with(unbounded_water_alt, 1.0 / (1.0 + river_edge_dist * 5.0));
.with_max(unbounded_water_alt); //.with_max(unbounded_water_alt);
} }
river_water_level = river_water_level river_water_level = river_water_level.with(lake_water_alt, near_center);
.with(lake_water_alt, near_center);
lake_dist = lake_dist.min(river_edge_dist); lake_dist = lake_dist.min(river_edge_dist);
// Lake border prevents a lake failing to propagate its altitude to nearby rivers // Lake border prevents a lake failing to propagate its altitude to
if river_edge_dist <= 0.0 { // nearby rivers
lake_water_level = lake_water_level let off = 0.0;
// Make sure the closest lake is prioritised let len = 3.0;
.with(lake_water_alt, near_center + 0.1 / (1.0 + river_edge_dist)); 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 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); 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)) .with_min(min_alt.unwrap_or(riverbed_alt).min(riverbed_alt))
} else { } else {
const GORGE: f32 = 0.5; const GORGE: f32 = 0.25;
const BANK_SCALE: f32 = 24.0; const BANK_SCALE: f32 = 24.0;
// Weighting of this riverbank on nearby terrain (higher when closer to // Weighting of this riverbank on nearby terrain (higher when closer to
// the river). This 'pulls' the riverbank // the river). This 'pulls' the riverbank

View File

@ -84,6 +84,8 @@ impl Index {
pub fn colors(&self) -> AssetHandle<Arc<Colors>> { self.colors } pub fn colors(&self) -> AssetHandle<Arc<Colors>> { self.colors }
pub fn features(&self) -> AssetHandle<Arc<Features>> { self.features }
pub fn get_site_prices(&self, site_id: SiteId) -> Option<SitePrices> { pub fn get_site_prices(&self, site_id: SiteId) -> Option<SitePrices> {
self.sites self.sites
.recreate_id(site_id) .recreate_id(site_id)

View File

@ -701,7 +701,7 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
let warp_amp = Vec3::new(12.0, 12.0, 12.0); let warp_amp = Vec3::new(12.0, 12.0, 12.0);
let wposf_warped = wposf.map(|e| e as f32) let wposf_warped = wposf.map(|e| e as f32)
+ Vec3::new( + 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 + 1).get(wposf * warp_freq) as f32,
FastNoise::new(seed + 2).get(wposf * warp_freq) as f32, FastNoise::new(seed + 2).get(wposf * warp_freq) as f32,
) * warp_amp ) * warp_amp