@rig-c/pose 0.20.2 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/legs.ts +36 -1
- package/src/retarget.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rig-c/pose",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.3",
|
|
4
4
|
"description": "Puts motion from a body-18 pose sequence onto a rig built with rig-c: bone keys in rig-c's motion format, checked through rig-c's gate before anything is written. A CLI for agents that cannot see the rig.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/legs.ts
CHANGED
|
@@ -683,6 +683,23 @@ function placeHip(feet: Feet, offset: (i: number, s: Side) => Pt, travel: (i: nu
|
|
|
683
683
|
const tracked = new Array<Side | null>(n).fill(null);
|
|
684
684
|
for (const t of feet.tracked ?? []) for (let i = t.frames[0]; i <= t.frames[1]; i++) tracked[i] = t.side;
|
|
685
685
|
const trkX = trackFn ?? follow;
|
|
686
|
+
// #142: on a run (two or more flights), each support span's push-off ankle lift and side-to-side
|
|
687
|
+
// straight-length asymmetry would otherwise swing floorY - offset(i, s)[1] far past the pose's
|
|
688
|
+
// own bounce and ratchet the un-floored picture pass per cycle. Keep the support spans' mean floor
|
|
689
|
+
// shift across both support spans and flights, holding each grounded ankle on floorY via blends.
|
|
690
|
+
const isRun = feet.jumps.length >= 2 && feet.supports.length > 0;
|
|
691
|
+
let runShift = 0;
|
|
692
|
+
if (isRun && floorY !== null) {
|
|
693
|
+
const t0 = travel(0)[1];
|
|
694
|
+
const shifts: number[] = [];
|
|
695
|
+
for (let i = 0; i < n; i++) {
|
|
696
|
+
const s = feet.support[i] ?? null;
|
|
697
|
+
if (s === null) continue;
|
|
698
|
+
shifts.push(floorY - offset(i, s)[1] - (start[1] + travel(i)[1] - t0));
|
|
699
|
+
}
|
|
700
|
+
if (shifts.length > 0) runShift = shifts.reduce((a, b) => a + b, 0) / shifts.length;
|
|
701
|
+
}
|
|
702
|
+
const flightShift = runShift;
|
|
686
703
|
/** How the hip is derived on a frame: held over a foot's anchor, tracking the lower foot on the floor (#119), or carried by the pose's travel from a frame's hip (and for a jump against `floorY`, carried so the landing frame meets the floor and frames inside the flight never go below it, #103). */
|
|
687
704
|
type Mode =
|
|
688
705
|
| { kind: 'plant'; side: Side; anchor: Pt; from: number }
|
|
@@ -693,6 +710,13 @@ function placeHip(feet: Feet, offset: (i: number, s: Side) => Pt, travel: (i: nu
|
|
|
693
710
|
const o = offset(i, mode.side);
|
|
694
711
|
// In place (#92) the anchor's x follows the supporting ankle's own track from the frame it planted.
|
|
695
712
|
const dx = follow === undefined ? 0 : follow(i, mode.side) - follow(mode.from, mode.side);
|
|
713
|
+
if (isRun) {
|
|
714
|
+
const yPose = start[1] + travel(i)[1] - travel(0)[1] + (floorY === null ? 0 : runShift);
|
|
715
|
+
if (floorY === null) return [mode.anchor[0] + dx - o[0], yPose];
|
|
716
|
+
const d = -o[1];
|
|
717
|
+
const y = d > 0 ? Math.min(Math.max(yPose, mode.anchor[1] + STANCE_BOUNDS[0] * d), mode.anchor[1] + STANCE_BOUNDS[1] * d) : yPose;
|
|
718
|
+
return [mode.anchor[0] + dx - o[0], y];
|
|
719
|
+
}
|
|
696
720
|
return [mode.anchor[0] + dx - o[0], mode.anchor[1] - o[1]];
|
|
697
721
|
}
|
|
698
722
|
if (mode.kind === 'track') {
|
|
@@ -703,6 +727,13 @@ function placeHip(feet: Feet, offset: (i: number, s: Side) => Pt, travel: (i: nu
|
|
|
703
727
|
}
|
|
704
728
|
const a = travel(i);
|
|
705
729
|
const b = travel(mode.from);
|
|
730
|
+
if (isRun) {
|
|
731
|
+
let y = start[1] + a[1] - travel(0)[1] + (floorY === null ? 0 : flightShift);
|
|
732
|
+
if (mode.end !== undefined && floorY !== null && i <= mode.end) {
|
|
733
|
+
y = Math.max(y, floorY - Math.min(offset(i, 'r')[1], offset(i, 'l')[1]));
|
|
734
|
+
}
|
|
735
|
+
return [mode.at[0] + a[0] - b[0], y];
|
|
736
|
+
}
|
|
706
737
|
let y = mode.at[1] + a[1] - b[1];
|
|
707
738
|
if (mode.carry !== undefined && mode.land !== undefined && mode.end !== undefined && floorY !== null) {
|
|
708
739
|
if (mode.land < n && i <= mode.land && mode.land > mode.from) {
|
|
@@ -756,7 +787,7 @@ function placeHip(feet: Feet, offset: (i: number, s: Side) => Pt, travel: (i: nu
|
|
|
756
787
|
// The new support is held where it is on this frame, under the hip the old derivation gives here.
|
|
757
788
|
const here = of(mode!, i);
|
|
758
789
|
const o = offset(i, s);
|
|
759
|
-
from = mode;
|
|
790
|
+
from = isRun ? null : mode;
|
|
760
791
|
mode = plant(i, s, [here[0] + o[0], here[1] + o[1]]);
|
|
761
792
|
blendAt = i;
|
|
762
793
|
}
|
|
@@ -784,6 +815,10 @@ function placeHip(feet: Feet, offset: (i: number, s: Side) => Pt, travel: (i: nu
|
|
|
784
815
|
} else {
|
|
785
816
|
from = null;
|
|
786
817
|
hip.push(to);
|
|
818
|
+
const m = mode!;
|
|
819
|
+
if (isRun && floorY !== null && m.kind === 'plant' && Math.abs(to[1] - (m.anchor[1] - offset(i, m.side)[1])) > BLEND_HOLD_WITHIN) {
|
|
820
|
+
blends.push({ frame: i, side: m.side, y: m.anchor[1] });
|
|
821
|
+
}
|
|
787
822
|
}
|
|
788
823
|
}
|
|
789
824
|
return { hip, anchors, blends };
|
package/src/retarget.ts
CHANGED
|
@@ -775,7 +775,16 @@ export function retarget(rest: Rest, map: JointMap, frames: ReadonlyArray<Partia
|
|
|
775
775
|
const ankleSeries = { r: series.get('r_ankle')!, l: series.get('l_ankle')! };
|
|
776
776
|
const lower = stanceRangeOf(ankleSeries, { r: series.get('r_hip')!, l: series.get('l_hip')! });
|
|
777
777
|
blendHold = holdBlend(planted.blends, n, posedFeet, lower);
|
|
778
|
+
const holdAnchorX = feet!.jumps.length >= 2 ? blendHold.stretch.map((b, i) => (b ? posedFeet(i).ankle[b.side][0] : 0)) : null;
|
|
778
779
|
stretchChain(blendHold.stretch);
|
|
780
|
+
if (holdAnchorX !== null) {
|
|
781
|
+
for (let i = 0; i < n; i++) {
|
|
782
|
+
const b = blendHold.stretch[i];
|
|
783
|
+
if (!b) continue;
|
|
784
|
+
hip[i]![0] += holdAnchorX[i]! - posedFeet(i).ankle[b.side][0];
|
|
785
|
+
travel[i]![0] = hip[i]![0] - tb.worldX;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
779
788
|
// --stance (#60): with the hip placed, a free ankle within the tolerance of the floor has its leg
|
|
780
789
|
// stretched (every bone of its chain's scalex, about the chain's root) until it reaches it.
|
|
781
790
|
if (opts.stance !== undefined && opts.stance !== 'off') {
|