diff --git a/CHANGELOG.fr.md b/CHANGELOG.fr.md index ffbb151..49beacc 100644 --- a/CHANGELOG.fr.md +++ b/CHANGELOG.fr.md @@ -6,6 +6,10 @@ La section « Non publié » est reprise par `a2m release` sous le numéro de la ## [Non publié] +### Modifié + +- Documentation en deux langues : `README.md` en anglais, `README.fr.md` en français. + ## [1.4.1] - 2026-10-20 ### Modifié diff --git a/CHANGELOG.md b/CHANGELOG.md index 43ec071..550b441 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The "Unreleased" section is taken by `a2m release` under the number of the new v ## [Unreleased] +### Changed + +- Documentation in two languages: `README.md` in English, `README.fr.md` in French. + ## [1.4.1] - 2026-10-20 ### Changed diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..96d2935 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,138 @@ +# Slice Wrap — add-on Blender (5.1 → 5.x) + +*[English version](README.md)* + +Transforme un maillage **troué, à doubles parois ou bruité** (scan, génération IA type Pixal3D / Trellis) +en une **surface propre, fermée et détaillée**, prête à sculpter. Aucune dépendance : numpy seulement +(fourni avec Blender). + +Panneau : **Vue 3D > barre latérale (N) > onglet « Slice Wrap »**. + +## Pourquoi pas le Voxel Remesh de Blender ? +Le Voxel Remesh (et *Mesh to Volume* en Geometry Nodes) reconstruit un volume… mais **fuit** dès que la +coque a un trou : l'intérieur n'est pas rempli et on obtient une double peau, du moiré, des ratés. +Slice Wrap remplit le volume **tranche par tranche selon X, Y et Z** : un trou ne fait fuir que les quelques +tranches qu'il traverse, les autres directions le compensent. + +## Utilisation +Tout s'applique à **l'objet sélectionné** (actif) : il n'y a pas de cible à choisir. La projection se fait toujours +sur la source de l'enveloppe. Sans maillage sélectionné, les boutons sont grisés. + +1. Sélectionnez le maillage source (troué) en mode Objet. +2. Réglez au besoin la section **Envelope** et **Wrap**, puis cliquez **Slice Wrap** (un clic) : + Envelope → Wrap Setup → Freeze, et **Despike** en plus si **Despike After** est coché. +3. Le résultat `` (par défaut `_slicewrapped`) est prêt à sculpter (base légère + niveaux + Multires). La source est cachée. + +### Calculs longs : confirmation, progression, annulation +Slice Wrap, Envelope, Regenerate et Despike affichent d'abord un message : le calcul peut être long, Blender +ignorera les clics pendant ce temps (il n'est pas planté), Échap annule. Case « Show this message next time » +(aussi dans *Preferences > Add-ons > Slice Wrap > Confirm Long Operations*). +Pendant le calcul (ainsi que Freeze et Analyze) : **barre de progression** avec l'étape en cours et le temps écoulé, +dans la barre d'état en bas de la fenêtre et en haut du panneau. **Échap** annule : rien n'est créé ni modifié. +Limite : quelques opérations internes de Blender (subdivision Multires, Multires Reshape, Voxel Remesh) sont d'un +seul tenant. Sur un maillage lourd, l'affichage reste figé quelques secondes sur cette étape, puis la progression +reprend. + +### Nom et rangement du résultat +- **Suffix** (défaut `_slicewrapped`) : nom du maillage créé = nom de la source + suffixe. +- **Numérotation automatique** : si le nom existe déjà, `.001`, `.002`… comme Blender — **aucun objet existant + n'est jamais écrasé** (même avec un suffixe vide, la source reste intacte). +- **Collection** (case + nom, défaut `SliceWrapCollection`) : le résultat y est rangé ; si la collection existe, + elle est simplement réutilisée (son contenu n'est pas touché), sinon elle est créée et liée à la scène. + Case décochée : le résultat va dans les collections de la source. +- **Regenerate** est le seul bouton qui recalcule un objet existant : l'enveloppe active, sur place. + +### Sous-panneau « Steps » (replié) — chaque étape séparément +| # | Bouton | Ce qu'il fait | +|---|--------|---------------| +| 1 | **Envelope** | Sur l'objet actif (la source, jamais modifiée) : voxels → fermeture des trous → remplissage par tranches → surface fermée (Voxel Remesh sur volume déjà plein, sans fuite) → plus grande pièce → lissage de Taubin. Crée `` (numéroté si le nom existe). | +| | ↻ **Regenerate** | Recalcule l'enveloppe active depuis sa source avec les réglages actuels (pseudo-modificateur). Refusé si l'enveloppe est déjà wrappée. | +| 2 | **Wrap Setup** | Gonfle l'enveloppe le long des normales (pour qu'elle soit entièrement *au-dessus* de la peau), ajoute **Multires** (N niveaux) puis **Shrinkwrap** : *Project*, le long des normales, **vers l'intérieur seulement**, avec une distance limite. | +| 3 | **Freeze** | Fige la projection **dans les niveaux du Multires** (Multires Reshape) et retire le Shrinkwrap. Avec **Repair Missed Rays**, les sommets dont la projection a raté — rien touché (aiguilles) ou trop loin (creux sur une paroi interne) — sont détectés exactement (comparaison avant / après) et reconstruits depuis leurs voisins. | + +Astuce : pour couper le socle / les épaules avant la projection, faites **Envelope**, coupez (Bisect), puis +**Wrap Setup** et **Freeze**. + +### Sous-panneau « Despike » — outil manuel +Filtre anti-pointes résiduel : un sommet n'est corrigé que s'il est **isolé**, nettement plus loin de la moyenne +de ses voisins que ceux-ci ne le sont des leurs ; le relief normal (oreilles, paupières) n'est pas lissé. +- **Distance** : écart minimal pour être une pointe (0 = automatique : longueur moyenne d'arête). +- **Strength** (0–1) : part du chemin vers la moyenne des voisins. +- **Iterations** : nombre de passes. **Isolation** : la pointe doit dévier N fois plus que ses voisins. +- **Vertex Group Filters** : liste (+ / − / vider) des groupes de sommets à traiter. Le **poids** du groupe module + la force (fondu possible en bordure). **Liste vide = toute la surface.** Si la liste contient des groupes + dont aucun n'existe, le Despike refuse de s'exécuter (pour ne jamais traiter toute la surface par erreur). + Les groupes de la base sont propagés aux niveaux du Multires. +- **Protect Detail** : atténue le Despike en proportion du détail (analyse de forme recalculée à la volée), pour + ne jamais aplatir paupières, narines ou oreilles. + +### Sous-panneau « Analyze » — optionnel, ne modifie jamais la géométrie +Analyse la forme de l'objet actif (Multires compris) : pour chaque sommet, la répartition des normales sur un +voisinage (tenseur de covariance) et la courbure moyenne signée. Résultat écrit sur le maillage de base : + +| Donnée | Type | Contenu | +|--------|------|---------| +| `sw_detail` | attribut float 0–1 | densité de détail (la surface « tourne » beaucoup) — carte de densité pour une retopo | +| `sw_curvature` | attribut float −1…1 | > 0 convexe (bosse), < 0 concave (creux) | +| `sw_anisotropy` | attribut float 0–1 | ~1 : la surface tourne dans **une** direction (pli, crête, doigt) ; ~0 : dans toutes | +| `sw_shape` | attribut entier | tag : 0 Flat, 1 Bulge (dôme), 2 Hollow (cuvette), 3 Ridge (crête), 4 Fold (pli), 5 Saddle (selle) | +| `sw_flow` | attribut vecteur | direction du pli / de la crête = direction que doit suivre une boucle d'arêtes | +| `SW_Detail_Color`, `SW_Shape_Color` | couleurs | affichage (boutons **Detail** / **Shapes**, ✕ pour revenir) | +| `SW_Detail`, `SW_Bulge`, `SW_Hollow`, `SW_Ridge`, `SW_Fold`, `SW_Saddle` | groupes de sommets | filtres Despike, masques, ou carte de densité d'un remailleur | + +Couleurs des tags : gris Flat · rouge Bulge · bleu Hollow · jaune Ridge · cyan Fold · violet Saddle. +Les couleurs portent le suffixe `_Color` car groupes de sommets et attributs partagent le même espace de noms. + +## Réglages +- **Voxel : Relative / Absolute** — la finesse de l'enveloppe. + - *Relative* (défaut, **Voxel %** = 0,6 % de la plus grande dimension) : indépendant de l'échelle — le même + réglage donne le même résultat sur une tête de 23 cm, une tête normalisée à 1 m ou une main importée à 3,7 m. + Plus petit = plus fidèle mais plus lourd ; trop fin sur une source bruitée → la projection « voit » le grain. + - *Absolute* (**Voxel Size** en unités) : même finesse physique sur plusieurs objets de tailles différentes + (ex. tête et mains d'un même personnage, pour qu'elles se raccordent avec une densité identique), ou pour + viser une densité précise. La valeur équivalente du mode Relative est affichée sous le champ. +- **Close Holes** (3) : bouche les trous jusqu'à ~2 × cette valeur en voxels. +- **Slice Fill X/Y/Z** : axes de remplissage par tranches (les trois par défaut). +- **Remove Filaments** (1), **Smooth** (20 itérations de Taubin). +- **Inflate** (0 = auto : 2 voxels) et **Limit** (0 = auto : 4 × gonflement) pour le Shrinkwrap. +- **Multires Levels** (2) : densité de la projection (×16 faces). +- **Repair Missed Rays** (activé) et **Despike After** (désactivé) pour la chaîne en un clic. +- Analyze : **Neighborhood** (8 anneaux d'arêtes), **Flat Below** (0,15), **Directional Above** (0,55). + +## Conseils +- Couper la source **et** l'enveloppe là où elles ne servent pas (socle, épaules) améliore la projection. +- Les **surplombs** (pavillon de l'oreille) restent le point faible d'une projection le long des normales : + quelques pointes peuvent subsister → Despike, ou pinceau Smooth. +- Après Freeze, l'objet garde une **base légère** + niveaux Multires : sculptez, ou bakez les détails. + +## Installation +- **Depuis le dépôt d'extensions d'a2msystemes.org** (à venir) : les mises à jour seront proposées directement dans + Blender. Voir https://a2msystemes.org/projets/slice_wrap. +- **Paquet** : `slice_wrap-.zip` (page *Releases* du dépôt Gitea, ou `dist\` après construction) → + *Edit > Preferences > Get Extensions > ⌄ > Install from Disk…* +- **Construire et publier** : chaîne d'outils `a2m` (repo `ange/apc-toolchain`) — `a2m validate --load`, + `a2m build` (→ `dist\slice_wrap-.zip`), `a2m release [patch|minor|major]` (version, CHANGELOG, tag, + release Gitea avec le zip et `publication.json`), `a2m release --dev` (pré-release de test). + Historique des versions : [CHANGELOG.fr.md](CHANGELOG.fr.md). +- **Développement** : copier / lier ce dossier dans + `%APPDATA%\Blender Foundation\Blender\\extensions\user_default\slice_wrap`. + +## Fichiers +- `__init__.py` : réglages, opérateurs, panneaux (principal, Steps, Despike, Analyze), liste des groupes. +- `core.py` : algorithmes (voxelisation, morphologie, remplissage par tranches, Taubin, réparation des ratés, despike, + analyse de forme). +- `blender_manifest.toml` : manifeste d'extension. + +## Tests (Blender 5.2.1) +Tête Pixal3D brute de 11,8 M faces → enveloppe 70 k faces (11 s) → Wrap Multires 2 → Freeze avec réparation +(~93 k ratés réparés) — chaîne complète en ~1,5–2 min. Despike filtré sur un groupe « Oreilles » : 683 sommets +corrigés contre 4 749 sur toute la surface. Analyze (1,1 M sommets évalués) en 9 s : Flat 86 %, Ridge 5 %, +Bulge 3 %, Fold 3 %, Hollow 2 %, Saddle 1 % — hélice des oreilles et lèvres en Ridge, paupières et commissures en Fold. + +## Pistes (non implémentées) +- **Marqueurs de flow** dessinés par l'utilisateur (courbes / Grease Pencil sur la surface) avec des tags + (« pli », « gonflement », « boucle œil »…), combinés aux tags automatiques d'Analyze. +- **Stratégies par tag** pour une retopologie guidée : boucles parallèles à `sw_flow` sur un Fold / Ridge, anneaux + concentriques autour d'un Hollow (œil, bouche), pôle au sommet d'un Bulge, anneaux perpendiculaires sur un + cylindre (doigt), densité pilotée par `sw_detail`. diff --git a/README.md b/README.md index 20fac0c..ed42046 100644 --- a/README.md +++ b/README.md @@ -1,136 +1,137 @@ -# Slice Wrap — add-on Blender (5.1 → 5.x) +# Slice Wrap — Blender add-on (5.1 → 5.x) -Transforme un maillage **troué, à doubles parois ou bruité** (scan, génération IA type Pixal3D / Trellis) -en une **surface propre, fermée et détaillée**, prête à sculpter. Aucune dépendance : numpy seulement -(fourni avec Blender). +*[Version française](README.fr.md)* -Panneau : **Vue 3D > barre latérale (N) > onglet « Slice Wrap »**. +Turns a **holey, double-walled or noisy** mesh (scan, AI generation such as Pixal3D / Trellis) into a +**clean, closed and detailed surface**, ready to sculpt. No dependencies: numpy only (shipped with Blender). -## Pourquoi pas le Voxel Remesh de Blender ? -Le Voxel Remesh (et *Mesh to Volume* en Geometry Nodes) reconstruit un volume… mais **fuit** dès que la -coque a un trou : l'intérieur n'est pas rempli et on obtient une double peau, du moiré, des ratés. -Slice Wrap remplit le volume **tranche par tranche selon X, Y et Z** : un trou ne fait fuir que les quelques -tranches qu'il traverse, les autres directions le compensent. +Panel: **3D Viewport > Sidebar (N) > "Slice Wrap" tab**. -## Utilisation -Tout s'applique à **l'objet sélectionné** (actif) : il n'y a pas de cible à choisir. La projection se fait toujours -sur la source de l'enveloppe. Sans maillage sélectionné, les boutons sont grisés. +## Why not Blender's Voxel Remesh? +Voxel Remesh (and *Mesh to Volume* in Geometry Nodes) rebuilds a volume… but **leaks** as soon as the shell has a +hole: the inside is not filled and you get a double skin, moiré and misses. +Slice Wrap fills the volume **slice by slice along X, Y and Z**: a hole only leaks into the few slices it crosses, +and the other directions make up for it. -1. Sélectionnez le maillage source (troué) en mode Objet. -2. Réglez au besoin la section **Envelope** et **Wrap**, puis cliquez **Slice Wrap** (un clic) : - Envelope → Wrap Setup → Freeze, et **Despike** en plus si **Despike After** est coché. -3. Le résultat `` (par défaut `_slicewrapped`) est prêt à sculpter (base légère + niveaux - Multires). La source est cachée. +## Usage +Everything applies to the **selected (active) object**: there is no target to pick. The projection always goes +onto the source of the envelope. Without a selected mesh, the buttons are greyed out. -### Calculs longs : confirmation, progression, annulation -Slice Wrap, Envelope, Regenerate et Despike affichent d'abord un message : le calcul peut être long, Blender -ignorera les clics pendant ce temps (il n'est pas planté), Échap annule. Case « Show this message next time » -(aussi dans *Preferences > Add-ons > Slice Wrap > Confirm Long Operations*). -Pendant le calcul (ainsi que Freeze et Analyze) : **barre de progression** avec l'étape en cours et le temps écoulé, -dans la barre d'état en bas de la fenêtre et en haut du panneau. **Échap** annule : rien n'est créé ni modifié. -Limite : quelques opérations internes de Blender (subdivision Multires, Multires Reshape, Voxel Remesh) sont d'un -seul tenant. Sur un maillage lourd, l'affichage reste figé quelques secondes sur cette étape, puis la progression -reprend. +1. Select the (holey) source mesh in Object Mode. +2. Adjust the **Envelope** and **Wrap** sections if needed, then click **Slice Wrap** (one click): + Envelope → Wrap Setup → Freeze, plus **Despike** if **Despike After** is checked. +3. The result `` (by default `_slicewrapped`) is ready to sculpt (light base + Multires + levels). The source is hidden. -### Nom et rangement du résultat -- **Suffix** (défaut `_slicewrapped`) : nom du maillage créé = nom de la source + suffixe. -- **Numérotation automatique** : si le nom existe déjà, `.001`, `.002`… comme Blender — **aucun objet existant - n'est jamais écrasé** (même avec un suffixe vide, la source reste intacte). -- **Collection** (case + nom, défaut `SliceWrapCollection`) : le résultat y est rangé ; si la collection existe, - elle est simplement réutilisée (son contenu n'est pas touché), sinon elle est créée et liée à la scène. - Case décochée : le résultat va dans les collections de la source. -- **Regenerate** est le seul bouton qui recalcule un objet existant : l'enveloppe active, sur place. +### Long computations: confirmation, progress, cancel +Slice Wrap, Envelope, Regenerate and Despike first show a message: the computation can take a while, Blender will +ignore clicks meanwhile (it has not crashed), Esc cancels. "Show this message next time" checkbox (also in +*Preferences > Add-ons > Slice Wrap > Confirm Long Operations*). +During the computation (as well as Freeze and Analyze): a **progress bar** with the current step and the elapsed +time, in the status bar at the bottom of the window and at the top of the panel. **Esc** cancels: nothing is +created or modified. +Limitation: a few internal Blender operations (Multires subdivision, Multires Reshape, Voxel Remesh) run in one +go. On a heavy mesh, the display stays frozen on that step for a few seconds, then progress resumes. -### Sous-panneau « Steps » (replié) — chaque étape séparément -| # | Bouton | Ce qu'il fait | -|---|--------|---------------| -| 1 | **Envelope** | Sur l'objet actif (la source, jamais modifiée) : voxels → fermeture des trous → remplissage par tranches → surface fermée (Voxel Remesh sur volume déjà plein, sans fuite) → plus grande pièce → lissage de Taubin. Crée `` (numéroté si le nom existe). | -| | ↻ **Regenerate** | Recalcule l'enveloppe active depuis sa source avec les réglages actuels (pseudo-modificateur). Refusé si l'enveloppe est déjà wrappée. | -| 2 | **Wrap Setup** | Gonfle l'enveloppe le long des normales (pour qu'elle soit entièrement *au-dessus* de la peau), ajoute **Multires** (N niveaux) puis **Shrinkwrap** : *Project*, le long des normales, **vers l'intérieur seulement**, avec une distance limite. | -| 3 | **Freeze** | Fige la projection **dans les niveaux du Multires** (Multires Reshape) et retire le Shrinkwrap. Avec **Repair Missed Rays**, les sommets dont la projection a raté — rien touché (aiguilles) ou trop loin (creux sur une paroi interne) — sont détectés exactement (comparaison avant / après) et reconstruits depuis leurs voisins. | +### Naming and placing the result +- **Suffix** (default `_slicewrapped`): name of the created mesh = source name + suffix. +- **Automatic numbering**: if the name already exists, `.001`, `.002`… like Blender — **no existing object is ever + overwritten** (even with an empty suffix, the source stays intact). +- **Collection** (checkbox + name, default `SliceWrapCollection`): the result is placed in it; if the collection + exists it is simply reused (its content is not touched), otherwise it is created and linked to the scene. + Unchecked: the result goes into the collections of the source. +- **Regenerate** is the only button that recomputes an existing object: the active envelope, in place. -Astuce : pour couper le socle / les épaules avant la projection, faites **Envelope**, coupez (Bisect), puis -**Wrap Setup** et **Freeze**. +### "Steps" sub-panel (collapsed) — each step separately +| # | Button | What it does | +|---|--------|--------------| +| 1 | **Envelope** | On the active object (the source, never modified): voxels → hole closing → slice filling → closed surface (Voxel Remesh on an already full volume, no leak) → largest piece → Taubin smoothing. Creates `` (numbered if the name exists). | +| | ↻ **Regenerate** | Recomputes the active envelope from its source with the current settings (pseudo-modifier). Refused if the envelope is already wrapped. | +| 2 | **Wrap Setup** | Inflates the envelope along the normals (so that it lies entirely *above* the skin), adds **Multires** (N levels) then **Shrinkwrap**: *Project*, along the normals, **inwards only**, with a limit distance. | +| 3 | **Freeze** | Freezes the projection **into the Multires levels** (Multires Reshape) and removes the Shrinkwrap. With **Repair Missed Rays**, vertices whose projection missed — nothing hit (needles) or too far (hollow on an inner wall) — are detected exactly (before / after comparison) and rebuilt from their neighbours. | -### Sous-panneau « Despike » — outil manuel -Filtre anti-pointes résiduel : un sommet n'est corrigé que s'il est **isolé**, nettement plus loin de la moyenne -de ses voisins que ceux-ci ne le sont des leurs ; le relief normal (oreilles, paupières) n'est pas lissé. -- **Distance** : écart minimal pour être une pointe (0 = automatique : longueur moyenne d'arête). -- **Strength** (0–1) : part du chemin vers la moyenne des voisins. -- **Iterations** : nombre de passes. **Isolation** : la pointe doit dévier N fois plus que ses voisins. -- **Vertex Group Filters** : liste (+ / − / vider) des groupes de sommets à traiter. Le **poids** du groupe module - la force (fondu possible en bordure). **Liste vide = toute la surface.** Si la liste contient des groupes - dont aucun n'existe, le Despike refuse de s'exécuter (pour ne jamais traiter toute la surface par erreur). - Les groupes de la base sont propagés aux niveaux du Multires. -- **Protect Detail** : atténue le Despike en proportion du détail (analyse de forme recalculée à la volée), pour - ne jamais aplatir paupières, narines ou oreilles. +Tip: to cut the base / shoulders before projecting, run **Envelope**, cut (Bisect), then **Wrap Setup** and +**Freeze**. -### Sous-panneau « Analyze » — optionnel, ne modifie jamais la géométrie -Analyse la forme de l'objet actif (Multires compris) : pour chaque sommet, la répartition des normales sur un -voisinage (tenseur de covariance) et la courbure moyenne signée. Résultat écrit sur le maillage de base : +### "Despike" sub-panel — manual tool +Residual anti-spike filter: a vertex is only corrected if it is **isolated**, clearly further from the average of +its neighbours than they are from theirs; normal relief (ears, eyelids) is not smoothed. +- **Distance**: minimum deviation to count as a spike (0 = automatic: average edge length). +- **Strength** (0–1): fraction of the way towards the neighbours' average. +- **Iterations**: number of passes. **Isolation**: the spike must deviate N times more than its neighbours. +- **Vertex Group Filters**: list (+ / − / clear) of the vertex groups to process. The group **weight** modulates + the strength (fade-out possible at the border). **Empty list = the whole surface.** If the list contains groups + none of which exist, Despike refuses to run (so as never to process the whole surface by mistake). + The groups of the base are propagated to the Multires levels. +- **Protect Detail**: attenuates Despike in proportion to the detail (shape analysis computed on the fly), so as + never to flatten eyelids, nostrils or ears. -| Donnée | Type | Contenu | -|--------|------|---------| -| `sw_detail` | attribut float 0–1 | densité de détail (la surface « tourne » beaucoup) — carte de densité pour une retopo | -| `sw_curvature` | attribut float −1…1 | > 0 convexe (bosse), < 0 concave (creux) | -| `sw_anisotropy` | attribut float 0–1 | ~1 : la surface tourne dans **une** direction (pli, crête, doigt) ; ~0 : dans toutes | -| `sw_shape` | attribut entier | tag : 0 Flat, 1 Bulge (dôme), 2 Hollow (cuvette), 3 Ridge (crête), 4 Fold (pli), 5 Saddle (selle) | -| `sw_flow` | attribut vecteur | direction du pli / de la crête = direction que doit suivre une boucle d'arêtes | -| `SW_Detail_Color`, `SW_Shape_Color` | couleurs | affichage (boutons **Detail** / **Shapes**, ✕ pour revenir) | -| `SW_Detail`, `SW_Bulge`, `SW_Hollow`, `SW_Ridge`, `SW_Fold`, `SW_Saddle` | groupes de sommets | filtres Despike, masques, ou carte de densité d'un remailleur | +### "Analyze" sub-panel — optional, never modifies the geometry +Analyses the shape of the active object (Multires included): for each vertex, the spread of the normals over a +neighbourhood (covariance tensor) and the signed mean curvature. Result written on the base mesh: -Couleurs des tags : gris Flat · rouge Bulge · bleu Hollow · jaune Ridge · cyan Fold · violet Saddle. -Les couleurs portent le suffixe `_Color` car groupes de sommets et attributs partagent le même espace de noms. +| Data | Type | Content | +|------|------|---------| +| `sw_detail` | float attribute 0–1 | detail density (the surface "turns" a lot) — density map for a retopology | +| `sw_curvature` | float attribute −1…1 | > 0 convex (bump), < 0 concave (hollow) | +| `sw_anisotropy` | float attribute 0–1 | ~1: the surface turns in **one** direction (fold, ridge, finger); ~0: in all directions | +| `sw_shape` | integer attribute | tag: 0 Flat, 1 Bulge (dome), 2 Hollow (bowl), 3 Ridge, 4 Fold, 5 Saddle | +| `sw_flow` | vector attribute | direction of the fold / ridge = direction an edge loop should follow | +| `SW_Detail_Color`, `SW_Shape_Color` | colours | display (**Detail** / **Shapes** buttons, ✕ to go back) | +| `SW_Detail`, `SW_Bulge`, `SW_Hollow`, `SW_Ridge`, `SW_Fold`, `SW_Saddle` | vertex groups | Despike filters, masks, or density map for a remesher | -## Réglages -- **Voxel : Relative / Absolute** — la finesse de l'enveloppe. - - *Relative* (défaut, **Voxel %** = 0,6 % de la plus grande dimension) : indépendant de l'échelle — le même - réglage donne le même résultat sur une tête de 23 cm, une tête normalisée à 1 m ou une main importée à 3,7 m. - Plus petit = plus fidèle mais plus lourd ; trop fin sur une source bruitée → la projection « voit » le grain. - - *Absolute* (**Voxel Size** en unités) : même finesse physique sur plusieurs objets de tailles différentes - (ex. tête et mains d'un même personnage, pour qu'elles se raccordent avec une densité identique), ou pour - viser une densité précise. La valeur équivalente du mode Relative est affichée sous le champ. -- **Close Holes** (3) : bouche les trous jusqu'à ~2 × cette valeur en voxels. -- **Slice Fill X/Y/Z** : axes de remplissage par tranches (les trois par défaut). -- **Remove Filaments** (1), **Smooth** (20 itérations de Taubin). -- **Inflate** (0 = auto : 2 voxels) et **Limit** (0 = auto : 4 × gonflement) pour le Shrinkwrap. -- **Multires Levels** (2) : densité de la projection (×16 faces). -- **Repair Missed Rays** (activé) et **Despike After** (désactivé) pour la chaîne en un clic. -- Analyze : **Neighborhood** (8 anneaux d'arêtes), **Flat Below** (0,15), **Directional Above** (0,55). +Tag colours: grey Flat · red Bulge · blue Hollow · yellow Ridge · cyan Fold · purple Saddle. +Colours carry the `_Color` suffix because vertex groups and attributes share the same namespace. -## Conseils -- Couper la source **et** l'enveloppe là où elles ne servent pas (socle, épaules) améliore la projection. -- Les **surplombs** (pavillon de l'oreille) restent le point faible d'une projection le long des normales : - quelques pointes peuvent subsister → Despike, ou pinceau Smooth. -- Après Freeze, l'objet garde une **base légère** + niveaux Multires : sculptez, ou bakez les détails. +## Settings +- **Voxel: Relative / Absolute** — the resolution of the envelope. + - *Relative* (default, **Voxel %** = 0.6 % of the largest dimension): scale-independent — the same setting gives + the same result on a 23 cm head, a head normalised to 1 m or a hand imported at 3.7 m. + Smaller = more faithful but heavier; too fine on a noisy source → the projection "sees" the grain. + - *Absolute* (**Voxel Size** in units): same physical resolution on several objects of different sizes + (e.g. head and hands of the same character, so that they join with an identical density), or to target a + precise density. The equivalent value of the Relative mode is shown under the field. +- **Close Holes** (3): plugs holes up to ~2 × this value in voxels. +- **Slice Fill X/Y/Z**: slice filling axes (all three by default). +- **Remove Filaments** (1), **Smooth** (20 Taubin iterations). +- **Inflate** (0 = auto: 2 voxels) and **Limit** (0 = auto: 4 × inflate) for the Shrinkwrap. +- **Multires Levels** (2): density of the projection (×16 faces). +- **Repair Missed Rays** (on) and **Despike After** (off) for the one-click chain. +- Analyze: **Neighborhood** (8 edge rings), **Flat Below** (0.15), **Directional Above** (0.55). + +## Tips +- Cutting the source **and** the envelope where they are not needed (base, shoulders) improves the projection. +- **Overhangs** (outer ear) remain the weak point of a projection along the normals: a few spikes may remain → + Despike, or the Smooth brush. +- After Freeze, the object keeps a **light base** + Multires levels: sculpt, or bake the details. ## Installation -- **Depuis le dépôt d'extensions d'a2msystemes.org** (à venir) : les mises à jour seront proposées directement dans - Blender. Voir https://a2msystemes.org/projets/slice_wrap. -- **Paquet** : `slice_wrap-.zip` (page *Releases* du dépôt Gitea, ou `dist\` après construction) → +- **From the a2msystemes.org extension repository** (coming soon): updates will be offered directly in Blender. + See https://a2msystemes.org/en/projects/slice_wrap. +- **Package**: `slice_wrap-.zip` (*Releases* page of the Gitea repository, or `dist\` after building) → *Edit > Preferences > Get Extensions > ⌄ > Install from Disk…* -- **Construire et publier** : chaîne d'outils `a2m` (repo `ange/apc-toolchain`) — `a2m validate --load`, - `a2m build` (→ `dist\slice_wrap-.zip`), `a2m release [patch|minor|major]` (version, CHANGELOG, tag, - release Gitea avec le zip et `publication.json`), `a2m release --dev` (pré-release de test). - Historique des versions : [CHANGELOG.fr.md](CHANGELOG.fr.md). -- **Développement** : copier / lier ce dossier dans +- **Build and publish**: `a2m` toolchain (repository `ange/apc-toolchain`) — `a2m validate --load`, `a2m build` + (→ `dist\slice_wrap-.zip`), `a2m release [patch|minor|major]` (version, CHANGELOG, tag, Gitea release + with the zip and `publication.json`), `a2m release --dev` (test pre-release). + Version history: [CHANGELOG.md](CHANGELOG.md). +- **Development**: copy / link this folder into `%APPDATA%\Blender Foundation\Blender\\extensions\user_default\slice_wrap`. -## Fichiers -- `__init__.py` : réglages, opérateurs, panneaux (principal, Steps, Despike, Analyze), liste des groupes. -- `core.py` : algorithmes (voxelisation, morphologie, remplissage par tranches, Taubin, réparation des ratés, despike, - analyse de forme). -- `blender_manifest.toml` : manifeste d'extension. +## Files +- `__init__.py`: settings, operators, panels (main, Steps, Despike, Analyze), group list. +- `core.py`: algorithms (voxelisation, morphology, slice filling, Taubin, missed-ray repair, despike, shape + analysis). +- `blender_manifest.toml`: extension manifest. ## Tests (Blender 5.2.1) -Tête Pixal3D brute de 11,8 M faces → enveloppe 70 k faces (11 s) → Wrap Multires 2 → Freeze avec réparation -(~93 k ratés réparés) — chaîne complète en ~1,5–2 min. Despike filtré sur un groupe « Oreilles » : 683 sommets -corrigés contre 4 749 sur toute la surface. Analyze (1,1 M sommets évalués) en 9 s : Flat 86 %, Ridge 5 %, -Bulge 3 %, Fold 3 %, Hollow 2 %, Saddle 1 % — hélice des oreilles et lèvres en Ridge, paupières et commissures en Fold. +Raw Pixal3D head of 11.8 M faces → 70 k-face envelope (11 s) → Wrap Multires 2 → Freeze with repair (~93 k misses +repaired) — full chain in ~1.5–2 min. Despike filtered on an "Ears" group: 683 vertices corrected versus 4,749 on +the whole surface. Analyze (1.1 M evaluated vertices) in 9 s: Flat 86 %, Ridge 5 %, Bulge 3 %, Fold 3 %, Hollow 2 %, +Saddle 1 % — ear helix and lips as Ridge, eyelids and mouth corners as Fold. -## Pistes (non implémentées) -- **Marqueurs de flow** dessinés par l'utilisateur (courbes / Grease Pencil sur la surface) avec des tags - (« pli », « gonflement », « boucle œil »…), combinés aux tags automatiques d'Analyze. -- **Stratégies par tag** pour une retopologie guidée : boucles parallèles à `sw_flow` sur un Fold / Ridge, anneaux - concentriques autour d'un Hollow (œil, bouche), pôle au sommet d'un Bulge, anneaux perpendiculaires sur un - cylindre (doigt), densité pilotée par `sw_detail`. +## Ideas (not implemented) +- **Flow markers** drawn by the user (curves / Grease Pencil on the surface) with tags ("fold", "bulge", + "eye loop"…), combined with the automatic Analyze tags. +- **Per-tag strategies** for a guided retopology: loops parallel to `sw_flow` on a Fold / Ridge, concentric rings + around a Hollow (eye, mouth), a pole at the top of a Bulge, perpendicular rings on a cylinder (finger), density + driven by `sw_detail`.