arkavo-org / arkavo-org/VRMMetalKit
VRMC_springBone_extended_collider parsed but applied inconsistently — chaotic per-variant clustering, doesn't track swept axes
- Dominant language
- Swift
- Stars
- 6
- Forks
- 2
- Avg merge
- 18h 51m
- Merged PRs (30d)
- 26
Description
## Summary
VMK 0.14.0 *parses* `VRMC_springBone_extended_collider` (plane, inverted sphere, inverted capsule, plus per-joint `angleLimit`) but applies the data inconsistently. An 18-variant swing sweep over shape × placement and shape × angle-limit produces only 7 distinct SHA256 image hashes, with clusters that **don't track any single swept axis** — variants of different shapes and different angle limits end up byte-identical, while seemingly-similar variants end up distinct.
If VMK didn't support the extension at all, we'd expect ALL 18 variants to be byte-identical (chain physics with no collider applied = same trajectory). The 7-bucket clustering means VMK is reading SOMETHING from the extension and using it to vary chain behavior — but not coherently with the variant's actual shape/placement/angle-limit parameters.
Filed against 0.14.0 (commit `f25a947`).
## Reproduction
```bash
git clone https://github.com/arkavo-org/vrm-conformance && cd vrm-conformance
cargo build --release -p vrm-asset-generator
cd adapters/vrm-metal-kit && swift build --configuration release && cd ../..
./target/release/vrm-asset-generator emit-springbone-extended-sweep \
--output-dir /tmp/extended-sweep
# Render every swing variant (animation drives chain through the collider):
for plan in /tmp/extended-sweep/swing_springbone_extended_*.test.yaml; do
test_id=$(basename "$plan" .test.yaml)
./target/release/vrm-runner execute-test-plan \
--plan "$plan" \
--adapter-bin adapters/vrm-metal-kit/.build/release/vrm-metal-kit-adapter \
--asset-dir /tmp/extended-sweep \
--output-dir /tmp/vmk-out --renderer-name vrm-metal-kit --json >/dev/null
done
# Hash each render and group by SHA:
for f in /tmp/vmk-out/swing_springbone_extended_*_vrm-metal-kit.png; do
shasum -a 256 "$f"
done | awk '{print $1}' | sort | uniq -c | sort -rn
```
## Observed clustering
| SHA256 (first 16) | variants in bucket |
|---|---|
| `3e429a38a5b6d29b` | icaps_anglelimit_60, icaps_ploose, icaps_ptight, isphere_anglelimit_90, plane_anglelimit_90 |
| `0c9ecdad02d5d40d` | isphere_anglelimit_30, isphere_ploose, isphere_ptight, plane_ploose |
| `24ce53729b83c6ca` | icaps_anglelimit_90, plane_anglelimit_60, plane_ptight |
| `a3cb07bdb4d9b3b4` | icaps_anglelimit_30, plane_anglelimit_30 |
| `d6ac96ed397f436b` | icaps_pmed, isphere_anglelimit_60 |
| `60cdad84ce1f8be1` | isphere_pmed |
| `dc9c3afe293609f1` | plane_pmed |
Note that the largest bucket spans 3 shapes × 4 different parameter values. This wouldn't happen if VMK applied each variant's collision geometry correctly — each unique configuration should produce a unique chain pose under animation.
## Expected
Distinct shape / placement / angle-limit configurations should produce distinct chain trajectories under the same animation. A coherent grouping (e.g., "all `plane` variants cluster together because plane support is broken") would be diagnosable; the current chaotic grouping suggests intermittent parsing or unit-conversion issues somewhere on the extended-collider path.
## Suggested investigation
1. Verify how `extensions.VRMC_springBone_extended_collider.shape` fields are read from each collider entry — possibly the parser branches on shape type but falls through to a default for non-`Sphere`/`Capsule` cases.
2. Verify `angleLimit` is being applied per-joint and not silently ignored — three of the 7 buckets are pure-`anglelimit` swept variants that ended up distinct, suggesting partial implementation.
3. The single-element buckets (`plane_pmed`, `isphere_pmed`) are anomalous — what makes `_pmed` variants distinct from `_ptight` / `_ploose` of the same shape? Possibly a placement-offset arithmetic edge case at the medium value.
## Companion finding
three-vrm 3.5.0 rejects the same assets entirely at `load_vrm` time, so cross-renderer comparison is currently VMK + godot-vrm only. See [vrm-conformance findings](https://github.com/arkavo-org/vrm-conformance/blob/main/docs/findings.md) § "three-vrm 3.5.0 rejects assets that declare VRMC_springBone_extended_collider".
## Related
- vrm-conformance phase-3 extended-collider corpus: [`docs/superpowers/plans/2026-05-15-springbone-phase3-extended-colliders.md`](https://github.com/arkavo-org/vrm-conformance/blob/main/docs/superpowers/plans/2026-05-15-springbone-phase3-extended-colliders.md)
- VMK#67 (verify and document SpringBone angle limit implementation) — possibly the same surface
- This is companion to VMK#236 (warmupPhysics doesn't resolve collisions)
Contributor guide
Research direction
Start with the adapters/vrm-metal-kit Swift adapter and trace its VRMC_springBone_extended_collider handling, especially shape fields and per-joint angleLimit. Generate the corpus with vrm-asset-generator emit-springbone-extended-sweep, then run the listed vrm-runner plans and compare image hashes. Done means distinct configurations produce coherent, distinguishable trajectories under the same animation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, swift
- Domain
- computer-graphics, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100