Files
Ransom-s-wake/docs/briefs/terrain-varied-landforms.md
T
OlivierandClaude Fable 5.1 48e054557c
Quality Gate / Quality Gate (pull_request) Failing after 3m18s
feat(world): volumetric coral heads on patch reefs
Three procedural coral head meshes (boulder, brain-ridged, lobed domes on
a flat base, vertex-shaded crevices) are scattered on gentle rock between
12 and 40 m, clustered by noise, one MultiMesh per tile and variant, with
an opaque shader under the shared water column. The coral assertions
run on the Banc du Vigilant, whose patch reef lies in the lit band.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 08:22:09 +02:00

206 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Proposition — formes de relief variées pour les sites de plongée
**Statut : exécuté en autonomie le 2026-10-06** sur demande d'Olivier
(« implémente ce genre de terrains variés, terrain statique, ne te concentre que
sur le terrain, pas les effets de rendu ou la végétation »). Les décisions
ouvertes sont listées en §8.
Rédigée à partir de cinq photos de référence fournies par Olivier, de l'ADR
0012, de `tools/site_terrain_baker.gd` et du brief
`docs/briefs/terrain-site-zone1-gameplay.md`.
---
## 1. Objectif
Étendre le vocabulaire de formes du script de cuisson pour que les sites
suivants (U-Boot « sous falaise », navire océanographique « dans un canyon »,
GDP §15) puissent être authorés avec le même pipeline que le Banc du Vigilant :
canyons à parois raides et strates, crevasses étroites, éperons et chaos de
blocs, buttes rocheuses, falaises sinueuses. Terrain statique, surface unique
(ADR 0010), aucun changement de rendu ni de végétation.
Terminé quand :
- chaque forme des cinq références a une primitive nommée, testée unitairement,
dans `tools/site_terrain_baker.gd` ;
- un site de démonstration cuit (`content/sites/terrain_showcase.tres`) montre
les cinq formes côte à côte, se charge en moins de 3 s et passe des tests de
contrat géométriques (profondeur, pente, largeur, matériau) ;
- le Banc du Vigilant est cuit à l'identique (aucun octet de
`zone1_vigilant_terrain.res` ne change) ;
- `bash scripts/quality_gate.sh` passe.
## 2. Lecture des références
| Photo | Ce qu'on voit | Forme de relief | Ce qu'un champ de hauteur peut en garder |
|---|---|---|---|
| 1 | Deux masses rocheuses alvéolées encadrant un chenal de sable grossier | éperons rocheux + chenal | deux buttes aux bords irréguliers, chenal plat entre elles, rugosité forte sur la roche |
| 2 | Fente très étroite et profonde entre deux parois quasi verticales | crevasse | sillon de 5–6 m de large, 20 m de profondeur, parois à 80°+ ; pas de surplomb |
| 3 | Pente de mamelons rocheux arrondis | mamelons | buttes à flancs doux sur une pente, rugosité moyenne |
| 4 | Canyon aux parois verticales **stratifiées**, fond de sable plat **ridé**, mesas en haut | canyon à strates | tranchée à fond plat, parois raides quantifiées en gradins horizontaux, rides sur le fond, plateaux sommitaux |
| 5 | Platier : têtes de corail et blocs épars sur sable ridé | chaos de blocs | champ de demi-ellipsoïdes de 2–6 m de rayon, matériau roche, sable ridé entre |
Hors périmètre, volontairement : lumière, caustiques, couleur de l'eau,
herbier, corail (rendu et végétation).
## 3. Ce qui existe et ce qui manque
Le cuiseur additionne des primitives `elevation_delta(x, z)` puis déduit le
matériau de la pente (roche au-dessus de 20°) et applique des `MaterialPatch`
circulaires. Les primitives actuelles (`SlopedPlane`, `Blob`, `Ridge`,
`Groove`, `Step`, `Ripples`, `Roughness`) sont toutes **lisses** (gaussiennes
ou `smoothstep`) et **mono-segment**. Il manque :
1. des **tracés en polyligne** (canyon, crevasse, falaise sinueuse) ;
2. des **bords irréguliers** (bruit de contour) pour casser l'aspect « gaussien » ;
3. des **formes à sommet plat et flancs raides** (butte, mesa) ;
4. des **champs d'objets discrets** combinés par maximum, pas par somme
(blocs qui ne fusionnent pas en bosse) ;
5. une phase de **modification** après la somme, qui connaît la pente locale,
pour quantifier les parois en **strates** ;
6. un **matériau imposé par une primitive** (un bloc est roche même sur son
sommet plat).
## 4. Décision : extension du cuiseur
### 4.1 Contrat
- `Primitive.elevation_delta(x_m, z_m) -> float` : inchangé, additif.
- `Primitive.material_at(x_m, z_m) -> int` : nouveau, renvoie
`NO_MATERIAL` (-1) par défaut ; une valeur `SonarMaterial.Value` l'emporte sur
la règle de pente, dans l'ordre des primitives, avant les `MaterialPatch`.
- `Modifier.modify(x_m, z_m, elevation_m, gradient) -> float` : nouvelle phase.
`gradient` est la pente locale `Vector2(dE/dx, dE/dz)` calculée par
différences centrées sur le champ courant ; les modificateurs s'enchaînent
dans l'ordre de `Recipe.modifiers`, après la somme et avant le plancher.
- Ordre de cuisson : somme des primitives → modificateurs → plancher
`floor_elevation_m` → matériau par pente → matériau par primitive →
`MaterialPatch`.
### 4.2 Nouvelles primitives
| Primitive | Paramètres | Forme |
|---|---|---|
| `Canyon` | `path: PackedVector2Array`, `half_width_m`, `depth_m`, `wall_softness_m`, `edge_seed`, `edge_amplitude_m`, `floor_material` | tranchée à fond plat le long d'une polyligne ; parois `smoothstep` sur `wall_softness_m` ; distance au tracé perturbée par un bruit de contour ; se referme sur une demi-largeur à chaque bout ; impose `floor_material` (sable en général) sur le fond plat, même à travers une butte rocheuse |
| `Outcrop` | `centre`, `radius_x_m`, `radius_z_m`, `height_m`, `wall_width_m`, `edge_seed`, `edge_amplitude_m`, `rock_top` | butte elliptique à sommet plat, flanc de largeur `wall_width_m`, contour perturbé ; matériau roche partout où elle dépasse 30 % de sa hauteur si `rock_top` |
| `BoulderField` | `centre`, `radius_m`, `seed`, `count`, `boulder_radius_min_m`, `boulder_radius_max_m`, `height_ratio`, `angularity` (0–1) | `count` blocs tirés par `RandomNumberGenerator` seedé dans le disque, combinés par **maximum** ; roche sur toute leur emprise ; `angularity` 0 = demi-ellipsoïdes, 1 = dalles en super-ellipse allongées, orientées et basculées au hasard, sommet plat et épaules vives |
| `Escarpment` | `path: PackedVector2Array`, `drop_m`, `softness_m`, `slope_beyond`, `edge_seed`, `edge_amplitude_m` | `Step` le long d'une polyligne : le terrain descend à **droite** du sens de parcours ; ligne de crête perturbée par un bruit de contour |
### 4.3 Nouveau modificateur
| Modificateur | Paramètres | Effet |
|---|---|---|
| `Strata` | `layer_height_m`, `sharpness` (0–1), `minimum_slope_degrees`, `full_slope_degrees`, `region_m: Rect2` (vide = partout), `dip`, `warp_seed`, `warp_amplitude_m`, `thickness_variation` | quantifie l'élévation en gradins d'environ `layer_height_m` là où la pente dépasse `minimum_slope_degrees` (plein effet à `full_slope_degrees`) ; `sharpness` 0 = aucun effet, 1 = marches franches ; le fond plat et le plateau ne bougent pas ; `dip` incline la pile, le warp courbe et encoche les bancs, chaque banc a son épaisseur et sa dureté, les bornes restent ordonnées (pas d'inversion) |
Formule : `f = frac(e / h)`, `f' = clamp((f - 0.5) / (1 - s) + 0.5, 0, 1)`,
`e' = lerp(e, floor(e / h) * h + h * f', w)` avec
`w = smoothstep(tan(min), tan(full), |gradient|) * masque`.
### 4.3 bis Relief de fond (ajout du 2026-10-06, demande d'Olivier)
Les plateaux cuits avec la seule `Roughness` à 50 m (± 0,6 m) restaient
plats. `Roughness` prend maintenant un nombre d'octaves et un type fractal
(`FRACTAL_FBM` roulant, `FRACTAL_RIDGED` à crêtes) : une fréquence de 0,004
sur cinq octaves donne des mamelons et des cuvettes de 250 m à 15 m en une
primitive. Le modificateur `SlopeRoughness` (`seed`, `frequency`,
`amplitude_m`, `minimum_slope_degrees`, `full_slope_degrees`) ajoute un bruit
à crêtes pondéré par la pente : la roche s'éraille, le sable reste lisse. Les
deux sites l'utilisent (ondulation ± 2,2 m, roche ± 0,7 m).
### 4.4 Ce qui ne change pas
Le contrat de données (`SiteTerrainData`, ADR 0012 §2), l'acteur de monde, la
collision, le sonar, le shader. Les `.res` restent les artefacts dérivés ; la
recette reste le document d'auteur. Le bruit de contour est un
`FastNoiseLite` seedé, donc déterministe.
## 5. Site de démonstration : `terrain_showcase`
But : prouver chaque forme en jeu et au sonar, servir de catalogue pour
l'auteur des sites suivants. Pas un site de mission : un seul placement
(balise de mouillage), aucune épave, aucune route.
| Donnée | Valeur |
|---|---|
| Champ | 513 × 513 cellules, 1,0 m, origine (-256, -256) |
| Zone jouable | 440 × 440 m centrée |
| Plateau de base | 30 m, incliné de 4 m vers le sud |
| Profondeur min / max | 18 m / 80 m |
| Départ | (0, -12, 0), cap nord |
Plan de masse (nord en haut) :
```text
+---------------------------------------------+
| NW : canyon à strates NE : crevasse |
| mesa à -24 m, tranchée fente 6 m de |
| 28 m de large au sommet, large, 20 m |
| 20 m de profond, parois à de profond, |
| 55°, gradins 4 m, fond ridé entre buttes |
| [départ] |
| SW : chaos de blocs SE : éperons |
| 90 blocs r 2–6 m sur deux buttes |
| sable ridé alvéolées, |
| chenal 20 m |
| ====== falaise sinueuse (Escarpment) ===== |
| tombant vers -80 m, mamelons sur la pente |
+---------------------------------------------+
```
## 6. Tests
- **Unitaires (`run_site_baker_tests.gd`)** : `Canyon` (fond plat à la
profondeur demandée, nul hors tracé, suit le coude d'une polyligne,
fermeture aux bouts) ; `Outcrop` (sommet à `height_m`, roche sur le sommet
si `rock_top`, nul à deux rayons) ; `BoulderField` (déterministe, nul hors
disque, roche sur un bloc, maximum et non somme) ; `Escarpment` (côté droit
plus bas, drop égal à `drop_m`) ; `Strata` (une pente raide devient des
gradins : au moins deux niveaux plats ; un fond plat ne bouge pas) ;
cuisson du Banc du Vigilant identique à l'artefact versionné.
- **Contrat (`run_site_content_tests.gd`, section showcase)** : canyon
(profondeur ≥ 18 m sous le sommet bruité de la mesa, fond de sable plat à
± 1 m sur 10 m, paroi ≥ 60° quelque part sur une transversale, ≥ 2 replats
distincts) ; crevasse (fond de sable ≥ 16 m sous le plateau ouvert, 3 à 8 m
de large à 10 m sous le plateau) ; chaos (roche sur un
bloc, sable entre deux blocs, ≥ 40 cellules de roche distinctes… mesuré par
fraction de roche dans le disque) ; éperons (chenal plus bas que les deux
buttes, roche sur chaque butte) ; falaise (marche ≥ 18 m mesurée dans la
seule bande de crête, pour que la pente en contrebas ne masque pas une
marche absente) ; bornes et profondeurs globales.
- **Intégration (`run_site_terrain_integration.gd`)** : chargement du showcase
sous 3 s, rayon dans le canyon plus bas que sur la mesa, scan de référence
lisant roche et sable.
## 7. Documentation
- ADR 0012 : amendement §3 (liste des primitives, phase de modification,
matériau par primitive), sans changer le contrat de données.
- `content/README.md`, `tests/README.md` : le site de démonstration.
- Captures sous `docs/briefs/captures/` : `terrain_showcase_terrain_preview.png`
(champ de hauteur vu de dessus, roche teintée) et cinq vues en jeu, graybox,
`terrain_showcase_canyon.png` (gradins et fond ridé), `_crevasse.png`,
`_boulders.png`, `_spurs.png`, `_escarpment.png` (face de la falaise vue du
pied) ; pour le Banc du Vigilant recuit, `zone1_vigilant_tombant.png`
(gradins du tombant), `zone1_vigilant_plateau.png` (plateau ondulé) et
`zone1_vigilant_patch_reef.png` (têtes de corail autour du caboteur). Les
captures sont faites avec le shader à normal maps et ombrage de détail
(brief du Banc du Vigilant, §7) ; brouillard et lumière restent ceux de la
scène de site.
## 8. Décisions laissées à Olivier
1. **Résolution** : le showcase est cuit à 1,0 m par cellule (crevasse de 6 m
lisible). Les gradins imposent une paroi d'au moins 2 à 3 cellules par
couche : à 1 m par cellule, des couches de 4 m sur une paroi à 55° ; une
paroi à 76° (première cuisson) ne montrait aucun gradin. Les sites de mission restent à 1,5 m sauf décision contraire ; une
crevasse de 5 m à 1,5 m par cellule n'a que trois cellules de large.
2. **Strates sur le Banc du Vigilant** : décidé par Olivier le 2026-10-06,
appliquées à la rupture et au tombant (bande z ≥ 118 m, couches de 4 m,
plein effet dès 40° ; la Saignée, l'Échine et les amers sont hors bande).
Le `.res` du site a été recuit ; l'objet secondaire, les débris et les
routes restent dans leurs contrats.
3. **Sites de mission suivants** (U-Boot sous falaise, océanographique en
canyon) : les primitives sont prêtes ; le plan de masse de chaque site
reste à proposer et valider séparément.