🔧 Dedup Vertices (Coincident Merge)
The 30 seconds that kills Z-fighting in your generated mesh
- glb_path
Open any image-to-3D output in wireframe and you'll see it: hundreds of vertices sitting on top of each other at the same coordinate, because the mesher emits per-face vertices and never bothered to weld them. Visually that gives you shimmering, speckled surfaces - Z-fighting where two coplanar triangles disagree about which one is in front - and it inflates your file size for nothing. Dedup Vertices is the fix, and it's about as close to a free lunch as mesh cleanup gets.
The pack reports it typically strips 30–50% of the vertices off TRELLIS output with no visible change to the mesh. That's not a quality trade, it's just removing redundancy.
How it works
It builds a KD-tree over the position buffer, asks for every pair of vertices closer than tolerance, and runs union-find over those pairs to group them into clusters. Each cluster collapses into one vertex placed at the average of its members, faces get remapped to the new indices, and vertices-in-a-cluster that produce a degenerate triangle (two corners landing on the same index) are dropped along with their faces.
The other vertex attributes get carried through the same remap: floats are averaged, integer attributes (joint indices, that kind of thing) take the first survivor, and WEIGHTS_0 gets averaged and renormalised so the skin weights still sum to 1. Somebody thought about rigged meshes here.
Inputs and outputs
glb_path- filename in ComfyUI'sinput/, or an absolute path.tolerance(default 0.0005, range 1e-5 to 1e-2) - merge distance, in the mesh's own units. The default is about 0.5mm in a metre-scale GLB. If you're still seeing speckle, nudge up to 0.001–0.002. If you're seeing lost detail around fingers, eyes, or thin cloth, back it off.
One output: glb_path, written to output/. It's an output node, so no downstream wiring is needed for it to run.
Install
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-poser-nodes.git
Restart, or install via ComfyUI Manager by searching melite-poser-nodes. The pack's declared deps are py-soma-x[anny], trimesh and xatlas; this particular node needs none of them - it's numpy plus scipy.spatial.cKDTree, and scipy ships with ComfyUI's runtime. If scipy is missing from your environment for some reason, this is the node that will tell you.
Where people get burned
The rebuild throws away the embedded textures. This is the one that actually bites. The dedup pass constructs a fresh BIN chunk containing the position array, the other vertex attributes, and the indices - the image and texture bufferViews that pointed into the old binary aren't copied over. Your UV mapping survives; the texture images packed in the GLB don't reliably come with them. So: what you get back is a clean, welded geometry file. If you need the texture, either run dedup before you texture, or plan to re-attach the maps afterwards (which is the job SkinApply and RaySwapBaseColorTexture exist for).
Only the first primitive is processed. Like its sibling cleanup nodes, it reads meshes[0].primitives[0] and leaves the rest alone. Multi-material GLBs get partial treatment.
Don't confuse this with CleanMesh. Dedup is welding and nothing else. Wrap it with repair and decimation and you've rebuilt CleanMesh - so if you want a face budget too, use that node instead and save yourself a graph pass.
Tolerance is in mesh units, and mesh units vary. A SOMA body GLB is in centimetres; a TRELLIS export is usually metre-scale. 0.0005 means very different things in those two files. If the node reports merging everything or merging nothing, that's your first suspect.
MIT-licensed, published from a private inference estate in September 2026, which is why there's no Reddit thread to cross-check against - but the code path is short enough to read in one sitting, and the WEIGHTS_0 handling is a good sign that the author was working with skins, not just static props.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| glb_path | STRING | — | |
| tolerance | FLOAT | 0.00050.00001–0.01 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| glb_path | STRING | — |