12 KiB
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
(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
Transformer un maillage troué, à doubles parois ou bruité (scan, génération IA type Pixal3D / Trellis — ex.
tête brute de 11,8 M faces) en une surface fermée, propre et détaillée, prête à sculpter ou à retopologiser,
puis fournir une analyse de forme (densité de détail, tags, direction des plis).
Né pendant le projet personnage « Chiara » (C:\Users\a-mma\Desktop\CharacterDesign\Work3D) : le Voxel Remesh de
Blender donnait du moiré et des fuites sur la tête générée ; un script de remplissage voxel tranche par tranche a
résolu le problème, d'où l'add-on.
Concept à préserver : Slice Wrap = « maillage troué → surface propre + analyse ». Aucune logique de topologie /
flow ici : la retopologie guidée est un projet séparé, Slice Retopo
(E:\0000WorkTechnique\0002dev\slice_retopo_addon), qui lit les attributs produits par Slice Wrap.
Pipeline (bouton « Slice Wrap » = étapes 1 → 3, + 4 si « Despike After »)
- Envelope (
core.build_envelope) — sur la source (jamais modifiée) : échantillonnage de surface (sommets + points sur les triangles > ½ voxel) → voxels occupés → fermeture morphologique (close_iter) → remplissage 3D global ∪ remplissage 2D tranche par tranche selon X, Y, Z (un trou ne fait fuir que les tranches qu'il traverse) → ouverture (open_iter, filaments) → surface en cubes → Voxel Remesh de Blender sur ce volume déjà plein (aucune fuite possible) → plus grande pièce → lissage de Taubin (smooth_iter). Numpy pur (pas de scipy / skimage dans le Python de Blender). - Wrap Setup — gonflement le long des normales (défaut 2 voxels) pour que l'enveloppe soit entièrement au-dessus de la peau, Multires (niveaux, Catmull-Clark) puis Shrinkwrap : Project, aucun axe (= le long des normales), Negative seul, Limit (défaut 4 × gonflement), Cull Off, Offset 0.
- Freeze — copie évaluée →
multires_reshape(la projection est figée DANS les niveaux du Multires : base légère + détails) ; Repair Missed Rays : chaque sommet est comparé avant / après projection ; resté sur place (< 0,3 × gonflement → aiguille) ou parti trop loin (> 2 × la moyenne de ses voisins → creux sur une paroi interne) = raté, reconstruit par diffusion depuis ses voisins réussis. - Despike (manuel ou en fin de chaîne) — ne corrige qu'un sommet isolé : écart à la moyenne des voisins
Distance (0 = longueur moyenne d'arête) ET > Isolation × l'écart moyen des voisins ; Strength, Iterations ; filtres par groupes de sommets (poids = intensité ; liste vide = toute la surface ; liste non vide mais aucun groupe trouvé = refus) ; Protect Detail (× (1 − détail)).
- Analyze (optionnel, ne modifie pas la géométrie) — tenseur de covariance des normales sur
Neighborhoodanneaux (valeurs propres λ1 ≥ λ2 ≥ λ3) + courbure moyenne signée :sw_detail(λ2+λ3 normalisé),sw_anisotropy((λ2−λ3)/(λ2+λ3)),sw_curvature,sw_shape(0 Flat, 1 Bulge, 2 Hollow, 3 Ridge, 4 Fold, 5 Saddle),sw_flow(vecteur propre de λ3 = direction du pli), couleursSW_Detail_Color/SW_Shape_Color, groupesSW_Detail,SW_Bulge,SW_Hollow,SW_Ridge,SW_Fold,SW_Saddle. Écrit sur les N premiers sommets du maillage évalué = sommets de base.
Décisions et pourquoi
- Pas de vrai modificateur (impossible en Python) → opérateurs + paramètres mémorisés sur le résultat
(
slice_wrap_source,slice_wrap_pitch,slice_wrap_inflate) + Regenerate (recalcul sur place). - Nom du résultat = source + Suffix (défaut
_slicewrapped), numéroté .001, .002… : aucun objet existant n'est jamais écrasé (avant la v1.3, relancer remplaçait le maillage existant — corrigé). Seul Regenerate recalcule l'objet actif. Refusé si l'enveloppe est déjà wrappée (Multires / Shrinkwrap). - Collection optionnelle (défaut cochée,
SliceWrapCollection) : réutilisée si elle existe (contenu intact), sinon créée et liée à la scène ; décochée → collections de la source. - Voxel Relative / Absolute — conservé (décision utilisateur, 2026-10-17) : Relative (défaut 0,6 % de la plus grande dimension, ≈ 170 voxels) rend le réglage indépendant de l'échelle (têtes IA normalisées à ~1 m, tête réelle 23 cm, main C4D importée à 3,7 m) ; Absolute donne la même densité physique à plusieurs parties d'un même personnage (tête, mains, pieds à raccorder). L'équivalent absolu du mode Relative est affiché. Possible plus tard : ranger Absolute dans une option avancée repliée.
- Défaut 0,6 % (et non 0,4 %) : une base trop dense fait « voir » le grain de la source à la projection.
- Despike par isolation et non par seuil seul : le seuil seul attrapait 8 % des sommets (oreilles, paupières).
- Réparation des ratés au Freeze (on connaît exactement les sommets ratés) plutôt que deviner après coup.
- Couleurs suffixées
_Color: groupes de sommets et attributs partagent le même espace de noms. - Plus de réglage Target (décision utilisateur, 2026-10-17) : il compliquait l'interface pour rien. Tout
s'applique à l'objet actif et sélectionné (
_obj_mode_mesh) ; Wrap Setup projette surslice_wrap_source. - Calculs longs = générateurs + opérateur modal (
_LongOperator) : l'API bpy n'est pas thread-safe, donc pas de thread. Les étapes (step_*,core.build_envelope,despike,fix_missed_rays,analyze_shape…) cèdent la main en produisant (fraction, texte) ;core.subimbrique les progressions,core.runexécute d'une traite (scripts / tests,bpy.opssans INVOKE). Depuis l'UI : confirmation (invoke_props_dialog, préférenceconfirm_long), puis timer 0,02 s, tranches de 0,15 s, saisie absorbée, Échap →gen.close(): chaque étape nettoie dansexcept BaseException/finally(aucun demi-résultat ; la scène n'est modifiée qu'à la fin). Progression :workspace.status_text_set(fonction)+ boîte en haut du panneau. Les étapes lisentbpy.contextà chaque usage (le contexte d'un opérateur n'est plus valide aux ticks suivants). Pas deREGISTERsur ces opérateurs (un redo relancerait un modal). Surcoût mesuré ~10 %. Appels Blender d'un seul tenant (Multires subdivide / Reshape, Voxel Remesh) : l'écran reste figé sur leur libellé.
Fichiers
__init__.py: réglages (SliceWrapSettings), étapes (step_envelope,step_wrap,step_freeze,step_despike,step_analyze,_reshape_from_evaluated,_result_collection), opérateurs (run,envelope,regenerate,wrap_setup,freeze,despike,analyze,show,group_add/remove/clear), panneaux (principal, Steps replié, Despike, Analyze replié), listeSLICEWRAP_UL_groups.core.py: voxels (dilate,erode,_outside,fill), maillage (mesh_world_arrays,sample_surface,voxelize,blocky_mesh), nettoyage (taubin,keep_largest_island,despike,group_weights,fix_missed_rays), analyse (analyze_shape,write_analysis),unique_object_name,build_envelope.tests/run_tests.py: suite (sphère trouée bruitée ;--head= tête réelle + rendus). Exclu du paquet.blender_manifest.toml: extension 5.1+ (décidé le 2026-10-20) ;[build]exclut__pycache__/, zips,.a2m/,.claude/,.git/,.gitignore,CLAUDE.md,tests/,dist/..a2m/project.toml: données du projet pour la chaîne d'outils a2m et le site (écrit para2m adopt).CHANGELOG.md(en) /CHANGELOG.fr.md(fr) : historique ; la section « Unreleased » / « Non publié » donne les notes de la prochaine release.
Commandes
- Tests :
"C:\Program Files\Blender Foundation\Blender 5.2\blender.exe" -b -P tests/run_tests.py -- <dossier> [--head]→RESULTAT : TOUT OK(~1 min, 29 contrôles dont annulations) ; avec--head, regarderslice_wrap_head_face.png/_cote.png. À lancer avant chaque release (la chaîne a2m ne lance pas encore les tests de l'addon). - Construction et publication : chaîne d'outils a2m (repo
ange/apc-toolchain, remplace les ancienstools/Build-Package.ps1ettools/New-GiteaRelease.ps1, retirés le 2026-10-20) :a2m validate --load(manifest validé et addon chargé dans Blender 5.1 et 5.2, profil temporaire),a2m build→dist\slice_wrap-<version>.zip,a2m release [patch|minor|major](version du manifest, CHANGELOG, commit, tagv<version>, release Gitea avec le zip etpublication.json),a2m release --dev(pré-release de test, réservée aux membres). Publication = action externe : ne la lancer qu'à la demande de l'utilisateur. .gitignore:__pycache__/,dist/,*.zip, rendus de test.
Historique
Voir CHANGELOG.fr.md (une entrée par version ; les changements à venir dans « Non publié »).
Mesures de référence (Blender 5.2.1, tête Pixal3D brute 11,8 M faces)
Enveloppe 70 k faces en 11 s ; chaîne complète ~1,5–2 min ; ~93 k ratés réparés au Freeze ; Despike filtré « Oreilles » 683 corrections vs 4 749 global ; Analyze 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).
Dépôt d'extensions Blender sur a2msystemes.org (idée du 2026-10-17, prise en charge par APC)
But : les addons de l'utilisateur (Slice Wrap, Slice Retopo, suivants) installables et mis à jour via Preferences > Get Extensions > Repositories > Add Remote Repository, au lieu d'Install from Disk. Cette note est à l'origine du projet APC (A2M Publication Contract) : le dépôt n'est plus à écrire ici.
- Publication :
a2m release(chaîne d'outilsange/apc-toolchain) joint à chaque release Gitea le zip et unpublication.json(contratange/apc-spec) ; le script de déploiement du site (ange/site-a2msystemes-org) en fabriqueblender-addons/index.jsonet les pages du projet. Adresse du dépôt et pages : voir le site. - À rappeler à l'utilisateur : les addons déjà installés par Install from Disk (dépôt
user_default) ne reçoivent pas les mises à jour → les désinstaller puis réinstaller une fois depuis le nouveau dépôt.
Pistes
- Option avancée repliée pour Absolute ; préréglages par type d'objet (tête, main, accessoire).
- Accélérer le remplissage (propagation par lignes / scanline au lieu d'une dilatation voxel par voxel).
- Surplombs (pavillon de l'oreille) : seconde projection Nearest Surface Point limitée à un groupe de sommets.
- Remaillage adaptatif (octree + Dual Contouring) pour props / LOD / cible de bake (pas pour l'animation).
- Retopologie guidée → projet Slice Retopo (marqueurs + retopo_tags + motifs ; voir son CLAUDE.md).
Préférences de travail de l'utilisateur
- « Ne fais rien, explique » = aucune modification ; valider le plan avant les gros lancements ; expliquer les paramètres (à quoi ils servent) avant de décider.
- Ne pas casser le concept de base d'un add-on en ajoutant des fonctions : sous-panneaux optionnels.
- Dans son Blender ouvert (MCP) : lecture seule d'abord, copie « au cas où », sauvegarder / restaurer la vue.
- Calculs longs dans des fenêtres PowerShell externes ; vider la VRAM ComfyUI avant chaque génération
(
~/.claude/CLAUDE.md).
Skills du projet (.claude/skills/)
slice-wrap-dev— faire évoluer, tester et livrer cet add-on.mesh-wrap-cleanup— la méthode wrap et le nettoyage manifold (à la main ou avec l'add-on).blender-addon-testing— tests en arrière-plan, rendus de contrôle, paquet d'extension, pièges de l'API.blender-live-mcp— travailler dans le Blender ouvert de l'utilisateur sans rien casser.ai-3d-asset-pipeline— génération 3D par IA (ComfyUI) qui produit les maillages sources.