Nodes/Melite Autorig Nodes/🎬 Kimodo Export FBX (Retarget)
ComfyUI Node

🎬 Kimodo Export FBX (Retarget)

KimodoExportFBX is four nodes in a trenchcoat — pick your inputs carefully

By JayDataEngineer·Created 2 months ago·Updated 4 days ago· 1
🎬 Kimodo Export FBX (Retarget)
    • animated_path
    â—„rigged_pathâ–º
    â—„fps30â–º
    â—„file_formatfbxâ–º
    â—„npz_pathâ–º
    â—„in_placetrueâ–º
    â—„decimate_ratio0.20â–º
    â—„source_glbâ–º
    â—„preserve_texturetrueâ–º

    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, from SaveRiggedModel.
    • npz_path - the SOMA-77 motion file from KimodoTextToPose (the author's separate melite-kimodo-nodes pack). Empty means conversion only.
    • source_glb - a raw textured mesh. source_glb + npz_path is the one-click door: rig and animate in a single node.
    • fps and file_format - the output frame rate, and fbx versus glb. 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.npz is 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 at np.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_ratio and 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_KEY it logs ... cannot validate and 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/, then output/, then a recursive walk of output/. Most "file not found" errors here are a stale filename from an earlier run - outputs are timestamped, so nothing is reused.
    CategoryMelite/AutoRig

    Inputs (8)

    NameTypeDefaultDescription
    rigged_pathSTRINGPath to a rigged GLB/FBX with Mixamo bone names. Connect from SaveRiggedModel or provide a path.
    fpsINT301–120Output animation frame rate.
    file_formatCOMBOfbxFBX for Unity/Unreal/Kimodo. GLB for web/Three.js.
    npz_pathoptSTRINGOptional: SOMA-77 motion NPZ for retargeting. If provided, Blender retargets motion onto the character. If empty, just converts format.
    in_placeoptBOOLEANtrueIn-place motion: zero root horizontal drift so character walks on a treadmill (stays centered). Recommended for Pose Studio.
    decimate_ratiooptFLOAT0.200–1Mesh decimation ratio (0=off, 0.2=reduce to 20%% of faces). Uses Collapse mode which preserves skin weights. Reduces file size ~70%%.
    source_glboptSTRINGOptional: 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_textureoptBOOLEANtrueSOMAX 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)

    NameTypeDescription
    animated_pathSTRING—