Nodes/ComfyUI-Tools/3d - Simplify Trellis2 Mesh using mesh optimizer
ComfyUI Node

3d - Simplify Trellis2 Mesh using mesh optimizer

The same decimator, for TRELLIS.2's own mesh type

By visualbruno·Created 8 months ago·Updated a day ago· 5
3d - Simplify Trellis2 Mesh using mesh optimizer
  • mesh
  • mesh
◄target_face_count100000►
◄weld_verticestrue►
◄lock_bordertrue►
◄sparsefalse►
◄error_absolutefalse►
◄prunefalse►
◄regularizefalse►
◄permissivefalse►
◄regularize_lightfalse►

Why there are two of these

ComfyUI doesn't have a universal mesh. It has socket types that certain packs happen to agree on, and TRELLIS.2's pipeline passes around a MESHWITHVOXEL - a mesh object whose vertices and faces live as torch tensors and which carries the voxel field alongside the surface. That object is not a trimesh.Trimesh, so the pack's other simplifier won't accept it, and plugging a mesh output into a socket the node doesn't recognise is a dead end, not an error message you can work with.

Hence this node: identical simplification, same nine parameters, but it takes MESHWITHVOXEL and returns MESHWITHVOXEL. If you're inside a TRELLIS.2 graph, this is the one you want; if you're holding a trimesh, use Simplify Trimesh instead. This is the same author who wrote the community's most-used TRELLIS.2 ComfyUI wrapper, which is why the pipeline-specific node exists in a pack that otherwise doesn't know about TRELLIS at all.

How it works

Mechanically it's the sibling node with three extra lines of translation. It deep-copies the incoming mesh - so upstream nodes keep the original - pulls vertices and faces off the copy into numpy arrays, then runs the same two-stage meshoptimizer path: weld duplicate vertices with the remap routine, call meshopt_simplify with your target face count and a fixed internal error budget, compact the vertex buffer. Then it writes the new arrays back onto the copy, and that's what comes out the other side. The voxel data riding along on the object is untouched, so the simplified mesh can still go back into a TRELLIS.2 refinement or texturing stage.

The practical value is the same as the trimesh node and the reason it shows up in TRELLIS workflows: the decode and remesh stage is where faces explode to a million-plus, and the community answer - repeated in the TRELLIS.2 workflow threads - is to drop a simplify node after each remesh rather than try to carry the full-resolution mesh into texturing or export.

Inputs and outputs

Everything is shared with the trimesh version, so the short version:

  • mesh - the MESHWITHVOXEL to thin.
  • target_face_count - 100,000 by default, up to 10,000,000.
  • weld_vertices - leave it on; welding identical vertices is what gives the simplifier real topology to collapse, since generated meshes are split at seams.
  • lock_border - on by default, pins open boundary edges in place.
  • sparse, error_absolute, prune, regularize, permissive, regularize_light - meshoptimizer's option flags exposed as booleans, aimed at messy or disconnected topology. prune and permissive are the two worth reaching for on voxel-derived triangle soup; regularize is the one to leave alone unless you know you want evenly sized triangles.

Output: mesh, the same MESHWITHVOXEL type, back into the graph for a texture stage or an export node. It's flagged as an output node, so it runs as a terminal too.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/visualbruno/ComfyUI-Tools

Or install "ComfyUI-Tools" from ComfyUI Manager and restart. You'll obviously need a TRELLIS.2 pack installed as well, or you'll have a node with a socket nothing can fill. Only trimesh comes from the pack's requirements; the simplifier itself is the prebuilt meshoptimizer binary sitting in the pack's libs/ folder.

Where people get burned

The mesh libs only exist for two platforms. Windows gets a DLL, Linux x86-64 gets a .so, and everything else fails when the pack's 3D module is imported - which takes every node in the pack with it, not just this one. Same constraint as the trimesh simplifier.

Faces come back as float tensors. The node writes the simplified face indices back with .float(), which is what this object type wears. If a downstream TRELLIS.2 node refuses the mesh or produces nonsense, that's the first thing to check, and casting upstream is cheaper than fighting it.

No UV or attribute survival. Only vertex positions go into the simplifier; UVs, normals and colours tied to the old buffer aren't remapped. Simplify before you unwrap or texture, not after. And if you drop the face count too far before a mesh-refinement pass, you've thrown away the detail the refiner was going to work from - which is usually a bigger quality loss than the triangle count saved was worth.

CategoryVisualBrunoTools/3d

Inputs (10)

NameTypeDefaultDescription
meshMESHWITHVOXEL—
target_face_countINT1000001–10000000—
weld_verticesBOOLEANtrue—
lock_borderBOOLEANtrue—
sparseBOOLEANfalse—
error_absoluteBOOLEANfalse—
pruneBOOLEANfalse—
regularizeBOOLEANfalse—
permissiveBOOLEANfalse—
regularize_lightBOOLEANfalse—

Outputs (1)

NameTypeDescription
meshMESHWITHVOXEL—