investigate(springbone): inside-collider diagnostic + substep ordering#300
Draft
arkavo-com wants to merge 2 commits into
Draft
investigate(springbone): inside-collider diagnostic + substep ordering#300arkavo-com wants to merge 2 commits into
arkavo-com wants to merge 2 commits into
Conversation
#237) Two related changes against VMK#237 (extended-collider conformance bucket collapse) plus a finding that reframes the bug. * **Diagnostic harness** (`SpringBoneCollision.metal`, `SpringBoneBuffers.swift`, `SpringBoneComputeSystem.swift`, `VRMRenderer.swift`): per-bone last-write buffer the sphere/capsule kernels populate with `(shape_type, angleLimit, distance, boundary, penetration, group_matched)` when opted in via `renderer.setInsideColliderDiagnosticsEnabled(true)`. Sentinel shape_type values distinguish "never ran" / "kernel-entered no match" / "outside-branch with inside-flag=0" / "inside-sphere fired" / "inside-capsule fired" so future investigations can pin parameter- propagation bugs without re-instrumenting. * **Substep ordering**: sphere + capsule collision now interleave with the distance constraint iteration (`SpringBoneComputeSystem.swift`'s XPBD loop). Inside-* containment is re-applied after every distance pass instead of only once at the end; plane stays outside the loop (only outside-collision semantics). Defensive improvement for any scenario where distance constraint can pull a contained joint back outside the surface. **Finding** (`SpringBoneExtendedColliderBehaviorTests` new test `testInsideSphereAngleLimitReachesShader`): the diagnostic confirms `BoneParams.angleLimit` reaches the shader correctly (1.047 rad / 60° read by every non-root bone). The conformance bucket collapse for `springbone_extended_isphere_*` variants is **not** a propagation bug — chain joints stay at distance 0.0046 / 0.0506 / 0.1005 m from the sphere centre, well inside the 0.20 m and 0.40 m boundaries at pmed / ploose. Inside-sphere collision correctly never engages; only ptight (r=0.10) clips the chain (its distinct bucket). Angle-limit values 30°/60°/90° collapse because the chain's actual swing never exceeds 30° from bind, so none of the cones bite. Fixture-engineering outcome, not a VMK bug. Suite: 170 tests, 0 unexpected failures (added one diagnostic test). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Substep ordering change interleaves sphere/capsule collision with the distance-constraint iteration loop — verifying the static T-pose render is byte-near-identical (88-byte delta vs prior PNG, no visible artifact). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
(shape_type, angleLimit, distance, boundary, penetration, group_matched), opt-in viarenderer.setInsideColliderDiagnosticsEnabled(true)). Sentinelshape_typevalues distinguish "never ran" / "kernel-entered no match" / "outside-branch with inside-flag=0" / "inside-sphere fired" / "inside-capsule fired" so future investigations can pin parameter-propagation bugs without re-instrumenting.SpringBoneComputeSystem.swift's XPBD loop). Inside-* containment is re-applied after every distance pass instead of only once at the end; plane stays outside the loop.testInsideSphereAngleLimitReachesShaderdocuments thatBoneParams.angleLimitreaches the shader correctly (1.047 rad / 60° read by every non-root bone).Finding
The conformance bucket collapse for
springbone_extended_isphere_*variants is not a VMK propagation bug. The diagnostic confirms parser / GPU buffer build / shader branch / group filter / per-jointangleLimitare all wired correctly. Chain joints stay at distance 0.0046 / 0.0506 / 0.1005 m from the sphere centre, well inside the 0.20 m and 0.40 m boundaries at pmed / ploose, so inside-sphere collision correctly never engages; only ptight (r=0.10) is tight enough to clip the chain. Angle-limit values 30°/60°/90° collapse because the chain's actual swing never exceeds 30° from bind.vrm-conformance suite addressed it on their side by reducing inside-sphere/capsule placement radii from
[0.10, 0.20, 0.40]to[0.04, 0.06, 0.08]. Bucket count 7 → 11 (+57%), non-zero penetration across all 18 swing variants.Behaviour change
Sphere and capsule collision dispatches now run once per distance-constraint iteration instead of once at the end of the substep. For models that previously sat inside their colliders without distance constraint forcing them out, behaviour is unchanged. For models where distance constraint can pull a joint back outside a containment surface, the joint is now pushed back in within the same substep instead of carrying the violation forward. Plane behaviour unchanged.
Performance:
constraintIterations=4, substeps=4 → 16 dispatches/frame for sphere+capsule combined vs. 4 before. Each dispatch is one bone-count grid (≪ 100 threads typical), trivially cheap.Test plan
swift test --filter SpringBone --disable-sandbox— 170 tests, 0 unexpected failures (1 expected failure caught by XCTExpectFailure)swift test --filter SpringBoneExtendedColliderBehaviorTests --disable-sandbox— 7 tests, including the new diagnostic testswift buildcleanmake shaders-macoscleanAvatarSample_A.pngregenerated, no visible artifact (88-byte delta from prior render)Closes #237
🤖 Generated with Claude Code