diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 1fc47a4a..54173498 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -792,9 +792,18 @@ over the same span**. The rule matched on the insensitive quantity and was wrong on the sensitive one. **Check a new interpretation against the fastest-moving field you have, not the one that happens to agree.** -❔ Left open: the residual **11.5 px** between 980.5 and 992.0. A rotation about -a declared pivot rather than the centre would displace by roughly that, and -nothing here measures it — so do not fit to close it. +✅ **CLOSED — the 11.5 px was my fit's resolution, not geometry.** Closed by +adding observables rather than tuning. The vertex buffer carries positions *and* +colours at the same instant, so all four must agree on one `t`. Solved +independently: quad A x → **357.88**, quad B x → **357.58**, alphas → 355.75 and +354.09. ⚠️ **The alphas are ~50× less precise per unit** (0.27–0.33 levels/unit, +so one byte of quantisation is worth 1.5–1.9 units = 6–8 px of sweep). At +**t = 357.7** everything lands: centres **−0.70** and **−0.48 px**, alphas within +one level, parent alpha **0** throughout. + +✅ **And there is no pivot correction to look for**: the leaf pivot is +**(200, 90)** against a 399×180 sprite — the pivot *is* the centre, so rotation +displaces it by nothing. ## Status diff --git a/docs/re/structures/ui-leaf-vs-parent-alpha.md b/docs/re/structures/ui-leaf-vs-parent-alpha.md index 749d7232..e586e908 100644 --- a/docs/re/structures/ui-leaf-vs-parent-alpha.md +++ b/docs/re/structures/ui-leaf-vs-parent-alpha.md @@ -108,9 +108,47 @@ t=355 is inside a long segment where a one-keyframe shift barely moves it, while can look confirmed on the insensitive quantity and be wrong on the sensitive one.** -❔ The residual **11.5 px** between 980.5 and 992.0 is not explained by this and -is left open — a rotation about a pivot rather than the centre would displace by -about that much, and nothing here measures it. +## ✅ The 11.5 px residual is CLOSED — it was the alpha-only fit's resolution + +Left open above as *"do not fit to close it"*. It is closed by **adding +observables, not by tuning a parameter**. + +The draw's vertex buffer carries positions *and* colours at the **same instant**, +so all four quantities must agree on one `t`. Solving for `t` from each +independently: + +| observable | solved t | sensitivity | its own precision | +|---|---|---|---| +| quad A x | **357.88** | 4.00 px/unit | ±0.12 units | +| quad B x | **357.58** | 4.06 px/unit | ±0.12 units | +| quad A alpha | 355.75 | **0.326 levels/unit** | **±1.54 units** | +| quad B alpha | 354.09 | **0.265 levels/unit** | **±1.89 units** | + +⚠️ **The alphas are ~50× less precise per unit of time**, because alpha is a byte +changing by only ~0.3 levels per keyframe unit — so a single level of +quantisation is worth **1.5–1.9 units**, which at 4 px/unit is **6–8 px of +sweep**. The 11.5 px was that, not geometry. + +At the position-derived **t = 357.7**, every observable lands: + +| | predicted | measured | diff | +|---|---|---|---| +| quad A centre x | 991.30 | 992.0 | **−0.70 px** | +| quad B centre x | 466.72 | 467.2 | **−0.48 px** | +| quad A alpha | 195.64 | 195 | +0.64 | +| quad B alpha | 182.95 | 182 | +0.95 | + +✅ **Sub-pixel on both positions, inside one byte on both alphas** — while the +parent's alpha is **0** throughout. And the leaf **pivot is (200, 90)** against a +399×180 sprite, i.e. the pivot *is* the sprite centre, so rotation displaces the +centre by nothing. There is no pivot/rotation correction to find. + +⚠️ **The methodological point is the same one this exchange started with, +inverted.** Earlier, a rule *looked confirmed* because it was checked against +alpha — the insensitive field. Here the same insensitivity produced a spurious +11.5 px residual. **The insensitive quantity does not just fail to falsify; it +manufactures apparent error.** Solve on the fastest-moving field and check the +slow one, never the reverse. ---