feat(hand-shapes): morph-target hand-pose solver — fist/grip that actually deform

The morph lane's blocking bug was believed to be coincident duplicate verts hidden
from the solver's convergence gate. Welding was necessary but nowhere near
sufficient: the previous relaxation could satisfy every stretch bar without posing
anything, so the numbers it reported were not measuring the thing they claimed.

Measured on Ariki_Female_QuatSkin_LowPoly_40, the tracked "left hand is fully
clean" baseline was a morph that moved fingertips 0.3cm, and the right hand was a
rigid 6.5cm translation of the whole hand with its shape intact. Gated Laplacian
diffusion of a delta field has a null space — constants — and edge stretch cannot
see any of it: a rigid translation stretches no edge and neither does a collapse to
zero. Both exits report perfect bars.

Six defects fixed, each with its measurement in the code comments:

  weld_roi           356 duplicate groups solved twice, deltas up to 2.55cm apart
  stitch_components  hand is 6 overlapping sheets with 1-10mm gaps; Dijkstra
                     cannot cross one, so each bone saw only its own sheet
  refit_fingers      skeleton finger chain ran to 19.8cm; the flesh ends at 14.0cm,
                     so curl_02/curl_03 drove almost no weight (shipped skeleton
                     untouched — this is solver-local scaffolding)
  solve_weights      chain-arc partition of unity; the old 8mm isotropic kernels
                     left ZERO of 17,480 verts owned above 0.85, and a 3-way blend
                     averages the curl away. Plus a support cutoff: outside every
                     kernel, renormalized 1e-81 noise had handed a mid-palm vertex
                     index_02_r=0.50 and flung it 29cm
  build_roi          joint-sphere ROI, so the rim is a wrist band and not a fractal
                     of interior chart holes
  relax              strain-only edge projection + ROI-border seam constraints,
                     replacing the diffusion described above

All 8 shapes now pass every bar with real deformation: p99.9 <= 1.58x, zero edges
over 5x, zero needles with the sliver floor removed, seam <= 3.2mm, cross-hand
independence exactly 0.0000cm, mesh fingertip travel 4.6-6.2cm on fist and
3.5-4.7cm on grip (both hands). Gates now report mesh travel and seam alongside
stretch, because stretch alone cannot gate this lane.

Verified in anim_hand_test_bed: fist and grip read as a real curl on both hands,
static and mid-dance, no fins/shards/needles. It is a loose fist rather than a
clenched one — her fingers are ~4-5cm past the knuckles.

Demo GLB stays out of git (122.6 MB, ariki-game/scratchpad/). Ship decision, the
thumb-axis refit, and the TDR crash from 8 dense targets are open — see README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 10:50:16 -07:00
parent 0913a5972c
commit 36fc0494e8
4 changed files with 1756 additions and 0 deletions
@@ -0,0 +1,360 @@
{
"body": "C:/Users/Jeremy/tinqs/ariki-game/assets/quaternius/derived-bodies/Ariki_Female_QuatSkin_LowPoly_40.glb",
"roi_verts": 19159,
"weld": {
"enabled": true,
"tol_m": 1e-05,
"nodes": 17480,
"merged_groups": 1605,
"max_group": 4,
"rim": 749
},
"stitch_edges": 980,
"seam_edges": 1613,
"poses": {
"flat_l": {
"raw": {
"max": 2.5649668819269853,
"p999": 1.4997998775715617,
"n_gt2": 6,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.92,
"needles": 0,
"max_grow_mm": 2.14
},
"relaxed": {
"max": 1.35,
"p999": 1.3499999999999406,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.34,
"needles": 0,
"max_grow_mm": 1.44
},
"tip_bone_cm": {
"thumb": 0.63,
"index": 0.15,
"middle": 0.15,
"ring": 0.15,
"pinky": 0.14
},
"tip_mesh_cm": {
"index": 0.11,
"middle": 0.11,
"ring": 0.11,
"pinky": 0.11
},
"relax_iters": 236,
"viol_edges_left": 0,
"viol_seam_left": 0,
"seam_max_mm": 1.23
},
"relaxed_l": {
"raw": {
"max": 12.689021649045726,
"p999": 8.077834064456647,
"n_gt2": 1020,
"n_gt5": 248,
"slv_n": 2125,
"slv_gt5x": 43,
"slv_grow_gt1mm": 96,
"slv_max_grow_mm": 9.97,
"needles": 291,
"max_grow_mm": 17.03
},
"relaxed": {
"max": 1.3589166079445092,
"p999": 1.3501469074679688,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.35,
"needles": 0,
"max_grow_mm": 3.77
},
"tip_bone_cm": {
"thumb": 3.86,
"index": 1.42,
"middle": 1.39,
"ring": 1.33,
"pinky": 1.3
},
"tip_mesh_cm": {
"index": 0.96,
"middle": 0.99,
"ring": 0.99,
"pinky": 0.96
},
"relax_iters": 1500,
"viol_edges_left": 304,
"viol_seam_left": 12,
"seam_max_mm": 1.99
},
"fist_l": {
"raw": {
"max": 52.899800203384736,
"p999": 34.724530961525744,
"n_gt2": 2213,
"n_gt5": 1455,
"slv_n": 2125,
"slv_gt5x": 103,
"slv_grow_gt1mm": 158,
"slv_max_grow_mm": 51.07,
"needles": 1558,
"max_grow_mm": 65.54
},
"relaxed": {
"max": 1.634544698690311,
"p999": 1.3844521052494323,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.44,
"needles": 0,
"max_grow_mm": 4.11
},
"tip_bone_cm": {
"thumb": 9.73,
"index": 7.19,
"middle": 7.1,
"ring": 6.82,
"pinky": 6.75
},
"tip_mesh_cm": {
"index": 4.91,
"middle": 4.9,
"ring": 4.76,
"pinky": 4.62
},
"relax_iters": 1500,
"viol_edges_left": 1939,
"viol_seam_left": 48,
"seam_max_mm": 1.32
},
"grip_l": {
"raw": {
"max": 49.79406421161323,
"p999": 30.545310726816965,
"n_gt2": 2150,
"n_gt5": 1353,
"slv_n": 2125,
"slv_gt5x": 101,
"slv_grow_gt1mm": 140,
"slv_max_grow_mm": 40.91,
"needles": 1454,
"max_grow_mm": 73.2
},
"relaxed": {
"max": 1.8239868532277623,
"p999": 1.4628749431140193,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.57,
"needles": 0,
"max_grow_mm": 3.73
},
"tip_bone_cm": {
"thumb": 10.03,
"index": 5.47,
"middle": 5.39,
"ring": 5.18,
"pinky": 5.09
},
"tip_mesh_cm": {
"index": 3.71,
"middle": 3.72,
"ring": 3.63,
"pinky": 3.52
},
"relax_iters": 1500,
"viol_edges_left": 1984,
"viol_seam_left": 53,
"seam_max_mm": 1.32
},
"flat_r": {
"raw": {
"max": 7.3444863267240175,
"p999": 3.087924956802205,
"n_gt2": 103,
"n_gt5": 6,
"slv_n": 2125,
"slv_gt5x": 2,
"slv_grow_gt1mm": 4,
"slv_max_grow_mm": 5.93,
"needles": 8,
"max_grow_mm": 6.94
},
"relaxed": {
"max": 1.3508407237549374,
"p999": 1.3500148699201415,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.35,
"needles": 0,
"max_grow_mm": 2.11
},
"tip_bone_cm": {
"thumb": 0.77,
"index": 0.15,
"middle": 0.16,
"ring": 0.15,
"pinky": 0.15
},
"tip_mesh_cm": {
"index": 0.13,
"middle": 0.13,
"ring": 0.13,
"pinky": 0.12
},
"relax_iters": 1500,
"viol_edges_left": 141,
"viol_seam_left": 17,
"seam_max_mm": 1.47
},
"relaxed_r": {
"raw": {
"max": 45.958092227798915,
"p999": 19.548705590243003,
"n_gt2": 736,
"n_gt5": 315,
"slv_n": 2125,
"slv_gt5x": 24,
"slv_grow_gt1mm": 60,
"slv_max_grow_mm": 40.74,
"needles": 339,
"max_grow_mm": 50.09
},
"relaxed": {
"max": 1.6604900471831592,
"p999": 1.4451486205473596,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.68,
"needles": 0,
"max_grow_mm": 2.78
},
"tip_bone_cm": {
"thumb": 4.59,
"index": 1.42,
"middle": 1.42,
"ring": 1.36,
"pinky": 1.32
},
"tip_mesh_cm": {
"index": 1.13,
"middle": 1.15,
"ring": 1.13,
"pinky": 1.11
},
"relax_iters": 1500,
"viol_edges_left": 686,
"viol_seam_left": 60,
"seam_max_mm": 2.63
},
"fist_r": {
"raw": {
"max": 118.26346663296857,
"p999": 58.38873513669817,
"n_gt2": 3820,
"n_gt5": 1139,
"slv_n": 2125,
"slv_gt5x": 106,
"slv_grow_gt1mm": 299,
"slv_max_grow_mm": 116.16,
"needles": 1245,
"max_grow_mm": 132.62
},
"relaxed": {
"max": 1.7741351039193665,
"p999": 1.535993990998224,
"n_gt2": 0,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.63,
"needles": 0,
"max_grow_mm": 4.39
},
"tip_bone_cm": {
"thumb": 12.24,
"index": 7.22,
"middle": 7.28,
"ring": 6.97,
"pinky": 6.87
},
"tip_mesh_cm": {
"index": 6.01,
"middle": 6.24,
"ring": 6.2,
"pinky": 6.16
},
"relax_iters": 1500,
"viol_edges_left": 6109,
"viol_seam_left": 247,
"seam_max_mm": 3.23
},
"grip_r": {
"raw": {
"max": 134.1470205961321,
"p999": 64.71684078507103,
"n_gt2": 3189,
"n_gt5": 1040,
"slv_n": 2125,
"slv_gt5x": 89,
"slv_grow_gt1mm": 253,
"slv_max_grow_mm": 129.98,
"needles": 1129,
"max_grow_mm": 150.49
},
"relaxed": {
"max": 2.226320726002906,
"p999": 1.5799820313724093,
"n_gt2": 1,
"n_gt5": 0,
"slv_n": 2125,
"slv_gt5x": 0,
"slv_grow_gt1mm": 0,
"slv_max_grow_mm": 0.75,
"needles": 0,
"max_grow_mm": 4.04
},
"tip_bone_cm": {
"thumb": 13.09,
"index": 5.5,
"middle": 5.53,
"ring": 5.29,
"pinky": 5.18
},
"tip_mesh_cm": {
"index": 4.5,
"middle": 4.66,
"ring": 4.6,
"pinky": 4.54
},
"relax_iters": 1500,
"viol_edges_left": 5005,
"viol_seam_left": 197,
"seam_max_mm": 3.07
}
}
}