Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0027f74a56 | ||
|
|
c88a7f9a2a | ||
|
|
8a92c2b784 | ||
|
|
d351379a23 |
No files matched your search
@@ -6,6 +6,12 @@ La section « Non publié » est reprise par `a2m release` sous le numéro de la
|
|||||||
|
|
||||||
## [Non publié]
|
## [Non publié]
|
||||||
|
|
||||||
|
## [1.4.2] - 2026-10-20
|
||||||
|
|
||||||
|
### Modifié
|
||||||
|
|
||||||
|
- Documentation en deux langues : `README.md` en anglais, `README.fr.md` en français.
|
||||||
|
|
||||||
## [1.4.1] - 2026-10-20
|
## [1.4.1] - 2026-10-20
|
||||||
|
|
||||||
### Modifié
|
### Modifié
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ The "Unreleased" section is taken by `a2m release` under the number of the new v
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.4.2] - 2026-10-20
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Documentation in two languages: `README.md` in English, `README.fr.md` in French.
|
||||||
|
|
||||||
## [1.4.1] - 2026-10-20
|
## [1.4.1] - 2026-10-20
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
# Slice Wrap — add-on Blender : surface propre à partir d'un maillage troué, wrap, nettoyage et analyse
|
# Slice Wrap — add-on Blender : surface propre à partir d'un maillage troué, wrap, nettoyage et analyse
|
||||||
|
|
||||||
L'utilisateur parle **français** : répondre et documenter en français. Libellés d'interface Blender en anglais
|
L'utilisateur parle **français** : répondre et documenter en français. Libellés d'interface Blender en anglais
|
||||||
(convention Blender), descriptions / docstrings / README en français.
|
(convention Blender), descriptions / docstrings en français. Documentation en deux langues, à tenir à jour
|
||||||
|
ensemble : `README.fr.md` en français, `README.md` en anglais (sa traduction) ; de même `CHANGELOG.fr.md` /
|
||||||
|
`CHANGELOG.md` (les fiches du site et les notes de version les lisent dans les deux langues).
|
||||||
|
|
||||||
## But
|
## But
|
||||||
Transformer un maillage **troué, à doubles parois ou bruité** (scan, génération IA type Pixal3D / Trellis — ex.
|
Transformer un maillage **troué, à doubles parois ou bruité** (scan, génération IA type Pixal3D / Trellis — ex.
|
||||||
|
|||||||
+138
@@ -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 `<source><suffixe>` (par défaut `<source>_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 `<source><suffixe>` (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-<version>.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-<version>.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\<version>\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`.
|
||||||
@@ -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)
|
*[Version française](README.fr.md)*
|
||||||
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 »**.
|
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 ?
|
Panel: **3D Viewport > Sidebar (N) > "Slice Wrap" tab**.
|
||||||
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
|
## Why not Blender's Voxel Remesh?
|
||||||
Tout s'applique à **l'objet sélectionné** (actif) : il n'y a pas de cible à choisir. La projection se fait toujours
|
Voxel Remesh (and *Mesh to Volume* in Geometry Nodes) rebuilds a volume… but **leaks** as soon as the shell has a
|
||||||
sur la source de l'enveloppe. Sans maillage sélectionné, les boutons sont grisés.
|
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.
|
## Usage
|
||||||
2. Réglez au besoin la section **Envelope** et **Wrap**, puis cliquez **Slice Wrap** (un clic) :
|
Everything applies to the **selected (active) object**: there is no target to pick. The projection always goes
|
||||||
Envelope → Wrap Setup → Freeze, et **Despike** en plus si **Despike After** est coché.
|
onto the source of the envelope. Without a selected mesh, the buttons are greyed out.
|
||||||
3. Le résultat `<source><suffixe>` (par défaut `<source>_slicewrapped`) est prêt à sculpter (base légère + niveaux
|
|
||||||
Multires). La source est cachée.
|
|
||||||
|
|
||||||
### Calculs longs : confirmation, progression, annulation
|
1. Select the (holey) source mesh in Object Mode.
|
||||||
Slice Wrap, Envelope, Regenerate et Despike affichent d'abord un message : le calcul peut être long, Blender
|
2. Adjust the **Envelope** and **Wrap** sections if needed, then click **Slice Wrap** (one click):
|
||||||
ignorera les clics pendant ce temps (il n'est pas planté), Échap annule. Case « Show this message next time »
|
Envelope → Wrap Setup → Freeze, plus **Despike** if **Despike After** is checked.
|
||||||
(aussi dans *Preferences > Add-ons > Slice Wrap > Confirm Long Operations*).
|
3. The result `<source><suffix>` (by default `<source>_slicewrapped`) is ready to sculpt (light base + Multires
|
||||||
Pendant le calcul (ainsi que Freeze et Analyze) : **barre de progression** avec l'étape en cours et le temps écoulé,
|
levels). The source is hidden.
|
||||||
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
|
### Long computations: confirmation, progress, cancel
|
||||||
- **Suffix** (défaut `_slicewrapped`) : nom du maillage créé = nom de la source + suffixe.
|
Slice Wrap, Envelope, Regenerate and Despike first show a message: the computation can take a while, Blender will
|
||||||
- **Numérotation automatique** : si le nom existe déjà, `.001`, `.002`… comme Blender — **aucun objet existant
|
ignore clicks meanwhile (it has not crashed), Esc cancels. "Show this message next time" checkbox (also in
|
||||||
n'est jamais écrasé** (même avec un suffixe vide, la source reste intacte).
|
*Preferences > Add-ons > Slice Wrap > Confirm Long Operations*).
|
||||||
- **Collection** (case + nom, défaut `SliceWrapCollection`) : le résultat y est rangé ; si la collection existe,
|
During the computation (as well as Freeze and Analyze): a **progress bar** with the current step and the elapsed
|
||||||
elle est simplement réutilisée (son contenu n'est pas touché), sinon elle est créée et liée à la scène.
|
time, in the status bar at the bottom of the window and at the top of the panel. **Esc** cancels: nothing is
|
||||||
Case décochée : le résultat va dans les collections de la source.
|
created or modified.
|
||||||
- **Regenerate** est le seul bouton qui recalcule un objet existant : l'enveloppe active, sur place.
|
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
|
### Naming and placing the result
|
||||||
| # | Bouton | Ce qu'il fait |
|
- **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
|
||||||
| 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 `<source><suffixe>` (numéroté si le nom existe). |
|
overwritten** (even with an empty suffix, the source stays intact).
|
||||||
| | ↻ **Regenerate** | Recalcule l'enveloppe active depuis sa source avec les réglages actuels (pseudo-modificateur). Refusé si l'enveloppe est déjà wrappée. |
|
- **Collection** (checkbox + name, default `SliceWrapCollection`): the result is placed in it; if the collection
|
||||||
| 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. |
|
exists it is simply reused (its content is not touched), otherwise it is created and linked to the scene.
|
||||||
| 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. |
|
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
|
### "Steps" sub-panel (collapsed) — each step separately
|
||||||
**Wrap Setup** et **Freeze**.
|
| # | 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 `<source><suffix>` (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
|
Tip: to cut the base / shoulders before projecting, run **Envelope**, cut (Bisect), then **Wrap Setup** and
|
||||||
Filtre anti-pointes résiduel : un sommet n'est corrigé que s'il est **isolé**, nettement plus loin de la moyenne
|
**Freeze**.
|
||||||
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
|
### "Despike" sub-panel — manual tool
|
||||||
Analyse la forme de l'objet actif (Multires compris) : pour chaque sommet, la répartition des normales sur un
|
Residual anti-spike filter: a vertex is only corrected if it is **isolated**, clearly further from the average of
|
||||||
voisinage (tenseur de covariance) et la courbure moyenne signée. Résultat écrit sur le maillage de base :
|
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 |
|
### "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
|
||||||
| `sw_detail` | attribut float 0–1 | densité de détail (la surface « tourne » beaucoup) — carte de densité pour une retopo |
|
neighbourhood (covariance tensor) and the signed mean curvature. Result written on the base mesh:
|
||||||
| `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.
|
| Data | Type | Content |
|
||||||
Les couleurs portent le suffixe `_Color` car groupes de sommets et attributs partagent le même espace de noms.
|
|------|------|---------|
|
||||||
|
| `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
|
Tag colours: grey Flat · red Bulge · blue Hollow · yellow Ridge · cyan Fold · purple Saddle.
|
||||||
- **Voxel : Relative / Absolute** — la finesse de l'enveloppe.
|
Colours carry the `_Color` suffix because vertex groups and attributes share the same namespace.
|
||||||
- *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
|
## Settings
|
||||||
- Couper la source **et** l'enveloppe là où elles ne servent pas (socle, épaules) améliore la projection.
|
- **Voxel: Relative / Absolute** — the resolution of the envelope.
|
||||||
- Les **surplombs** (pavillon de l'oreille) restent le point faible d'une projection le long des normales :
|
- *Relative* (default, **Voxel %** = 0.6 % of the largest dimension): scale-independent — the same setting gives
|
||||||
quelques pointes peuvent subsister → Despike, ou pinceau Smooth.
|
the same result on a 23 cm head, a head normalised to 1 m or a hand imported at 3.7 m.
|
||||||
- Après Freeze, l'objet garde une **base légère** + niveaux Multires : sculptez, ou bakez les détails.
|
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
|
## Installation
|
||||||
- **Depuis le dépôt d'extensions d'a2msystemes.org** (à venir) : les mises à jour seront proposées directement dans
|
- **From the a2msystemes.org extension repository** (coming soon): updates will be offered directly in Blender.
|
||||||
Blender. Voir https://a2msystemes.org/projets/slice_wrap.
|
See https://a2msystemes.org/en/projects/slice_wrap.
|
||||||
- **Paquet** : `slice_wrap-<version>.zip` (page *Releases* du dépôt Gitea, ou `dist\` après construction) →
|
- **Package**: `slice_wrap-<version>.zip` (*Releases* page of the Gitea repository, or `dist\` after building) →
|
||||||
*Edit > Preferences > Get Extensions > ⌄ > Install from Disk…*
|
*Edit > Preferences > Get Extensions > ⌄ > Install from Disk…*
|
||||||
- **Construire et publier** : chaîne d'outils `a2m` (repo `ange/apc-toolchain`) — `a2m validate --load`,
|
- **Build and publish**: `a2m` toolchain (repository `ange/apc-toolchain`) — `a2m validate --load`, `a2m build`
|
||||||
`a2m build` (→ `dist\slice_wrap-<version>.zip`), `a2m release [patch|minor|major]` (version, CHANGELOG, tag,
|
(→ `dist\slice_wrap-<version>.zip`), `a2m release [patch|minor|major]` (version, CHANGELOG, tag, Gitea release
|
||||||
release Gitea avec le zip et `publication.json`), `a2m release --dev` (pré-release de test).
|
with the zip and `publication.json`), `a2m release --dev` (test pre-release).
|
||||||
Historique des versions : [CHANGELOG.fr.md](CHANGELOG.fr.md).
|
Version history: [CHANGELOG.md](CHANGELOG.md).
|
||||||
- **Développement** : copier / lier ce dossier dans
|
- **Development**: copy / link this folder into
|
||||||
`%APPDATA%\Blender Foundation\Blender\<version>\extensions\user_default\slice_wrap`.
|
`%APPDATA%\Blender Foundation\Blender\<version>\extensions\user_default\slice_wrap`.
|
||||||
|
|
||||||
## Fichiers
|
## Files
|
||||||
- `__init__.py` : réglages, opérateurs, panneaux (principal, Steps, Despike, Analyze), liste des groupes.
|
- `__init__.py`: settings, operators, panels (main, Steps, Despike, Analyze), group list.
|
||||||
- `core.py` : algorithmes (voxelisation, morphologie, remplissage par tranches, Taubin, réparation des ratés, despike,
|
- `core.py`: algorithms (voxelisation, morphology, slice filling, Taubin, missed-ray repair, despike, shape
|
||||||
analyse de forme).
|
analysis).
|
||||||
- `blender_manifest.toml` : manifeste d'extension.
|
- `blender_manifest.toml`: extension manifest.
|
||||||
|
|
||||||
## Tests (Blender 5.2.1)
|
## 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
|
Raw Pixal3D head of 11.8 M faces → 70 k-face envelope (11 s) → Wrap Multires 2 → Freeze with repair (~93 k misses
|
||||||
(~93 k ratés réparés) — chaîne complète en ~1,5–2 min. Despike filtré sur un groupe « Oreilles » : 683 sommets
|
repaired) — full chain in ~1.5–2 min. Despike filtered on an "Ears" group: 683 vertices corrected versus 4,749 on
|
||||||
corrigés contre 4 749 sur toute la surface. Analyze (1,1 M sommets évalués) en 9 s : Flat 86 %, Ridge 5 %,
|
the whole surface. Analyze (1.1 M evaluated vertices) in 9 s: Flat 86 %, Ridge 5 %, Bulge 3 %, Fold 3 %, Hollow 2 %,
|
||||||
Bulge 3 %, Fold 3 %, Hollow 2 %, Saddle 1 % — hélice des oreilles et lèvres en Ridge, paupières et commissures en Fold.
|
Saddle 1 % — ear helix and lips as Ridge, eyelids and mouth corners as Fold.
|
||||||
|
|
||||||
## Pistes (non implémentées)
|
## Ideas (not implemented)
|
||||||
- **Marqueurs de flow** dessinés par l'utilisateur (courbes / Grease Pencil sur la surface) avec des tags
|
- **Flow markers** drawn by the user (curves / Grease Pencil on the surface) with tags ("fold", "bulge",
|
||||||
(« pli », « gonflement », « boucle œil »…), combinés aux tags automatiques d'Analyze.
|
"eye loop"…), combined with the automatic Analyze tags.
|
||||||
- **Stratégies par tag** pour une retopologie guidée : boucles parallèles à `sw_flow` sur un Fold / Ridge, anneaux
|
- **Per-tag strategies** for a guided retopology: loops parallel to `sw_flow` on a Fold / Ridge, concentric rings
|
||||||
concentriques autour d'un Hollow (œil, bouche), pôle au sommet d'un Bulge, anneaux perpendiculaires sur un
|
around a Hollow (eye, mouth), a pole at the top of a Bulge, perpendicular rings on a cylinder (finger), density
|
||||||
cylindre (doigt), densité pilotée par `sw_detail`.
|
driven by `sw_detail`.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
|
|
||||||
id = "slice_wrap"
|
id = "slice_wrap"
|
||||||
version = "1.4.1"
|
version = "1.4.2"
|
||||||
name = "Slice Wrap"
|
name = "Slice Wrap"
|
||||||
tagline = "Closed envelope of holey meshes, then wrap, freeze and despike"
|
tagline = "Closed envelope of holey meshes, then wrap, freeze and despike"
|
||||||
maintainer = "Ange-Marie MAURIN"
|
maintainer = "Ange-Marie MAURIN"
|
||||||
|
|||||||
+3
-1
@@ -4,7 +4,8 @@
|
|||||||
- rapide (~40 s) : sphère trouée et bruitée → nom / numérotation / collection / Regenerate, Envelope fermée,
|
- rapide (~40 s) : sphère trouée et bruitée → nom / numérotation / collection / Regenerate, Envelope fermée,
|
||||||
Wrap + Freeze (réparation), Despike (global, filtré, refus groupe absent, Protect Detail), Analyze.
|
Wrap + Freeze (réparation), Despike (global, filtré, refus groupe absent, Protect Detail), Analyze.
|
||||||
- --head : chaîne complète sur la tête brute Pixal3D (11,8 M faces, ~2 min) + rendus de contrôle.
|
- --head : chaîne complète sur la tête brute Pixal3D (11,8 M faces, ~2 min) + rendus de contrôle.
|
||||||
Termine par « RESULTAT : TOUT OK » ou la liste des échecs.
|
Termine par « RESULTAT : TOUT OK » ou la liste des échecs ; code de retour 0 si tout est bon, 1 sinon
|
||||||
|
(convention de la chaîne a2m : `tests/run_tests.py`, lancé avant chaque release).
|
||||||
"""
|
"""
|
||||||
import importlib
|
import importlib
|
||||||
import math
|
import math
|
||||||
@@ -236,3 +237,4 @@ if "--head" in ARGS and os.path.isfile(HEAD):
|
|||||||
|
|
||||||
mod.unregister()
|
mod.unregister()
|
||||||
print("RESULTAT :", "TOUT OK" if not fails else "ECHECS " + ", ".join(fails))
|
print("RESULTAT :", "TOUT OK" if not fails else "ECHECS " + ", ".join(fails))
|
||||||
|
sys.exit(1 if fails else 0) # code de retour lu par « a2m validate --tests » et « a2m release »
|
||||||
Reference in new issue
Block a user