Nodes/ComfyTV/Mesh Boolean
ComfyUI Node

Mesh Boolean

Mesh Boolean without a modeling app

By jtydhr88·Created 3 months ago·Updated about 16 hours ago· 725
Mesh Boolean
  • model
  • model_b
  • model
  • image
force_run_token0
project_id
parent_output_id0
operationunion
resolution256
smooth_iters0
transform_b
captured_image
transform_a

Mesh Boolean is the node you reach for when a generated or imported mesh needs a hole cut through it, or two shapes need to become one. Drilling a window into a wall, subtracting one prop from another, fusing a base onto a figure - that's boolean geometry, and it's the kind of thing you'd normally open a full 3D app for. ComfyTV does it on the canvas, with the two meshes positioned live in the node body's viewport.

ComfyTV is the canvas-style app layer on ComfyUI where every operation is its own node. This sits in the 3D geometry workshop next to Mesh Ops, Mesh Primitive and Mesh Bake Maps - and it slots between them: Mesh Primitive makes the shapes, Mesh Boolean combines/carves them, Mesh Ops cleans the result, Mesh Bake Maps textures it.

How it works. The boolean is computed over a voxelized SDF (signed distance field) of both meshes, at a resolution you choose. Each mesh gets its own transform - position, rotation, scale - set with the gizmo in the node body (that's the transform_a / transform_b JSON). The operation runs on the SDFs: union keeps both volumes, difference removes model B's volume from model A, intersect keeps only the shared volume. The result is meshed back out and optionally smoothed with smooth_iters of Taubin smoothing. The preview viewport snapshot becomes the node's image output, so you can see what you carved.

The inputs that matter. The force_run_token, project_id, parent_output_id, transform_a and transform_b inputs are internal plumbing (gizmo-driven). The real set:

  • model / model_b - the two meshes. Both required; the node errors if either is missing.
  • operation - union, difference (B's volume out of A), or intersect.
  • resolution - 32–1024, default 256. Higher = sharper cut but way more faces; the tooltip's advice is worth taking: follow with a decimate for an exact count.
  • smooth_iters - 0–20 Taubin smoothing passes on the result.

Outputs are model (the boolean result, feeding Mesh Ops/Bake or a render stage) 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. 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 biggest one is expecting a sharp, clean cut from a low resolution. SDF booleans are voxel-based: at 256 you'll get visible faceting on the cut face - crank resolution up for a cleaner edge and accept the face explosion, then decimate. Second: the two meshes must actually overlap in the way the operation expects; difference with B entirely outside A just returns A, which reads as "nothing happened." And remember the gizmo positions matter - the booleans are computed on the transformed meshes, so re-positioning B in the viewport and forgetting to re-run means a stale result. One genuinely useful pattern: difference with a simple Mesh Primitive cylinder is the fastest way to drill a clean hole through any flat mesh.

CategoryComfyTV/3D

Inputs (11)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
operationCOMBOuniondifference removes model B's volume from model A.
resolutionINT25632–1024SDF voxel grid resolution. Higher = sharper cut, more faces; follow with a decimate for an exact count.
smooth_itersINT00–20Taubin smoothing iterations on the result.
transform_bSTRINGInternal — TRS of model B (position/quaternion/scale JSON) set by the gizmo in the node body.
captured_imageSTRINGInternal — /view? URL of the preview-viewport snapshot. Written by the 3D preview in the node body; becomes the `image` output.
transform_aSTRINGInternal — TRS of model A (position/quaternion/scale JSON) set by the gizmo in the node body.
modeloptCOMFYTV_MODEL
model_boptCOMFYTV_MODEL

Outputs (2)

NameTypeDescription
modelCOMFYTV_MODEL
imageCOMFYTV_IMAGE