From e5c49af547ad41e5811917e07b1ff307ca8da654 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 14 May 2022 17:00:03 +0100 Subject: [PATCH] Faster, prettier, and less troublesome terrain warping --- world/src/block/mod.rs | 63 ++++++++--------------------------------- world/src/column/mod.rs | 61 +++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 73 deletions(-) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 621b53c89e..b59aa2ff0e 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -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 { diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 3fb174d264..51fe3ab7d1 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -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,