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.
83 lines
4.2 KiB
Markdown
83 lines
4.2 KiB
Markdown
# 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
|
|
|
|
```sh
|
|
# 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.cjs` reads 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.
|
|
- `resolveChar` defaults to `Grandma_mixamo`, which is not currently uploaded to the
|
|
account. **`X Bot`** is a Mixamo stock rig and works; for anim-only export the source
|
|
rig is irrelevant anyway, since `_rotOnly` keeps rotations only.
|
|
- Anim-only FBX (`SKIN` unset) has **no mesh** and renders nothing. Judging a
|
|
silhouette needs `SKIN=1`.
|
|
- Don't retarget onto `Hum_M_1_mixamo.fbx` to 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" trap `build_player_anims.py`
|
|
documents.
|