Nodes/ComfyUI_Antonioilev_Lightpack/🌊 Mesh One Surface
ComfyUI Node

🌊 Mesh One Surface

Manifold3d does the work, and one slider is decorative

By AntonioilevΒ·Created 2 days agoΒ·Updated a day agoΒ· 0
🌊 Mesh One Surface
  • mesh
  • info
  • mesh
β—„merge_tolerance0β–Ί
β—„force_manifoldtrueβ–Ί
β—„fix_windingtrueβ–Ί

Everything you generate is a lie about solidity. The mesh looks solid; the file contains an outer skin, an inner skin, and probably a few shards in between. Slicers hate it, physics engines hate it, and every retopo you attempt inherits it.

"One surface" is the promise: collapse all of that into the single outer shell. Two of the three parameters are real and the third is decorative, so let's do the honest version.

What it does

  1. Welds vertices with merge_vertices(merge_tex=False, merge_norm=False) - exact-position welding, no tolerance. So it does not close micro-gaps; it only unifies vertices that are already identical.
  2. Drops degenerate faces.
  3. If force_manifold is on and manifold3d is installed, it converts the mesh into manifold3d's representation, builds a Manifold, and calls keep_largest(). That's the actual magic: manifold3d guarantees manifold output and keep_largest discards every interior shell in one go, including the "matryoshka" copies nobody can select by hand.
  4. Back in trimesh, if the result still isn't watertight, fill_holes() runs as a fallback.
  5. fix_winding() and fix_normals() if fix_winding is on.

The info output is a proper one-liner: WATERTIGHT | In: 84211 faces, Manifold Applied | 1.86s or NON-MANIFOLD | ... when it couldn't get there.

The parameters, honestly

  • mesh - TRIMESH in.
  • force_manifold (default on) - the whole point. See the dependency section.
  • fix_winding (default on) - leave it.
  • merge_tolerance (default 1e-6, range 0 to 0.01, step 1e-8) - this one does nothing. The function accepts it and never reads it; the weld is called with an exact-match setting. Adjusting it will change neither the result nor the timing. Worth knowing before you spend an evening sweeping it, and worth reporting upstream.

The dependency, which is the whole node

python -m pip install manifold3d

Without manifold3d, the module prints a warning at import (manifold3d not found. Install it for better sealing) and force_manifold becomes a no-op - you're left with degenerate-face removal, welding, and a fill_holes() fallback. The node still runs, still reports a time, and still gets you a mesh. It just isn't the node you asked for, and the only evidence is a warning line in the console that scrolls past during startup.

The info string is your receipt: if it doesn't say Manifold Applied, manifold3d isn't there or the conversion threw. Which brings the honest caveat about the whole design - everything is inside one big try/except, and if manifold3d raises (very large meshes, or float32/uint32 conversion trouble on some inputs) the node prints the error, appends Error: ... to the info, and hands back a partly-processed mesh. Check info, don't check the colour of the run.

What keep_largest() will cost you

It keeps the largest connected shell. On a bust, that's exactly right. On an asset that's legitimately several parts - a character with a separate hat, a scene with two props, a mesh you split on purpose - it will silently delete everything but the biggest piece and report WATERTIGHT, which is technically true. Turn force_manifold off for multi-part assets, or hold the parts in separate branches and concatenate after.

Same applies to detail that is only connected by proximity: hair strands, chains, thin straps. If the topology doesn't actually join them, they're a separate shell and a small one.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/Antonioilev/ComfyUI_Antonioilev_Lightpack.git
python -m pip install trimesh manifold3d

Restart ComfyUI, then read the console for both the manifold3d warning and the pack banner ([Antonioilev_Light_pack] Loaded N nodes (M failed)). Manager users: the pack installs by name - Antonioilev Light Pack - but the repo ships no requirements.txt, so nothing gets pulled in for you, and that includes manifold3d. This is the pattern across the whole pack: the code is one clone, the dependencies are a scavenger hunt.

Chain it after Clean Mesh and before Mesh Fixer Fast: get one shell first, then repair the holes in it. If you use it after Mesh Fixer Fast you'll be sealing a mesh whose inner shell was already deleted, which is a waste of the expensive step.

CategoryAntonioilev/Mesh

Inputs (4)

NameTypeDefaultDescription
meshTRIMESHβ€”
merge_toleranceFLOAT00–0.01β€”
force_manifoldBOOLEANtrueβ€”
fix_windingBOOLEANtrueβ€”

Outputs (2)

NameTypeDescription
infoSTRINGβ€”
meshTRIMESHβ€”