🎬 Kimodo Export FBX (Retarget)
KimodoExportFBX is four nodes in a trenchcoat — pick your inputs carefully
- animated_path
Your character is rigged. It isn't moving. This is the node that makes it move - or converts it, or rigs a raw mesh, depending on which inputs you fill in. That's the trap: KimodoExportFBX doesn't have modes you select. It has modes you accidentally trigger by wiring something up.
The decision tree is by input combination:
| rigged_path | npz_path | source_glb | what runs | |---|---|---|---| | yes | yes | - | retarget motion onto the rig (Blender) | | yes | - | - | plain format conversion, GLB↔FBX (Blender) | | - or yes | - | yes | SOMA weight transfer onto the raw mesh (torch, no Blender unless FBX) | | yes | yes | yes | SOMA weight transfer then retarget, in one pass |
Watch rows three and four: filling source_glb overrides rigged_path for the rigging half. Wire both because "surely both are useful" and your carefully prepared rigged file gets ignored.
How the retarget works
Headless Blender, via the pack's blender_retarget.py. SOMA-77 motion and a Mixamo-named armature don't share a coordinate frame - SOMA is X-left/Y-up/Z-forward, Blender is X-right/Y-forward/Z-up - so every rotation gets conjugated through a fixed conversion matrix and each bone's matrix_basis is solved from its parent's world rotation: on per-joint delta rotations if the NPZ carries global rotation matrices, otherwise by matching rest-direction to posed-direction.
Here's what decides whether you get a person or a cautionary tale. The delta reference is not frame 0 of the motion - it's the true T-pose from bind_rig_transform inside skin_standard.npz, because frame 0 of a walk cycle is an A-pose and the difference is up to 84° on the arms. Without that file, the script logs T-pose not found, falling back to frame 0 (may produce body horror) and does exactly that.
Inputs you'll actually touch
rigged_path- a GLB/FBX with Mixamo bone names; in this pack's flow, fromSaveRiggedModel.npz_path- the SOMA-77 motion file fromKimodoTextToPose(the author's separatemelite-kimodo-nodespack). Empty means conversion only.source_glb- a raw textured mesh.source_glb+npz_pathis the one-click door: rig and animate in a single node.fpsandfile_format- the output frame rate, andfbxversusglb. Pick the format for the destination, not for quality.in_place(default on) - zeroes horizontal root drift so the character walks on a treadmill and stays centered. Leave it on unless you want it travelling across the scene.decimate_ratio(default 0.2) - Blender's Decimate modifier in Collapse mode, which preserves skin weights, dropping the mesh to ~20% of its faces. 0 disables it. Set it to 0 when you're going to look closely.preserve_texture(default on) - SOMA-standalone mode only. Turn it off for a flat untextured body you'll re-texture later. No effect in retarget mode.
One output: animated_path, a STRING at output/3D/KimodoAnimated_<timestamp>.fbx (or .glb). Wire it onward. If it's coming back into a graph that wants a TRIMESH object, export glb - trimesh doesn't read FBX.
Install
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-autorig-nodes.git
Then restart. ComfyUI Manager: search "melite". pip gives you trimesh, scipy, requests - and deliberately not Blender, which the pack shells out to instead. It looks for the binary at BLENDER_BIN, then blender on PATH, then a hardcoded portable path, and finally raises a FileNotFoundError that names the requirement. On a headless box:
export BLENDER_BIN=/opt/blender-4.2.5-linux-x64/blender
Worth knowing where that failure lands: it's raised at node execution, only on the branches that run Blender. So the pure-torch SOMA path with file_format: glb doesn't need Blender installed at all.
Where people get burned
- "both rigged_path and source_glb are empty" - the only up-front validation. Nothing else is checked before work starts.
- SOMA-standalone modes need a file you probably don't have.
skin_standard.npzis looked up at the absolute path/opt/kimodo/kimodo/assets/skeletons/somaskel77/skin_standard.npz, with no env override. Not running the author's estate layout? The weight transfer dies atnp.load. The retarget path only warns and falls back to frame 0. - Ten-minute ceiling. Blender runs under a 600-second timeout; long clips with a heavy mesh can hit it. Drop
decimate_ratioand retry. - The MIMO vision check needs a key. After a successful retarget, the node renders four frames and posts them to a remote vision endpoint to look for mangled joints. Without
MIMO_API_KEYit logs... cannot validateand moves on - the export still succeeds, so a missing key costs you the QA pass and nothing else. Frames of your character do leave the machine when it runs. If the verdict never shows up,BLENDER_EEVEE_NEXT(a Blender 4.2+ engine name) failing to render is usually why. - Relative paths. Anything non-absolute resolves against
input/, thenoutput/, then a recursive walk ofoutput/. Most "file not found" errors here are a stale filename from an earlier run - outputs are timestamped, so nothing is reused.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| rigged_path | STRING | Path to a rigged GLB/FBX with Mixamo bone names. Connect from SaveRiggedModel or provide a path. | |
| fps | INT | 301–120 | Output animation frame rate. |
| file_format | COMBO | fbx | FBX for Unity/Unreal/Kimodo. GLB for web/Three.js. |
| npz_pathopt | STRING | Optional: SOMA-77 motion NPZ for retargeting. If provided, Blender retargets motion onto the character. If empty, just converts format. | |
| in_placeopt | BOOLEAN | true | In-place motion: zero root horizontal drift so character walks on a treadmill (stays centered). Recommended for Pose Studio. |
| decimate_ratioopt | FLOAT | 0.200–1 | Mesh decimation ratio (0=off, 0.2=reduce to 20%% of faces). Uses Collapse mode which preserves skin weights. Reduces file size ~70%%. |
| source_glbopt | STRING | Optional: original textured GLB. When provided (and no npz_path), GPU transfers the rig + skin weights from rigged_path onto THIS mesh, preserving textures. Uses AABB-aligned torch.cdist nearest-neighbor on the RTX 4090 (~10s for 500K verts) and writes the GLB directly — no Blender involved. | |
| preserve_textureopt | BOOLEAN | true | SOMAX standalone mode only. When True (default), the output GLB keeps the source mesh's textures. When False, all textures are stripped and the mesh is given a flat SOMA-blue material — useful when you want to apply textures later in Pose Studio or an external tool. Ignored for retarget. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| animated_path | STRING | — |