fix(art): repair the Synty retarget's real faults, and correct the diagnosis#33
Merged
Conversation
…agnosis The character retarget did not work, and the reason recorded in docs/HANDOFF-synty.md was wrong. It said the maths was correct and the glTF export was broken. Three faults were in play, and the first two hid the third. **1. `BONE_MAP`'s source side matched no real bone.** It listed `Hips`, `Abdomen`, `Torso`, `LowerArm.L`, `Wrist.L`, `UpperLeg.L`; our rig has `hips`, `spine`, `chest`, `forearm.L`, `hand.L`, `thigh.L`. The lookup skipped whatever it could not find, so zero bones mapped, zero keyframes were written, and all five actions came out empty — with nothing logged. The table is corrected against both armatures, and an unmatched name is now fatal instead of skipped, because that silence is what let a bind-posed character look like an export bug. **2. `export_bake_animation=True` overrode the actions.** With it on the exporter emits one baked animation per object, named after the object, covering all 55 bones in T/R/S. That is exactly the reported symptom — "all five clips collapse into a single animation named target_rig" — and it was never action-handling at all. It is off, and each action now gets its own NLA track. A bake that yields no curves is also fatal now. **3. The "limbs splayed, 1.90 x 2.00 x 2.47 m" measurement was an artefact.** The scene carries a stray 42-vertex Icosphere that dominated the bounding box. Measured on the character mesh alone the figure is 2.03 x 0.32 x 1.79 — right height, right depth. Nothing was ever splayed. With those fixed, all five clips export under their own names and the legs animate correctly. What is left is a real rest-pose mismatch, measured rather than guessed: our source rig rests arms-down at 0.69 m across and no clip exceeds 0.72, while Synty's bind is a T-pose 2.03 m across. Rest-relative retargeting transfers deviation from rest, so the arms never leave the T-pose. Two fixes were tried and rejected on measurements, and both are recorded so they are not repeated: copying world orientation outright discards the bone-axis conventions along with the rest difference and lays the figure down (2.14 x 0.52 x 0.39); re-resting the target into the source's A-pose produces incoherent corrections — 169 degrees on the left upper arm against 11 on the right, where a mirror pair must be symmetric. No asset changes. The committed characters are untouched and the bots keep using the generated one, so nothing in the game moves. The recommended next route, now in the handoff, is to stop retargeting and skin the Synty mesh to our existing rig, which already has all five clips working. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The character retarget did not work, and the reason recorded in
docs/HANDOFF-synty.mdwas wrong — it said the maths was correct and the export was broken. Three faults were in play, and the first two hid the third.1.
BONE_MAP's source side matched no real boneHips,Abdomen,Torsohips,spine,chestLowerArm.L,Wrist.Lforearm.L,hand.LUpperLeg.L,LowerLeg.Lthigh.L,shin.LThe lookup skipped whatever it could not find, so zero bones mapped, zero keyframes were written, and all five actions came out empty — with nothing logged. Corrected against both armatures; an unmatched name is now fatal, because that silence is what let a bind-posed character look like an export bug.
2.
export_bake_animation=Trueoverrode the actionsWith it on, the exporter emits one baked animation per object, named after the object, covering all 55 bones in T/R/S. That is exactly the reported symptom — "all five clips collapse into a single animation named
target_rig". It was never action handling. Now off, with each action on its own NLA track, and a bake that yields no curves is fatal.3. The "splayed limbs" measurement was an artefact
The scene carries a stray 42-vertex
Icospherethat dominated the bounding box. Measured on the character mesh alone: 2.03 × 0.32 × 1.79 — right height, right depth. Nothing was ever splayed. (The sphere is still in the committedfighter_*.glb; tracked in the handoff.)What's left, measured
All five clips now export under their own names and the legs animate correctly. The remaining blocker is a genuine rest-pose mismatch:
Rest-relative retargeting transfers deviation from rest, so the arms never leave the T-pose. Two fixes were tried and rejected on measurements, recorded so they aren't repeated:
Scope
No asset changes. The committed characters are untouched and the bots keep using the generated one, so nothing in the game moves — this is a repaired tool plus a correct diagnosis, not a shipped character. I'm not going to wire up a character whose arms are stuck out sideways.
The recommended next route, now in the handoff: stop retargeting and skin the Synty mesh to our existing rig, which already has all five clips working. That removes the skeleton-to-skeleton problem instead of solving it.
249 tests pass; lint, typecheck and build clean.
🤖 Generated with Claude Code