Commit graph

5 commits

Author SHA1 Message Date
fdf52f61ee Phase 1 review: raw grayscale, the wide gradient as hero, fixed batch naming
Presentation only. No generation file is touched — Topography, TerrainNoise,
IslandFalloff, Pass1Result, TerrainGenConfig and GenerationScale are all unchanged.

Batch naming, fixed in code. The prefix is the AUTHORING TASK number, not a running
counter: 04_review means "the batch task 04 authored", not "the fifth batch". It had
already drifted — tasks 02 and 03 produced 00_smoke through 05_trophy_10240 across
two tasks, so no folder name said which task made what. Now the task number is an
explicit argument to ToolingPaths.BatchRoot(taskNumber, descriptor), which composes
the prefix itself and REFUSES a descriptor that carries its own. All three tools
take it as ISLA_TASK. Verified: ISLA_BATCH=05_foo is refused with a stated reason
and exit 2, and creates no folder.

Also fixed: an exception out of _Ready does not stop Godot — it logs and the process
sits there with no main loop, so a misconfigured run HUNG rather than failing. A
hang looks like slow work, which is worse than a crash. The batch tools now catch,
print what was refused, and exit non-zero.

Grayscale mode: normalize a field to its own [min,max]. This is the one place
per-image normalization is correct — everywhere else anchors are fixed so images
compare, but here the point is to see one field at full contrast. The range is
printed and indexed so a shade reads back to a height. You cannot judge noise
through a palette: a ramp bends the distribution, a hillshade adds shape the data
does not have.

The wide Costa-Rica palette, and the reframing the developer asked for: the pretty
map is the WIDE GRADIENT RENDERED FLAT, and relief is no longer the hero. On raw
pass-1 noise a hillshade has nothing coherent to shade, so it renders fine fractal
bumpiness as fuzz that actively hides the elevation the colour is showing. Strong
hillshade is retained as diagnostic_relief and labelled a dev view — its bumpiness
is exaggerated slope, not extra terrain. Subtle relief is kept for comparison, with
the honest note that it still fuzzes until Phase 2 carves coherent landforms.

Legend: a colour bar with ticks drawn from the palette's own ramp, so it cannot
drift from the map beside it. Ticks are RELATIVE height and the image says NOT
METRES — the conversion is Phase 2's, and labelling it "m" would invent a fact in
the artefact a reader most trusts. Text comes from a 5x7 bitmap font written for
this, specifically so a legend does not drag in the SubViewport capture path.
2026-08-19 22:55:53 -04:00
b1cf282295 Phase 1: shaded relief and the Hispaniola palette — the grin gate
Presentation only. Nothing here touches Topography, the noise, or any generation
constant; the renderer is handed a height field LOADED from a .f32 dump and has no
way to produce one, so a look change provably cannot move the terrain.

Hillshade: Horn 3x3, cell size 1, edges clamped (never wrapped — the Trench border
is a wall, not a seam). ZExaggeration is required rather than optional: measured
median land slope is 0.22 degrees unexaggerated, so the island shades as a flat
plane. Chosen from a measured slope table — zex 75 gives 16/28/37 deg at land
median/p90/p99, which reads as natural relief. It is a look dial; raw units are not
metres and no code may read it as if they were.

Palette: stops placed on the MEASURED height distribution, not spread linearly.
Land is bottom-heavy (median 0.456, p99 1.113, max 1.415 over 8.6M land columns
across four seeds), so a linear ramp would spend 99% of its range on 1% of the land
and the map would read as green with a few white dots. Bathymetry is compressed by
d/(d+0.35) so the shallow shelf gets the range and the featureless abyss flattens.
Anchors are absolute and fixed across the batch — a map coloured on its own min/max
cannot be compared with its neighbour, and comparison is the point of a batch.

Blend: the naive tint x hillshade darkens everything by 29% before any slope is
involved, because flat ground shades to sin(altitude). So shade is normalized by
its flat-ground value first — flat terrain keeps its true tint and only SLOPE moves
the colour — then shadows multiply while highlights screen toward white. That
asymmetry is the difference between a colour ramp and a map you would frame.

Relief fades to zero with depth below sea. Not only taste: the deep floor is the
Trench, a synthetic wall whose gradient is ~1.5x the p99 land gradient, so shading
it faithfully draws a bright rim around the map and lights the abyss with noise
mottle. The fade puts relief on the near-shore shelf where the bathymetry is real.

Three named looks (atlas / relief / dusk), gated like any other change and kept
deliberately few — iteration fatigue on a subjective gate is a real failure mode.
Each pair isolates one question.

HeightMapRenderer.cs is retired: its raw I/O moved to HeightField.cs and its ramp
to ReliefPalette.cs, so there is one palette everywhere and the generator's own
quick-look is coloured identically to a beauty render.

No biome words, no classification, no water. The 0.15 line is a colour boundary.
2026-08-19 21:58:44 -04:00
b60d78b752 Move the user:// isolation warning out of project.godot
Godot rewrites project.godot on import and strips all comments, replacing the
header with its own boilerplate. The isolation SETTINGS survived — name,
use_custom_user_dir and custom_user_dir_name are intact and the probe still
passes — but the block explaining why they must not be touched was deleted.

A comment there is therefore not a durable place for a warning. The warning
moves to README.md, which records the behaviour so nobody puts it back, and the
actual guarantee stays where it was always enforced: UserDirProbe, which exits
non-zero if user:// ever resolves to the old prototype's directory.

Also drops the now-empty [rendering] section the rewriter removed as redundant
(forward_plus is already declared in config/features).
2026-08-19 21:31:12 -04:00
9af5c73b04 Phase 1: port the crown-jewel noise and pass-1, and render the island
Ports MapGenerator.GenerateTopography's pass-1 loop (reference ~:553-619 at tag
pre-rewrite-reference / ab78883) into Tools/. Working code and its tuned constants
carried over verbatim, read from source rather than re-derived from a design
summary (D-050). Six elements, in the reference's execution order — the order is
load-bearing: the sinker lands before the Pow (superlinear), the Trench after it
(a raw additive wall), preTrenchFalloff captured between them.

The fractal config is now PINNED. The reference set only NoiseType/Seed/Frequency,
so the island's entire fractal character was Godot 4.7.1 constructor defaults that
nothing recorded. Measured on 4.7.2 (NoiseDefaultsProbe): Fbm / 5 / 0.5 / 2.0 / 0.0
— identical to the 4.7.1 values, so pinning reproduces the look with no delta. The
terrain no longer depends on an engine default, and the probe makes a future drift
visible instead of silent.

Two deliberate departures from the reference's literals, both flagged in-code:
  - the latitude noise offset is expressed in map widths, not the reference's raw
    +1000 px, so a resize no longer samples a different slice of the noise field
    (chat1/00 §4.2). Pinned to 1000/8192 so the 8K realization is unchanged.
  - the `if (temperature < 0.65f)` spine gate is dropped as the provable no-op it
    is — southernFade already reaches exactly 0 at 0.65. Bit-identical.

The reference's "temperature" is ported as a latitude field and deliberately NOT
named temperature: it is stage-1-local input to terrain geometry, and climate is
stage 3 (D-049 §2, D-056). The ±0.1 wobble is kept — it is what stops the spine's
southern terminus being a ruler-straight line.

Deferred to Phase 2 with the seam open: coast shelf and offshore islets (below-sea,
judged once water renders). Pass1Result exposes PreTrenchFalloff at their exact
consumption point, plus HMaxSeed for the seed-dependent curve.

Render is a direct Godot.Image, not the SubViewport capture path — that machinery
exists to composite vector overlays and is why --headless hangs; Phase 1 has none.
Hypsometric above 0.15, bathymetric below, fixed ramp anchors so seeds and ablation
rungs are comparable. No biome words anywhere.

Verified: land fraction 51.5% identical at 1024, 2048 and 10240 — the scaling
discipline holds across a 10x resize. Full-size 10240 pass: 36.3 s.

No curve, erosion, rivers, water, crater, biomes, roads, or mesher.
2026-08-19 21:27:20 -04:00
9107b0822b Phase 0: clean project skeleton for the v2 rewrite
Stands up the CODE_REPO the rewrite is written into (D-049, D-058). Godot 4.7.2 /
.NET 8 / Godot.NET.Sdk 4.7.2. Nothing is generated, meshed, or ported — this is the
shell and the two data contracts.

Four layers, each with its boundary stated in a directory README:
  Core/    math + data only, and engine-free — depends on nothing above it
  Server/  authoritative logic                (empty this phase)
  Client/  rendering                          (empty this phase)
  Tools/   the offline generator — may NOT reference Client   (Phase 1 fills it)

Contracts (compiling stubs, no algorithms):
  - Column model (D-053): a 2D grid of columns, each a stack of (material, thickness)
    runs, any material at any depth. Air is the TOP RUN — there is no air-vs-solid
    height branch, and no surface-height accessor exists to reintroduce one. Water is
    not a band; it stays an overlay.
  - Material schemas (D-054): terrain and building as two append-only registries,
    bridged by a recipe seam that is deliberately EMPTY. Identity is a registry key,
    never a serialized ordinal. Mesh style is per-ORIGIN and is not a material field.

Rails, so Phase 1 inherits them rather than rediscovering them:
  - GenerationScale: MapSize is a parameter, everything derives from it, nothing uses
    a raw pixel number. Tightening over the reference — decorrelation offsets are
    declared in map widths, not pixels (chat1/00 §4.2).
  - ToolingPaths: config/blueprint/output paths all env-overridable, resolved in one
    place, so a batch cannot touch the developer's live files.
  - FileSafety: the permanent no-deletion rules as throws rather than sentences.

user:// isolation: project name and use_custom_user_dir both pin the runtime dir to
~/.local/share/islaApocalypse-v2/, away from the old prototype's preserved seeds and
batches. Tools/Scenes/UserDirProbe.tscn confirms it rather than assuming it.
2026-08-19 20:21:12 -04:00