ComfyUI Node

Pose Composer 3D

A Kinematic Skeleton With Actual Camera Angles

By Spit8·Created 2 months ago·Updated 2 months ago· 1
Pose Composer 3D
    • pose
    • guide
    • prop_mask
    • prop_hint
    pose_sourcelibrary
    actionidle
    camera_presetSE
    yaw0
    pitch0
    roll0
    distance0.00
    use_manual_camerafalse
    width1024
    height1024
    propnone
    prop2none
    fov_deg35
    pose_prompt
    llm_base_urlhttps://api.openai.com/v1
    llm_modelgpt-4o-mini
    llm_api_key

    Most pose tools make you draw a stick figure in 2D and pray it reads as "three-quarter view." CP_PoseComposer3D skips the praying: it builds the pose in actual 3D - a kinematic skeleton, joint angles applied per-bone, a perspective camera orbiting it - then projects the result down to a 2D OpenPose canvas. That's why its camera presets (S, SE, E, NE, N, NW, W, SW) actually look like different angles instead of the same skeleton rotated in the flat plane.

    It's the creative core of the pack, and CP_PoseTransferPrep is really just this node wrapped with a captioner. If you want to fiddle with poses directly - or drive them from a text prompt - this is where the knobs live.

    How it works

    A 3D humanoid skeleton with FK joint angles gets posed, a perspective camera (fov 35° by default) looks at it from one of eight isometric positions, and the 3D joint positions are projected to 2D pixel keypoints. Props attach to joints as 3D polylines and are drawn in cyan on the guide - over the OpenPose sticks, so the body's COCO-18 keypoints stay untouched for ControlNet compatibility. The prop is a visual hint plus a prompt string, not a separate conditioning channel.

    pose_source has two modes:

    • library - pick a named action (idle, walk_01..04, run_01..04, jump, fight_01/02, work_01/02, cast, ride_idle).
    • text - describe a pose and the node calls an OpenAI-compatible chat API to get Euler joint angles back, then clamps them to per-joint limits so the pose doesn't break. Defaults point at https://api.openai.com/v1 with gpt-4o-mini; point it at http://127.0.0.1:11434/v1 for a local Ollama (llama3.2, any non-empty key). It also honors CHARACTERPOSE_LLM_API_KEY or OPENAI_API_KEY as env fallbacks.

    The inputs that matter

    • camera_preset - the eight compass positions. SE (¾ front-right) is the default and the RPG-sprite standard.
    • use_manual_camera - off by default, in which case yaw/pitch/roll are fine-tune offsets on the preset. Flip it on for absolute yaw/pitch/roll control.
    • prop / prop2 - sword, shield, staff, bow, horse, or none.
    • action (library) or pose_prompt + the llm_* trio (text).

    Outputs: pose (the POSE object), guide (the drawn OpenPose guide image), prop_mask (the prop strokes as a mask - feed it to a canny preprocessor yourself if you want a real ControlNet channel), and prop_hint (the text hint to inject into your prompt).

    Installing

    Same pack as always:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Spit8/_ComfyUI_CharacterPose
    pip install -r _ComfyUI_CharacterPose/requirements.txt
    

    Restart ComfyUI; it's under CharacterPose/Pose. The text-pose mode needs network access to whatever LLM endpoint you configure; library mode needs nothing.

    Gotchas

    • Text mode calls an API. It's OpenAI-compatible and needs no key for local Ollama, but the default config does hit api.openai.com - if you don't want that, set the base URL first.
    • A 3D pose projected to 2D still lands with the same-view bias every pose pipeline has: a ¾ pose is genuinely a ¾ pose. Don't expect the composer to conjure a camera angle the skeleton can't physically present.
    • Props are guide strokes + prompt hints, full stop. If you need a hard prop lock, you'll be feeding prop_mask to your own ControlNet canny channel.

    The node that makes "same character, eight different camera angles" a dropdown instead of a struggle. For game sprites, that's most of the job.

    CategoryCharacterPose/Pose

    Inputs (17)

    NameTypeDefaultDescription
    pose_sourceCOMBOlibrary2 options: library, text
    actionCOMBOidle16 options: cast, fight_01, fight_02, idle, jump, ride_idle, +10
    camera_presetCOMBOSE8 options: S, SE, E, NE, N, NW, +2
    yawFLOAT0-180–180
    pitchFLOAT0-60–60
    rollFLOAT0-30–30
    distanceFLOAT0.000–8
    use_manual_cameraBOOLEANfalse
    widthINT102464–4096
    heightINT102464–4096
    propCOMBOnone6 options: none, sword, shield, staff, bow, horse
    prop2optCOMBOnone6 options: none, sword, shield, staff, bow, horse
    fov_degoptFLOAT3515–90
    pose_promptoptSTRING
    llm_base_urloptSTRINGhttps://api.openai.com/v1
    llm_modeloptSTRINGgpt-4o-mini
    llm_api_keyoptSTRING

    Outputs (4)

    NameTypeDescription
    posePOSE
    guideIMAGE
    prop_maskIMAGE
    prop_hintSTRING