- TopingSystem with TopingDef registry, procedural mesh gen, instance collection - 2 toping types: stone bevel (h=0.06, smooth) + grass edge (h=0.12, bumpy) - 16 mesh variants per type indexed by 4-bit adjacency bitmask (~6 unique with symmetry) - Wedge cross-section: outer wall + sloped top, grass has sinusoidal height profile - Instance collection scans exposed +Y faces, checks same-material neighbors - Cross-chunk adjacency via VoxelWorld::getVoxel() - Integrated into VoxelRenderPath: init at Start(), stats in HUD - ~191K instances, 1920 mesh vertices for 170 chunks (validated) - Research doc (research_connected_meshes.md) + plan (plan_phase4.md)
252 lines
15 KiB
Markdown
252 lines
15 KiB
Markdown
# Recherche : Systèmes de meshes connectés/contextuels pour moteurs voxel
|
||
|
||
**Objectif** : Trouver le meilleur système (bitmask, WFC, dual grid, hybride) pour placer automatiquement des meshes décoratifs adaptatifs sur un terrain voxel temps réel.
|
||
|
||
**Mots-clés** : auto-tiling 3D, connected meshes, Wave Function Collapse, dual grid, marching squares mesh variants, modular mesh kit, contextual mesh placement.
|
||
|
||
---
|
||
|
||
## 1. Taxonomie des approches
|
||
|
||
### 1.1 Bitmask auto-tiling (lookup table)
|
||
|
||
Le plus simple : examiner les N voisins d'une cellule, construire un bitmask, indexer une table de mesh variants.
|
||
|
||
| Variante | Voisins | Cas bruts | Cas uniques (symétrie) | Meshes à créer |
|
||
|----------|---------|-----------|----------------------|----------------|
|
||
| 4-bit cardinal (2D) | 4 | 16 | ~6 | 6 + rotations |
|
||
| 8-bit blob (2D) | 8 | 256 | 47 | 47 |
|
||
| 4-bit per-face (3D) | 4 par face | 16 par face | ~6 par face | ~30 (6 faces × 5) |
|
||
| 6-bit face (3D) | 6 | 64 | ~18 | 18 |
|
||
|
||
**Avantages** : O(1), trivial à implémenter, déterministe, mise à jour instantanée.
|
||
**Inconvénients** : pas de cohérence globale, nombre de meshes croît vite avec la complexité.
|
||
|
||
**Implémentations notables** : Godot TileMap, RPG Maker, Vintage Story (JSON block models avec variantes par adjacence).
|
||
|
||
### 1.2 Wave Function Collapse (WFC)
|
||
|
||
Solveur de contraintes itératif : maintenir un ensemble de tiles possibles par cellule, collapser la cellule de moindre entropie, propager les contraintes aux voisins. Backtracking si contradiction.
|
||
|
||
**Avantages** : diversité visuelle, cohérence globale, flexible (n'importe quel tileset).
|
||
**Inconvénients** : coût CPU non-trivial, backtracking imprévisible, design de tilesets complexe, mal adapté au temps réel 60Hz.
|
||
|
||
**Implémentations notables** :
|
||
- [mxgmn/WaveFunctionCollapse](https://github.com/mxgmn/WaveFunctionCollapse) — référence originale (C#, ~12K stars)
|
||
- [BorisTheBrave/DeBroglie](https://github.com/BorisTheBrave/DeBroglie) — la lib WFC la plus complète (C#, 3D, symétries, painting)
|
||
- [Tessera](https://www.boristhebrave.com/2019/11/28/tessera-3d-tile-level-generation/) — outil Unity basé sur DeBroglie
|
||
- [marian42/wavefunctioncollapse](https://github.com/marian42/wavefunctioncollapse) — WFC 3D Unity pour bâtiments
|
||
|
||
### 1.3 Dual grid (marching squares/cubes avec meshes artisanaux)
|
||
|
||
La grille logique (données voxel) est **décalée d'une demi-cellule** par rapport à la grille visuelle. Chaque cellule visuelle examine 4 (2D) ou 8 (3D) coins de la grille logique → bitmask → lookup dans une table de mesh pré-modélisés.
|
||
|
||
C'est mathématiquement équivalent à **Marching Cubes**, mais au lieu de générer des triangles procéduralement, chaque cas est un **mesh artisanal**.
|
||
|
||
| Dimension | Coins | Cas bruts | Cas uniques (symétrie) |
|
||
|-----------|-------|-----------|----------------------|
|
||
| 2D | 4 | 16 | 6 |
|
||
| 3D | 8 | 256 | 15 (MC classique) ou ~23 (ambiguïtés) |
|
||
|
||
**Avantages** : très peu de meshes à créer (~10-15), transitions automatiquement seamless (bords partagés par construction), O(1) par cellule.
|
||
**Inconvénients** : la grille visuelle ne correspond pas à la grille logique (décalage ½ cellule → complique physique/gameplay), courbes limitées à un rayon de ½ cellule, multi-matériaux nécessite un traitement spécial.
|
||
|
||
**Sources clés** :
|
||
- [Oskar Stålberg tweet dual grid](https://x.com/OskSta/status/1448248658865049605)
|
||
- [Boris the Brave: Quarter-Tile Autotiling](https://www.boristhebrave.com/2023/05/31/quarter-tile-autotiling/) — variante sans décalage de grille
|
||
- [Wildtile](https://dualgridvoxels.docs.carbidefunction.co.uk/) — implémentation Unity 3D dual grid
|
||
- [TileMapDual](https://github.com/pablogila/TileMapDual) — implémentation Godot 2D
|
||
|
||
### 1.4 Quarter-tile / Eighth-tile (Boris the Brave)
|
||
|
||
**Alternative au dual grid sans décalage de grille**. Chaque cellule est subdivisée en 4 quadrants (2D) ou 8 octants (3D). Chaque quadrant sélectionne un sous-mesh basé sur 3 voisins (la cellule + 2 adjacents).
|
||
|
||
| Dimension | Sous-meshes uniques | Qualité visuelle |
|
||
|-----------|-------------------|-----------------|
|
||
| 2D (quarter-tile) | 5-6 | Équivalent blob (47 tiles) |
|
||
| 3D (eighth-tile) | ~10 | Équivalent MC (15 cas) |
|
||
|
||
**Avantages** : données restent sur les cellules (pas de décalage), peu de meshes à créer, qualité blob avec effort minimal.
|
||
**Inconvénients** : 4-8× plus de sous-meshes à instancier par cellule (mais GPU instancing amortit).
|
||
|
||
**Source** : https://www.boristhebrave.com/2023/05/31/quarter-tile-autotiling/
|
||
|
||
### 1.5 Marching cubes multi-matériaux (Boris the Brave)
|
||
|
||
Extension de marching squares/cubes pour N matériaux au lieu de 2 (solide/vide). **Seulement 15 cas topologiques** quel que soit le nombre de matériaux — seul le pattern de relations entre coins compte, pas les valeurs absolues.
|
||
|
||
**Insight clé** : une frontière herbe-pierre et une frontière sable-neige utilisent le **même template de mesh**, juste avec des textures différentes.
|
||
|
||
**Recommandation de l'auteur pour la 3D** : *"In 3D, I'd recommend that you just do regular marching cubes to get a single surface for all colors, then use a pixel shader to colorize that surface."* — c'est exactement notre approche Phase 3.
|
||
|
||
**Source** : https://www.boristhebrave.com/2021/12/29/2d-marching-cubes-with-multiple-colors/
|
||
|
||
---
|
||
|
||
## 2. Études de cas — Jeux et moteurs
|
||
|
||
### 2.1 Townscaper (Oskar Stålberg, 2020)
|
||
|
||
**Le cas de référence pour les meshes connectés procéduraux.**
|
||
|
||
**Technique** : pas du WFC standard, mais un système de contraintes déterministe sur dual grid :
|
||
- L'utilisateur peint des blocs solides/vides sur une grille irrégulière (Voronoi relaxé)
|
||
- Chaque point du dual grid examine les 8 cellules environnantes → bitmask → sélection de module
|
||
- ~80 modules pré-modélisés couvrent toutes les configurations
|
||
- **Pas de backtracking** : chaque configuration est valide par design ("every configuration must be valid")
|
||
- **Pas de randomness** : sélection déterministe (1 seul module valide par état)
|
||
|
||
**Différences clés vs WFC standard** :
|
||
|
||
| Aspect | WFC standard | Townscaper |
|
||
|--------|-------------|------------|
|
||
| Contradictions | Possibles → backtracking | Impossibles par design |
|
||
| Propagation | Globale | Locale uniquement |
|
||
| Sélection | Aléatoire parmi les valides | Déterministe (1 module/état) |
|
||
| Modules | 100+ | ~80 (~15-20 canoniques) |
|
||
| Performance | Variable (backtracking) | O(1) par cellule |
|
||
| Grille | Régulière | Irrégulière (Voronoi) |
|
||
|
||
**Principes réutilisables** :
|
||
1. Bitmask → lookup déterministe (pas besoin de solveur)
|
||
2. Exploiter les symétries (rotation/reflection) : 256 → ~15-20 cas uniques
|
||
3. Mise à jour locale uniquement (le voxel modifié + ses voisins immédiats)
|
||
4. Couleurs/matériaux = variations de texture sur les mêmes modules, pas des modules séparés
|
||
|
||
**Sources** :
|
||
- [How Townscaper Works (gamedeveloper.com)](https://www.gamedeveloper.com/game-platforms/how-townscaper-works-a-story-four-games-in-the-making)
|
||
- [Oskar Stålberg talk at Konsoll](https://konsoll.org/speaker/oskar-stalberg/)
|
||
- Threads Twitter/X avec diagrammes animés du dual grid
|
||
|
||
### 2.2 Wonderbox (Aquiris, Amilton Diesel)
|
||
|
||
**Statut** : pas de documentation technique publique trouvée. Amilton Diesel (Technical Art Director chez Aquiris, maintenant chez Epic Games) n'a pas publié de breakdown technique indexable. Le style visuel (blocs modulaires colorés en diorama) suggère un système de modules connectés, mais les détails techniques restent propriétaires.
|
||
|
||
**Sources** :
|
||
- [Aquiris press page](https://press.aquiris.com.br/games/wonderbox)
|
||
- [Wonderbox Behance gallery](https://www.behance.net/gallery/116125497/AQUIRIS-WONDERBOX)
|
||
|
||
### 2.3 Enshrouded (Keen Games, Holistic Engine)
|
||
|
||
**Technique** : moteur voxel propriétaire avec terrain SDF (signed distance field) + isosurface extraction lisse. Fondamentalement différent d'un moteur blocky — les voxels stockent des distances, pas des matériaux binaires.
|
||
|
||
**Décoration** : meshes placés sur la surface du terrain (vegetation, rochers) séparément du mesh voxel. Le système est hand-crafted par les artistes avec outils internes + Substance Painter.
|
||
|
||
**Pertinence** : limitée pour notre cas (terrain blocky, pas SDF). Le pattern architectural "terrain voxel + meshes décoratifs instanciés séparément" est par contre le même que notre Phase 4.
|
||
|
||
### 2.4 Portal Knights (Keen Games)
|
||
|
||
**Technique** : rendu blocky standard (cubes). Pas de système de décoration par adjacence documenté. Pertinence limitée.
|
||
|
||
### 2.5 Vintage Story (2024)
|
||
|
||
**Technique** : block models définis en JSON avec variantes sélectionnées par règles d'adjacence. Chaque bloc peut avoir plusieurs mesh variants, la sélection dépend du contexte (voisins, face exposée). Système data-driven (pas de code par type de bloc).
|
||
|
||
**Pertinence** : bon modèle pour un système de toping data-driven, mais le code source n'est pas ouvert pour la partie rendering.
|
||
|
||
### 2.6 Veloren (open source, Rust)
|
||
|
||
**Technique** : voxel RPG open source avec système de décoration combinant structures pré-créées + scatter-based placement. Codebase bien documentée sur [gitlab.com/veloren/veloren](https://gitlab.com/veloren/veloren).
|
||
|
||
---
|
||
|
||
## 3. "Driven WFC" — L'approche hybride (Boris the Brave)
|
||
|
||
L'article le plus pertinent pour notre cas : [Driven WFC](https://www.boristhebrave.com/2021/06/06/driven-wavefunctioncollapse/).
|
||
|
||
**Concept** : utiliser WFC comme "remplisseur de détails", pas comme générateur de structure. Un système externe (utilisateur, heightmap, algorithme) détermine la macro-structure ; WFC sélectionne les variantes compatibles dans les contraintes.
|
||
|
||
**Application au toping** :
|
||
1. Le monde voxel détermine la macro-structure (quels blocs existent, quels matériaux)
|
||
2. Le bitmask d'adjacence **contraint** quelles variantes de toping sont valides
|
||
3. Optionnellement, WFC **sélectionne** parmi les variantes valides pour de la variété visuelle
|
||
|
||
C'est exactement le workflow de Townscaper : l'utilisateur peint la structure → le système contraint les modules possibles → sélection déterministe (ou aléatoire pour plus de variété).
|
||
|
||
**Pour notre prototype** : commencer par la sélection déterministe (bitmask → lookup), ajouter la variété WFC plus tard si nécessaire.
|
||
|
||
---
|
||
|
||
## 4. Articles techniques clés (Boris the Brave)
|
||
|
||
| Article | URL | Pertinence |
|
||
|---------|-----|-----------|
|
||
| **Quarter-Tile Autotiling** | https://www.boristhebrave.com/2023/05/31/quarter-tile-autotiling/ | ⭐⭐⭐ Alternative au dual grid, ~5-6 meshes pour qualité blob |
|
||
| **Beyond Basic Autotiling** | https://www.boristhebrave.com/2021/09/12/beyond-basic-autotiling/ | ⭐⭐⭐ Multi-matériaux, composition par couches |
|
||
| **Multi-Color Marching Squares** | https://www.boristhebrave.com/2021/12/29/2d-marching-cubes-with-multiple-colors/ | ⭐⭐⭐ 15 cas quel que soit le nombre de matériaux |
|
||
| **Driven WFC** | https://www.boristhebrave.com/2021/06/06/driven-wavefunctioncollapse/ | ⭐⭐⭐ WFC comme détail-filler, pas générateur |
|
||
| **Classification of Tilesets** | https://www.boristhebrave.com/2021/11/14/classification-of-tilesets/ | ⭐⭐ Taxonomie formelle, aide au design |
|
||
| **WFC Explained** | https://www.boristhebrave.com/2020/04/13/wave-function-collapse-explained/ | ⭐⭐ Comprendre AC-4, support counting |
|
||
| **Editable WFC** | https://www.boristhebrave.com/2022/04/25/editable-wfc/ | ⭐⭐ Re-solving local pour édition temps réel |
|
||
| **Constraint-Based Tile Generators** | https://www.boristhebrave.com/2021/10/31/constraint-based-tile-generators/ | ⭐⭐ Comparaison WFC vs Model Synthesis |
|
||
| **Marching Cubes Tutorials (2D/3D)** | https://www.boristhebrave.com/2018/04/15/marching-cubes-tutorial/ | ⭐ Fondamentaux dual grid |
|
||
|
||
---
|
||
|
||
## 5. Comparaison pour notre cas d'usage
|
||
|
||
Notre besoin : placer des meshes décoratifs 3D sur les faces exposées de voxels dans un moteur temps réel (60+ FPS, monde dynamique animé).
|
||
|
||
| Critère | Bitmask 4-bit | Quarter-tile | Dual grid 3D | WFC | Driven WFC |
|
||
|---------|--------------|-------------|-------------|-----|-----------|
|
||
| **Complexité code** | Très faible | Faible | Moyen | Élevé | Moyen |
|
||
| **Meshes à créer** | 16 (~6 uniques) | 5-6 | 10-15 | Variable | Variable |
|
||
| **Qualité visuelle** | Basique | Blob-quality | Smooth transitions | Excellent | Très bon |
|
||
| **Performance** | O(1) lookup | O(1) lookup × 4 | O(1) lookup | O(N) solver | O(1) + O(N) init |
|
||
| **Multi-matériaux** | N² explosion | Couches | 15 cas pour N mat | Naturel | Naturel |
|
||
| **Mise à jour dynamique** | Instantanée | Instantanée | Instantanée | Re-solve local | Re-solve local |
|
||
| **Cohérence globale** | Non | Non | Non | Oui | Partielle |
|
||
| **Adapté à 60Hz anim** | ✅ | ✅ | ✅ | ❌ | ⚠️ (init seul) |
|
||
|
||
---
|
||
|
||
## 6. Recommandation
|
||
|
||
### Approche recommandée : Bitmask 4-bit + Quarter-tile optionnel
|
||
|
||
**Phase 4.1** : Bitmask 4-bit simple (16 cas, ~6 uniques avec symétrie)
|
||
- Implémentation triviale, validé rapidement
|
||
- Suffisant pour le prototype (rebords, bordures)
|
||
- Le plan existant dans `plan_phase4.md` est adapté
|
||
|
||
**Phase 4.2** (optionnel) : Upgrade vers Quarter-tile
|
||
- Même données voxel, meilleure qualité visuelle
|
||
- Chaque face subdivisée en 4 quadrants, ~5-6 sous-meshes
|
||
- Qualité visuelle blob (47 tiles) avec seulement 5-6 meshes par type de toping
|
||
- Référence : Boris the Brave quarter-tile article
|
||
|
||
**Non recommandé pour le prototype** :
|
||
- WFC complet : trop complexe, mal adapté à l'animation 60Hz
|
||
- Dual grid 3D : nécessiterait de refactorer le mesher (décalage de ½ cellule)
|
||
- Socket-based modules : overhead d'authoring trop important
|
||
|
||
### Insight clé de Townscaper applicable directement
|
||
|
||
**"Every configuration must be valid"** — concevoir les meshes de toping pour que TOUTE combinaison de bitmask produise un résultat visuellement acceptable. Pas de fallback, pas de cas d'erreur. Chaque bitmask (0-15) a un mesh dédié, même si certains sont dégénérés (mesh vide pour bitmask 0 = pas de voisins du bon type).
|
||
|
||
### Multi-matériaux via composition par couches
|
||
|
||
Au lieu de créer des meshes séparés pour chaque paire de matériaux (explosion N²), utiliser des **meshes de bordure composés par couche** :
|
||
- Un set de meshes "bordure" par matériau qui se compose par-dessus le quad voxel de base
|
||
- La texture/couleur vient du matériau, pas du mesh
|
||
- C'est l'approche "Beyond Basic Autotiling" de Boris the Brave
|
||
|
||
---
|
||
|
||
## Sources complètes
|
||
|
||
### Articles techniques
|
||
- Boris the Brave — https://www.boristhebrave.com/ (voir tableau section 4)
|
||
- How Townscaper Works — https://www.gamedeveloper.com/game-platforms/how-townscaper-works-a-story-four-games-in-the-making
|
||
- Wildtile docs — https://dualgridvoxels.docs.carbidefunction.co.uk/
|
||
- Transvoxel — https://transvoxel.org/
|
||
|
||
### Repos open source
|
||
- [mxgmn/WaveFunctionCollapse](https://github.com/mxgmn/WaveFunctionCollapse) — WFC référence (~12K stars)
|
||
- [BorisTheBrave/DeBroglie](https://github.com/BorisTheBrave/DeBroglie) — WFC lib C# la plus complète
|
||
- [TileMapDual](https://github.com/pablogila/TileMapDual) — dual grid 2D Godot
|
||
- [Veloren](https://gitlab.com/veloren/veloren) — voxel RPG open source Rust
|
||
|
||
### Talks et vidéos
|
||
- Oskar Stålberg talks (YouTube : "Oskar Stålberg Townscaper", "Oskar Stålberg procedural")
|
||
- Sebastian Lague voxel terrain (YouTube, 2023-2024)
|