- DRAFT.md : cases 8.1-8.6 cochées, état 'terminée et vérifiée 2026-09-18', bilan final. - README.md : workflow manuel et déclaratif (extraits Mesh::new -> Geometry/from_geometry), note API create_mesh(Geometry), section architecture + table quick reference, roadmap +1 (CPU storage). - ROADMAP.md (1.2) : colors + refactor Mesh/Scene cochés 'fait', déviation D3 'implémenté'. - PLAN.md : statut réel à jour 2026-09-18 (Étape 8 effectuée). - resources/README.md : Mesh::new() -> from_geometry() + rétention CPU.
12 KiB
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 docsdocs/*restent stables.
État. Étape 8 terminée et vérifiée le 2026-09-18 :
Mesh.geometry: Arc<Geometry>+ buffers dérivés, APIcreate_meshbaséeGeometry, exemples réécrits, validation verte, docs à jour.
É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 :
Geometryexiste 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 CPUposition/normal/uv/color→ contrat GPU (stride 56 o,VertexBufferLayoutconstruit sur ses offsets, standard shader litcolorunlit).Mesh(lib/src/resources/mesh.rs) :{ vertex_buffer, index_buffer, num_vertices, num_indices, material: Option<Arc<Material>> }, construit viaMesh::new(device, vertices, indices)/Mesh::with_material. Il n'utilise pasGeometry: il prend des&[Vertex]et les uploade.Scene::create_mesh(id, vertices: &[Vertex], indices, material)(lib/src/scene/scene.rs) uploade viaMesh::newpuis lie le matériau. Les buffers GPU restent la seule donnée : aucune rétention CPU.Entity={ mesh_id, transform };iter_entitiesrenvoie(&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: TransformsurMesh→ 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 :
positionsobligatoire ;normals,uvs,colors,indicesoptionnels mais doivent avoir la même longueur quepositionsquand 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(..)retournantSelf. - ajouter une validation
Geometry::validate() -> Result<(), GeometryError>(ou unSelf::from_...vérifiant les longueurs) — erreur si les tableaux optionnels ont une longueur différente depositions.
- ajouter
É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 zippositions/normals/uvs/colorsavec 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_buffersiindicesprésent (index u16).
- conserver
num_vertices/num_indices(dérivés de la géométrie) pourrender. - 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 docresources/mod.rs(ligne «mesh::new()uploads Vertex arrays... ») pour refléterGeometry.
- ajouter le champ
É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>, appelleMesh::from_geometry(self.device(), arc, mat).
- il construit
- mettre à jour la doc de
Scene/resourcessur le rôle deGeometry. - ré-export : exposer
Geometryà la racine (déjà viamath::Geometry) et, à la convenance, depuiswsg_lib::resourcespour les exemples.
- changer
É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 deGeometry(ouGeometry::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")).
- remplacer
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).
- construire une
lib/examples/manual.rs(exemple bas-niveau, utiliseMesh::new(renderer.device(), &vertices, ...)) :- réécrire sur
Mesh::from_geometry(device, Arc<Geometry>, None).
- réécrire sur
- mettre à jour les en-têtes / commentaires des exemples (références à
Vertexen public).
Étape 8.6 — Validation
cargo fmt --all(aucun diff résiduel).cargo check --workspacepuiscargo build --workspacesans warning (veiller à la régularité des tableaux dans les exemples).cargo test --workspace(zéro test à ce stade, mais compilation clean).cargo doc --no-depssans warningmissing_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 codeMesh::new→Geometry, section architecture) et les statutsdocs/PLAN.md+docs/ROADMAP.md(cocher le refactor 1.2 « stockage CPU » ; laissertransformdocumenté comme déviation en D3).
Point d'étape
- Caser le refactor :
Mesh.geometry: Arc<Geometry>+ buffers dérivés, APIcreate_meshbaséeGeometry, exemples réécrits, validation verte, docs à jour. - Deux commits séparés comme d'habitude : un
refactor(...)(8.1–8.5) puis undocs(...)(8.6). Rédiger un court bilan et ouvrir la question du prochain chantier.
Bilan (2026-09-18)
L'Étape 8 est terminée et vérifiée :
Geometry(math) : champcolors, constructeurGeometry::new(positions)+ builder fluent (.with_normals/.with_uvs/.with_colors/.with_indices),validate()+GeometryError,indices()etto_vertices()/try_into_vertices()(zip positions/normals/uvs/colors avec défauts normale[0,0,1], uv[0,0], blanc opaque).Mesh(resources) : retientgeometry: Arc<Geometry>(CPU, D5) + buffers GPU pré-uploadés ; constructeur uniqueMesh::from_geometry(device, Arc<Geometry>, Option<Arc<Material>>)(D4) —Mesh::new/with_material(&[Vertex]) supprimés ; accesseursgeometry()/material()/set_material().Scene:create_mesh(id, Geometry, Option<&str>)(D4) ;Geometryexposé viamath(D2) et ré-exporté en convenance depuisresources.- Exemples cube/simple/manual réécrits sur
Geometry(8.5).simplepasse parNonepour vérifier le matériau par défaut (Scene::default_material). - Validation :
cargo fmt(aucun diff),build/checksans warning,testvert (1 unitaire shader + 1 doc-testGeometry::new),docsansmissing_docs, 3 exemples lancés (rendu sans panic). - Commits :
refactor(...)(8.1–8.5) +docs(...)(8.6).
Prochain chantier possible : la suite du ROADMAP — gestion des matériaux/textures (Phase 2/4,
ex. Texture + uniform diffuse), ou remonter vers les handles typés (Phase 2/5) / pipeline
GPU-driven (Phase 3) avec la bounding box dans Geometry (le champ colors et la rétention CPU
Arc<Geometry> posent déjà la base du culling).
Fin du DRAFT Étape 8 — implémentée et vérifiée le 2026-09-18.