Faster, prettier, and less troublesome terrain warping

This commit is contained in:
Joshua Barretto 2022-05-14 17:00:03 +01:00
parent 8c72ed9012
commit e5c49af547
2 changed files with 51 additions and 73 deletions

View File

@ -71,61 +71,22 @@ impl<'a> BlockGen<'a> {
warp_factor,
surface_color,
sub_surface_color,
//tree_density,
//forest_kind,
//close_structures,
marble: _,
marble_mid: _,
marble_small: _,
rock_density: _,
// temp,
// humidity,
stone_col,
snow_cover,
cliff_offset,
cliff_height,
// water_vel,
ice_depth,
gradient,
..
} = sample;
let wposf = wpos.map(|e| e as f64);
let (_definitely_underground, height, basement_height, water_height) =
if (wposf.z as f32) < alt - 64.0 * chaos {
// Shortcut warping
(true, alt, basement, water_level)
} else {
// Apply warping
let warp = world
.gen_ctx
.warp_nz
.get(wposf.div(24.0))
.mul((chaos - 0.1).max(0.0).min(1.0).powi(2))
.mul(16.0);
let warp = Lerp::lerp(0.0, warp, warp_factor);
let height = alt + warp;
(
false,
height,
basement + height - alt,
(if water_level <= alt {
water_level + warp
} else {
water_level
}),
)
};
// Sample blocks
let water = Block::new(BlockKind::Water, Rgb::zero());
let grass_depth = (1.5 + 2.0 * chaos).min(height - basement_height);
if (wposf.z as f32) < height - grass_depth {
let stone_factor = (height - grass_depth - wposf.z as f32) * 0.15;
let grass_depth = (1.5 + 2.0 * chaos).min(alt - basement);
if (wposf.z as f32) < alt - grass_depth {
let stone_factor = (alt - grass_depth - wposf.z as f32) * 0.15;
let col = Lerp::lerp(
sub_surface_color,
stone_col.map(|e| e as f32 / 255.0),
@ -134,12 +95,12 @@ impl<'a> BlockGen<'a> {
.map(|e| (e * 255.0) as u8);
if stone_factor >= 0.5 {
if wposf.z as f32 > height - cliff_offset.max(0.0) {
if wposf.z as f32 > alt - cliff_offset.max(0.0) {
if cliff_offset.max(0.0)
> cliff_height
- (FastNoise::new(37).get(wposf / Vec3::new(6.0, 6.0, 10.0)) * 0.5
+ 0.5)
* (height - grass_depth - wposf.z as f32)
* (alt - grass_depth - wposf.z as f32)
.mul(0.25)
.clamped(0.0, 8.0)
{
@ -159,12 +120,12 @@ impl<'a> BlockGen<'a> {
} else {
Some(Block::new(BlockKind::Earth, col))
}
} else if wposf.z as i32 <= height as i32 {
let grass_factor = (wposf.z as f32 - (height - grass_depth))
} else if wposf.z as i32 <= alt as i32 {
let grass_factor = (wposf.z as f32 - (alt - grass_depth))
.div(grass_depth)
.sqrt();
// Surface
Some(if water_level > height.ceil() {
Some(if water_level > alt.ceil() {
Block::new(
BlockKind::Sand,
sub_surface_color.map(|e| (e * 255.0) as u8),
@ -184,11 +145,11 @@ impl<'a> BlockGen<'a> {
None
}
.or_else(|| {
let over_water = height < water_height;
let over_water = alt < water_level;
// Water
if over_water && (wposf.z as f32 - water_height).abs() < ice_depth {
if over_water && (wposf.z as f32 - water_level).abs() < ice_depth {
Some(Block::new(BlockKind::Ice, CONFIG.ice_color))
} else if (wposf.z as f32) < water_height {
} else if (wposf.z as f32) < water_level {
// Ocean
Some(water)
} else {

View File

@ -116,7 +116,39 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
.map(|site| index.sites[*site].spawn_rules(wpos))
.fold(SpawnRules::default(), |a, b| a.combine(b));
let gradient = sim.get_gradient_approx(chunk_pos);
const SAMP_RES: i32 = 8;
let altx0 = sim.get_interpolated(wpos - Vec2::new(1, 0) * SAMP_RES, |chunk| chunk.alt);
let altx1 = sim.get_interpolated(wpos + Vec2::new(1, 0) * SAMP_RES, |chunk| chunk.alt);
let alty0 = sim.get_interpolated(wpos - Vec2::new(0, 1) * SAMP_RES, |chunk| chunk.alt);
let alty1 = sim.get_interpolated(wpos + Vec2::new(0, 1) * SAMP_RES, |chunk| chunk.alt);
let gradient =
altx0
.zip(altx1)
.zip_with(alty0.zip(alty1), |(altx0, altx1), (alty0, alty1)| {
Vec2::new(altx1 - altx0, alty1 - alty0)
.map(f32::abs)
.magnitude()
/ SAMP_RES as f32
});
let wposf3d = Vec3::new(wposf.x, wposf.y, alt as f64);
let marble_small = (sim.gen_ctx.hill_nz.get((wposf3d.div(3.0)).into_array()) as f32)
.powi(3)
.add(1.0)
.mul(0.5);
let marble_mid = (sim.gen_ctx.hill_nz.get((wposf3d.div(12.0)).into_array()) as f32)
.mul(0.75)
.add(1.0)
.mul(0.5);
//.add(marble_small.sub(0.5).mul(0.25));
let marble = (sim.gen_ctx.hill_nz.get((wposf3d.div(48.0)).into_array()) as f32)
.mul(0.75)
.add(1.0)
.mul(0.5);
let marble_mixed = marble
.add(marble_mid.sub(0.5).mul(0.5))
.add(marble_small.sub(0.5).mul(0.25));
let lake_width = (TerrainChunkSize::RECT_SIZE.x as f64 * 2.0f64.sqrt()) + 6.0;
let neighbor_river_data = neighbor_river_data
@ -830,7 +862,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
let cliff_offset = cliff * cliff_height;
let riverless_alt_delta = riverless_alt_delta + (cliff - 0.5) * cliff_height;
let warp_factor = water_dist.map_or(1.0, |d| d.max(0.0) / 64.0);
let warp_factor = water_dist.map_or(1.0, |d| (d / 64.0).clamped(0.0, 1.0));
// NOTE: To disable warp, uncomment this line.
// let warp_factor = 0.0;
@ -838,7 +870,11 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
let warp_factor = warp_factor * spawn_rules.max_warp;
let riverless_alt_delta = Lerp::lerp(0.0, riverless_alt_delta, warp_factor);
let alt = alt + riverless_alt_delta;
let warp = ((marble_mid * 0.2 + marble * 0.8) * 2.0 - 1.0)
* 15.0
* gradient.unwrap_or(0.0).min(1.0)
* warp_factor;
let alt = alt + riverless_alt_delta + warp;
let basement =
alt + sim.get_interpolated_monotone(wpos, |chunk| chunk.basement.sub(chunk.alt))?;
// Adjust this to make rock placement better
@ -864,25 +900,6 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
.clamped(0.0, 1.0),
);
let wposf3d = Vec3::new(wposf.x, wposf.y, alt as f64);
let marble_small = (sim.gen_ctx.hill_nz.get((wposf3d.div(3.0)).into_array()) as f32)
.powi(3)
.add(1.0)
.mul(0.5);
let marble_mid = (sim.gen_ctx.hill_nz.get((wposf3d.div(12.0)).into_array()) as f32)
.mul(0.75)
.add(1.0)
.mul(0.5);
//.add(marble_small.sub(0.5).mul(0.25));
let marble = (sim.gen_ctx.hill_nz.get((wposf3d.div(48.0)).into_array()) as f32)
.mul(0.75)
.add(1.0)
.mul(0.5);
let marble_mixed = marble
.add(marble_mid.sub(0.5).mul(0.5))
.add(marble_small.sub(0.5).mul(0.25));
// Colours
let Colors {
cold_grass,