Files
Ransom-s-wake/docs/briefs/cockpit-modeles-integration.md
OlivierandClaude Opus 5.5 2c1ea50aba
Quality Gate / Quality Gate (pull_request) Successful in 7m6s
feat(cockpit): replace procedural cockpit with twelve scripted models
Instance twelve Blender-scripted glTF models in the cockpit scene and
rebuild the cabin around them: gauge panel, sonar, switch panel, alert
box, speaker, porthole, hull wall, caged lamps, gas bottle, handrails
and side consoles. Presentation only; no domain, application or world
rule changes beyond enabling glow in the test environment.

- Needles, alert lamps and sonar screen are driven by the existing
  snapshots; the alert box now carries SYS/ATTN/ALRM.
- Depth dial reads percent of certified depth.
- Sonar display restyled as a turquoise holographic relief with a
  shader grid and height scale; SubViewport matches the glass (960x604).
- Cabin lighting retuned: warm pooled lamp light, cool porthole rim,
  lamp shadows, dial backlight.
- Procedural stand-ins removed (bulkhead, tanks, consoles, levers,
  indicator columns, placeholder pipe run, dial face PNGs).
- Tests adapted where nodes disappeared; one assertion removed
  (pipe_segment_count) until the pipe kit is placed.
- Model .glb files are committed without LFS; textures Godot extracts
  next to them at import are ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:46:46 +02:00

385 lines
26 KiB
Markdown
Raw Permalink 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.
# Brief — intégrer les cinq modèles du cockpit
**Statut : exécuté.** Ce brief a servi à l'intégration des cinq premiers modèles ; sept autres (hublot, coque, lampe, bouteille, mains courantes, console) ont suivi et la cabine a été reconstruite autour. Il reste comme trace des décisions (section 10) ; l'état réel est celui du code et de `assets/README.md`.
Rédigé le 2026-10-06 à partir d'une lecture du dépôt (code non exécuté, barrière non lancée) et des
modèles produits dans une session Blender séparée. Tout ce qui est marqué « non vérifié » doit être
vérifié avant d'être cru.
---
## 1. Objectif
Le cockpit de production (`game/presentation/cockpit/`) fabrique aujourd'hui tous ses instruments en
code, à partir de primitives. Cinq modèles 3D texturés existent maintenant pour les instruments
principaux. Le travail : les importer, les placer dans `cockpit_interior.tscn` à la place de la géométrie
procédurale qu'ils remplacent, et les brancher sur les mêmes données qu'aujourd'hui, sans déplacer une
seule règle de jeu.
Ce n'est pas une refonte du cockpit. Coque, hublot, équipements latéraux, tuyauterie, lampes en cage,
consoles, leviers et HUD restent tels quels.
Terminé quand :
- les cinq modèles sont dans la scène, à l'échelle, orientés vers la caméra du pilote ;
- les quatre aiguilles, les voyants d'alerte et l'écran du sonar affichent les mêmes données qu'avant ;
- `bash scripts/quality_gate.sh` passe, sans contrôle affaibli ;
- des captures à 1280 × 720 et 1920 × 1080 sont jointes, à côté de
`docs/visual_targets/cockpit-objective-v1.jpg`.
## 2. À lire avant de toucher au code
Obligatoire par `AGENTS.md` : `docs/ENGINEERING_GUARDRAILS.md`, puis :
- `docs/adr/0004-forward-plus-only.md` — matériaux PBR, post-traitement en réglage de qualité ;
- `docs/adr/0006-sonar-contract-and-acquisition-gate.md` — une seule texture sonar, un seul renderer ;
- `docs/adr/0008-composition-owned-service-lifetimes.md` — la composition câble, la présentation affiche ;
- `docs/visual_targets/README.md` et l'image cible ;
- `docs/VERTICAL_SLICE_TECHNICAL_PLAN.md` L823-842 — hiérarchie visuelle du cockpit, ce qui relève de la
tranche 6 ;
- `game/presentation/cockpit/assets/README.md` — registre de provenance, à compléter.
## 3. Les cinq modèles
### 3.1 Où ils sont
Copiés le 2026-10-06 dans `game/presentation/cockpit/assets/models/`, **non suivis par git** (décision 8 :
ne pas les commiter sans l'accord d'Olivier). Jamais ouverts dans Godot.
| Fichier | Poids | Pièce |
|---|---|---|
| `gauge_panel.glb` | ~20 Mo | tableau de jauges |
| `sonar.glb` | ~15 Mo | écran sonar |
| `switch_panel.glb` | ~16 Mo | panneau d'interrupteurs |
| `alert_box.glb` | ~4,5 Mo (atlas 1024²) | boîtier d'alerte à trois voyants |
| `speaker.glb` | ~4,5 Mo (atlas 1024²) | boîtier haut-parleur |
Les sources (scripts Blender, `.blend`) restent dans un dossier temporaire de session, hors dépôt :
`C:\Users\olivi\AppData\Local\Temp\claude\C--Users-olivi-Projects-Ares-Shift--claude-worktrees-blender-game-piece-c61349\7aedfdfa-be9c-40ed-8dc7-d4243ff07bc3\scratchpad\`.
Ne pas les modifier ; une retouche de modèle se demande à Olivier.
Environ 60 Mo au total, presque entièrement des textures PNG embarquées, 2048² sauf mention (couleur, ORM, normales,
parfois émission). **Les textures bougent encore** : des passes d'équilibrage sont en cours. Les noms de
fichiers, les noms de nœuds et les pivots sont stables. Importer par référence au `.glb`, sans recopier
maillages ni matériaux dans la scène, pour qu'un fichier remplacé se mette à jour seul.
Ce seront les **premiers assets 3D importés du dépôt** : aucun `.glb`, `.gltf`, `.obj` ni `.fbx` n'y existe.
### 3.2 Conventions communes
- glTF 2.0, mètres, exporté de Blender avec +Y vers le haut. Dans Blender la façade regarde −Y, donc
**dans Godot la façade regarde +Z** — même convention que le `Dashboard` actuel. Non vérifié à l'import.
- Chaque modèle a une racine maillée et, selon les cas, des enfants séparés pour ce qui s'anime ou
s'allume. Les enfants n'ont ni rotation ni échelle propres, sauf les aiguilles (voir 5.1).
- Échelle de création arbitraire, différente par pièce : voir section 4.
- Matériaux simple face, texture d'occlusion déclarée (canal rouge de l'ORM), tangentes exportées.
- Extension glTF utilisée : `KHR_materials_emissive_strength` sur les matériaux émissifs.
### 3.3 Contrat de chaque modèle
**Tableau de jauges — `gauge_panel.glb`** (créé à 1,2 m de large, origine au bas-centre de la façade)
- `GaugePanel` : boîtier, panneaux, lunettes, vis, interrupteurs décoratifs, barre à deux manchons.
- `GaugeDials` : les quatre cadrans imprimés, un matériau, une texture 4096 × 1024.
- `Needle_Oxygen`, `Needle_Battery`, `Needle_Hull`, `Needle_Depth` : une aiguille chacune, origine sur
l'axe du cadran, deux surfaces (lame, axe). Voir 5.1 pour l'angle.
- Six voyants, enfants séparés de `GaugePanel`, chacun avec son matériau émissif `GP_<nom du nœud>` :
`Light_OxygenOk` (vert), `Light_OxygenWarn`, `Light_BatteryWarn`, `Light_HullWarn`, `Light_Strip_0`,
`Light_Strip_1` (ambre). **Propriété à piloter : `emission_energy_multiplier`**, 0 = éteint (verre
sombre coloré), 1 = allumé. **Ne pas masquer un nœud `Light_*`** : les faces du boîtier sous la
lentille sont supprimées, on verrait un trou. Éteindre par l'émission seulement.
- Le boîtier `Gauges_Body` n'a plus aucune émission. Les cadrans `Gauges_Dials` portent un léger
rétro-éclairage (facteur d'émission 0,2 sur leur propre texture), pilotable aussi.
**Écran sonar — `sonar.glb`** (créé à 1,0 m de large, origine au centre du boîtier)
- `Sonar` : boîtier, renfoncement, trois boutons ambre (émission cuite, toujours allumés), deux molettes,
deux poignées laiton, presse-étoupe.
- `SonarScreen` : la vitre, maillage plat séparé, matériau émissif propre portant une image fixe de
démonstration. **UV de 0 à 1 sur l'image visible.** Vitre visible : 0,690 × 0,434 à l'échelle de
création, soit un rapport de **1,59**.
**Panneau d'interrupteurs — `switch_panel.glb`** (créé à 0,7 m de large, origine au bas-centre de la façade,
façade inclinée de 27° vers l'arrière)
- `SwitchPanel` : boîtier, plaque, cadres. `SwitchLabels` : étiquettes, matériau et texture propres
(POMPE 1, POMPE 2, SPOT, ALARME, ECLAIRAGE, VENTILATION, SONAR, NAVIGATION, AUXILIAIRE).
- Dix enfants animables, pose de repos à rotation nulle, **rotation autour de X** :
| Nœuds | Plage (`rotation_degrees.x`) |
|---|---|
| `Toggle_Eclairage`, `Toggle_Ventilation`, `Toggle_Sonar`, `Toggle_Navigation`, `Toggle_Auxiliaire` | 0 (bas) → −70 (haut) |
| `Rocker_Pompe1`, `Rocker_Pompe2`, `Rocker_Spot` | 0 → +16 |
| `Cover_Alarme` (capot rouge) | 0 (fermé) → −100 (relevé) |
| `Lever_Alarme` | 0 → −100 environ ; traverse le capot s'il est levé capot fermé |
Plages vérifiées en pose dans Blender, pas dans Godot.
**Boîtier d'alerte — `alert_box.glb`** (créé à 0,30 m de large hors pattes, origine au bas-centre)
- `AlertBox` : boîtier, grille, plaque, étiquettes laiton ALERTE / ATTENTION / DANGER, presse-étoupes.
- `Lamp_Alerte` (vert), `Lamp_Attention` (ambre), `Lamp_Danger` (rouge) : une lentille chacune, matériaux
`AB_Lamp_Alerte`, `AB_Lamp_Attention`, `AB_Lamp_Danger`, texture d'émission propre.
**Propriété à piloter : `emission_energy_multiplier`** du matériau de la lentille. 0 = éteint
(la lentille reste lisible en verre coloré), 1,0 = allumé comme conçu.
**Haut-parleur — `speaker.glb`** (créé à 0,26 m de large hors pattes, origine au bas-centre)
- `Speaker`, un nœud, matériau `Speaker_Body`. Rien d'animé, rien d'allumé.
## 4. Échelle et placement
**Se caler sur le cockpit existant, pas sur une maquette extérieure.** Le cockpit de production a déjà
ses cotes et sa caméra ; les modèles s'y adaptent.
Repères du cockpit actuel (`cockpit_interior.tscn`, mètres, avant = −Z) :
- caméra : `(0, 0.52, −0.48)`, FOV 82° ; regard libre ±30° en lacet, −17° à +11,5° en tangage, plus un
retour de mouvement (jusqu'à environ −35° / +29,5° en tangage, ±8,8° en roulis). **Aucune translation.**
- `%Dashboard` : `(0, 0.05, −1.22)`, incliné de −12°, dalle de 1,56 × 0,44 × 0,14 ;
- bloc d'instruments actuel : 1,42 m de large ; cadrans de 0,203 / 0,203 / 0,186 / 0,242 m de diamètre ;
- `SonarMonitor` : `(0.54, 0.59, −1.04)`, rotation `(−5°, −42°, −2°)`, écran actuel de 0,216 × 0,141 m ;
- hublot : centre `(0, 0.47, −1.32)`, vitre de 1,12 m.
Conséquences, à vérifier une fois les modèles importés :
- **Tableau de jauges** : ses cadrans font environ 0,21 m (petits) et 0,27 m (profondeur) à l'échelle de
création. Il tombe donc presque juste **à l'échelle 1** sur le bloc d'instruments actuel. Le poser sur
`%Dashboard`, nom et chemin à décider (voir 7).
- **Sonar** : pour retrouver un écran d'environ 0,216 m de large, échelle d'environ **0,31**. Garder la
position et l'orientation de `SonarMonitor`, tourné vers la caméra.
- **Panneau d'interrupteurs, boîtier d'alerte, haut-parleur** : pas d'équivalent exact aujourd'hui.
Tailles réelles plausibles proposées par l'étude d'ensemble : 0,26 m, 0,135 m et 0,145 m de large
(échelles 0,37, 0,45 et 0,56). Emplacements d'après l'image cible : interrupteurs en bas à gauche,
boîtier d'alerte sur la paroi gauche, haut-parleur sur la paroi droite. Ajuster à l'œil contre la cible.
**Contrainte de point de vue, importante.** Les modèles ont été faits pour une caméra à position fixe :
dos ouverts, faces invisibles supprimées. Ils sont sains tant que la caméra reste dans un cône d'environ
35° (40° pour le sonar) autour de la normale de leur façade. La caméra du jeu ne se translate pas, donc
une fois chaque pièce tournée vers elle, tourner la tête ne change rien. À faire : après placement,
mesurer l'angle entre la normale de chaque façade et la direction pièce → caméra ; au-delà de 30°,
réorienter la pièce plutôt que d'accepter le risque. Regarder aussi chaque pièce en tangage extrême.
Une maquette Blender du cockpit entier existe (`…\scratchpad\capsule\capsule_layout.json`), dérivée de
la seule image cible, avec ses propres cotes. Elle ne fait pas foi ici : elle suppose un cockpit plus
grand et une caméra différente. Utile seulement comme idée de disposition relative.
## 5. Brancher les instruments
Règle du dépôt : la présentation affiche des instantanés, elle ne calcule aucune règle. Le chemin de
données ne change pas — `VerticalSliceRoot` appelle `present(update, telemetry)` à chaque pas physique,
`CockpitInstrumentPanel` puis `CockpitDetailing` redistribuent des valeurs simples. Seul le dernier
maillon change : ce qui tourne et ce qui s'allume.
### 5.1 Aiguilles
Aujourd'hui (`cockpit_analog_gauges.gd` L263-265) :
`needle.rotation_degrees.z = lerpf(125.0, −125.0, ratio)`, balayage de 250°.
Les cadrans des nouveaux modèles sont imprimés pour un balayage de **240°** :
`rotation_degrees.z = 120 − 240 × ratio`
- ratio 0 → +120° (en bas à gauche), ratio 1 → −120° (en bas à droite), sens horaire vu du pilote.
- **Les aiguilles ne sont pas à zéro dans le fichier** : elles sont exportées dans une pose de
démonstration (ratios 0,70 / 0,50 / 0,90 / 0,54). Écrire l'angle absolu, ne pas additionner.
- Formule vérifiée par lecture du `.glb` et dans Blender. **Signe non vérifié dans Godot** : poser les
quatre aiguilles à 0, 0,5 et 1 et regarder où elles pointent avant de conclure.
- Les ratios restent ceux choisis dans `CockpitDetailing.present` (L49-60). Ne pas les recalculer ailleurs.
Graduations imprimées : oxygène, batterie et coque de 0 à 100 %, avec bande rouge 0-17, jaune 17-29,
verte 29-100. **Profondeur imprimée de 0 à 100 %** (décision 1), sans bande de couleur, avec un repère
rouge juste après 100 : l'aiguille trace `profondeur courante / profondeur certifiée`, comme aujourd'hui.
### 5.2 Voyants d'alerte
Aujourd'hui `CockpitAnalogGauges._update_indicator_bank` (L140-150) allume exactement un voyant sur trois
selon `snapshot.alerts.maximum` : vert sous ATTENTION, ambre pour ATTENTION et RETURN, rouge pour
CRITICAL et FAILURE ; allumé = énergie 2,8, éteint = 0,04.
Le boîtier d'alerte porte exactement ces trois voyants. Même correspondance, en pilotant
`emission_energy_multiplier` de chaque lentille. Qui reprend ce rôle — boîtier d'alerte, voyants du
tableau, ou les deux — est la décision 2.
Rappel du plan de jeu (`GAME_DESIGN_PLAN.md` L258-268) : aucune information critique ne dépend de la
seule couleur. Les étiquettes ALERTE / ATTENTION / DANGER et la position des voyants y contribuent ;
le panneau d'alerte du HUD reste.
### 5.3 Écran du sonar
Aujourd'hui `CockpitInstrumentPanel.attach_sonar_texture` (L85-94) pose sur `%SonarScreen` un
`StandardMaterial3D` non éclairé portant la texture du `SubViewport` (960 × 540), en `material_override`.
Avec le modèle : même méthode, sur le nœud `SonarScreen` importé. Points à respecter :
- le test exige que `%SonarScreen` soit un `MeshInstance3D` à nom unique, dont le +Z local est la normale
sortante, tourné vers la caméra (voir 7). La vitre du modèle regarde +Z après import ; à vérifier ;
- le `material_override` remplace l'image de démonstration embarquée : voulu ;
- une seule texture partagée entre vue compacte et vue agrandie (ADR 0006), asserté par le test ;
- **rapport d'aspect** : la texture est en 16:9 (1,78), la vitre du modèle en 1,59, l'ancien quad en 1,53.
L'image est déjà écrasée d'environ 14 % aujourd'hui. Décision 3.
- ne pas ajouter de grille ni de tracé factice par-dessus : le test interdit tout nœud `SonarReferenceTrace`,
et l'ancienne grille en boîtes émissives (`SonarGridVertical/Horizontal`) disparaît avec l'ancienne console.
### 5.4 Interrupteurs
Purement décoratifs aujourd'hui, et ils le restent dans ce lot : aucune interaction, aucun raycast,
aucune action d'entrée n'existe. Les laisser en pose de repos. Les rendre manipulables serait un nouveau
périmètre traversant entrées, application et présentation (décision 4).
### 5.5 Haut-parleur
Décor. Il n'y a aucun audio dans `game/` aujourd'hui.
## 6. Rendu : ce qui conditionne l'aspect
Les modèles ont été réglés et jugés sous une transformation de couleur linéaire (« Standard » de
Blender). Bonne nouvelle : le projet est au tonemapper par défaut de Godot, **Linear**, donc proche.
Sous une courbe filmique ou AgX, les mêmes modèles sortent pâles et délavés ; ce piège a déjà coûté
plusieurs corrections à tort. Ne pas toucher aux textures pour compenser un réglage d'environnement.
État actuel, relevé dans `game/world/sites/vehicle_test_environment.tscn` : tonemap non réglé (Linear),
**glow éteint, SSAO éteint**, brouillard et brouillard volumétrique actifs, ambiance
`ambient_light_source = 3` sans ressource Sky. Conséquences :
- **Voyants** : sans glow, pas de halo. Les lentilles se lisent par leur seule surface. Les halos de
l'image cible n'ont pas été peints dans les textures, exprès. Décision 5.
- **Forces d'émission** : réglées sur un éclairage d'essai. À recaler ici, par `emission_energy_multiplier`
ou l'énergie d'émission du matériau, pas en retouchant les textures.
- **Occlusion** : chaque modèle porte une occlusion cuite, qui n'agit que sur la lumière ambiante, et une
crasse de contact cuite dans la couleur de base. Si le SSAO est activé un jour, surveiller le cumul.
- **Ambiance** : vérifier à l'image ce que `ambient_light_source = 3` donne réellement sans Sky avant de
juger les matériaux.
- **Noirs métalliques** : cadres, lunettes, fond de grille et renfoncement de l'écran sont des noirs à
`metallic = 1`. C'est voulu : un diélectrique renvoie 4 % et passait au gris sous éclairage.
- **Éclairage non peint** : aucun reflet n'est cuit dans les textures (une exception possible sur le
boîtier d'alerte, en cours de reprise). Les reflets viennent de la rugosité, du métal et des normales,
donc des lampes de `cockpit_practical_lighting.gd`.
L'environnement appartient à la couche `world`, pas au cockpit. Le modifier sort du périmètre de ce lot
sauf décision contraire.
## 7. Tests : ce qui casse, ce qui doit tenir
Un seul test touche le cockpit : `tests/integration/run_vertical_slice_foundation.gd`. Il asserte sur des
noms, des types et des comptes de nœuds. `AGENTS.md` interdit d'affaiblir un contrôle pour faire passer
un changement ; quand la structure change légitimement, le test est **réécrit pour exprimer le même
comportement sur la nouvelle structure**, dans le même commit, et le changement est justifié.
| Ligne | Assertion | Effet du remplacement |
|---|---|---|
| 93-97, 108 | un nœud existe à `Dashboard/AnalogGauges` | garder ce chemin pour le conteneur des jauges, ou adapter |
| 125-127 | `%SonarScreen` est un `MeshInstance3D` | le maillage importé doit porter ce nom unique |
| 130, 142-145, 330-343 | `SonarMonitor/Housing` est un `BoxMesh`, écran en avant du boîtier | **casse** : le boîtier importé est un `ArrayMesh`. Réécrire la mesure (bornes du maillage) |
| 134-137, 305-314 | `global_basis.z` de l'écran · direction caméra > 0,85 | l'écran doit rester tourné vers la caméra, +Z sortant |
| 152 | `abs(battery_needle_degrees()) > 100` au départ | tient avec la nouvelle formule (batterie pleine → −120°) |
| 153 | `textures_are_loaded()` : acier + quatre faces de cadran | **casse** si les PNG de faces sont retirés (décision 6) |
| 155 | `dashboard_control_count() >= 8` | le nouveau panneau porte 10 commandes |
| 158 | `sonar_control_count() >= 4` | le modèle a 3 boutons et 2 molettes : redéfinir ce que la méthode compte |
| 162-164 | 4 jauges, 3 indicateurs, exactement 1 actif | dépend de la décision 2 |
| 165-167 | textes des afficheurs cachés (kWh, kW, L/min, bar) | les `Label3D` cachés doivent continuer d'être mis à jour |
| 169-172 | texture sonar partagée | inchangé |
| 150-151, 156-157, 159-161 | couples, tuyaux, équipements latéraux, 2 lampes, cloison | ne pas y toucher |
`tests/run_load_checks.gd` instancie toute scène sous `game/` : `cockpit_interior.tscn` doit s'instancier
seule, modèles compris.
**La barrière échoue sur toute ligne `ERROR:`, `SCRIPT ERROR:` ou `WARNING:`** dans la sortie des tests.
Un glTF qui émet un avertissement au chargement (extension inconnue, texture manquante, tangentes) la
fait donc tomber. Contrôler les journaux d'import et de chargement des cinq fichiers **en premier**,
avant tout travail de scène. Le script d'export a signalé un avertissement connu côté Blender
(« More than one shader node tex image used for a texture ») ; savoir s'il a un équivalent côté Godot
n'est pas vérifié.
Tout comportement nouveau reçoit son test : angle des aiguilles aux ratios 0, 0,5 et 1 ; un seul voyant
allumé par niveau d'alerte ; écran tourné vers la caméra.
## 8. Architecture et conventions
- Tout ce lot vit dans `game/presentation/cockpit/`. Aucune dépendance vers `world`, `infrastructure` ni
`composition` (`check_architecture.sh` L93-99). Rien dans `src/` ni `scenes/`.
- Suivre le patron existant : une classe par fichier, `class_name` en PascalCase préfixé `Cockpit`,
fichier en snake_case préfixé `cockpit_`, dépendances redéclarées en `const X = preload(...)`, GDScript
typé, membres privés en `_`, garde de nullité en tête de chaque `present`, petites méthodes de lecture
pour les tests (`gauge_count()`, `indicator_count()`…).
- Une seule implémentation par concept : la conversion ratio → angle d'aiguille a **un** propriétaire.
En remplaçant `CockpitAnalogGauges`, supprimer l'ancienne, ne pas laisser deux formules.
- Supprimer la géométrie procédurale remplacée, ne pas la cacher. Le dépôt cache déjà neuf nœuds
d'afficheurs par `hide_obsolete_elements` ; ne pas allonger cette liste.
- Ce qui est remplacé : tout `AnalogGauges` (boîtier, quatre jauges, aiguilles, verre, `IndicatorBank`
selon la décision 2) ; `SonarMonitor/Housing`, le quad `%SonarScreen`, tout `SonarConsoleDetailing` ;
les deux bancs `SwitchPlate` / `ToggleSwitch` de `DashboardDetailing`.
- Ce qui reste : coque, hublot et cloison, `SideEquipment` en entier, tuyauterie, couples,
`PracticalLighting`, consoles, leviers, cadre structurel du tableau (`TopRail`, `BottomRail`,
`SideRail`, `PanelScrew`), `%ReturnLabel`, `%StatusLabel`, `EmergencyDial` (décision 7), HUD.
- Vérifier les collisions avec ce qui reste : le cadre structurel et le rail inférieur
(`LowerSteelRail`, `LeftGrip`, `RightGrip`) occupent la zone de la barre du nouveau tableau, qui porte
déjà ses propres manchons. Probable doublon à retirer ; à juger à l'image.
- Fichiers de plus de 350 lignes et fonctions de plus de 40 : seuils de revue du dépôt.
## 9. Import et dépôt
- **Emplacement** : `game/presentation/cockpit/assets/models/`, à côté du code qui les utilise, comme
les textures actuelles. Noms en snake_case, déjà appliqués (section 3.1).
- **Les `.import` ne sont pas versionnés** dans ce dépôt ; la barrière les régénère par `--import`.
Tout réglage d'import non par défaut serait donc perdu en CI. S'en tenir aux réglages par défaut et
faire toute adaptation dans la scène ou le code, sauf décision de versionner les `.glb.import`.
- **60 Mo de binaires** dans un dépôt sans Git LFS ni `.gitattributes`, alors que le plan de jeu nomme
LFS pour les gros assets. Décision 8 : pas de LFS, et pas de commit des `.glb` sans accord d'Olivier.
Conséquence à signaler dans le compte rendu : tant que les `.glb` ne sont pas commités, la scène ne se
charge que sur cette machine ; un clone neuf échouerait à la barrière.
- **Budget de textures** (`GAME_DESIGN_PLAN.md` L958-960) : atlas 1K pour les kits courants, 2K réservé
au sous-marin et aux éléments héroïques. Le cockpit relève du 2K. Boîtier d'alerte et haut-parleur sont
passés en 1024 (aucune différence visible à leur taille d'écran).
- **Provenance** : compléter `assets/README.md` dans sa forme actuelle. Les modèles sont générés par
scripts Blender écrits pour le projet, d'après des planches de concept générées pour le projet ;
aucune ressource tierce. Polices des cadrans et des étiquettes : Arial et Impact, rendues en texture.
**Point de licence à vérifier** avant diffusion : ce sont des polices système de Windows.
- `project.godot` porte une **modification non commitée** qui supprime `[physics]` et `[rendering]`
(ré-enregistrement par l'éditeur, selon toute apparence). Ne pas la commiter par accident avec ce lot.
- Ne jamais modifier `.godot/` à la main.
## 10. Décisions prises
Tranchées par Olivier le 2026-10-06. Elles priment sur toute formulation conditionnelle des sections
précédentes (« voir la décision N », « dépend de la décision N »).
1. **Cadran de profondeur : pourcentage de la profondeur certifiée.** Le cadran du modèle est regradué de
0 à 100 % (texture régénérée par le script du modèle, livrée avec le `.glb`). L'aiguille trace
`courante / certifiée`, comme aujourd'hui : aucun changement de domaine. Aucun seuil de jeu n'est
imprimé sur le cadran au-delà du repère de fin de course.
2. **L'alerte SYS / ATTN / ALRM est portée par le boîtier d'alerte** : `Lamp_Alerte` (verte) = SYS,
`Lamp_Attention` (ambre) = ATTN, `Lamp_Danger` (rouge) = ALRM, exactement une allumée. Les six voyants
`Light_*` du tableau de jauges ne portent pas ce rôle ; faute de donnée par instrument dans le
snapshot, ils restent dans un état fixe de repos (à proposer, pas à inventer une règle).
3. **Sonar : le `SubViewport` passe au rapport de la vitre** (1,59 ; 960 × 604). Vérifier que le rendu
sonar ne suppose pas 16:9 ; adapter le test qui lit sa taille s'il y en a un.
4. **Interrupteurs décoratifs.** Posés au repos (rotations nulles). Aucune entrée, aucune commande.
5. **Glow activé, discret.** Réglage d'environnement traité en réglage de qualité selon l'ADR 0004. Seuil
réglé pour que seuls voyants et écran sonar débordent, pas le papier des cadrans. Livrer une capture
avec et sans.
6. **Faces de cadran : celles du modèle.** Les PNG `*_gauge_face_albedo*.png` sont retirés et
`textures_are_loaded()` adapté à ce qui est réellement chargé.
7. **`EmergencyDial` / « ÉJECTION · X » est conservé.** Le levier d'alarme sous capot rouge reste
décoratif, capot fermé.
8. **Dépôt : pas de Git LFS.** Git ordinaire, sans `.gitattributes`. Comme chaque version d'un `.glb`
reste à jamais dans l'historique et que les textures bougent encore, **ne pas commiter les `.glb`
sans l'accord explicite d'Olivier** : travailler avec les fichiers en place, non suivis, et commiter
scène, code et tests à part. Fichiers sous `game/presentation/cockpit/assets/models/`
(à côté des textures de cockpit existantes), noms en snake_case : `gauge_panel.glb`, `sonar.glb`,
`switch_panel.glb`, `alert_box.glb`, `speaker.glb`. Les `.glb.import` ne sont pas versionnés, comme le
reste de `.godot/` et des imports du dépôt.
## 11. Ce qui n'a jamais été vérifié
- Aucun des cinq `.glb` n'a été ouvert dans Godot. Import, orientation, échelle, matériaux, sens de
rotation des aiguilles et des interrupteurs : tout est à constater.
- L'aspect sous l'éclairage réel du cockpit : les modèles n'ont été vus que dans Blender.
- La barrière qualité n'a pas été lancée pendant la rédaction de ce brief.
- Les numéros de ligne cités datent du 2026-10-06 ; les relire avant de s'y fier.
## 12. Ordre de travail conseillé
1. Copier les `.glb` (hors commit), lancer `--import`, lire les journaux : zéro avertissement, sinon
s'arrêter et le signaler — le correctif est côté modèles.
2. Instancier les cinq modèles dans une scène d'essai, constater axes, échelle, hiérarchie et matériaux
contre la section 3. Signaler tout écart avant d'aller plus loin.
3. Placer dans `cockpit_interior.tscn` (section 4), mesurer les angles de vue.
4. Brancher aiguilles, voyants, écran (section 5), avec leurs tests.
5. Supprimer la géométrie procédurale remplacée, adapter le test d'intégration (section 7).
6. Captures aux deux résolutions, à côté de l'image cible. Barrière verte.
7. Compte rendu : ce qui est fait, ce qui diffère de ce brief, ce qui reste, ce qui n'a pas pu être vérifié.
En cas de défaut d'un modèle (trou visible, mauvais axe, texture fausse, nœud manquant) : ne pas le
réparer dans Godot. Le décrire précisément, capture à l'appui ; il se corrige dans le script Blender qui
a produit le fichier.