Files
wsg/docs/DRAFT.md
T
Jérôme Bousquié 6f6b72ae8d docs(draft): valider les décisions restantes Étape 8 (D2, D4, D5, D6)
- D2 : Geometry reste en math (structure de donnees pure), re-export racine
- D4 : voie unique Mesh::from_geometry(Arc<Geometry>) ; suppression de l API &[Vertex]
- D5 : retention CPU (Arc<Geometry>) + buffers GPU pre-uploades
- D6 : convertisseur nomme Geometry::to_vertices() avec regles de remplissage

Toutes les decisions D1-D6 et la proposition 8.1 sont desormais validees.
2026-09-18 08:42:35 +02:00

138 lines
10 KiB
Markdown
Raw 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.
# DRAFT — Plan d'implémentation
> **Usage.** Ce fichier (dans `docs/`) sert de brouillon pour le plan détaillé de l'étape en cours.
> **Son contenu est effacé au début de chaque nouvelle étape.** La source de vérité de l'état est
> le code + README.md ; les autres docs `docs/*` restent stables.
> **État.** Étape 8 en préparation — refactor du stockage CPU des données géométriques :
> `Mesh` contient `geometry: Arc<Geometry>`. Étape 7 terminée et vérifiée le 2026-09-17.
---
# Étape 8 — Stockage CPU : `Mesh` contient `Arc<Geometry>`
## Objectif
Donner à `Mesh` une source de vérité **CPU partagée** pour sa géométrie, en plus de ses buffers GPU.
Le ROADMAP 1.2 demande `Mesh { geometry: Arc<Geometry>, vertex_buffer, index_buffer, ... }` :
on met en œuvre la partie *stockage CPU* (`geometry: Arc<Geometry>`), en **déviant sur le champ
`transform`** (voir Décisions D3).
Valeurs apportées :
- **Réutilisation mémoire** : plusieurs meshes peuvent partager le même `Arc<Geometry>` (ex. deux
meshes cube différents partagent une géométrie cube).
- **Base pour les phases suivantes** : bounding box (culling, Phase 3), compute transforms, accès UV
pour les textures (Phase 4), accès normales pour des calculs CPU.
- **Nettoyage du modèle de données** : `Geometry` existe aujourd'hui (`lib/src/math/geometry.rs`)
mais n'est **référencé nulle part** dans le code. Il devient le type canonique côté CPU.
## État de départ vérifié (2026-09-17)
- `Geometry` (lib/src/math/geometry.rs) : `{ positions: Vec<[f32;3]>, normals, uvs,
indices }` — **défini et ré-exporté mais jamais utilisé** (aucune construction, aucun champ lu).
- `Vertex` (lib/src/resources/vertex.rs) : tuple CPU `position/normal/uv/color` → **contrat GPU**
(stride 56 o, `VertexBufferLayout` construit sur ses offsets, standard shader lit `color` unlit).
- `Mesh` (lib/src/resources/mesh.rs) : `{ vertex_buffer, index_buffer, num_vertices,
num_indices, material: Option<Arc<Material>> }`, construit via `Mesh::new(device, vertices, indices)`
/ `Mesh::with_material`. Il n'**utilise pas** `Geometry` : il prend des `&[Vertex]` et les uploade.
- `Scene::create_mesh(id, vertices: &[Vertex], indices, material)` (lib/src/scene/scene.rs) uploade
via `Mesh::new` puis lie le matériau. Les buffers GPU restent la seule donnée : aucune rétention CPU.
- `Entity` = `{ mesh_id, transform }` ; `iter_entities` renvoie `(&str, &Arc<Mesh>, &Transform)`
(lib/src/scene/scene.rs). Un mesh est **partagé** par plusieurs entités à des transforms différents.
- Le ROADMAP 1.2 liste `transform: Transform` sur `Mesh` → **déviation justifiée en D3**.
## Décisions / compromis
| # | Question | Options | Décision retenue | Justification |
|---|----------|---------|------------------|---------------|
| D1 | Format CPU stocké | (a) garder `Geometry` en tableaux éclatés `positions/normals/uvs/indices` ; (b) y ajouter `colors` ; (c) ranger un `Vec<Vertex>` | **(a)+(b) : `Geometry` en tableaux + `colors`, et conversion `Geometry -> Vec<Vertex>`** — **validé 2026-09-18** | Respecte le contrat GPU (`Vertex`) sans duplication conceptuelle : `Geometry` = données CPU pures, `Vertex` = format d'upload interleaved. Le shader lit `color` ⇒ il faut porter la couleur dans `Geometry`. |
| D2 | Où `Geometry` vit / qui le ré-exporte | (a) reste en `math` ; (b) déplacé en `resources` | **(a) reste en `math`**, ré-exporté de `lib.rs` — **validé 2026-09-18** | Cohérent : c'est une structure de *données* pure, comme `Transform`/`Camera`. Exposer via `math::Geometry` (déjà le cas) + une ré-export `resources` optionnelle à la convenance. |
| D3 | Champ `transform` sur `Mesh` | (a) l'ajouter (ROADMAP littéral) ; (b) le laisser sur `Entity` | **(b) : `transform` reste sur `Entity`** — **validé 2026-09-18** | Un `Mesh` est **partagé** par plusieurs entités à des transforms différents (modèle instancé). Mettre un `transform` unique sur `Mesh` casserait ce modèle (Étape 4/7). **Déviation documentée** au ROADMAP 1.2. |
| D4 | API de création | (a) `Mesh::new(device, vertices, indices)` actuel ; (b) `Mesh::new(device, geometry)` ; garder ou non surcharge | **(b) : `Mesh::from_geometry(device, Arc<Geometry>)` ; suppression de l'ancienne voie `&[Vertex]` dans `Mesh` et `Scene`** — **validé 2026-09-18** | Une seule source canonique. Les examples (non contraignants) sont réécrits pour construire une `Geometry`. `Vertex` reste utilisé en interne pour l'upload. |
| D5 | Rétention CPU + GPU | (a) ne garder que GPU ; (b) garder CPU `Arc` **et** les buffers GPU pré-uploadés | **(b) : `Mesh` garde `geometry: Arc<Geometry>` ET `vertex_buffer`/`index_buffer`** — **validé 2026-09-18** | Pas de re-upload par frame (perf) ; le `Arc` sert les phases futures (bbox, compute, textures). Double stockage assumé. |
| D6 | Convertisseur `Geometry -> Vertex` | (a) méthode `Geometry::to_vertices()` ; (b) impl `From<&Geometry>` | **(a) `Geometry::to_vertices()`** (ou `into_vertices`) — **validé 2026-09-18** | Explicite, avec règles de remplissage documentées (normales/UV/couleur par défaut si absents). |
## Étape 8.1 — Étendre `Geometry` (couleur + validation) — **proposition validée 2026-09-18**
- [ ] Dans `lib/src/math/geometry.rs` :
- [ ] ajouter `colors: Option<Vec<[f32; 4]>>` en champ optionnel (parallèle à `normals`/`uvs`).
- [ ] documenter les invariants : `positions` obligatoire ; `normals`, `uvs`, `colors`,
`indices` optionnels mais doivent avoir la même longueur que `positions` quand présents.
- [ ] ajouter un constructeur ergonomique, ex. `Geometry::new(positions, indices) ->
Geometry` (positions/valeurs par défaut) et un builder fluent
`.with_normals(..)/.with_uvs(..)/.with_colors(..)` retournant `Self`.
- [ ] ajouter une **validation** `Geometry::validate() -> Result<(), GeometryError>` (ou un
`Self::from_...` vérifiant les longueurs) — erreur si les tableaux optionnels ont une
longueur différente de `positions`.
## Étape 8.2 — Convertisseur `Geometry` → `Vec<Vertex>`
- [ ] Dans `lib/src/math/geometry.rs` (ou un petit trait dédié), implémenter :
- [ ] `Geometry::to_vertices() -> Vec<Vertex>` qui zip `positions`/`normals`/`uvs`/`colors`
avec des valeurs par défaut : normale `[0,0,1]`, uv `[0,0]`, couleur blanche `[1,1,1,1]`.
- [ ] documenter clairement ces défauts (i.e. une géométrie sans normales via Phong sera plate).
- [ ] (optionnel) `Geometry::indices()` accesseur sûr (clone ou slice) pour l'upload.
## Étape 8.3 — `Mesh` contient `Arc<Geometry>` et construit ses buffers
- [ ] Dans `lib/src/resources/mesh.rs` :
- [ ] ajouter le champ `geometry: Arc<Geometry>`.
- [ ] remplacer/ajouter `Mesh::from_geometry(device: &wgpu::Device, geometry: Arc<Geometry>,
material: Option<Arc<Material>>) -> Mesh` :
- [ ] `let vertices = geometry.to_vertices(); let indices = geometry.indices;`
- [ ] upload `vertex_buffer` (stride = `size_of::<Vertex>()`, `create_buffer_init`),
- [ ] upload `index_buffer` si `indices` présent (index u16).
- [ ] conserver `num_vertices`/`num_indices` (dérivés de la géométrie) pour `render`.
- [ ] accesseurs publics : `geometry() -> &Arc<Geometry>`, `material()`, `set_material()`.
- [ ] **supprimer** les anciennes voies `Mesh::new(device, vertices: &[Vertex], ...)` /
`Mesh::with_material(...)` (remplacées). Mettre à jour la doc `resources/mod.rs` (ligne
« `mesh::new()` uploads Vertex arrays... ») pour refléter `Geometry`.
## Étape 8.4 — Adapter `Scene` / l'API déclarative
- [ ] Dans `lib/src/scene/scene.rs` :
- [ ] changer `create_mesh(id, vertices: &[Vertex], indices, material)` →
`create_mesh(id, geometry: Geometry, material: Option<&str>) -> Result<...>` :
- [ ] il construit `Arc<Geometry>`, appelle `Mesh::from_geometry(self.device(), arc, mat)`.
- [ ] mettre à jour la doc de `Scene` / `resources` sur le rôle de `Geometry`.
- [ ] ré-export : exposer `Geometry` à la racine (déjà via `math::Geometry`) et, à la convenance,
depuis `wsg_lib::resources` pour les exemples.
## Étape 8.5 — Réécrire les exemples (non contraignants) sur `Geometry`
- [ ] `lib/examples/cube.rs` :
- [ ] remplacer `cube_vertices() -> Vec<Vertex>` / `cube_indices()` par un builder de
`Geometry` (ou `Geometry::new(...).with_normals(...).with_indices(...)`) ; couleur blanche
par défaut → vérifier le rendu Phong inchangé.
- [ ] appeler `scene.create_mesh("cube_mesh", geometry, Some("cube_material"))`.
- [ ] `lib/examples/simple.rs` :
- [ ] construire une `Geometry` (positions ± couleurs par sommet pour le quad unlit) ;
- [ ] `scene.create_mesh("quad", geometry, None)` (matériau par défaut).
- [ ] `lib/examples/manual.rs` (exemple bas-niveau, utilise `Mesh::new(renderer.device(),
&vertices, ...)`) :
- [ ] réécrire sur `Mesh::from_geometry(device, Arc<Geometry>, None)`.
- [ ] mettre à jour les en-têtes / commentaires des exemples (références à `Vertex` en public).
## Étape 8.6 — Validation
- [ ] `cargo fmt --all` (aucun diff résiduel).
- [ ] `cargo check --workspace` puis `cargo build --workspace` **sans warning** (veiller à la
régularité des tableaux dans les exemples).
- [ ] `cargo test --workspace` (zéro test à ce stade, mais compilation clean).
- [ ] `cargo doc --no-deps` **sans warning `missing_docs`** (la crate est en `#![warn(missing_docs)]`).
- [ ] Lancer les 3 exemples (simple, cube, manual) et constater l'absence de panic / rendu visé.
- [ ] Mettre à jour `README.md` (extraits de code `Mesh::new` → `Geometry`, section architecture)
et les statuts `docs/PLAN.md` + `docs/ROADMAP.md` (cocher le refactor 1.2 « stockage CPU » ;
laisser `transform` documenté comme déviation en D3).
## Point d'étape
- [ ] Caser le refactor : `Mesh.geometry: Arc<Geometry>` + buffers dérivés, API `create_mesh`
basée `Geometry`, exemples réécrits, validation verte, docs à jour.
- [ ] Deux commits séparés comme d'habitude : un `refactor(...)` (8.1–8.5) puis un `docs(...)`
(8.6). Rédiger un court bilan et ouvrir la question du prochain chantier.
---
_Fin du DRAFT Étape 8 — à valider avant implémentation._