Nodes/BrainDead Nodes/BD Mesh Repair
ComfyUI Node

BD Mesh Repair

The daily-driver mesh fix — holes, duplicates, degenerate faces, and normals in one pass

By BizaNator·Created 8 months ago·Updated 3 days ago· 15
BD Mesh Repair
  • mesh
  • mesh
  • status
remove_duplicatestrue
remove_degeneratetrue
close_holestrue
max_hole_edges100
repair_normalstrue
merge_threshold0.0001

BD Mesh Repair runs a topology cleanup on a mesh using PyMeshLab: closes holes, merges duplicate vertices, removes degenerate faces, and fixes face orientation and normals. If you've ever imported a mesh and immediately seen black flickering faces (bad normals), welding seams (duplicate vertices), or a hole where a surface should be, you know why this exists. It's the mesh equivalent of "save and compress" - you run it on nearly everything before the mesh goes anywhere further.

The context matters here: the whole reason meshes come out of this ecosystem broken is that generated geometry is triangle soup. The KB's 3D essay is blunt about it - image-to-3D output has "terrible topology and messed-up UV unwrapping" by professional standards. A repair pass doesn't retopologize anything; what it does is fix the mechanical failures (holes, dupes, degenerates, flipped faces) so the mesh is actually usable downstream, whether that's baking, UV unwrap, or export to an engine.

The inputs - all optional, all on by default

Every repair is a toggle, and they all default to ON, which is the right call:

  • remove_duplicates - merge duplicate/close vertices. Fixes the "welded seam" look where two halves of a mesh don't quite line up.
  • remove_degenerate - drop zero-area faces and duplicate faces. Degenerate triangles don't render, don't UV properly, and slow everything down.
  • close_holes - close open boundaries, up to max_hole_edges (default 100). Deliberate openings (eyes, mouth on a head mesh) above that size stay open.
  • repair_normals - fix face orientation and recompute normals. This is the one that kills the black-flicker problem.
  • merge_threshold - how close two vertices must be to count as duplicates (default 0.0001, quite strict). Raise it slightly if seams persist.

Outputs: the repaired mesh (same TRIMESH type - feeds straight into the next BD node) and a status string.

Where it fits

Think of it as the routine cleanup, upstream of the specialist tools. BD Mesh Repair is what you run on a fresh load or right after generation; when you then hit a hole too big for max_hole_edges, that's when BD Mesh Lib Fill Holes (MeshLib's curvature-aware filler for large, irregular holes) comes in. When you need decimation, BD Smart Decimate or BD CuMesh Simplify follows. Repair first, then transform - most mesh tooling behaves much better on a clean manifold.

Installing

Standard BrainDead install - ComfyUI Manager search "BrainDead" or clone + pip install -r requirements.txt, restart. The dependency to know about: it calls into PyMeshLab (pymeshlab). The node lazy-imports it and reports a clean error if it's missing, so pip install pymeshlab is the fix if you see it. Also needs trimesh (the pack's mesh foundation) and a current ComfyUI for the V3 API.

One habit: don't assume ON-everything is right for every mesh. If your mesh has intentional holes (a mouth cavity, a window frame), close_holes with a default max_hole_edges of 100 will leave those alone, but if you're repairing something with deliberately large openings and they keep getting filled, lower the cap rather than fighting the output. And run it before UV unwrap - unwrapping a mesh with duplicate vertices is how you get UV islands that never behave.

Category🧠BrainDead/Mesh

Inputs (7)

NameTypeDefaultDescription
meshTRIMESH
remove_duplicatesoptBOOLEANtrueMerge duplicate/close vertices
remove_degenerateoptBOOLEANtrueRemove zero-area faces and duplicates
close_holesoptBOOLEANtrueClose holes in mesh
max_hole_edgesoptINT1003–1000Max edges for hole closing
repair_normalsoptBOOLEANtrueFix face orientation and recompute normals
merge_thresholdoptFLOAT0.00010.00001–0.01Distance threshold for vertex merging

Outputs (2)

NameTypeDescription
meshTRIMESH
statusSTRING