Mesh To Voxel
Turn any 3D mesh into a colored voxel block and watch it render in your browser
- mesh
- Voxel Block
Mesh To Voxel is the front door of this whole pack. You hand it a 3D mesh and it hands back a VOXEL_BLOCK - a cubic grid of colored voxels that everything else in ComfyUI-Voxels is built around. If the pack's pitch (turn meshes into animated "voxel videos") is what brought you here, this is where the pipeline starts.
ComfyUI has no built-in notion of voxels, so the pack defines its own VOXEL_BLOCK type: a voxel_size × voxel_size × voxel_size × 4 numpy array of RGBA values, uint8. That's the currency of every node in this pack, and this node is the mint.
How it works
The mechanism is pleasingly simple and it's all in the node source. It takes the mesh's vertices, computes the bounding box, then scales everything so the longest axis fits inside your chosen grid. Each vertex gets floored to an integer grid coordinate and clipped to stay in bounds, and its vertex color is summed into that voxel. After every vertex lands, colors are averaged and the alpha channel is set to 255 for anything occupied. Net result: a clean N×N×N block where occupied voxels hold the averaged color of the mesh surface around that spot.
That last part is worth understanding: only the vertices get counted, and vertices live on the surface. A closed mesh gives you a hollow voxel shell, not a filled solid - usually exactly what you want for that retro voxel look, but don't expect it to fill interior volume.
The inputs that matter
Only two inputs, and only one you'll touch:
- mesh (
MESH) - a trimesh object, the sameMESHtype ComfyUI's own 3D mesh loader hands you. The node literally checksisinstance(mesh, Trimesh), so feed it a real mesh, not a file path. - voxel_size (
INT, default 20, range 1–100) - grid resolution per axis. 20 is a nice chunky default (8000 potential voxels). Crank toward 100 and you get fine detail but a lot of memory and a browser that struggles to render a million cubes in the viewer. Start at 20.
It returns one output, Voxel Block (VOXEL_BLOCK). Wire it into Voxel Viewer to look at it in 3D, or Voxel Block Saver to write it to disk.
Where people get burned
- No vertex colors = black voxels. The color comes from
mesh.visual.vertex_colors. A plain imported OBJ with no color data voxelizes fine but comes out all black. That's not a bug in the node, it's what the mesh carried in. - Flat or degenerate meshes break the scale math. The grid scale is computed from the bounding-box span, so a mesh with zero span in one axis divides by something tiny and you get a weird or empty block.
- It re-runs every queue.
IS_CHANGEDreturns a random value, so this node always executes even with unchanged inputs. Harmless, but it means you can't skip cached results. - Pair it with the right twin. There are two mesh-to-voxel nodes in this pack - Mesh To Voxel and Voxelize Mesh. This one preserves colors and fits the mesh into the grid properly. The other one uses PyVista and is, bluntly, the rough draft. Default to this one.
Installing it
The pack's README is empty and it has no requirements.txt, so the usual one-click story is only half the story:
# ComfyUI Manager: search "ComfyUI-Voxels", or:
cd ComfyUI/custom_nodes
git clone https://github.com/DanielHabib/ComfyUI-Voxels
# then restart ComfyUI
Because there's no requirements.txt, you may need to add this node's real dependency by hand:
pip install trimesh numpy
A quick reality check: this repo has a single commit, was last touched in September 2024, and has about four stars. It's a small experiment, not a maintained project. For a beginner that mostly matters because you shouldn't expect bug fixes - and for what it does, it genuinely works. Feed it a colored mesh, and a few seconds later you've got a voxel block you can spin around in your browser.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| mesh | MESH | — | |
| voxel_size | INT | 201–100 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Voxel Block | VOXEL_BLOCK | — |