docs: ADR 0012 authored heightfield dive sites

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
OlivierandClaude Fable 5.1 committed 2026-10-06 19:36:31 +02:00
1 parent 79484643a2
commit 4da0ce3525
1 file changed
+68
@@ -0,0 +1,68 @@
# 0012 — Sites de plongée en champ de hauteur authoré
- Statut : accepté
- Date : 2026-10-06
- Remplace : aucun
## Contexte
Le seul terrain de production est une formule analytique codée dans
`vehicle_test_environment.gd`. La tranche 3 exige un site conçu à la main,
lisible au sonar (ADR 0010 : surface unique), avec une route sûre et une route
risquée, et le sonar a besoin de distinguer roche et sable par cellule, pas par
corps. Il faut un contrat de données pour le terrain, son stockage dans le
dépôt et sa production.
## Décision
1. Un site de plongée est décrit par une ressource typée `DiveSiteDefinition`
(`game/domain/sites/`) : identifiant, terrain, limites jouables, point de
départ, placements d'objets et routes de contrôle.
2. Le terrain est un champ de hauteur à surface unique `SiteTerrainData` :
grille régulière de `columns × rows` cellules de `cell_size_m` mètres,
élévations en mètres (axe Y monde, négatif sous la surface) dans un
`PackedFloat32Array`, matériau sonar par cellule dans un `PackedByteArray`
(`SonarMaterial.Value`, ROCK ou SAND). Repère : +X est, +Z sud, +Y haut ;
la colonne croît avec +X, la ligne avec +Z ; la cellule `(0, 0)` est à
`(origin_x_m, origin_z_m)`.
3. Les données sont cuites hors exécution par `tools/bake_site_terrain.gd` à
partir d'une recette déclarative de primitives géomorphologiques nommées
(plateau, crête, piton, sillon, rupture de pente, rides, rugosité
déterministe par graine). La recette est le document d'auteur versionné ;
le résultat est écrit en `.res` binaire sous `content/sites/`. Le jeu ne
génère jamais de terrain à l'exécution.
4. Un PNG 16 bits n'est pas utilisé pour les hauteurs : le chargeur d'images
de Godot ramène les PNG 16 bits en 8 bits, soit des marches de 0,27 m sur
68 m de dénivelé. Un PNG 8 bits de prévisualisation est produit pour la
revue humaine seulement.
5. Un seul acteur de monde, `BathymetricTerrainActor`, construit le maillage
visuel et la `HeightMapShape3D` depuis le même champ ; un test compare les
deux. Il expose `sonar_material_at(position)` et
`sonar_reflectivity_at(position)` que l'acquisition sonar privilégie sur
les métadonnées de corps.
6. Les limites de la zone jouable sont une règle applicative
(`PlayableBoundsRule`) qui produit un avertissement ; elles ne sont jamais
un mur de terrain (ADR 0010).
## Conséquences
- L'environnement de test du véhicule devient une définition de site cuite,
sans formule analytique dans `game/`.
- Toute modification de terrain passe par la recette puis une cuisson ; les
fichiers `.res` sont des artefacts dérivés mais versionnés pour que le
chargement du site reste sous 3 s et que le jeu n'ait pas besoin de l'outil.
- Les tests de contrat de contenu peuvent vérifier profondeur, position et
dégagement des placements contre le champ de hauteur réel.
- Une sculpture manuelle (Blender) ultérieure devra ré-exporter vers le même
`SiteTerrainData` ; le contrat ne change pas.
## Alternatives considérées
- **Plugin de terrain externe** : rejeté, dépendance et ADR supplémentaires
sans besoin démontré ; une heightmap tuilée suffit à la V1.
- **Génération à l'exécution depuis la recette** : rejeté, le plan impose un
site conçu à la main et un chargement borné ; la cuisson garantit un
artefact figé et revu.
- **Heightmap PNG 16 bits** : rejeté pour la raison de précision ci-dessus.
- **Maillage sculpté sans champ de hauteur** : rejeté, le sonar et les tests
ont besoin d'une requête de hauteur et de matériau par position.