Commit Graph
3 Commits
Author SHA1 Message Date
Nicholas Butzke 922983429e big 2026-08-02 02:20:02 -04:00
Nicholas ButzkeandClaude Opus 5 c8b0337aa7 fix(characters): rig-independent weapon mount, measured facing, revert Miku
WEAPON MOUNT, all models. set_weapon() seated the gun with a fixed
rotation_degrees = (0, 90, -90). A bone attachment is expressed in the
BONE's axes and no two rigs agree on those, so one constant mounted the
weapon differently on every character. It never needed to be right: the
pose layer aims the gun by rotating the wrist until the weapon's forward
lies on the aim line, so the identity means "forward is the hand bone's
-Z", which is true on any rig, and the wrist absorbs the roll. The grip
now sits at the bone origin, so the gun is in the hand rather than at an
offset from a differently-oriented bone. Verified by render on kiyoko:
rifle shouldered, both hands on it.

FACING. flatten_and_scale() now measures toes-versus-ankles and snaps the
character to face Blender -Y, the convention the runtime's blanket flip is
built around. Kiyoko was 180 degrees off. Snapped to the nearest quarter
turn so splayed feet in a rest pose are not read as a turned character.

MIKU. Re-imported without --grow-cloth. Her grown hair chains were the
cause of the stretching: cloth_bones.py clears a vertex's body weights and
re-assigns it to the fitted polyline, so a poor fit does not degrade to
"stiff", it degrades to "torn". She now has no hair simulation — stiff but
correct — until that tool blends against the weights it replaces instead
of destroying them.

ARIA'S SKIRT IS NOT SIMULATED. Worth recording plainly, because it looks
better than Taila's and the obvious conclusion is the wrong one: aria has
ZERO cloth chains. Her skirt never clips because it is rigidly skinned and
follows the legs it is weighted to. There is nothing to port to Taila
except switching her simulation off.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-07-26 16:29:04 -04:00
Nicholas ButzkeandClaude Opus 5 fc9e6f4275 feat(characters): four VRoid characters imported and selectable
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]>
2026-07-26 13:45:27 -04:00