Part of #818 (Track A3). Status: PARTIAL — foot half shipped, gesture half missing.
src/FootContact.{h,cpp} ships contact detection (detectContacts), analytic two-bone IK (solveKnee) and edge blending (blendWeight), wired through AnimationMerger::pinFeet with GUI/CLI/MCP surfaces.
Remaining — the gesture end-effector pass
AnimationMerger.cpp:5654 still carries the limitation this issue exists to remove:
"Good-but-imperfect: locomotion looks right; arm-precise gestures place the arm approximately. A true IK/look-at retarget ... is the follow-up for exact gesture placement."
This is the observed "wave goes to the back / arm stops mid-throw / wave hits the face" class of bug on retargeted clips.
Design: for upper_body actions, solve two-bone arm IK so the retargeted WRIST matches the canonical wrist position (scaled by limb-length ratio), instead of only chaining local deltas down the arm.
The machinery already exists and should be reused rather than rewritten:
FootContact::solveKnee is generic two-bone IK — shoulder→elbow→wrist is geometrically identical to hip→knee→foot.
TargetBindFrame::roleBoneIdx already resolves arm roles (7/8/9 right, 11/12/13 left) exactly as it resolves the leg roles pinFeet uses.
pinFeet already does the manual FK over tracks, the canonical-frame mapping (tb.Ct), and the "fold a world-space correction into parent-relative keyframes" rewrite. The arm pass is the same shape with a different target rule (match a per-frame canonical position rather than pin to a span anchor).
Suggested surface: a sibling post-process (AnimationMerger::pinGestures or a shared src/RetargetIK.{h,cpp}), default ON behind the epic's QTMESH_T2M_IK=0 escape hatch, CLI --no-ik, mirroring pinFeet's GUI/CLI/MCP wiring.
Acceptance
- Wrist target error ≤ 5% of arm length on a wave clip retargeted to a rig with different arm proportions (fails today).
- Existing foot-pin behaviour and non-gesture clips unchanged (locomotion must not regress).
- Headless unit tests on a synthetic rig, in the
FootContact_test.cpp style.
Part of #818 (Track A3). Status: PARTIAL — foot half shipped, gesture half missing.
Done (#856)
src/FootContact.{h,cpp}ships contact detection (detectContacts), analytic two-bone IK (solveKnee) and edge blending (blendWeight), wired throughAnimationMerger::pinFeetwith GUI/CLI/MCP surfaces.Remaining — the gesture end-effector pass
AnimationMerger.cpp:5654still carries the limitation this issue exists to remove:This is the observed "wave goes to the back / arm stops mid-throw / wave hits the face" class of bug on retargeted clips.
Design: for
upper_bodyactions, solve two-bone arm IK so the retargeted WRIST matches the canonical wrist position (scaled by limb-length ratio), instead of only chaining local deltas down the arm.The machinery already exists and should be reused rather than rewritten:
FootContact::solveKneeis generic two-bone IK — shoulder→elbow→wrist is geometrically identical to hip→knee→foot.TargetBindFrame::roleBoneIdxalready resolves arm roles (7/8/9 right, 11/12/13 left) exactly as it resolves the leg rolespinFeetuses.pinFeetalready does the manual FK over tracks, the canonical-frame mapping (tb.Ct), and the "fold a world-space correction into parent-relative keyframes" rewrite. The arm pass is the same shape with a different target rule (match a per-frame canonical position rather than pin to a span anchor).Suggested surface: a sibling post-process (
AnimationMerger::pinGesturesor a sharedsrc/RetargetIK.{h,cpp}), default ON behind the epic'sQTMESH_T2M_IK=0escape hatch, CLI--no-ik, mirroringpinFeet's GUI/CLI/MCP wiring.Acceptance
FootContact_test.cppstyle.