π§β Ground Body Β· camera-space β world
Getting a floating, upside-down estimator mesh onto the floor, the right way up
- glb_path
Every body that comes out of the Multi-HMR 2 estimator is in OpenCV camera space: +X right, +Y down, +Z forward, and the person hovering at camera distance - the pack's own live probe puts the mesh roughly 0.4m across and centred around zβ1.85m. Nothing that renders a turnaround or composites a character can use that. It wants +Y up, feet on the ground, origin at the centre.
This node is the map between those two conventions, and it's the difference between a body that appears in the right place in your scene and one that appears inverted and mid-air.
What it does, exactly
It loads the GLB, merges any multi-geometry scene into one mesh, then applies a rotation of Ο about the Z axis. That's not a guess - the transformation is known because the pack knows its own estimator's convention, and that rotation flips the down-axis to up while keeping things right-handed. After the flip it grounds the feet (minimum Y to zero), centres X and Z on the bounding box, and writes a fresh GLB to output/anny/anny_grounded_body_<timestamp>.glb.
Scale is preserved. Metres in, metres out - a 1.7m person stays 1.7m, which matters if you're compositing them against anything with real dimensions.
Then a sanity check: if the tallest extent of the result isn't Y, the node refuses with the actual extents printed. That's the guard against feeding it a mesh from some other estimator with a different convention. It's a suspiciously specific guard and that's the point - it exists because the pack was burned by a body that was vertically correct in extent but upside down in orientation.
The UV seat
Worth calling out, because it's the part people trip over later. If every geometry in the GLB already carries a TEXCOORD_0 channel, that UV data is carried through the transform verbatim. If it doesn't, the node unwraps with xatlas - real island charts and packing, not a planar projection bolted on to make something downstream shut up.
And if xatlas isn't installed, it raises rather than exporting a position-only body. The pack's reasoning is blunt: downstream consumers (coat detail maps, fit seating) refuse a body with no UVs, so writing one would just move the failure somewhere less legible. xatlas is in the pack's requirements.txt, so a normal install has it.
Inputs and outputs
One input, glb_path, and the tooltip tells you exactly what to wire: AnnySelectPerson.glb_path. One output, also glb_path - a new file in output/anny/, not the one you passed in. Nothing is mutated in place.
It's an output node, meaning it always executes when it's part of a queued graph. Terminal artifacts get written even if nothing downstream consumes them, which is why you can drop it at the end of a chain and just look at the GLB.
Install
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-kimodo-nodes.git
cd melite-kimodo-nodes
pip install -r requirements.txt
Restart. The only two dependencies this node touches are trimesh and xatlas, both declared by the pack - no model, no checkpoint, no GPU work. It's the cheapest node in the family by a wide margin and it runs in well under a second.
Where people get burned
The transform is a one-shot and the guard doesn't catch re-entry. Rotation by Ο about Z preserves the extent of a mesh, so if you feed this an already-world-space, already-Y-up body - or its own output from a previous run - the extent check passes happily and you get a body flipped upside down. Chain it once, from the estimator mesh, and don't loop it back into itself or into a graph that already grounded.
The other thing to internalise: this node knows exactly one convention, Multi-HMR 2's. Gloves, props and GLBs from every other image-to-3D model in the ecosystem are in whatever frame their author chose, and some of them are already Y-up with feet at the origin. Running those through here will rotate them for no reason. Check orientation before you reach for it.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| glb_path | STRING | estimator mesh GLB path β wire AnnySelectPerson.glb_path |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| glb_path | STRING | β |