✂ Clean Mesh (Dynamic Guard)
For the skirt, the inner shell, and the seam nobody wanted
- mesh
- info
- mesh
Ask anyone who generates meshes what they spend their time on and you get the same answer: "they all need cleanup - all the frontier models produce the same mesh soup." That's the honest state of image-to-3D in 2026, and it's why a node like this exists.
Clean Mesh is not a general repairs-everything node. It is a targeted fix for three specific artifacts of generated characters: the ragged skirt at the bottom of a bust, the hidden inner shell that Hunyuan3D-style reconstructions leave inside the outer surface, and the folded seam where two roughly-coplanar shells got stitched.
How it works, in order
- Vertices get welded, then
flat_bottomslices off the bottom 1.5% of the model's Z extent (hard-coded, no slider). That removes the crinkled cut edge that makes slicers complain. - The mesh is split into disconnected parts. Each part is scored: is it pointing outward (its centroid direction dotted against its average face normal), or is it big and high up the model? Parts that fail both tests get dropped. That's what deletes the inner shell.
- The seam pass is the "dynamic guard". It walks face adjacency looking for pairs whose face normals are nearly opposite (
fold_threshold, default -0.85), grows connected clusters out of those folded edges, and for clusters bigger thanscale_threshold× the model's extent, deletes the candidate faces whose normals point back toward the model's axis. It's a raycaster with a sanity check, and deleting inward-facing triangles from a fold is exactly the fix for a doubled-up shoulder or a crease that reads as a black gash. - With
close_holeson, trimesh'sfill_holes()runs as a last courtesy, then winding and normals get fixed.
What you actually set
mesh- the TRIMESH in. Feed it the raw generator output, before anything else.fold_threshold, range -1.0 to -0.5, default -0.85. Less negative is more aggressive: -0.6 catches far more adjacency pairs as "folded". If your seams survive, come up to -0.7; if it starts eating good geometry, go to -0.95.scale_threshold(default 0.3) - how big a folded cluster has to be relative to the whole object before the deleter cares. Lower it and small folds get processed too; that's where over-deletion comes from.flat_bottom(default on) - turn it off for anything whose bottom is the actual subject, like a scan.close_holes(default on) - cheap, occasionally causes new garbage on very complex topology, so it's the first thing to switch off when the result got worse.
One honest note: protect_outer is a dead switch. It's in the input list and the function signature, but the shipped code never reads it - the outward test is hard-coded. Leave it on, ignore it, and don't build a workflow around it.
Outputs are info (STRING - note it's slot one) and mesh (slot two). The info string is terse, but if you're debugging, watch the face count land here and compare it with the viewer.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Antonioilev/ComfyUI_Antonioilev_Lightpack.git
python -m pip install trimesh scipy
Manager works too (search Antonioilev Light Pack), but Manager cannot install dependencies for this repo because the repo declares none - no requirements.txt, no install.py. This node imports trimesh, numpy and scipy.sparse, and scipy ships with most ComfyUI environments already. Restart after installing; startup prints [Antonioilev_Light_pack] Loaded N nodes (M failed) and any module that failed its imports is listed under that with the actual Python error.
Where people get burned
Nothing changed. On a clean single-shell mesh there is genuinely nothing for this node to do. It is not a decimator and not a smoother - Refine Mesh and Mesh Fixer Fast cover those.
It ate a legitimate part. Two eyes, two hands, a detached prop - the outer-face heuristic can drop a part that points oddly. Set flat_bottom off only if you need it, keep scale_threshold at 0.3 or higher, and check the result in a 3D preview rather than trusting the console.
Wrong order in the chain. Clean Mesh works on raw topology. Run it before you colour, texture, or cap; the cap and the colour layers assume a stable mesh.
Chain it as: generator → Clean Mesh → Mesh One Surface / Mesh Fixer Fast → Refine Mesh → export. Skip it and you'll be fighting the skirt in Blender at 1am, which is the thing this whole pack is trying to spare you.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| mesh | TRIMESH | — | |
| fold_threshold | FLOAT | -0.85-1–-0.5 | — |
| scale_threshold | FLOAT | 0.300.01–0.9 | — |
| protect_outer | BOOLEAN | true | — |
| flat_bottom | BOOLEAN | true | — |
| close_holes | BOOLEAN | true | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| info | STRING | — |
| mesh | TRIMESH | — |