# Architecture de Rendu : Cycle Update/Render et Gestion des Données Ce document définit la stratégie de gestion de la mutabilité et des données du moteur wsg_lib, conçue pour maximiser la performance et garantir la sécurité mémoire via Rust. ## 1. La Dichotomie Update / Render Pour éviter les conflits de données et optimiser le pipeline GPU, le moteur sépare strictement le cycle de vie de la frame en deux phases : ### Phase Update (Mutabilité Totale) - L'utilisateur peut modifier librement l'état de la Scene (transformations, propriétés des matériaux, ajout/suppression d'entités). - C'est l'unique zone de mutation autorisée. Le système est en "lecture-écriture". ### Phase Render (Lecture et Orchestration) - La Scene est considérée comme immuable vis-à-vis du rendu. - Le moteur itère automatiquement sur les entités pour soumettre les commandes au GPU. - L'utilisateur dispose d'une "trappe" via `AppHandler::render()` pour injecter du code de rendu personnalisé, mais sans modifier l'état métier des objets. ## 2. Gestion des Données : Indirection par ID (Handle) Pour contourner les limitations du Borrow Checker de Rust lors de l'accès aux ressources, le moteur utilise une approche par **Indirection (Handles/IDs)**. - **HashMaps et Vecs indexés** : Les ressources (`Mesh`, `Material`) ne sont pas stockées sous forme de références directes (`&Mesh`) dans les entités. Elles sont stockées dans des conteneurs centralisés dans la Scene. - **Identifiants (Handles)** : Chaque entité possède un `MeshId` ou `MaterialId`. - **Avantage** : Cela élimine les problèmes de durées de vie (lifetimes) complexes. Vous pouvez passer des IDs partout sans bloquer la mutabilité des conteneurs parents. - **Performance** : Cette approche permet au moteur de trier les entités par `MaterialId` avant le rendu, réduisant drastiquement les changements d'état GPU (**State Change Overhead**). ## 3. Points d'Attention du Borrow Checker Bien que cette architecture facilite la gestion de la mémoire, des règles strictes s'appliquent à `App` : - **Conflit de Mutabilité** : App contient à la fois la Scene et le Renderer. Il est interdit d'emprunter `&mut scene` et `&mut renderer` simultanément. - **Solution** : Dans la boucle de rendu interne (`App::run`), le moteur doit être structuré pour séquencer les accès : `let scene = &app.scene;` suivi de `let renderer = &mut app.renderer;` puis `renderer.render_scene(scene);`. - **Séparation des Responsabilités** : Le RenderLoop doit posséder la main sur l'ordonnancement pour éviter que l'utilisateur ne tente de muter la scène pendant que le renderer est en train de lire les données. ## 4. Synthèse des Avantages - **Performance (Batching)** : Le rendu automatique par le moteur permet d'implémenter des stratégies de rendu optimales invisibles pour l'utilisateur. - **Ergonomie** : L'utilisateur n'écrit pas de boucles de rendu complexes. Il se concentre sur sa logique métier dans `update()`. - **Sécurité** : L'utilisation d'IDs évite les cycles de références et les références pendantes, rendant le code plus sûr et plus facile à maintenir. ## 5. Guide de Développement pour l'Utilisateur > "Si vous devez changer la position d'un objet ou son matériau, faites-le dans `update()`. Si vous avez besoin d'afficher un élément de debug ou un rendu spécial, faites-le dans `render()`, mais traitez les objets de la scène comme des données en lecture seule." Cette structure permet au projet d'être extrêmement scalable. L'ajout futur de fonctionnalités (Lumières, Textures, Caméras) ne nécessitera que d'ajouter de nouveaux conteneurs dans la Scene et de mettre à jour le système de tri dans `Renderer::render_scene()`.