Nodes/ComfyUI-MeshTools/MeshTools Decimate (Advanced)
ComfyUI Node

MeshTools Decimate (Advanced)

Decimation with every knob exposed

By agenticvibes·Created 5 months ago·Updated 5 months ago· 0
MeshTools Decimate (Advanced)
  • trimesh
  • trimesh
subdivideParts16
target_face_num
target_face_ratio
strategyNone
maxError
maxEdgeLen
maxBdShift
maxTriangleAspectRatio
criticalTriAspectRatio
tinyEdgeLength
stabilizer
angleWeightedDistToPlane
optimizeVertexPos
collapseNearNotFlippable
touchNearBdEdges
maxAngleChange
decimateBetweenParts
minFacesInPart

MeshTools Decimate (Advanced) is the full-parameter version of the pack's decimator, and the first thing to know about it is that you probably don't need it. The pack ships a Simple Decimate node that does the same job with two settings, and the author's own docs say the simple one is easier for most users. So what is this for? When simple edge-collapse to a target count isn't good enough - when the shape is drifting, when you're pushing an extreme reduction, when you want the mesh to survive aggressive culling with minimal visual damage - the Advanced node hands you the entire meshlib DecimateSettings object as a pile of widgets and lets you drive it.

Under the hood it's the same machinery as Simple Decimate: meshlib's decimateMesh, with packMesh on and parallel processing via subdivideParts. The difference is every quality lever the library exposes. That's the pitch: edge-collapse decimation is a greedy process that decides which edges to collapse, and meshlib gives you knobs to bias that decision toward shape preservation, boundary stability, and triangle quality. This node exposes all of them.

The inputs that matter

There are a lot of fields here (the full list is the whole meshlib settings struct), but a beginner sets four:

  • target_face_num or target_face_ratio - the destination, exactly like Simple Decimate. You must set one; if both are 0, the node raises a ValueError. One of the two, not neither.
  • subdivideParts (default 16) - parallel threads. Match your core count.
  • strategy - the big one: MinimizeError preserves shape, ShortestEdgeFirst is faster. If you care about quality, this is the first knob to set.

Then there's the quality tier you'll touch when the defaults disappoint:

  • maxError - maximum geometric error allowed per decimation step. Lower = more accurate. This is the classic "how much shape drift do I tolerate" dial.
  • maxAngleChange - caps how much a face normal can swing per step (in radians). Great for keeping flat regions flat.
  • maxTriangleAspectRatio - rejects decimations that create thin, sliver triangles; criticalTriAspectRatio is the hard version of the same idea.

Everything else - maxEdgeLen, maxBdShift, tinyEdgeLength, stabilizer, angleWeightedDistToPlane, optimizeVertexPos, collapseNearNotFlippable, touchNearBdEdges, decimateBetweenParts, minFacesInPart - defaults to "off/unset" and only applies when you give it a value. The node only sets a settings field if the widget is above its zero-value, so you can't break it by leaving them alone.

How it works

The mechanism detail that matters: a value only takes effect if it's non-zero (or true). maxError defaults to 0, which meshlib reads as "no constraint." So the sane workflow is: set your target count and strategy, run it, and then turn on maxError or maxTriangleAspectRatio one at a time if the output looks wrong. Throwing all sixteen knobs at the first run is how you end up unable to tell what moved.

The node also prints the resulting vertex/face counts to the console, which is the fastest way to confirm the decimation actually did what you asked.

Output is a single trimesh socket, ready to chain into Export or Postprocess.

Installing

cd ComfyUI/custom_nodes
git clone https://github.com/agenticvibes/ComfyUI-MeshTools
cd ComfyUI-MeshTools
pip install -r requirements.txt

Or search "ComfyUI-MeshTools" in ComfyUI Manager. The meshlib dependency comes from requirements.txt - MeshLib is a big industrial 3D library but installs from PyPI without model downloads or a GPU.

Common issues

  • "target_face_num or target_face_ratio must be set" - same trap as the simple node. Both default to 0, and the node refuses to guess.
  • It looks worse than Simple Decimate - you ran it with defaults, which is the same as Simple Decimate but slower to think about. Set strategy to MinimizeError and give maxError a small value (0.01–0.05) for the shape-preserving behavior.
  • The output has thin triangles - push maxTriangleAspectRatio down. If you need to hard-guarantee quality, set criticalTriAspectRatio and steps that violate it get rejected outright.
  • Slow on huge meshes - it's threaded via subdivideParts, so make sure that's set to something near your core count rather than the default on a 4-core machine.

Honest take: most people will live happily in Simple Decimate. Reach for this one the day a decimated mesh makes you squint - and then change one knob at a time, because you'll never know which of the sixteen fixed it otherwise.

CategoryMeshTools

Inputs (19)

NameTypeDefaultDescription
trimeshTRIMESHInput mesh to decimate
subdividePartsINT161–64Number of parallel threads for decimation. Match to your CPU core count
target_face_numoptINT0–10000000Absolute target face count. Set either this or target_face_ratio
target_face_ratiooptFLOAT0–0.999Target as fraction of original faces (0.5 = half). Set either this or target_face_num
strategyoptCOMBONoneDecimation priority: MinimizeError preserves shape, ShortestEdgeFirst is faster
maxErroroptFLOAT0–1Maximum geometric error allowed per decimation step. Lower = more accurate
maxEdgeLenoptFLOATMaximum allowed edge length after decimation
maxBdShiftoptFLOATMaximum boundary vertex displacement during decimation
maxTriangleAspectRatiooptFLOATReject decimations that create thin triangles above this ratio
criticalTriAspectRatiooptFLOATHard limit on triangle aspect ratio — decimation steps that exceed this are rejected
tinyEdgeLengthoptFLOATEdges shorter than this are prioritized for collapse
stabilizeroptFLOATStabilization factor to prevent oscillation during optimization
angleWeightedDistToPlaneoptBOOLEANWeight error metric by face angles for more perceptually uniform results
optimizeVertexPosoptBOOLEANOptimize vertex positions after each collapse for better shape preservation
collapseNearNotFlippableoptBOOLEANAllow collapsing edges near non-flippable boundaries
touchNearBdEdgesoptBOOLEANAllow decimation of edges near mesh boundaries
maxAngleChangeoptFLOATMaximum allowed change in face normal angle per step (radians)
decimateBetweenPartsoptBOOLEANAllow decimation across part boundaries in multi-part meshes
minFacesInPartoptINTMinimum faces to keep in each mesh part during parallel decimation

Outputs (1)

NameTypeDescription
trimeshTRIMESH