COAST. The task's premise -- "the island edge is the steepest part" -- is
right, and the diagnostic locates it precisely: it is the SEABED, not the
land. HeightCurve.Apply returns early at and below sea level, so tasks
05-09 reshaped the land and never touched the water. Measured on the same
seed, distance-from-shore vs height:
land reaches 10 m seabed reaches 10 m gradient
curve OFF 31 px 31 px 0.254/0.258
curve ON (ships) 186 px 31 px 0.038/0.258
So the landward side is ALREADY the broad shallow shelf terrain_design.md
asks for -- 54% of the island sits under 14 m -- and flattening it further
would only make it mushy. What is left is a shoreline that shelves gently
on land and then drops 6.7x steeper the moment it goes under.
CoastShelf fixes that side: depth' = depth * (1 - 0.775*exp(-depth/100 m)).
The seabed leaves the waterline at 22.5% of its former gradient and
recovers smoothly, so deep water and the Trench keep their shape. Measured
after: 5 m depth at 43 px (was 15), 10 m at 75 (was 31), 30 m at 150 (was
94) -- a 2.4-2.9x wider shallows.
It is strictly positive for positive depth, so it CANNOT move the waterline
by one pixel. Biomes and water bodies come out bit-identical, which is why
the coast is separable from elongation in the batch rather than tangled
with it -- contrary to the task's expectation that all coast work moves
biomes.
ELONGATION. IslandAxisX/Y replace the 1.15/0.90 literals (the spine shares
AxisX, as it always shared the literal). Sized by replaying candidate
falloffs against real terrain rather than guessing -- the replay reproduces
the shipped extents exactly, bbox and land count.
That replay says the task's suggested 1.30/0.85 buys +2.0% aspect, because
THE ISLAND IS ALREADY TRENCH-CLAMPED IN X: it spans 90.5% of the map width,
and 1.15 -> 1.40 moves the west coast only 393 -> ~360 px. Aspect responds
almost entirely to AxisY, which costs land:
1.30/0.85 +2.0% aspect +2.9% land 1.30/0.80 +4.9% -2.2%
1.30/0.82 +3.7% aspect -0.1% land 1.30/0.75 +11.5% -7.3%
Default 1.30/0.78 -- a visible step (+~8% aspect, measured 1.137 -> 1.200)
at ~4% land. The developer's eye tunes it from the batch; the table above
is the price list.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
61 lines
3 KiB
C#
61 lines
3 KiB
C#
using Godot;
|
|
|
|
/// <summary>
|
|
/// The island-falloff shaping functions (terrain-water task 11) — pure numeric
|
|
/// functions of their inputs (D-035; a named future C++ candidate, kept standalone).
|
|
///
|
|
/// SMOOTH CREST — the mountain spine's ridge axis is the line x = centre, and
|
|
/// `1 - |x - cx|` peaks there with a slope discontinuity. Measured on the shipped
|
|
/// terrain, that crease is the single largest slope step anywhere on the map once
|
|
/// the by-design Trench walls are excluded (top 4 of 5999 columns). SmoothAbs
|
|
/// rounds the crest without moving its height.
|
|
///
|
|
/// COAST SHELF — the height curve is identity at and below sea level, so it never
|
|
/// touched the SUBMARINE slope. Measured: land rises from the shoreline at
|
|
/// 0.038 m/px while the seabed drops at 0.258 m/px — the shoreline is a shelf on
|
|
/// the land side and a ramp on the sea side. CoastShelf compresses shallow depth
|
|
/// so the shallows extend much further out, leaving deep water and the Trench
|
|
/// essentially untouched.
|
|
///
|
|
/// Every one of these is monotone in the sign of (sea - height): none of them can
|
|
/// turn water into land or land into water on its own. The coast shelf therefore
|
|
/// leaves the biome and water classification bit-identical, which is why it is
|
|
/// separable from elongation in the batch.
|
|
/// </summary>
|
|
public static class IslandFalloff
|
|
{
|
|
// ---- centre-line crest ------------------------------------------------
|
|
// Rounding radius in normalized spine-width units (1.0 = MapSize/2 * IslandAxisX
|
|
// ~ 4710 px at 8K with the default axis). 0.03 ~ 141 px: it cuts the crest's
|
|
// 1-px kink by 99.3% (-7.64e-04 -> -5.41e-06 raw) while filling at most 3.9 m,
|
|
// decaying under 0.5 m by ~1100 px from the axis.
|
|
public const float CREST_EPSILON = 0.03f;
|
|
|
|
/// <summary>
|
|
/// A C¹ stand-in for |d|: exactly 0 with zero slope at d = 0, and converging to
|
|
/// |d| within e²/(2|d|) away from it. Replaces the V-shaped crest of the spine
|
|
/// with a rounded one WITHOUT lowering it — SmoothAbs(0) is 0, so the peak keeps
|
|
/// its full height.
|
|
/// </summary>
|
|
public static float SmoothAbs(float d, float epsilon)
|
|
{
|
|
float a = Mathf.Abs(d);
|
|
return a * a / Mathf.Sqrt(a * a + epsilon * epsilon);
|
|
}
|
|
|
|
// ---- coast shelf ------------------------------------------------------
|
|
// depth' = depth * (1 - STRENGTH * exp(-depth / SCALE_M)).
|
|
// At the shoreline the seabed starts at (1 - STRENGTH) of its former gradient and
|
|
// recovers smoothly, so the shallows widen and the deep ocean keeps its shape.
|
|
// C^inf everywhere, and strictly positive for positive depth — it cannot move the
|
|
// waterline by even one pixel.
|
|
public const float SHELF_STRENGTH = 0.775f; // 0 = off, ->1 = a flat lagoon
|
|
public const float SHELF_SCALE_M = 100f; // metres of depth over which it relaxes
|
|
|
|
/// <summary>Remaps a positive depth in metres. Returns the new depth in metres.</summary>
|
|
public static float CoastShelf(float depthMetres)
|
|
{
|
|
if (depthMetres <= 0f) return depthMetres;
|
|
return depthMetres * (1f - SHELF_STRENGTH * Mathf.Exp(-depthMetres / SHELF_SCALE_M));
|
|
}
|
|
}
|