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 exported from Apple's tooling (Reality Composer, some Maya and USD pipelines) suffix every joint with _joint: hips_joint, left_arm_joint, left_forearm_joint, left_upLeg_joint. None of those spellings resolve today, so the whole rig maps zero joints, falls under the retarget coverage floor, and the avatar falls back to a default body.
Verify it yourself:
import { canonicalizeBoneName } from './src/glb-canonicalize.js';
console.log(canonicalizeBoneName('left_arm_joint')); // null
console.log(canonicalizeBoneName('upperarm_l')); // 'LeftArm' (Unreal, already supported)
What to change
File: src/glb-canonicalize.js, the EXTRA_ALIASES block.
The simplest correct fix is to strip a trailing _joint token before lookup, so left_arm_joint falls through to the leftArm spelling that already resolves. Look at how the existing suffix handling works first: there is an established rule that only strips a suffix when the plain form does not already resolve, and there is a test named only strips the suffix when the plain form does not already resolve that documents why.
Do not map root. It is a transform node above the skeleton, not a body joint.
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 exported from Apple's tooling (Reality Composer, some Maya and USD pipelines) suffix every joint with
_joint:hips_joint,left_arm_joint,left_forearm_joint,left_upLeg_joint. None of those spellings resolve today, so the whole rig maps zero joints, falls under the retarget coverage floor, and the avatar falls back to a default body.Verify it yourself:
What to change
File:
src/glb-canonicalize.js, theEXTRA_ALIASESblock.The simplest correct fix is to strip a trailing
_jointtoken before lookup, soleft_arm_jointfalls through to theleftArmspelling that already resolves. Look at how the existing suffix handling works first: there is an established rule that only strips a suffix when the plain form does not already resolve, and there is a test namedonly strips the suffix when the plain form does not already resolvethat documents why.Do not map
root. It is a transform node above the skeleton, not a body joint.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.