arkavo-org / arkavo-org/VRMMetalKit

SpringBone equilibrium: fixing one parameter breaks the rest on tuned models

Open
#162 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
6
Forks
2
Avg merge
18h 51m
Merged PRs (30d)
26

Description

## Summary

The current spring-bone implementation reaches a stable, visually correct result on AvatarSample_A_1.0 only because of a specific *equilibrium* between two pieces of code: the parser bug at \`VRMExtensionParser.swift:666\` (force \`gravityPower=0\` to \`1.0\`) and the inertia compensation re-enabled in PR #143 (\`SpringBonePredict.metal:107-142\`). The model author tuned \`stiffness=0.85 / gravityPower=0 / dragForce=0.4\` against this combination — when either piece is changed in isolation, hair behavior degrades visibly.

## Symptoms during the failed-fix experiment

Two commits attempted to clean up this equilibrium:

1. \"Stop overriding author-specified \`gravityPower=0\`\" — preserve author intent in the parser.
2. \"Gate inertia compensation on \`gravityPower > 0\`\" — don't apply world-space inertia preservation to chains the author wanted held only by stiffness.

Both were theoretically clean. Together they broke AvatarSample_A's hair: persistent \"cat-ear\" tufts at rest, sharp spiking during head rotation. Reverted in the same branch (history flattened in PR #159's final form), preserving the working equilibrium.

## Why this is hard

- **Cross-model regression risk.** AvatarSample_A's tuning is data; we don't know how other VRoid models tuned theirs. Any change to the springbone math could fix one model and break another.
- **Author-engine coupling.** The author's intent is encoded against the engine's actual behavior, not the engine's *intended* behavior. Fixing the engine creates a divergence from the author-tested combination.
- **Test gap.** No automated visual regression test for hair behavior across multiple models. The TDD harness in PR #143 covers physics math invariants (no NaN, no bone explosion, etc.) but not \"does hair look right.\"

## What a real fix needs

1. **Cross-model test rig.** Render a fixed VRMA on N representative models, capture frame samples at known timestamps, score hair against reference renders (VRoid Hub or stored ground-truth PNGs).
2. **Reference renders.** For each fixture, capture the model author's intended look (VRoid Hub embed, official VRM Consortium sample renders, etc.) as a ground-truth comparison target.
3. **Decide on physics semantics.** Either keep the current \"parser-bug + inertia compensation\" combo as the codified behavior and document it as load-bearing, or migrate to a clean physics model with a known migration cost on existing models.
4. **Communicate breaking changes.** If the physics model changes, model authors who tuned against current behavior need re-tuning guidance (or backwards-compatibility shims).

## Out of scope for any quick PR

This is multi-day investigation work, not a tractable single commit.

## Discovered during

PR #159 review cycle. Investigation triggered by feedback that hair was \"moon-gravity\" / \"wet-noodle\" on \`Approval.vrma\`. Two well-intentioned fixes broke a working equilibrium; reverts restored the working state. The diagnostic exercise itself was valuable but the cleanup commits are the only ones shipping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Contributor guide

Open the contributing guide

Research direction

Start by reading VRMExtensionParser.swift:666 and SpringBonePredict.metal:107-142, then review the physics-math TDD harness from PR #143 and the reverted experiments in PR #159. Build the proposed cross-model VRMA render comparison using representative fixtures and reference renders, then document the chosen physics semantics, regression results, and any migration guidance.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
computer-graphics, testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.