Gate 2.4 asked for lean/stagger/brace clips staged by wind band. The answer,
measured twice, is that the asset shouldn't exist.
1. The lean cannot be a clip. _rotOnly drops Hips.quaternion from every clip at
load (player.js:53, applied :239). Parsed the shipped pack to confirm rather
than trust the read: 17 clips, 195 channels each, 64 survive. A lean baked
into a clip's hips is discarded. And stripping it is right — the wind's
bearing swings (the change; site_02's venturi) and a canned clip has one
fixed lean axis, so only the sim can aim it. Same trick as the knockdown and
climbY. The lean is D's root pitch; thresholds proposed off Beaufort 7
("inconvenience felt when walking against the wind" = 13.9 m/s), which lands
storm_01 never leaning, storm_03 gusting through the line, storm_02 in gale.
2. Mixamo has no wind animations. Searched the real API, not assumed: shiver
returns zero, brace returns eleven ledge-hang clips, wind returns Catwalk
Turn. The factory header already recorded this in Sprint 3.
Rendered the two real candidates on a skinned rig, twice each — as authored and
as the game shows them. Pushing is a squat shoving a couch. Leaning is a man
waiting for a bus. Both rejected. Both would have passed every check we own:
they load, they're metre-scale, their nodes survive. Dims can't answer "is this
the right shape" — the bike rule, catching a whole feature this time.
Brace and stagger already ship (TakeCover, StumbleBack, Reaction). D should wire
the root lean first; I'll hand-author a WindPosture additive into the gap we can
both see, if one remains. Spine rotation survives _rotOnly, so it would land.
Evidence, harness and repro in tools/character/windclip_candidates/, plus the
four pipeline traps I hit in order so the next lane doesn't.
selftest 335/0/0, unchanged — no asset added, no shipped file touched.
|
||
|---|---|---|
| .. | ||
| README.md | ||
| rejected_Leaning.png | ||
| rejected_Pushing.png | ||
| skinshot.py | ||
Wind clips — the Mixamo candidates, and why they're rejected
Lane E, Sprint 13 gate 2.4 ("wind clips for the player — lean / stagger / brace, staged by wind band, through the Mixamo pipeline").
Outcome: no clip shipped. The Mixamo pipeline cannot supply a wind lean, and the lean was never going to be a clip in the first place. Both halves of that are measured, and the evidence is in this folder. Full argument in THREADS [E] 2026-07-17/18.
1. Mixamo has no wind animations
Searched the real API (fetch.cjs search, on ultra), not assumed:
| term | what comes back |
|---|---|
brace |
eleven Braced Hang ledge-climbing clips |
wind |
Standing Idle 04, Catwalk Walk Turn 180 |
shiver |
nothing, 0 results |
stagger |
three walks (Swagger Walk, Walking, Walking) |
lean |
Leaning On A Wall, Leaning, One Shoulder Lean |
push |
Pushing, Push Up, Button Pushing |
The factory's own header already recorded half of this in Sprint 3 — "Hammering / Sweeping Floor / Bracing don't exist on Mixamo — skipped." This is the case the asset-pipeline skill names directly: truly bespoke clips don't exist on Mixamo — hand-author, don't keep searching.
2. The two real candidates, rendered and rejected
skinshot.py films a skinned Mixamo FBX twice: as authored, and as the game
shows it (Hips rotation cleared, which is what player.js:_rotOnly does at load).
The second row is the honest one.
rejected_Pushing.png— not a wind lean. A deep squat shoving something heavy along the ground, standing up at the end. It reads as moving a couch. The forward angle I hoped to borrow is a squat, not a lean.rejected_Leaning.png— a casual weight-on-the-back-foot lean, the "propped against a bar" pose. Hands slack, no tension, near-identical across all five frames. A person waiting for a bus, not one in a gale.
Neither is close enough to fix by retiming. Shipping either would have passed every check we have — they load, they're metre-scale, their nodes survive — and been wrong on screen. That's the bike rule: the verify can't answer "is this the right shape."
3. The useful technical result
In both strips the raw and stripped rows are near-identical, which is worth
knowing: these clips carry their lean in the spine, and spine rotation survives
_rotOnly intact. So a hand-authored posture (spine curl, shoulder hunch, arm up)
would survive the loader. What cannot survive is a lean authored into the hips —
_rotOnly drops Hips.quaternion from every clip (player.js:53, applied :239).
Measured on the shipped pack: 17 clips, 195 channels each, 64 survive.
Which is why the lean belongs in player.sim.js as a root pitch aimed at
wind.dirAt(t) — the wind's bearing swings (the change; site_02's venturi) and a
canned clip has one fixed lean axis. Same trick as the knockdown and climbY.
Reproducing
# on ultra (the FBX libraries and the Mixamo login live there; JING5 has neither)
mkdir -p /tmp/shadeswind && cd /tmp/shadeswind
cp ~/Documents/mixamo-fetch/fetch.cjs .
printf 'Pushing\nLeaning\n' > wishlist.txt
SKIN=1 node fetch.cjs "X Bot" # SKIN=1: needs a mesh to judge a silhouette
/Applications/Blender.app/Contents/MacOS/Blender -b --factory-startup \
-P skinshot.py -- /tmp/shadeswind/out/Pushing.fbx Pushing
Notes for whoever next reaches for this pipeline:
fetch.cjsreads its token from a logged-in Brave on ultra via CDP (port 9222). Nobody types a password; the session is already there. It 429s after a handful of exports — space them out.resolveChardefaults toGrandma_mixamo, which is not currently uploaded to the account.X Botis a Mixamo stock rig and works; for anim-only export the source rig is irrelevant anyway, since_rotOnlykeeps rotations only.- Anim-only FBX (
SKINunset) has no mesh and renders nothing. Judging a silhouette needsSKIN=1. - Don't retarget onto
Hum_M_1_mixamo.fbxto preview: its armature carries FBX's 0.01 unit scale and the clip's action doesn't, so the body collapses to ~3 cm. That's the same "peds cannot round-trip through Blender" trapbuild_player_anims.pydocuments.