180 lines
10 KiB
Markdown
180 lines
10 KiB
Markdown
# 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` | 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 |
|
||
| `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 |
|
||
| mesas à -24 m, tranchée fente 6 m de |
|
||
| 28 m de large, 24 m de large, 20 m |
|
||
| profond, gradins 2,5 m, de profond, |
|
||
| fond ridé entre buttes |
|
||
| [départ] |
|
||
| SW : chaos de blocs SE : éperons |
|
||
| 80 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 ≥ 20 m sous la mesa, fond plat à ± 1 m sur 10 m, paroi ≥ 60°
|
||
quelque part sur une transversale, ≥ 2 replats de gradin) ; crevasse
|
||
(fond ≥ 16 m sous les bords, largeur au fond ≤ 8 m) ; 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 (drop ≥ 20 m entre deux points de
|
||
part et d'autre) ; 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 : PNG de prévisualisation du showcase sous `docs/briefs/captures/`.
|
||
|
||
## 8. Décisions laissées à Olivier
|
||
|
||
1. **Résolution** : le showcase est cuit à 1,0 m par cellule (crevasse de 6 m
|
||
lisible). 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.
|