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
510 lines
28 KiB
Markdown
510 lines
28 KiB
Markdown
# 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,02–0,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. |
|