DOCS/v2/immersif-frontiere-plan.md
Thomas Fransolet 6221978526 Docs en attente : canal VR et contenu immersif livrés, SectionForm, roadmap
Cartes 600, 610 et 620 closes (back-office XR, ressource 360, appairage tablette),
250 et 320 retirées du planifié, 015 et 330 à jour ; STATUS, roadmap, test-plan,
todo-features et plans VR / frontière immersif alignés ; kanban.html regénéré.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011VxSQeGQYUvPmSEoGdnidA
2026-09-15 20:06:34 +02:00

510 lines
28 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.

# Contenu immersif — frontière entre le Studio IA et le canal XR — 📦 V2
> **Statut** : document de frontière, écrit le 2026-09-11. Rien de codé.
>
> **Ce document ne remplace ni [studio-plan.md](studio-plan.md) ni [vr-quest-unity-plan.md](vr-quest-unity-plan.md).**
> Il tranche ce que ces deux plans se renvoient mutuellement en dépendance : le Studio met la 3D en
> lot 11 en disant « dépend du chantier VR », et le plan VR décrit les POI sur GLB (§9) en supposant
> un GLB qui arrive de quelque part, sans jamais dire d'où. Ce n'est pas un trou de conception, c'est
> une frontière que personne ne tient.
>
> ⚠️ **Rien ici n'est V1.** La bascule Postgres et le backlog V1 passent avant. Et le gate du Studio
> reste celui du lot 4 : si un conservateur ne produit pas 10 images cohérentes seul, aucune ligne de
> 3D ne s'écrit.
---
## 1. Les trois couches
La confusion vient de ce que « module 3D » désigne trois choses distinctes, décrites dans deux
documents différents. Les voici séparées.
### Couche 1 — Ressources immersives
Trois nouveaux types de ressource, qui s'affichent **partout où une ressource s'affiche** :
```
ResourceType += Panorama360 -- image équirectangulaire
Video360 -- vidéo équirectangulaire
Model3D -- GLB
```
Indépendant de la VR. Indépendant de l'IA. Un client web sans casque et sans Studio en profite.
⚠️ **Les trois valeurs se décident d'un coup, en une migration, en fin d'enum.** Aujourd'hui
`ResourceType` s'arrête à `Text = 10` (`Data/Resource.cs:94-110`, avec le commentaire qui interdit
d'insérer au milieu). `studio-plan.md` §5 réserve déjà `Model3D = 11`.
**Décision — `Video360` est un type distinct, pas un flag `IsEquirectangular` sur `Video`.** L'enum
distingue déjà `Image` / `ImageUrl` : un type séparé est cohérent avec l'existant et rend le filtrage
trivial dans le sélecteur de ressource, qui est le point de passage unique de toute l'app
(`select_resource_modal.dart:24` embarque `ResourcesScreen`).
### Couche 2 — Consommation
Trois usages de ces ressources :
| Usage | Porté par | Canaux |
|---|---|---|
| `SectionModel3D` + POI (titre, description, audio, multilingue) | une section | web, mobile, VR |
| `ImmersiveBackground` — fond d'une visite | `Configuration` | VR, dégradé ailleurs (§4) |
| `ImmersiveBackground` — fond du menu général | `ApplicationInstance` VR | VR |
| Rendu immersif complet | app Quest (Unity) | VR |
Le back-office XR (`Device.AppType` + onglet flotte, 8-12 j) se tient debout tout seul dans cette
couche : il rend le canal administrable et démontrable avant tout engagement sur Unity.
### Couche 3 — Studio IA
**Une source d'approvisionnement pour la couche 1, pas un module parallèle.** C'est la reformulation
qui règle la frontière : le Studio ne possède pas ses assets, il **alimente la médiathèque**, qui
reste la bibliothèque unique (`studio-plan.md` §3.0).
Ce que le Studio apporte que le client ne peut pas obtenir ailleurs, dans l'ordre de valeur :
1. **L'asset atterrit dans la médiathèque, référencé par une section, donc il part offline.**
C'est le point non réplicable. Un asset généré ailleurs est un fichier à re-uploader à la main,
et il ne part offline que s'il finit référencé par un champ de section
(`GetReferencedResourceIds`).
2. **L'identité visuelle est injectée côté serveur, jamais retapée.** La cohérence des quarante
images d'un parcours, pas l'accès au modèle.
3. **Le bon format, la bonne dimension, le bon prompt contextuel** — le titre et la description de
la fiche alimentent le prompt, la validation affecte directement au champ cible.
---
## 2. Ce que chaque couche vend
**Il n'y a pas d'add-on casque.** Arbitré le 2026-08-31 (`vr-quest-unity-plan.md` §6), reconfirmé
ici parce que la question revient : un add-on « VR » ne se vendrait que le jour où l'app Unity existe
*et* où le client achète un casque. L'add-on **« Contenu immersif », 70 €/mois et plus**, vend la
couche 1 — qui s'affiche déjà en web, mobile et kiosk. Un client le souscrit et en a pour son argent
**sans casque**. Le casque est le haut de gamme de l'add-on, pas sa condition d'existence.
| Ce qui est vendu | Véhicule | Montant |
|---|---|---|
| Ressources immersives (360, GLB, POI) + l'app Quest quand elle sortira | add-on « Contenu immersif » | à partir de 70 €/mois, s'accroche à n'importe quel palier |
| Génération IA (images, puis props et scènes) | add-on Studio, crédits dédiés | voir `studio-plan.md` §3.5 |
| Casques | achat client | hardware |
| Provisioning, config borne, formation, journée sur site | onboarding one-shot | 1200-1500 €, **seulement s'il y a des casques** |
| Modélisation 3D d'atelier, photogrammétrie d'objets de collection | sur devis, hors Studio | 3 à 15 k€ |
### 2bis. Quota IA et crédits Studio — deux monnaies, et pourquoi
> **Arrêté le 2026-09-11.** La question « le Studio consomme-t-il le quota IA ? » revient à chaque
> conversation. Réponse : **non**, et voici le critère pour ne plus se la reposer.
**Le critère n'est pas « IA / pas IA ». C'est « consommé en temps réel par le visiteur » contre
« produit une fois par le client ».** Cette ligne décide du modèle de facturation parce qu'elle décide
de la forme de la courbe d'usage.
| | **Quota IA** | **Crédits Studio** |
|---|---|---|
| Unité | tokens / mois | crédits |
| Renouvellement | reset mensuel, non reporté | **rechargeables, expiration 12 mois** |
| Véhicule | attribut du palier | add-on |
| Courbe d'usage | récurrente, suit la fréquentation | **en pics** (préparation d'une expo) |
| Couvre | chat visiteur, canal vocal, traduction | images, 3D, scènes, vidéo, **TTS pré-généré** |
Le reset mensuel est **juste** pour le quota IA : l'usage suit la fréquentation, il est corrélé aux
vacances scolaires, et il est normal qu'il ne se reporte pas.
Il est **faux** pour le Studio. Un musée génère 200 images en trois semaines pour préparer une expo,
puis rien pendant cinq mois. Un forfait mensuel se gaspille dix mois sur douze : le client a le
sentiment de payer pour rien, et la capacité provisionnée ne sert pas.
➡️ **Correction à porter dans `studio-plan.md` §3.5** : `ImageCreditsMonthKey` et le
`Kind: MonthlyReset` deviennent inutiles. Le `CreditLedger` est déjà append-only avec un
`Kind: Grant` — il encaisse le modèle rechargeable **sans changement de schéma**. Gratuit à décider
maintenant, migration en prod plus tard.
**Le TTS pré-généré va côté Studio**, et c'est contre-intuitif puisque c'est « de l'IA ». Trois
raisons : il se facture au caractère et non au token, il produit un fichier (donc du stockage, comme
une image générée), et il se déclenche par pics quand le conservateur rédige. Le mettre sur le quota
tokens visiteur mélangerait deux courbes sans rapport.
**La traduction est le cas limite, laissé où il est.** Par le critère ci-dessus elle devrait être en
crédits Studio — déclenchée par le client, une fois, produisant un asset durable. Mais elle est déjà
sur le quota tokens, elle est très bon marché, et la déplacer ne rapporterait rien. Décision : **ne
pas y toucher**, mais le savoir plutôt que de le redécouvrir.
**Vérifié dans le code le 2026-09-11 — ce que le quota IA couvre réellement :**
| Endpoint | Débite le quota | Note |
|---|---|---|
| `POST /api/Ai/chat` | ✅ `AiController.cs:394` | |
| `POST /api/Ai/translate` | ✅ `AiController.cs:347` | |
| `POST /api/Ai/reindex/{instanceId}` | ❌ | **Les embeddings RAG coûtent et passent gratuitement** |
| `GET /api/Ai/insights/{instanceId}` | ❌ | idem |
⚠️ **Trou existant, indépendant du Studio** : deux endpoints facturés chez Google ne débitent rien.
Et `AiTokensPerMonth` vaut `0` en Essentiel et Pro, `20_000_000` en Premium
(`MyInfoMateDbContext.cs:607-637`) — donc le quota IA est aujourd'hui un **attribut du palier**, pas
un add-on. À ne pas confondre avec les crédits Studio, qui sont un add-on.
⚠️ **L'add-on immersif doit porter sa propre enveloppe de stockage, explicite et finie, avec
facturation du dépassement.** Un client Pro à 99 € a un quota dimensionné pour du Pro ; une vidéo 360
de 5 minutes pèse des Go, un monde exporté en splats aussi. Le principe est posé dans
`vr-quest-unity-plan.md` §6 — **il n'est toujours pas chiffré, et il doit l'être avant d'ouvrir la
couche 1 à la vente.**
---
## 3. Génération de scène 3D — état réel du marché
> **Révisé le 2026-09-11.** Une première passe de cette analyse concluait « ne pas faire, l'assemblage
> est la seule voie ». C'était fondé sur un état du marché périmé : la conclusion change, la limite
> qui la motivait reste vraie.
### Ce qui existe
[Marble](https://www.worldlabs.ai/blog/marble-world-model) (World Labs) génère des environnements 3D
persistants depuis du texte, une image, une vidéo ou un panorama, et **expose une World API depuis
janvier 2026** — à partir de **~0,12 $ le monde en draft**. Exports : splats (SPZ/PLY), panorama 360,
collider mesh basse résolution, et **mesh texturé GLB** sur le palier Pro, qui porte aussi les droits
commerciaux.
➡️ **Ça entre dans la couche fournisseur sans rien y changer** : un `GenerationModel` de plus en base,
`ProviderKey = "worldlabs"`, `Kind = Scene3D`. C'est exactement ce que `studio-plan.md` §3.6 a été
conçu pour absorber.
### La limite qui ne bouge pas
Un monde Marble est une **scène capturée**, excellente vue depuis et autour de son point de vue,
qui dégrade dès qu'on s'en éloigne. Chiffres rapportés côté Quest 3 standalone : plafond raisonnable
autour de **500k splats** (2M restant du domaine du VR filaire), environnements cadrés sur une grille
de ~10×10 m, et un cas mesuré à **12 fps sous Unity contre 19 dans le navigateur Oculus**. Une borne
publique doit tenir 72 fps, huit heures par jour, sans personne à côté.
Et il n'y a pas de sémantique : pas de sol identifié, pas d'objets nommés, pas d'interactions. Le
collider mesh fourni donne la collision, pas la compréhension de la scène.
### Position retenue
| Usage | Verdict |
|---|---|
| Fond immersif d'une visite ou du menu VR (le visiteur regarde autour de lui depuis un point fixe) | ✅ **oui**, c'est le cas d'usage nominal de la techno |
| Monde de référence en **roomscale stationnaire** : le visiteur est *dans* la scène, sur ~3 m | ✅ **oui** — et c'est mieux qu'un assemblage de props Meshy |
| Environnement navigable, le visiteur se déplace librement dedans | ❌ **non** en V2. Ni la perf en borne, ni la sémantique n'y sont |
| Props d'ambiance générés depuis du texte, placés sur ancres | ✅ **oui**, faible risque : un prop raté se jette |
**Le cadre retenu est le roomscale stationnaire, pas un diorama.** Arbitré le 2026-09-11 : une zone
d'environ 3 m où le visiteur tourne sur lui-même, se penche et tend le bras, mais ne se déplace pas.
C'est exactement la zone où Marble est bon — son point de capture — et où le budget de perf tient.
Ce n'est pas un pis-aller : la contrainte supprime d'un coup la locomotion, les collisions, le motion
sickness, la cohérence d'échelle au-delà du champ proche et l'essentiel du budget de perf. Et elle est
*meilleure* produit qu'un diorama vu de l'extérieur, parce que le visiteur est **dans** la scène.
Le but n'a jamais été de faire un jeu VR.
**Placement sur ancres prédéfinies, jamais libre.** Le template d'environnement Unity expose N
snap points ; le client y accroche ses props. Un éditeur de placement libre en 3D dans un back-office
web est un chantier à lui seul, pour un gain nul à ce stade.
### Image → GLB : mature en API, piégeux en produit
Meshy / Tripo / Rodin ont des API qui marchent, et le multi-vues améliore nettement le résultat. Mais
ce qui sort est un objet isolé, silhouette lisible, topologie sale, texture baked, échelle et pivot
arbitraires.
> **Précisé le 2026-09-15 — tout passe par fal, y compris Meshy.** Vérifié ce jour : fal expose
> Meshy (v5, v6-preview, **v7**), Hi3D, Tripo3D, Hunyuan3D et Trellis. Aucun second fournisseur à
> intégrer. Le multi-vues a un endpoint dédié, `meshy/v7/multi-image-to-3d` (~1,20 $, 1,40 $ en
> ultra), face à ~0,020,05 $ en mono-image : **facteur ~25**, donc deux lignes de catalogue et une
> bascule annoncée à l'écran. Hi3D est excellent en fidélité structurelle mais **mono-image
> seulement**. Détail du flux de prise de vue guidé : `studio-plan.md`, lot 11 et décision 24.
⚠️ **Pour un objet de collection, le problème n'est pas la qualité, c'est la véracité.** Un visiteur
qui fait tourner « le casque de Léon » croit voir l'objet. Deux conséquences :
- Sur un `Model3D` généré, la provenance visible est **obligatoire, non désactivable** — contrairement
aux images, où le badge suffit et la gravure est une option (`studio-plan.md` décision n°6).
- L'offre doit séparer explicitement **« objet numérisé »** (photogrammétrie, sur devis, hors Studio)
de **« illustration 3D »** (Studio). Les vendre sous le même mot est un risque réputationnel chez
une institution scientifique.
### Le vrai sur-scope : l'éditeur, pas la génération
`vr-quest-unity-plan.md` §9 signale l'éditeur de placement de POI comme « le seul morceau non
trivial ». Il le sous-estime : **Flutter web n'a pas de stack 3D éditable.** `model_viewer_plus` est
une WebView autour de `<model-viewer>`, en lecture seule.
➡️ **Décision à prendre maintenant, parce qu'elle conditionne tout le chiffrage** : l'éditeur de POI
3D est une **page three.js embarquée en iframe**, pas un widget Flutter. Précédent dans le repo : la
démo villa d'Echternach (`visitapp-web/src/app/demo/villa-echternach/scene.ts`).
---
## 4. `ImmersiveBackground` — un type, deux porteurs
`Configuration` porte aujourd'hui `ImageId` et `LoaderImageId`, rien d'immersif. Poser un
`Configuration.BackgroundResourceId` à plat, puis un autre champ sur l'`ApplicationInstance`, puis un
troisième pour la scène, donne quatre champs « background » incohérents dans six mois.
```
ImmersiveBackground
ResourceId
Kind -- Pano | Video360 | Scene3D
FallbackResourceId? -- 2D, pour les canaux qui ne savent pas rendre
```
Porté par **`Configuration`** (le fond d'une visite) **et** par l'**`ApplicationInstance` VR** (le
fond du menu général — l'équivalent de home v3 côté mobile). Un seul type, deux porteurs, pas deux
modèles.
**Dégradation par canal, écrite dans le contrat** — sinon les fonds casseront silencieusement :
| Canal | `Pano` | `Video360` | `Scene3D` |
|---|---|---|---|
| VR (Quest) | rendu | rendu | rendu |
| Web | visite pivotante | visite pivotante | fallback 2D |
| Mobile | fallback 2D | fallback 2D | fallback 2D |
| Kiosk | fallback 2D | fallback 2D | fallback 2D |
Chaque canal déclare ce qu'il sait rendre ; le fallback est `Configuration.ImageId` par défaut.
---
## 4bis. Viewer de scène et viewer d'asset — un socle, deux modes
> **Arrêté le 2026-09-11.** La question « c'est le même viewer ? » se pose naturellement, et la
> réponse détermine un chiffrage à trois implémentations près.
**Ce qui les sépare est la caméra, et c'est une opposition franche.**
| | **Viewer d'asset** (l'épée du roi) | **Viewer de scène** (le monde de référence) |
|---|---|---|
| Caméra | **orbitale** — l'objet au centre, on tourne autour, on zoome | **look-around** — on est au centre, on regarde autour |
| Le visiteur | **manipule** l'objet | **est dans** la scène, ne manipule rien |
| Donnée | un GLB léger, objet isolé | un splat / mesh d'environnement, lourd |
| POI | sur la surface, **tournent avec l'objet** | fixes dans l'espace, on les regarde |
**Ce qu'ils partagent** : le loader GLB, le canvas, le raycast sur POI, et surtout **le même modèle
de POI** — une position locale (x,y,z). Donc **un socle de rendu avec un mode**, pas deux
implémentations. Et **un seul éditeur** dans le manager, avec un mode lui aussi.
⚠️ **Le point qui compte pour le chiffrage : ils ne vivent pas au même endroit.**
| | Web (React) | Mobile (Flutter) | VR (Unity) |
|---|---|---|---|
| Viewer d'asset | ✅ | ✅ | ✅ (item **E7**) |
| Viewer de scène | fallback pano | fallback 2D | ✅ (item **E5**) |
➡️ Le **viewer d'asset est trois implémentations**, le **viewer de scène une seule** plus deux
dégradés. À budgéter dans cet ordre, pas l'inverse : l'intuition pousse à commencer par la scène
parce qu'elle impressionne, alors que c'est l'asset qui coûte trois fois.
---
## 5. Décisions de rétro-compatibilité, du plus cher au moins cher
Les points **1 à 5 doivent être écrits dans `studio-plan.md` avant sa première migration.** Les
suivants peuvent s'écrire au fil de l'eau.
### 1. Pipeline d'ingestion unique côté serveur — ✅ **porté dans `studio-plan.md` le 2026-09-13**
> Décision 14 : URL d'envoi signée par l'API, puis un `ResourceIngestionService` unique pour tout fichier,
> uploadé ou généré (§8 lot 0). Les gros fichiers — GLB, vidéos 360 — vont directement chez Google
> sans traverser le VPS.
**Le trou le plus cher, et il est structurel, pas accidentel.** Aujourd'hui **l'upload est fait par
le navigateur en direct** (`resources_screen.dart:247-256`) ; le backend ne sait que supprimer
(`IResourceBlobService.DeleteAsync`). Le Studio, lui, produit côté serveur et post-traite **à la
validation d'un brouillon**.
➡️ Un GLB **uploadé** ne traverserait aucun traitement, un GLB **généré** traverserait le chemin
Studio. Deux chemins par construction.
- [ ] Déplacer le point de passage de « validation d'un asset Studio » à **« ingestion de tout asset,
quelle que soit sa provenance »**
- [ ] Un seul service de post-traitement, appelé par les deux chemins
- [ ] Le lot 0 (`UploadAsync`, `CopyAsync`, `ProbeSizeAsync`) est le prérequis mais **ne suffit pas**
Coût du retrofit : l'upload navigateur direct est partout dans manager-app, et il faudrait retraiter
la base d'assets existante.
### 2. Normalisation canonique des GLB
- [ ] Pivot recentré, échelle normalisée, up-axis fixé — **déterministes**
- [ ] Budgets de validation (tris, taille de texture, poids) : **rejet**, pas réparation
- [ ] Draco + KTX2 dans le même passage
- [ ] `Model3DVersion` sur la ressource
Coût du retrofit : **tout POI posé avant est perdu.** C'est ce qui rend ce point non négociable, pas
l'élégance du pipeline.
### 3. Invalidation et repositionnement des POI
Absent des deux plans. Et c'est structurellement plus grave qu'en géo : une lat/lon survit à un
changement de fond de carte, un (x,y,z) local est **détruit** par un changement de pivot, d'échelle ou
d'up-axis.
- [ ] POI attachés à `(resourceId, modelVersion)`
- [ ] Au remplacement ou à la régénération : POI **conservés et marqués « à revalider »**, jamais
supprimés en silence
- [ ] Écran de repositionnement dans l'éditeur
Peu de code si pris tôt. Coûteux en confiance client si découvert en prod.
### 4. Lignage en colonnes typées — ✅ **porté dans `studio-plan.md` le 2026-09-13** (décision 20, lot 0)
`Resource.AiProvenance` (jsonb) distingue uploadé (null) de généré (non-null) et liste des
`referenceResourceIds[]`. **Mais un tableau dans un jsonb n'est pas un lignage requêtable**, et rien
ne couvre un GLB **dérivé** — reprocessé, décimé, regénéré depuis le même jeu de photos.
- [ ] `Resource.Origin` : `Uploaded | Generated | Derived`**colonne**, pas jsonb
- [ ] `Resource.SourceResourceId` nullable — le lignage parent/enfant
- [ ] `AiProvenance` reste pour le détail (prompt effectif, seed, version d'identité)
Coût du retrofit : migration de données sur des assets déjà en base.
### 5. Renommer la monnaie de crédits — ✅ **porté dans `studio-plan.md` le 2026-09-11**
`ImageCreditsPerMonth`, `ImageCreditsThisMonth`, `ImageCreditsMonthKey`, `ImageCreditsHardCap`,
`SubscriptionPlan.ImageCreditsPerMonth`. Or une 3D coûte 10 à 50 fois une image, et un monde Marble
n'est pas une image du tout.
- [x] `ImageCredits*`**`StudioCredits*`** partout
- [x] `GenerationModel.CreditCost` déjà par modèle : rien d'autre à faire côté tarification
- [x] **Et le modèle change aussi** : crédits **rechargeables à expiration 12 mois** au lieu d'un
quota mensuel. Un musée génère en pics, pas linéairement — un forfait mensuel se gaspille dix
mois sur douze. Voir `studio-plan.md` §3.5 et le §2bis ci-dessus
**Gratuit aujourd'hui. Migration de colonnes en prod plus tard.** Le retrofit le moins cher à éviter
et le plus bête à subir. ➡️ **Fait** : décision n°3 du tableau §2, bloc §3.5, schéma §5 et lot 1 de
`studio-plan.md` sont à jour. Reste ouvert : le mapping Stripe `checkout.session.completed`
`Kind: Grant` pour la recharge.
### 6. Contrat fournisseur : multi-fichier et par kind — ✅ **porté dans `studio-plan.md` le 2026-09-13** (décision 21, §3.6)
`ProviderResult` est pensé mono-fichier image. Une génération 3D retourne GLB + preview + parfois
textures séparées ; un monde retourne splat + collider mesh + panorama.
- [ ] `ProviderResult` multi-fichier
- [ ] `GenerationKind` += `Model3D`, `SceneProp`, `Scene3D`
- [ ] **Timeout et politique de retry par kind** — le `PollFallback` à +90 s et le polling front à 2 s
de `studio-plan.md` §3.7 sont dimensionnés pour un job image de 20-60 s
- [ ] **Job composite** : générer 8 props est un job parent + N enfants, pas un job
### 7. `ImmersiveBackground` comme type réutilisable
Voir §4. Deux porteurs, un type, dégradation par canal dans le contrat.
### 8. Les trois valeurs `ResourceType` d'un coup
Voir §1, couche 1.
### 9. Éditeur 3D = iframe three.js
Décision d'architecture, pas d'implémentation. Voir §3.
### 10. Chiffrer l'enveloppe de stockage de l'add-on immersif
Voir §2. Posé en principe le 31/08, jamais chiffré.
### 11. Provenance obligatoire sur un `Model3D` généré
Voir §3. Et séparer « objet numérisé » de « illustration 3D » dans l'offre.
---
## 6. Droits et modération — ce qui reste ouvert
Couvert par `studio-plan.md` : `rightsHolder` = l'instance (les droits sont au client, écrit dans la
donnée), provenance complète, badge visiteur traduit dans les langues de la configuration, et la
redirection des personnes identifiables vers les personnages.
**Pas couvert, et spécifique à la 3D** : rien sur les objets dont le client **n'a pas** les droits —
prêts, dépôts, collections tierces. C'est le quotidien d'un musée, et générer un GLB depuis la photo
d'un objet en dépôt n'est pas anodin.
➡️ Traitement retenu : **CGU + une mention explicite dans l'écran de génération 3D**, pas de
vérification automatique. Pas de modération automatique entrée/sortie non plus. Acceptable au stade
pilote — **à condition de l'assumer par écrit**, pas de le découvrir.
---
## 7. Chemin critique
Ce n'est pas celui qu'on croit. La génération 3D est en toute fin, et c'est la brique la **moins**
risquée de la liste, parce qu'à ce stade tout ce qui la consomme existe et est validé.
```
Lot 0 — socle de stockage serveur (prérequis dur, sert aussi le TTS)
└─ + pipeline d'ingestion unique (décision n°1)
└─ Ressource 360° (le plus petit des trois chantiers médias)
└─ SectionModel3D + POI (GeoPoint réutilisé à 80 %)
└─ Back-office XR (8-12 j, se tient debout tout seul)
└─ Studio images (lots 1 à 6)
└─ ⛔ GATE lot 4 : un conservateur, 10 images, seul
└─ Studio 3D + scènes
└─ App Unity (go/no-go client pilote)
```
Le go/no-go de l'app Unity reste conditionné à **un client pilote disposant déjà de contenu immersif**
— et la couche 1 rend cette condition atteignable, puisqu'elle permet au client de *fabriquer* ce
contenu au lieu de devoir le posséder d'avance. C'est le changement le plus important qu'apporte le
Studio au dossier XR.
---
## 8. Ce qu'on ne fait pas
- **Environnement VR navigable** en V2 — roomscale stationnaire ~3 m seulement (§3)
- **Placement libre de props** — ancres prédéfinies
- **Locomotion en VR** — le visiteur tourne sur lui-même, il ne marche pas
- **Les mécaniques de jeu du §9** — notées, pas planifiées
- **Photogrammétrie / fac-similé d'objets de collection** — sur devis, hors Studio
- **Modération automatique** entrée/sortie — CGU + provenance + `rightsHolder` (§6)
- **Retopologie ou upscaling automatique** — budgets de validation et rejet, pas de réparation
- **Refonte du routing de manager-app** — les deux `switch` numérotés en dur de `main_screen.dart`
sont acceptés tels quels, comme dans `studio-plan.md`
---
## 9. Mécaniques de jeu immersives — 📝 idées notées, rien de planifié
> **Noté le 2026-09-11, à la suite du canal VR — pas dans son périmètre.** Aucune de ces mécaniques
> n'est chiffrée ni engagée. Elles sont ici pour ne pas être reperdues, et parce que **deux d'entre
> elles réutilisent des données qui existent déjà**, ce qui change leur coût relatif.
**Le principe structurant, à ne pas perdre** : un jeu configurable par le client **n'est pas un
moteur de jeu, c'est un type de section**. Trois mécaniques génériques couvrent l'essentiel de ce qui
a du sens en musée, et toutes tiennent dans les ~3 m du roomscale stationnaire. Le client compose ;
un vrai jeu sur mesure reste un devis.
| Mécanique | Ce que c'est | Données | Coût |
|---|---|---|---|
| **Répondre** | Quiz immersif : question devant, réponses sur 3-4 panneaux autour, réponse au regard ou à la main. Fond = `ImmersiveBackground` de la configuration | **`SectionQuiz`, déjà là** | rendu seul, **config nulle** |
| **Trouver** | Chasse aux détails dans un pano 360 : « trouve les 5 détails », « repère les 3 erreurs ». Le client pose des hotspots | même geste que poser des POI → **le même éditeur iframe sert deux fois** | faible, et **ça marche aussi en web** sur pano pivotant → se vend sans casque |
| **Ordonner** | Tri chronologique ou logique : attraper des objets autour de soi et les ranger. Frise, étapes d'un procédé | **`OrderedTranslationAndResource`, déjà dans le modèle** | faible, config = une liste ordonnée |
| **Avant / après** | « À quoi ressemblait cette place en 1900 ? » — le visiteur devine, puis bascule | **`BeforeAfterPairs`** du lot 9 du Studio | rendu seul |
**Le meilleur rapport valeur/effort est « Répondre »** : `SectionQuiz` est déjà configuré par les
clients aujourd'hui. Le jeu, c'est le rendu — zéro donnée nouvelle, zéro apprentissage côté client.
**Le plus intéressant commercialement est « Trouver »**, pour une raison qui n'a rien à voir avec la
VR : il fonctionne sur un pano 2D pivotant en web. Une mécanique de jeu qui se vend **sans casque**,
sur l'add-on immersif seul.
**Écarté, et pourquoi :**
| Idée | Pourquoi non |
|---|---|
| Remontage d'objet (amphore à reconstituer) | Effet musée énorme, mais il faut un GLB **pré-découpé en pièces**. Le client ne peut pas le produire seul → casse la règle d'autonomie. **Sur devis uniquement** |
| Escape game VR | La logique conditionnelle n'est pas configurable en trois champs. L'escape game reste sur le canal mobile, où il fonctionne déjà |
| Tir, action, visée | Hors sujet produit |
| Dialogue avec un PNJ scripté | Le guide IA le fait déjà mieux, et sans script à maintenir |
| Tout ce qui demande de marcher | Contredit le roomscale stationnaire (§3) |
---
## 10. Ce que ce document change dans les deux autres plans
| Plan | À reprendre |
|---|---|
| `studio-plan.md` | Le **lot 11 (3D)** passe de quatre lignes à un lot réel : `Scene3D` comme `GenerationKind`, World Labs dans le catalogue, provenance obligatoire sur `Model3D`. Les décisions n°1, 4, 5 et 6 du §5 ci-dessus touchent des lots **antérieurs** (lot 0, lot 1, lot 3) et doivent y être écrites. |
| `vr-quest-unity-plan.md` | Le **§9 (POI sur GLB)** gagne la version de modèle, l'invalidation des POI et la décision « éditeur en iframe three.js ». Le **§6 (pricing)** gagne l'enveloppe de stockage chiffrée. Le §2 lot XR-4 gagne `ImmersiveBackground` comme source du fond de scène. |
| `todo-features.md` | La « Ressource 360° » devient les **trois** valeurs d'enum, en une migration. |
| Kanban | Les cartes 250, 280, 300, 320 et 330 restent valides. Ce document est la source à citer en `src:` pour la frontière. |