ComfyUI Node

Mesh Simplifier

Shave a Million Faces Off Your ComfyUI 3D Mesh Without Melting the Textures

By roundyyy·Created about a year ago·Updated about a year ago· 10
Mesh Simplifier
  • mesh
  • simplified_mesh
simplify_methodtarget_faces
target_faces1000
percentage_reduction0.75
quality_threshold0.5
texture_weight1.0
preserve_boundaryTrue
boundary_weight1.0
optimal_positionTrue
preserve_normalTrue
planar_simplificationTrue
pre_cleanTrue

The name is a lie - Mesh Simplifier doesn't do any AI. It's a 3D mesh utility wearing a diffusion-workflow costume, and honestly that's the best thing about it. When ComfyUI-3D-Pack hands you a StableFast3D, Hunyuan3D, or ZeroScope3D mesh, it's usually carrying tens of thousands to millions of triangles that your target engine, game, or Blender scene doesn't need. This node drags that down to a sane face count while keeping the texture map on it, so you get a model that still looks like the original instead of a melted wireframe. The author (roundyyy on GitHub, r0undyy on Reddit) built it to clean up his own StableFast3D workflow after getting sick of the messy, intersecting geometry these models ship - so it's a dogfooded utility, not a demo.

How it works

Under the hood it's a file-based roundtrip: your mesh gets written to a temporary OBJ, PyMeshLab loads it into a MeshSet, runs decimation, and the result is read back into ComfyUI-3D-Pack's MESH format. No GPU involved - this is CPU number-crunching from the VCGLib mesh-processing library.

The actual decimation is Quadric Edge Collapse, the workhorse algorithm behind most mesh-simplification tools. For meshes with UV coordinates it runs the texture-aware variant (meshing_decimation_quadric_edge_collapse_with_texture) that folds texture distortion into its cost function; for naked meshes it runs the plain version. If pre_clean is on, it first merges close vertices, drops unreferenced vertices, and kills duplicate faces - which fixes a lot of the "jumbling" that raw 3D-gen output is famous for. It then runs a planar edge-flip optimization as a polish pass and copies your albedo and metallic-roughness maps back onto the simplified mesh.

The inputs that actually matter

There are eleven knobs, but you'll live most of your life on four:

  • simplify_method - target_faces or percentage_reduction. Pick one strategy; the other parameter gets ignored.
  • target_faces - exactly how many faces you want out (default 1000). This is the one I'd reach for: "give me 5k faces" is easier to reason about than a percentage.
  • percentage_reduction - the fraction to remove, not keep. 0.75 means "cut 75% of the faces," which confuses everyone once.
  • pre_clean - merge close vertices and delete duplicates first. Great for 3D-gen output, but it's also the setting that can trigger the texture-coordinate error below, so keep it in mind when things break.

The rest - quality_threshold, texture_weight, preserve_boundary, boundary_weight, optimal_position, preserve_normal, planar_simplification - are quality dials you can leave at defaults until you care. The one output, simplified_mesh, is a MESH that wires straight into 3D-Pack's Save 3D Mesh node.

Install

Two dependencies first: ComfyUI-3D-Pack is a hard requirement - the MESH type comes from it, not from this node - and PyMeshLab gets pulled in automatically. In ComfyUI Manager, search "Mesh Simplifier" and hit install. Manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/roundyyy/ComfyUI-mesh-simplifier
cd ComfyUI-mesh-simplifier
pip install -r requirements.txt

Then restart ComfyUI. Note the requirements pin trimesh==4.4.1 and numpy==1.26.4 exactly - the classic ComfyUI pain point, since every node shares one Python environment and another node's newer numpy can silently break this one. If simplification starts throwing odd errors after you installed something else, check those pins. Also: the whole thing is GPL-3.0 because PyMeshLab is GPL, which matters only if you're doing something weird with commercial redistribution.

Where people get burned

The README's known issues, straight from the author:

  • "Current mesh does not have Per Wedge Texture Coords" - UVs got lost somewhere. Try gentler simplification (fewer faces removed) or turn pre_clean off.
  • Missing textures after export - the node transfers albedo/metallic-roughness itself, so connect simplified_mesh directly into a Save 3D Mesh node rather than running it through anything else first.
  • Big meshes crash or eat RAM - PyMeshLab loads the whole thing into memory and it roundtrips through disk. If it dies on a giant model, raise target_faces or lower percentage_reduction.

One honest caveat: the OBJ roundtrip is lossy for fancy PBR setups, and very aggressive decimation will smear fine detail even with texture preservation. For a game-ready character you'd want a real retopo pass in Blender afterward. But for "I need this model at a fifth of the poly count and it has to keep its skin," this is the node the community was quietly asking for.

Category3D/Mesh

Inputs (12)

NameTypeDefaultDescription
meshMESH
simplify_methodCOMBOtarget_faces2 options: target_faces, percentage_reduction
target_facesINT100010–1000000
percentage_reductionFLOAT0.750.01–0.99
quality_thresholdFLOAT0.50.1–1
texture_weightFLOAT1.00–2
preserve_boundaryCOMBOTrue2 options: True, False
boundary_weightFLOAT1.00–2
optimal_positionCOMBOTrue2 options: True, False
preserve_normalCOMBOTrue2 options: True, False
planar_simplificationCOMBOTrue2 options: True, False
pre_cleanCOMBOTrue2 options: True, False

Outputs (1)

NameTypeDescription
simplified_meshMESH