What is wrong
three.ws plays one shared library of animation clips on any humanoid avatar a user uploads. That works because every rig is rewritten to one canonical skeleton first, in src/glb-canonicalize.js.
Skeletons coming out of Kinect v2 and Azure Kinect body tracking, and the many mocap and pose-estimation pipelines that copied that naming, put the side word at the end: ShoulderLeft, ElbowLeft, WristLeft, HipLeft, KneeLeft, AnkleLeft, FootLeft, with a spine chain of SpineBase, SpineMid, SpineShoulder.
None of it resolves today. The rig maps zero joints, falls under the retarget coverage floor, and the avatar falls back to a default body.
import { canonicalizeBoneName } from './src/glb-canonicalize.js';
canonicalizeBoneName('ElbowLeft'); // null <-- the gap
canonicalizeBoneName('elbowL'); // 'LeftForeArm' (already supported)
canonicalizeBoneName('leftElbow'); // 'LeftForeArm' (already supported)
Note the shape of the gap: the side-prefix (leftElbow) and the short side-suffix (elbowL) spellings both work. The full trailing side word (ElbowLeft) does not.
What to change
File: src/glb-canonicalize.js, the EXTRA_ALIASES block.
There is already a table for exactly this shape: the Second Life chain (mCollarLeft, mShoulderLeft, mKneeLeft) uses a trailing side word. Read those entries, then decide whether the right fix is more entries or a general trailing-Left/Right rule. Argue for your choice in the code comment the way the neighbouring blocks do.
Two joints need thought, and they are the interesting part of this issue:
SpineShoulder is the upper spine near the clavicles, not a shoulder. Map it to the spine chain.
ShoulderLeft in Kinect is the upper arm joint, not the clavicle. Compare with how the SMPL collar/shoulder collision is resolved elsewhere in this file, and with the existing test named splits an SMPL collar/shoulder collision.
How to prove it worked
Add cases to tests/glb-canonicalize.test.js beside the other per-convention blocks, then:
npx vitest run tests/glb-canonicalize.test.js # about 1 second
npm test # before you open the PR
Your test must cover both sides. A mapping that sends a left bone to a right canonical name tears the avatar apart in motion and it is the most common mistake in this file.
Also add a row to the conventions table in docs/rig-doctor.md, and if you want the detector to name the convention on sight, add a fingerprint to CONVENTIONS in src/rig-report.js with a test in tests/rig-report.test.js.
Reference
The MikuMikuDance support added on 2026-08-21 is the same shape of change end to end (alias map, detector fingerprint, tests, doc row). Read that diff, then do this one. The full walkthrough is in Your first contribution.
Comment here to claim it.
What is wrong
three.ws plays one shared library of animation clips on any humanoid avatar a user uploads. That works because every rig is rewritten to one canonical skeleton first, in
src/glb-canonicalize.js.Skeletons coming out of Kinect v2 and Azure Kinect body tracking, and the many mocap and pose-estimation pipelines that copied that naming, put the side word at the end:
ShoulderLeft,ElbowLeft,WristLeft,HipLeft,KneeLeft,AnkleLeft,FootLeft, with a spine chain ofSpineBase,SpineMid,SpineShoulder.None of it resolves today. The rig maps zero joints, falls under the retarget coverage floor, and the avatar falls back to a default body.
Note the shape of the gap: the side-prefix (
leftElbow) and the short side-suffix (elbowL) spellings both work. The full trailing side word (ElbowLeft) does not.What to change
File:
src/glb-canonicalize.js, theEXTRA_ALIASESblock.There is already a table for exactly this shape: the Second Life chain (
mCollarLeft,mShoulderLeft,mKneeLeft) uses a trailing side word. Read those entries, then decide whether the right fix is more entries or a general trailing-Left/Rightrule. Argue for your choice in the code comment the way the neighbouring blocks do.Two joints need thought, and they are the interesting part of this issue:
SpineShoulderis the upper spine near the clavicles, not a shoulder. Map it to the spine chain.ShoulderLeftin Kinect is the upper arm joint, not the clavicle. Compare with how the SMPL collar/shoulder collision is resolved elsewhere in this file, and with the existing test namedsplits an SMPL collar/shoulder collision.How to prove it worked
Add cases to
tests/glb-canonicalize.test.jsbeside the other per-convention blocks, then:Your test must cover both sides. A mapping that sends a left bone to a right canonical name tears the avatar apart in motion and it is the most common mistake in this file.
Also add a row to the conventions table in
docs/rig-doctor.md, and if you want the detector to name the convention on sight, add a fingerprint toCONVENTIONSinsrc/rig-report.jswith a test intests/rig-report.test.js.Reference
The MikuMikuDance support added on 2026-08-21 is the same shape of change end to end (alias map, detector fingerprint, tests, doc row). Read that diff, then do this one. The full walkthrough is in Your first contribution.
Comment here to claim it.