mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Better lake entrances and distance
This commit is contained in:
parent
f118d15745
commit
826aff2ea4
@ -295,6 +295,10 @@ pub fn quadratic_nearest_point(
|
||||
point: Vec2<f64>,
|
||||
line: Vec2<Vec2<f64>>,
|
||||
) -> Option<(f64, Vec2<f64>, f64)> {
|
||||
let eval_at = |t: f64| spline.x * t * t + spline.y * t + spline.z;
|
||||
|
||||
// Linear
|
||||
|
||||
// let line = LineSegment2 {
|
||||
// start: line.x,
|
||||
// end: line.y,
|
||||
@ -304,13 +308,37 @@ pub fn quadratic_nearest_point(
|
||||
// let pos = line.start + (line.end - line.start) * t;
|
||||
// return Some((t, pos, pos.distance_squared(point)));
|
||||
|
||||
// Quadratic
|
||||
|
||||
// let curve = QuadraticBezier2 {
|
||||
// start: spline.x,
|
||||
// ctrl: spline.y,
|
||||
// end: spline.z,
|
||||
// start: line.x,
|
||||
// ctrl: eval_at(0.5),
|
||||
// end: line.y,
|
||||
// };
|
||||
// let (t, pos) = curve.binary_search_point_by_steps(point, 16, 0.001);
|
||||
// return Some((t, pos, curve.evaluate(t).distance_squared(point)));
|
||||
// let t = t.clamped(0.0, 1.0);
|
||||
// let pos = curve.evaluate(t);
|
||||
// return Some((t, pos, pos.distance_squared(point)));
|
||||
|
||||
// Cubic
|
||||
|
||||
let ctrl_at = |t: f64, end: f64| {
|
||||
let a = eval_at(end);
|
||||
let b = eval_at(Lerp::lerp(end, t, 0.1));
|
||||
let dir = (b - a).normalized();
|
||||
let exact = eval_at(t);
|
||||
a + dir * exact.distance(a)
|
||||
};
|
||||
let curve = CubicBezier2 {
|
||||
start: line.x,
|
||||
ctrl0: ctrl_at(0.33, 0.0),
|
||||
ctrl1: ctrl_at(0.66, 1.0),
|
||||
end: line.y,
|
||||
};
|
||||
let (t, pos) = curve.binary_search_point_by_steps(point, 16, 0.001);
|
||||
let t = t.clamped(0.0, 1.0);
|
||||
let pos = curve.evaluate(t);
|
||||
return Some((t, pos, pos.distance_squared(point)));
|
||||
|
||||
let a = spline.z.x;
|
||||
let b = spline.y.x;
|
||||
|
@ -51,6 +51,22 @@ pub struct Colors {
|
||||
pub tropical_high: (f32, f32, f32),
|
||||
}
|
||||
|
||||
fn cubic(x: f64) -> f64 {
|
||||
if x < 0.5 {
|
||||
4.0 * x.powf(3.0)
|
||||
} else {
|
||||
1.0 - (-2.0 * x + 2.0).powf(3.0) / 2.0
|
||||
}
|
||||
}
|
||||
|
||||
fn revcubic(x: f64) -> f64 {
|
||||
if x < 0.5 {
|
||||
(x / 4.0).powf(1.0 / 3.0)
|
||||
} else {
|
||||
1.0 - (2.0 - 2.0 * x).powf(1.0 / 3.0) / 2.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ColumnGen<'a> {
|
||||
pub fn new(sim: &'a WorldSim) -> Self { Self { sim } }
|
||||
}
|
||||
@ -258,7 +274,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let river_width = Lerp::lerp(
|
||||
river_width_min,
|
||||
river_width_max,
|
||||
river_t.max(0.0).min(1.0).sqrt(),
|
||||
cubic(river_t.clamped(0.0, 1.0)),//.sqrt(),
|
||||
);
|
||||
|
||||
let river_width = river_width;// * (1.0 + river_width_noise * 0.3);
|
||||
@ -313,27 +329,36 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
fn with_max(self, max: f32) -> Self {
|
||||
Self { max: Some(self.max.unwrap_or(max).max(max)), ..self }
|
||||
}
|
||||
fn eval(&self) -> Option<f32> {
|
||||
if self.weight > 0.0 {
|
||||
let res = self.sum / self.weight;
|
||||
let res = self.min.map_or(res, |m| m.min(res));
|
||||
let res = self.max.map_or(res, |m| m.max(res));
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
}
|
||||
fn eval_or(&self, default: f32) -> f32 {
|
||||
let res = if self.weight > 0.0 {
|
||||
self.sum / self.weight
|
||||
} else {
|
||||
default
|
||||
};
|
||||
let res = match self.min {
|
||||
Some(min) => res.min(min),
|
||||
None => res,
|
||||
};
|
||||
let res = match self.max {
|
||||
Some(max) => res.max(max),
|
||||
None => res,
|
||||
};
|
||||
let res = self.min.map_or(res, |m| m.min(res));
|
||||
let res = self.max.map_or(res, |m| m.max(res));
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
let water_level = neighbor_river_data.clone().fold(
|
||||
WeightedSum::default().with_max(CONFIG.sea_level + 2.0), // TODO: Don't add 2.0
|
||||
|water_level, (river_chunk_idx, river_chunk, river, dist_info)| match (river.river_kind, dist_info) {
|
||||
let (river_water_level, lake_water_level, water_dist) = neighbor_river_data.clone().fold(
|
||||
(
|
||||
WeightedSum::default().with_max(CONFIG.sea_level + 2.0), // TODO: Don't add 2.0
|
||||
WeightedSum::default().with_max(CONFIG.sea_level + 2.0), // TODO: Don't add 2.0
|
||||
None,
|
||||
),
|
||||
|(mut river_water_level, mut lake_water_level, water_dist), (river_chunk_idx, river_chunk, river, dist_info)| match (river.river_kind, dist_info) {
|
||||
(
|
||||
Some(kind/*RiverKind::River { cross_section }*/),
|
||||
Some((_, dist, river_width, (river_t, (river_pos, _), downhill_chunk))),
|
||||
@ -344,29 +369,49 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let river_edge_dist = (river_dist - river_width * 0.5).max(0.0) as f32;
|
||||
// 0.0 = not near river, 1.0 = in middle of river
|
||||
let near_river = ((river_dist / river_width) as f32).min(1.0).mul(f32::consts::PI).cos().add(1.0).mul(0.5);
|
||||
let near_center = ((river_dist / (river_width * 0.5)) as f32).min(1.0).mul(f32::consts::PI).cos().add(1.0).mul(0.5);
|
||||
|
||||
match kind {
|
||||
RiverKind::River { .. } if river_edge_dist <= 0.0 => {
|
||||
RiverKind::River { .. } => {
|
||||
// Alt of river water *is* the alt of land
|
||||
let river_water_alt = Lerp::lerp(river_chunk.alt, downhill_chunk.alt, river_t as f32);
|
||||
water_level.with(river_water_alt, near_river)
|
||||
river_water_level = river_water_level
|
||||
.with(river_water_alt, near_center * 10.0);
|
||||
// .with_max(river_water_alt)
|
||||
},
|
||||
// Slightly wider threshold is chosen in case the lake bounds are a bit wrong
|
||||
RiverKind::Lake { .. } if river_edge_dist <= 8.0 => {
|
||||
RiverKind::Lake { .. } => {
|
||||
let lake_water_alt = Lerp::lerp(
|
||||
river_chunk.alt.max(river_chunk.water_alt),
|
||||
downhill_chunk.alt.max(downhill_chunk.water_alt),
|
||||
river_t as f32,
|
||||
);
|
||||
water_level.with_max(lake_water_alt)
|
||||
|
||||
river_water_level = river_water_level
|
||||
.with(lake_water_alt, near_center * 10.0);
|
||||
|
||||
if river_edge_dist <= 0.0 {
|
||||
lake_water_level = lake_water_level
|
||||
.with(lake_water_alt, near_center * 10.0);
|
||||
// .with_max(lake_water_alt);
|
||||
} else if river_edge_dist <= 12.0 {
|
||||
// lake_water_level = lake_water_level.with(lake_water_alt, near_river * 10.0);
|
||||
}
|
||||
},
|
||||
_ => water_level,
|
||||
}
|
||||
RiverKind::Ocean => {},
|
||||
};
|
||||
|
||||
let water_dist = Some(water_dist.unwrap_or(river_edge_dist).min(river_edge_dist));
|
||||
|
||||
(river_water_level, lake_water_level, water_dist)
|
||||
},
|
||||
(_, _) => water_level,
|
||||
(_, _) => (river_water_level, lake_water_level, water_dist),
|
||||
},
|
||||
);
|
||||
let water_level = water_level.eval_or(CONFIG.sea_level);
|
||||
let water_level = match (river_water_level.eval(), lake_water_level.eval()) {
|
||||
(Some(r), Some(l)) => r.max(l),
|
||||
(r, l) => r.or(l).unwrap_or(CONFIG.sea_level),
|
||||
};
|
||||
|
||||
let riverless_alt = alt;
|
||||
let alt = neighbor_river_data.clone().fold(
|
||||
@ -383,32 +428,32 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
// 0.0 = not near river, 1.0 = in middle of river
|
||||
let near_river = ((river_dist / river_width) as f32).min(1.0).mul(f32::consts::PI).cos().add(1.0).mul(0.5);
|
||||
|
||||
// Maximum depth of the river basin (including banks)
|
||||
let river_basin = (river_width as f32 + 1.0).ln() * 1.5;
|
||||
// River basin depth at the current column
|
||||
let basin_depth = near_river * river_basin;
|
||||
|
||||
let water_alt = match kind {
|
||||
RiverKind::River { .. } => {
|
||||
// Alt of river water *is* the alt of land
|
||||
Some(Lerp::lerp(river_chunk.alt, downhill_chunk.alt, river_t as f32))
|
||||
let river_water_alt = Lerp::lerp(river_chunk.alt, downhill_chunk.alt, river_t as f32);
|
||||
Some((river_water_alt, None))
|
||||
},
|
||||
RiverKind::Lake { .. } => Some(Lerp::lerp(
|
||||
river_chunk.alt.max(river_chunk.water_alt),
|
||||
downhill_chunk.alt.max(downhill_chunk.water_alt),
|
||||
river_t as f32,
|
||||
)),
|
||||
_ => None,
|
||||
RiverKind::Lake { .. } => {
|
||||
let lake_water_alt = Lerp::lerp(
|
||||
river_chunk.alt.max(river_chunk.water_alt),
|
||||
downhill_chunk.alt.max(downhill_chunk.water_alt),
|
||||
river_t as f32,
|
||||
);
|
||||
|
||||
Some((lake_water_alt, Some(riverless_alt)))
|
||||
},
|
||||
RiverKind::Ocean => Some((riverless_alt, Some(riverless_alt))),
|
||||
};
|
||||
|
||||
if let Some(water_alt) = water_alt {
|
||||
if let Some((water_alt, min_alt)) = water_alt {
|
||||
if river_edge_dist <= 0.0 {
|
||||
const MIN_DEPTH: f32 = 0.5;
|
||||
const MIN_DEPTH: f32 = 1.0;
|
||||
let near_centre = ((river_dist / (river_width * 0.5)) as f32).min(1.0).mul(f32::consts::PI).cos().add(1.0).mul(0.5);;
|
||||
let riverbed_depth = near_centre * river_width as f32 * 0.35 + MIN_DEPTH;
|
||||
let riverbed_depth = near_centre * river_width as f32 * 0.15 + MIN_DEPTH;
|
||||
// Handle rivers debouching into the ocean nicely by 'flattening' their bottom
|
||||
let riverbed_alt = (water_alt - riverbed_depth).max(riverless_alt.min(CONFIG.sea_level));
|
||||
alt.with_min(riverbed_alt)
|
||||
alt.with_min(min_alt.unwrap_or(riverbed_alt).min(riverbed_alt))
|
||||
} else {
|
||||
const GORGE: f32 = 0.5;
|
||||
const BANK_SCALE: f32 = 24.0;
|
||||
@ -417,7 +462,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
// 'pulls' the riverbank toward the river's altitude to make sure that we get a smooth
|
||||
// transition from normal terrain to the water.
|
||||
let weight = Lerp::lerp(
|
||||
BANK_STRENGTH / (1.0 + (river_edge_dist as f32 - 1.0).max(0.0) * BANK_STRENGTH / BANK_SCALE),
|
||||
BANK_STRENGTH / (1.0 + (river_edge_dist as f32 - 2.0).max(0.0) * BANK_STRENGTH / BANK_SCALE),
|
||||
0.0,
|
||||
(river_edge_dist / BANK_SCALE).clamped(0.0, 1.0),
|
||||
);
|
||||
@ -433,33 +478,6 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
} else {
|
||||
alt
|
||||
}
|
||||
|
||||
// match kind {
|
||||
// RiverKind::River { .. } => {
|
||||
// // Alt of river water *is* the alt of land
|
||||
// let river_water_alt = Lerp::lerp(river_chunk.alt, downhill_chunk.alt, river_t as f32);
|
||||
|
||||
// if river_edge_dist <= 0.0 {
|
||||
// const GORGE: f32 = 1.0;
|
||||
// let near_centre = ((river_dist / (river_width * 0.5)) as f32).min(1.0).mul(f32::consts::PI).cos().add(1.0).mul(0.5);;
|
||||
// let riverbed_depth = near_centre * river_width as f32 * 0.35 + GORGE;
|
||||
// alt.with_min(river_water_alt - riverbed_depth)
|
||||
// } else {
|
||||
// const BANK_SCALE: f32 = 8.0;
|
||||
// const BANK_STRENGTH: f32 = 100.0;
|
||||
// alt.with(river_water_alt, BANK_STRENGTH / (1.0 + river_edge_dist as f32 * BANK_STRENGTH / BANK_SCALE))
|
||||
// }
|
||||
// },
|
||||
// RiverKind::Lake { .. } => {
|
||||
// let lake_water_alt = Lerp::lerp(
|
||||
// river_chunk.alt.max(river_chunk.water_alt),
|
||||
// downhill_chunk.alt.max(downhill_chunk.water_alt),
|
||||
// river_t as f32,
|
||||
// );
|
||||
// alt
|
||||
// },
|
||||
// _ => alt,
|
||||
// }
|
||||
},
|
||||
(_, _) => alt,
|
||||
},
|
||||
@ -667,7 +685,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let riverless_alt_delta = riverless_alt_delta + (cliff - 0.5) * cliff_height;
|
||||
|
||||
let river_gouge = 0.5;
|
||||
let (_in_water, water_dist, alt_, old_water_level, _riverless_alt, warp_factor) = if let Some(
|
||||
let (_in_water, old_water_dist, alt_, old_water_level, _riverless_alt, warp_factor) = if let Some(
|
||||
(max_border_river_pos, river_chunk, max_border_river, max_border_river_dist),
|
||||
) =
|
||||
max_river
|
||||
@ -920,8 +938,8 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let warp_factor = 0.0;
|
||||
|
||||
let riverless_alt_delta = Lerp::lerp(0.0, riverless_alt_delta, warp_factor);
|
||||
let riverless_alt = alt + riverless_alt_delta; //riverless_alt + riverless_alt_delta;
|
||||
let alt = alt_ + riverless_alt_delta;
|
||||
// let riverless_alt = alt + riverless_alt_delta; //riverless_alt + riverless_alt_delta;
|
||||
let alt = alt/*alt_*/ + riverless_alt_delta;
|
||||
let basement =
|
||||
alt + sim.get_interpolated_monotone(wpos, |chunk| chunk.basement.sub(chunk.alt))?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user