Files
Ransom-s-wake/docs/briefs/terrain-varied-landforms.md
T
2026-10-06 22:02:55 +02:00

188 lines
11 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` | `count` demi-ellipsoïdes tirés par `RandomNumberGenerator` seedé dans le disque, combinés par **maximum** ; roche sur toute leur emprise |
| `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`, `centre`, `radius_m` (0 = partout) | quantifie l'élévation en gradins de `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 |
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.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). Le rendu (brouillard, rides en albédo) n'est pas l'objet de ce brief.
## 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 partout ?** Le modificateur est appliqué au canyon seulement.
L'appliquer à la falaise sud du Banc du Vigilant est un changement de
recette, donc de `.res`, donc une re-cuisson à valider.
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.