Mesh to Mesh Distance
How far off is your reconstruction? Now it's a number
- mesh_a
- mesh_b
- distance
- info
The core question of any 3D reconstruction or remesh pipeline is "how close is the result to the original?" Eyeballing two meshes side by side in a viewer tells you something, but it doesn't tell you how much - and it certainly can't be wired into an automated decision. Mesh to Mesh Distance turns that question into a single FLOAT you can log, compare, or use to gate a workflow: "if the remeshed version is within X of the source, keep it; otherwise try again."
It's part of ComfyUI-GeometryPack ("ComfyUI libigl") by Andrea Pozzetti. It computes its distances with point-cloud-utils, a solid MIT-licensed library for exactly this job.
How it works
You give it two meshes - mesh_a and mesh_b - and it samples each with sample_count points (default 10000, from 1000 up to 1000000), then measures between the two point clouds. The metric combo picks the flavor:
hausdorff(default) - the maximum deviation. It's the worst-case error: the single farthest gap between the two surfaces. Great for "is this approximation acceptable anywhere?"chamfer- the average nearest-neighbor distance. It's the overall similarity, forgiving of a few bad spots. Better for "is this roughly the same shape?"
The symmetric combo (default true) controls whether you get the round-trip distance or a one-sided A→B measure. With symmetric on, the info output reports both one-sided directions plus the symmetric value, which is genuinely useful: a large A→B vs B→A asymmetry tells you one mesh is a subset of the other, which is common when comparing a decimated version against its source.
The inputs that matter
metric- hausdorff for worst-case, chamfer for average. Pick by what "close enough" means to you.sample_count- more points, more faithful measure, slower run. 10k is fine for a first pass; bump to 100k+ when the two meshes have very different tessellations and you want the sampling to even things out.symmetric- leave ittrueunless you specifically want one direction.
Outputs: distance (FLOAT) and info (STRING with the full breakdown).
Where it fits
The obvious loop is reconstruction validation: original scan vs. the reconstructed surface, or a high-res mesh vs. its remesh/decimation. The subtler one is automation - wire distance into a compare or switch node so the graph retries a remesh when the threshold isn't met. That's the kind of thing ComfyUI makes genuinely pleasant once the number exists.
Install and caveats
Pack standard: search "GeometryPack" in ComfyUI Manager, or clone and install:
cd ComfyUI/custom_nodes
git clone https://github.com/PozzettiAndrea/ComfyUI-GeometryPack.git
cd ComfyUI-GeometryPack
pip install -r requirements.txt --upgrade
python install.py
Restart after. The pack's comfy-env installer drags in pixi plus a heavy isolated environment on first launch - slow first boot, and point-cloud-utils gets compiled/installed as part of it, so the first distance computation can have a one-time cost.
The main trap is units: the distance comes out in whatever units your meshes are in, and the two meshes need to be in the same coordinate frame. If mesh_a is normalized to a unit box and mesh_b is in millimeters, the "distance" is garbage and it won't look obviously wrong. Run both through the same transform (like Normalize to BBox) before comparing. And remember the numbers describe the sampled surface, not the mesh topology - a huge sample_count helps, but sampling can never fully see geometry a mesh hides.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| mesh_a | TRIMESH | — | |
| mesh_b | TRIMESH | — | |
| metric | COMBO | hausdorff | 2 options: hausdorff, chamfer |
| sample_countopt | INT | 100001000–1000000 | — |
| symmetricopt | COMBO | true | 2 options: true, false |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| distance | FLOAT | — |
| info | STRING | — |