Nodes/NodeRig/NodeRing Output
ComfyUI Node

NodeRing Output

A full 3D pose editor lives inside this one ComfyUI node — no Blender, no API key

By WizarDiego·Created 5 months ago·Updated 5 months ago· 0
NodeRing Output
    • pose_image
    • background_image
    flip_horizontalfalse

    NodeRing Output is the entire NodeRig pack wearing a trench coat: drop one node on the canvas and a full WebGL 3D scene editor appears inside it, ready to pose a character, render it, and hand the picture to your ControlNet or IPAdapter as an IMAGE tensor. It's the answer to a very specific pain - you want a pose ControlNet to match a gesture or composition you can't get by prompting, and you'd rather not round-trip through Blender or an online posing site to make it. The name is a lie in one direction: it never touches an API and needs no key. It's a local editor that talks to itself.

    Trade-off up front: this is a niche, quietly-updated pack with almost no community footprint. Treat it as a fiddle-to-first-use tool, not plug-and-play. Once it clicks, it's genuinely handy.

    What it actually is

    The node is a 600×600 iframe running a Three.js scene (rotate with the left mouse, dolly with scroll, pan with right). Load a GLB/GLTF model - one is built in, mannequin.gltf - and NodeRig auto-detects every Bone and SkinnedMesh in it. Click a bone to select it, shift-click a second bone to build an A→B pair, then drive them with Rotate/Translate/Scale sliders. There's an IK mode (Three.js CCD solver), a mirror axis for syncing pairs, a random-pose button, saved A+B pairs in localStorage, even lens effects - focal length, barrel distortion, bokeh, vignette, chromatic aberration. That last batch is the fun part: you can rough in the exact cinematic camera look you're after before the diffusion model ever sees the frame.

    The editor isn't a separate window. It's a DOM widget injected into the node itself by web/NodeRingUI.js, so the whole thing rides along when you save the workflow.

    How the magic pipe works

    There's a clean trick hiding in here. The 3D editor renders in your browser, but the node's process() runs in Python. The bridge is an aiohttp route: when you hit Send Memory in the editor, it POSTs the render (and optionally the background plate) as base64 to POST /NodeRing on ComfyUI's own server. That handler stashes the strings in NodeRing.latest_pose_b64 and NodeRing.latest_bg_b64 - class-level variables, not widget state. When you queue the graph, process() decodes them into torch IMAGE tensors. There's also a Save to /input button that writes noderig_pose.png into ComfyUI's input folder.

    Two mechanical details worth knowing. First, the class defines IS_CHANGED to return float("NaN"), the canonical "always rerun this node" idiom - the engine compares each run's value and NaN never equals itself, so the node fires every queue run and fresh renders flow downstream. That's intended for a source node like this, but it also defeats caching for everything after it. Second, it only works when the UI is actually open and you've sent a render: there's no API-only path, and a node with nothing stored decodes to a flat black 512×512 image.

    The inputs and outputs that matter

    The input list is one field long:

    • flip_horizontal - BOOLEAN, default false. Mirrors both outputs left-to-right when enabled. Handy when a pose reads wrong, and about as simple as an input gets.

    Outputs (both IMAGE):

    • pose_image - the full scene render: model plus lighting.
    • background_image - the background plate alone, no 3D model.

    pose_image typically feeds a ControlNet; background_image is nice for IPAdapter or a Florence-2 caption pass. One honest warning from the ControlNet side: this renders a shaded 3D figure, not an OpenPose stick skeleton, and pose ControlNets that expect keypoint diagrams can react oddly to shading. Depth or lineart conditions generally play nicer with a rendered mesh. Test your condition on a static pose before investing time in a full animation sequence.

    Installing it

    No requirements.txt, no model download - the only dependencies (Pillow, NumPy, torch) are already inside ComfyUI, and Three.js runs client-side in your browser. Either path works:

    cd ComfyUI/custom_nodes
    git clone https://github.com/WizarDiego/NodeRig
    

    ...then restart ComfyUI, or grab it via ComfyUI Manager by searching "NodeRig". The node appears under the NodeRig category as NodeRing Output.

    Troubleshooting

    • Black image out of the node - you haven't hit Send Memory in the editor, or you're running a queue without the browser open. The node only outputs what was last POSTed to it; queue once after sending.
    • Pose doesn't update - same root cause: a stale render is sitting in the class variable. Send, then run.
    • Everything downstream re-executes - that's the NaN IS_CHANGED doing its job. Normal for this pack.
    • No GLB? Upload your own via the dock; it persists between sessions in the pack's assets/models folder.

    It's a quirky tool with a steep enough first curve, but for quick, Blender-free character posing it's a genuinely fun addition to a ControlNet workflow.

    CategoryNodeRig

    Inputs (1)

    NameTypeDefaultDescription
    flip_horizontalBOOLEANfalse

    Outputs (2)

    NameTypeDescription
    pose_imageIMAGE
    background_imageIMAGE