Mesh Ops
The geometry workshop ComfyTV hides in one dropdown
- model
- model
- image
Mesh Ops is the Swiss-army knife of ComfyTV's 3D geometry workshop - eight mesh operations live behind a single operation dropdown, and which parameters appear depends on which one you pick. It's the node you run a generated or imported mesh through to make it usable: bring a million-triangle AI mesh down to a reasonable count, remesh it into clean topology, weld the vertices, fill the holes, unwrap the UVs, and export the result - all on the canvas, none of it requiring you to leave for Blender.
ComfyTV is the canvas-style app layer on ComfyUI where every operation is its own node. Mesh Ops sits between Mesh Primitive / Mesh Boolean (which make geometry) and Mesh Bake Maps (which textures it).
How it works. One node, one operation per run; the card in the node body shows that operation's parameters. The operations, with the ones you'll actually use first:
decimate- bring the face count down via QEM edge collapse to atarget_face_count, withplacement_mode(midpointpreserves thin features,qemkeeps hard surfaces sharper) and optionalfeature_edge_quadric_weightto protect creases. This is the first stop for AI-generated meshes.remesh- rebuild topology on a voxel grid atresolution(256 ≈ 100k faces, 512 ≈ 1M), withsign_modeudf(robust to messy input) orsdf(clean single surface), plusproject_backto pull vertices toward the original.weld- merge duplicate vertices withinepsilon_rel(a fraction of the bounding-box diagonal).fill_holes- cap open borders, bounded bymax_perimeterandmax_verts.smooth_normals- blend normals pastcrease_angle(180 = fully smooth).subdivide- split every triangle into 4,iterationstimes.unwrap- generate UVs withsegmenterpec(fast GPU chart segmentation) oradaptive(CPU), targetingatlas_resolutionwithpaddingbetween charts. The setup step before baking.export- write the mesh out asglb(everything),obj(UVs/normals/colors), orstl(bare triangles).
The inputs that matter. The force_run_token, project_id, parent_output_id and captured_image inputs are internal plumbing. The real set: model (required), operation, and the subset of parameters the selected operation uses - the tooltips in the node body tell you exactly which. Outputs are model (the processed mesh) and image (the viewport preview).
Install. Install the pack once:
cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV
Restart ComfyUI (full restart, not a browser refresh) and the stage appears under ComfyTV → 3D. ComfyUI Manager - search "ComfyTV" - works too. Zero Python dependencies (the pack's pyproject.toml dependency list is empty) and no model files - all geometry math. Desktop/multi-install users: clone into the running instance's path from the startup log or the node won't register.
Where people get burned. The big one is decimating to a face count that's too aggressive - generated meshes lose their surface detail fast, and at a few thousand faces a "carved from clay" look sets in. Set target_face_count generously and let feature_edge_quadric_weight protect the creases you care about. Second: remesh at high resolution is slow and produces huge meshes - 512 is a million faces, which is more than you usually want from a cleanup. And for AI-generated meshes, keep the 3D-generation reality in mind: the topology is already triangle soup, so remesh or unwrap before you bake, and expect to follow up with a decimate. The workflow that works: decimate → weld → fill_holes → unwrap → bake.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| force_run_token | INT | 00–2147483647 | Internal — bumped on Run to invalidate ComfyUI's input cache. |
| project_id | STRING | Internal — populated by the projectStore on the frontend. | |
| parent_output_id | INT | 00–2147483647 | Internal — lineage parent set by spawn handlers on the frontend. |
| operation | COMBO | decimate | Which mesh operation to run; the card shows its parameters. |
| target_face_count | INT | 50000100–5000000 | decimate — target max face count (QEM edge collapse). |
| placement_mode | COMBO | midpoint | decimate — midpoint: robust, preserves thin features. qem: QEM-optimal vertex placement (sharper hard surfaces). |
| feature_edge_quadric_weight | FLOAT | 00–1000 | decimate/qem — extra quadric weight on dihedral feature edges. 0 = off. |
| feature_edge_min_dihedral_deg | FLOAT | 300–180 | decimate/qem — min dihedral angle (deg) for a feature edge. |
| resolution | INT | 25632–1024 | remesh — voxel grid resolution. 256 ~ 100k faces, 512 ~ 1M. |
| sign_mode | COMBO | udf | remesh — udf: robust to messy input. sdf: clean single surface. |
| project_back | FLOAT | 0.000–1 | remesh — lerp verts toward the original surface. |
| smooth_iters | INT | 00–20 | Taubin smoothing iterations. |
| epsilon_rel | FLOAT | 0.00000–0.01 | weld — tolerance as a fraction of the bbox diagonal. |
| max_perimeter | FLOAT | 0.0300–10 | fill_holes — max hole perimeter to fill (mesh units). |
| max_verts | INT | 163–1024 | fill_holes — cap boundary verts per hole. |
| crease_angle | FLOAT | 1800–180 | smooth_normals — edges sharper than this stay hard. 180 = fully smooth. |
| iterations | INT | 11–4 | subdivide — each iteration splits every triangle into 4. |
| segmenter | COMBO | pec | unwrap — pec: fast GPU chart segmentation. adaptive: CPU. |
| atlas_resolution | INT | 1024256–8192 | unwrap — target atlas resolution for texel-density auto-scale. |
| padding | INT | 10–16 | unwrap — texel padding between charts. |
| format | COMBO | glb | export — glb keeps everything; obj keeps UVs/normals/colors; stl is bare triangles. |
| captured_image | STRING | Internal — /view? URL of the preview-viewport snapshot. Written by the 3D preview in the node body; becomes the `image` output. | |
| modelopt | COMFYTV_MODEL | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| model | COMFYTV_MODEL | — |
| image | COMFYTV_IMAGE | — |