Fixes the two root causes behind four of the seven reported breakages, and
rejects the source that cannot be fixed.
STAND UP FIRST. flatten_and_scale() now derives the up axis from the
skeleton and rotates the model upright before measuring anything. Aria and
Momo are correct: 1.75 m tall, 1.43 x 0.41 and 1.52 x 0.39 across, verified
by render.
The up vector is measured from the FEET to the HIPS, not from the hips to
the head. The head is not a reliable landmark — the spine walk ends on the
last non-cosmetic bone in the chain, which on a rig with a facial skeleton
can sit BELOW the hips. Momo's did, so the first cut of this fix stood her
neatly on her head: right size, right proportions, upside down. Feet cannot
be mistaken.
REACH BONES BY ROLE. SkinnedPlayerModel gained _role_bone(), and set_weapon
uses it. Four characters could not hold a gun because one hardcoded lookup
knew three spellings and their hands are called "Right wrist" and
"J_Bip_R_Hand" — both resolved perfectly in the sidecar the whole time.
HIKARI IS REJECTED. She now fails the gate: her feet and spine disagree
about which way is up, so the stand-up correction cannot resolve her
either, on top of zero-length cosmetic bones and a second armature that was
smuggling its own clips into the export. That is not a tuning problem, it
is a file that has been through two toolchains. De-registered and removed
rather than shipped broken — which is what the gate is for.
Six GLB skins remain, all passing. Smoke 0 failures, 11/11 movement tests.
Still open, recorded in the skill: kiyoko faces backwards, miku's grown
hair stretches under animation, the mannequin's rifle hold does not
convince, and taila's front skirt clipping.
Co-Authored-By: Claude Opus 5 <[email protected]>
Kiyoko, Hikari, Aria and Momo, all CC-BY from Sketchfab, licences recorded
beside each skin. Seven GLB characters selectable now.
kiyoko 13 meshes 20 cloth chains (62 bones) 0.0% cross-leg bleed
aria 15 meshes 15 cloth chains (37 bones) 0.0%
momo 5 meshes 9 cloth chains (35 bones) 0.0%
hikari 13 meshes 10 cloth chains (37 bones) 0.2%, 12 twist bones
These are the first characters imported that were NOT authored against the
library's own bone spelling, and every one of them broke something that
had been quietly wrong all along. All four failures were in code that
guesses anatomy from names, which is exactly what tools/rig_map.py exists
to stop doing:
- LIMB ROLES went to the first role in LIMB_ORDER that matched at all, so
shin's catch-all "leg" claimed UpperLeg before thigh's exact "upperleg"
was ever consulted, and the thigh went unassigned. The result depended
on the order bones arrived in. Claims are now granted longest-stem
first. This also broke Mixamo (LeftUpLeg/LeftLeg) and had simply never
been hit, because every character so far used Rigify DEF- names.
- Names cannot settle thigh-vs-shin at all. A bare "leg" is the SHIN on
Mixamo and the THIGH on a rig whose shin is "knee" — both common, same
token, opposite bones. RigRoles now walks the leg from the foot upward
and fills in whatever the names could not, stepping over twist bones.
- verify_character.py looked for legs by the substrings "thigh"/"shin",
which VRoid spells UpperLeg/LowerLeg. It declared every locomotion clip
static while the legs animated perfectly, and the cross-leg bleed check
found no leg vertex groups at all and passed vacuously. Two green-
looking lies from one missing lookup; both now read the sidecar's
resolved roles.
- The cosmetic/spring classifier matched whole tokens only, so Momo's
HairFL / HairFR / HairF_Top tokenised to "hairfl" and matched nothing.
She imported with six chains, all bust, and no hair. Both classifiers
now share one rule that also accepts a two-character positional suffix,
which is short enough that "forearm" and "earring" are still untouched.
Two more pipeline fixes:
- A source model's own clips leaked into the export. Clearing bpy.data
.actions before the library import is not enough — hikari carried two on
a second armature's NLA tracks, and NLA_TRACKS export mode ships
anything in a track anywhere in the file. They export as rest-pose
statues. Now everything not retargeted is stripped from every object.
- verify_character.py gained a check for cloth chains with no measurable
extent. A chain whose bones are zero-length is dropped by the runtime
and simulates nothing, while the sidecar still cheerfully reports it.
Known: hikari's ten cloth chains are all zero-length and her collider fit
found nothing, so her costume does not simulate — her rig has been through
two toolchains and its cosmetic bones are empty terminators. She animates
correctly otherwise. The new check now reports this instead of hiding it.
tools/retarget.py also carries local working-tree changes that predate
this session.
Co-Authored-By: Claude Opus 5 <[email protected]>