spine-rigc 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/AUTHORING.md +75 -19
- package/docs/INGEST.md +20 -13
- package/docs/MOTION.md +138 -85
- package/package.json +1 -1
- package/src/compile.ts +35 -1
- package/src/keys.ts +297 -2
- package/src/motion.ts +123 -3
- package/src/pose.ts +84 -6
- package/src/render.ts +32 -0
- package/src/rig.ts +241 -31
- package/src/types.ts +42 -0
- package/src/validate.ts +34 -4
package/docs/AUTHORING.md
CHANGED
|
@@ -1298,6 +1298,26 @@ emitted as written, in the default skin or anywhere else.
|
|
|
1298
1298
|
`spec` must be exactly `"rigc-rig/1"`. `name` must be a non-empty string. `bones`
|
|
1299
1299
|
must be non-empty. `slots` must be present (it may be empty).
|
|
1300
1300
|
|
|
1301
|
+
🔢 **Every number in a rig spec is finite at float32 precision** — at most
|
|
1302
|
+
±3.4028234663852886e38 — whatever field it is in, so the ranges the tables below
|
|
1303
|
+
state are ranges *within* that. The skeleton is written as float32, and a number
|
|
1304
|
+
past that line would be emitted as Infinity, which JSON writes as `null`: `1e309`
|
|
1305
|
+
(which JSON reads as Infinity) and `1e308` (a finite double with no float32) are
|
|
1306
|
+
both refused by the field they are in, before anything is compiled (§5.1). The cut
|
|
1307
|
+
manifest and the motion spec are held to the same line.
|
|
1308
|
+
|
|
1309
|
+
🔤 **Every field below holds one JSON type, and a value of another is refused.**
|
|
1310
|
+
Where a table says a field is a position, an angle, a scale, a mix, a count, a
|
|
1311
|
+
size or an index, it is a JSON **number** — `5`, never `"5"`; a flag is `true` or
|
|
1312
|
+
`false`, never `"true"` or `1`; a name or a path is a string; a list of vertices,
|
|
1313
|
+
uvs or triangles is an array of numbers, typed element by element. A JSON `null`
|
|
1314
|
+
is a value, not an absence, and is accepted only where a table below says what
|
|
1315
|
+
`null` means. The type of every key, shape by shape, is the table `RIG_TYPES` in
|
|
1316
|
+
[`src/rig.ts`](../src/rig.ts) (`MOTION_TYPES` in [`src/motion.ts`](../src/motion.ts),
|
|
1317
|
+
`MANIFEST_TYPES` in [`src/types.ts`](../src/types.ts)), and the refusal names the
|
|
1318
|
+
field, the type it found and the type it required (§5.1) — so that sentence, not a
|
|
1319
|
+
column restated beside each row here, is what to act on.
|
|
1320
|
+
|
|
1301
1321
|
🚫 **Every example value below is invented.** Names, coordinates, vertex lists and
|
|
1302
1322
|
payloads in this guide are written to illustrate a field, never copied out of a
|
|
1303
1323
|
reference export — an example lifted from one would be handing an authoring agent an
|
|
@@ -5429,11 +5449,14 @@ corpus inventory, and a ladder run reads this guide without following its refere
|
|
|
5429
5449
|
out of it.)
|
|
5430
5450
|
|
|
5431
5451
|
🔢 **A fourth surface is a pose that is not finite**, which `render` and `check`
|
|
5432
|
-
refuse before drawing anything, naming the bone or vertex and its value.
|
|
5433
|
-
|
|
5434
|
-
in
|
|
5435
|
-
|
|
5436
|
-
|
|
5452
|
+
refuse before drawing anything, naming the bone or vertex and its value.
|
|
5453
|
+
`A10_NO_NAN_AFTER_STEPPING` reads the same scan, so on a skeleton with an animation
|
|
5454
|
+
`validate` gets there first and in the same words: a bone `rotation` of `1e309`, in
|
|
5455
|
+
the setup pose or in a key, leaves the bone's world position finite and its matrix
|
|
5456
|
+
`NaN`, and A10 names the bone and the term. What it does not see is a skeleton with
|
|
5457
|
+
no animation (A10 SKIPs, so `render` is where that one is named) and a skin other
|
|
5458
|
+
than the default, which A10 does not pose. The sentence, and where to look for the
|
|
5459
|
+
number, is under *nothing to draw* in §3.4.
|
|
5437
5460
|
|
|
5438
5461
|
### 5.1 Compile errors — before the gate
|
|
5439
5462
|
|
|
@@ -5558,6 +5581,8 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5558
5581
|
| `a rig spec needs a non-empty "bones" array` | §3.2 — a rig with no bones has nothing to hang a slot on; every one has at least a root |
|
|
5559
5582
|
| `a rig spec needs a "slots" array (it may be empty; its ORDER is the draw order)` | §3.3 — write `[]` for a rig that draws nothing. ⚠️ These three arrive only when the key is really absent: **misspelt**, it is the unknown-key refusal above, naming what you wrote |
|
|
5560
5583
|
| `bone "X" names parent "Y", which is not declared before it` | move `Y` earlier in `bones` |
|
|
5584
|
+
| `<file>: <where> is a string "5"; a number is required` (also `is a boolean true`, `is an array [1]`, `is null`, `is a number 7; a string is required`, `…; an array of numbers is required`, `…; a boolean (true or false) is required`, `…; a string or null is required`) | §3 / §4 — write the value as the JSON type its field holds: a number as a JSON number (`5`, not `"5"`), a flag as `true`/`false`, a name as a string. Every field of the three input files has one type, and a value of another is refused by the field before any reader does arithmetic on it — which it used to: `"x": "5"` built as `5`, `true` as `1` and `[1]` as `1`, and a `null` built too, all green. An array is typed element by element, so the refusal names the index (`weights[3][1].x`, `vertices[0]`). `null` is refused as `null` except where the field states it means something (`skeleton.width`/`height`, `skeleton.audio`, a slot's and a setup entry's `attachment`, a deform key's `vertices`, the manifest's `image`, `states`, `contact_depth` and `cap_containment_ceiling`). `<where>` is the rig spec's wording (`bone "hip" x`, `skin "default" slot "s" attachment "a" rotation`, `constraint "aim" mix`), the dotted path in the cut manifest (`crop.h`, `parts[2].offset[0]`), and the motion spec's own path (`` `animations."walk".ik[0].keys[0].mix` ``). In the rig spec and the manifest it runs right after the key scan and before every other check, so a field check that used to name a type (a mesh name that is not a string, a `lengths` entry spelt as a string) now reads as this row; in the motion spec it runs after that file's own field checks, which keep their sentences. A closed set of names (`blend`, `inherit`, a constraint's `type`, a generator's `kind`) keeps its own refusal, which lists the names that exist |
|
|
5585
|
+
| `<file>: <where> is Infinity; a number in this file is finite at float32 precision, at most ±3.4028234663852886e+38, because the skeleton is written as float32 — …` (also `is -Infinity`, `is 1e+308`, and `is NaN` from a library caller) | §3 — state the number you meant, inside float32's range. One walk over the whole file, run right after the key scan and before any other rig-spec check, so a range rule never prints `NaN`. `<where>` is every number in the rig spec — a bone (`bone "hip" x`), a slot, a skin's attachment down to its arrays (`skin "default" slot "s" attachment "a" weights[3][1].x`), a constraint (`constraint "aim" mixRotate`), an event, `skeleton`, `invariants.meshTriangles` — and the dotted path in the cut manifest (`crop.h`) and in the motion spec (`` `animations.idle.tracks[0].keys[1].v[0]` ``, after the motion spec's own field checks, which keep their sentences). ⚠️ It sees numbers only: `"x": "NaN"` is a string, and the row above refuses it as one |
|
|
5561
5586
|
| `two bones are called "X"` | bone names are the join key; rename one |
|
|
5562
5587
|
| `two ik constraints are called "X" — a constraint resolves by name AND type (\`SkeletonData.findConstraint\`), so names are unique PER KIND: an ik and a transform constraint may share one, two of a kind may not` | §3.5 — rename one of the two. The kind in the sentence is the pair's own, so `two transform constraints are called "X"` is the same refusal on another kind; a name shared **across** kinds is not this error |
|
|
5563
5588
|
| `physics constraint "X" is declared in both the rig spec and the motion spec's physics table` | §4.6 — the rig spec declares a physics constraint's structure and the motion spec's `physics` table declares one outright; pick the file it belongs in. Per kind, like every other constraint name: an `ik` "X" in the rig spec beside a `physics` "X" here is two constraints and is not this error |
|
|
@@ -5783,7 +5808,7 @@ Fix A00 and run it again.
|
|
|
5783
5808
|
| `A07_ATLAS_TEXT_SHAPE` | both | atlas text: a region name with stray whitespace, or a blank line splitting a page block. rigc writes the atlas, so this means a hand-edited file. Three sentences are about blank lines and name three different repairs: `line 1: the file begins with a blank line` (or `with N blank lines` for a run, one finding) is a blank before the first page name — delete it; `line N: the file ends with a blank line` (or `with N blank lines`, one finding) is a blank after the last page block's final line — delete it, since rigc ends the file on one newline; `line N: consecutive blank lines` is two blank lines side by side between the first page and the last — delete one. None of the three is `the last page block declares no region`, which means a page name and its fields with no region after them. rigc writes none of the three: under `--atlas-in` the pack's blank lines are put in rigc's shape on re-emission (§0.2), so any of them means a file rigc did not write, handed to `validate`. ⚠️ An atlas with **no page block at all** — no non-blank line — is not one of those: its subject is absent, so this reports **SKIP** naming the byte count it read, and so do the four rules below whose subject is a page ([#608](https://github.com/firejune/rigc/issues/608)). A rig whose skins need no art writes exactly that file (§3.4), and before #608 this row refused it with two findings naming a page block that was not there. What an empty atlas does **not** excuse is an attachment that wants a region out of it — that is `A08` |
|
|
5784
5809
|
| `A08_REGION_NAMES_MATCH_ATTACHMENTS` | both | three things, and the message says which: an attachment whose `path` names **no region** of this atlas; a `path` carrying **stray whitespace**, printed quoted so you can see it; an **atlas region name** carrying stray whitespace (`A07` names that same line with its line number). The first two are read off the raw file **before** the loader is asked, so the miss is named here with the skin, the slot, the placeholder and the attachment's own name — the four things `AtlasAttachmentLoader`'s own `Region not found in atlas: <path> (attachment: <name>)` does not carry. There is no `spine-html` clause here — a placeholder is free to differ from the region its `path` names **SKIP** when no attachment names a region *and* the atlas declares none — both of its subjects at once |
|
|
5785
5810
|
| `A09_ANIMATION_DURATION_MATCHES_SPEC` | both | the loaded duration ≠ the declared one, or the two sides disagree about which animations exist (R7). Asymmetric by design: a frame of slack for an animation that ends early, and none worth the name for a key *past* the declared end, which is the same rule §4.5 states at compile time — held here against a skeleton the compiler never saw. **SKIP** when neither side has an animation at all — a static rig has no duration |
|
|
5786
|
-
| `A10_NO_NAN_AFTER_STEPPING` | both | stepping the animation produced a `
|
|
5811
|
+
| `A10_NO_NAN_AFTER_STEPPING` | both | stepping the animation produced a pose that is not finite. It reads the **whole world transform** — all six terms `a`, `b`, `c`, `d`, `worldX`, `worldY` of every bone — then every vertex of every region and mesh the slots show, at the **setup pose** and at every stepped frame of every animation, through the same scan `render` refuses on, so the two cannot disagree. The detail names where (`the setup pose`, or `animation "x" frame i of 120 (t=…s)`), then the bone and the term (`bone "x" has a NaN`), or the slot, attachment and vertex (`vertex 3 has x Infinity`) when every bone is finite and a vertex is not — a `scaleX` chain whose product stays under the largest double does that. A bone at `rotation: 1e309` has a finite position and a `NaN` matrix, which is why the position alone is not read. Look for a number past the largest double, a degenerate curve or a zero scale. 🦴 **It also poses every bone `inherit` key at its own time**: the runtime resolves a mode by folding the case of its first letter and nothing else, and a spelling that misses is stored as **NaN** — the world position stays finite, `updateWorldTransform` matches no mode, and the bone keeps the rotation, scale and shear it had. The detail names the animation, the bone, the key's time and its spelling, beside the five. A bone whose *setup* spelling misses poses no mode at all, and is named the same way from the stepping loop. Neither is reachable from a rig spec — `build` refuses both spellings by name (§5.1) — so on a green build this clause is about files rigc did not write. Which mode a correct spelling poses is not judged here, because the lookup that resolved it is the one that would be checked **SKIP** when the skeleton carries no animation: the NaN is produced by stepping, and a static rig is never stepped — the same subject `A09` skips on |
|
|
5787
5812
|
| `A11_NO_CLIPPING_ATTACHMENTS` | renderer | a clipping attachment; the target renderer skips them silently |
|
|
5788
5813
|
| `A12_NO_DARK_COLOR` | renderer | a slot `dark` colour or an `rgba2`/`rgb2` timeline; parsed, then ignored |
|
|
5789
5814
|
| `A13_MESH_BUDGET` | renderer | more mesh slots than the rig's `invariants.meshSlots`, or a mesh over its `invariants.meshTriangles`. Thin the mesh, or raise the budget in the rig spec. **SKIP** when the rig declares neither — which means *unmeasured*, not that the budget is inert: the same `meshSlots` is a **compile-time** refusal for rigc's own generators, before the gate (§3.7) **SKIP** also when the rig budgets **only** triangles and the skeleton carries no mesh. A declared slot budget still PASSes there, because zero mesh slots is a count measured against a ceiling |
|
|
@@ -8840,8 +8865,8 @@ Found within 2 px of the truth, out of 15 trials per cell (free search, default
|
|
|
8840
8865
|
|
|
8841
8866
|
| texture level (mean) | 24 px | 32 px | 48 px | 64 px | 96 px | 128 px | 192 px |
|
|
8842
8867
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
8843
|
-
| `native` (detail 3.49) | 13/15 (2 amb) | 15/15 | 15/15 | 15/15 |
|
|
8844
|
-
| `blur1` (detail 1.58) | 12/15 (3 amb) | 12/15 (
|
|
8868
|
+
| `native` (detail 3.49) | 13/15 (2 amb) | 15/15 | 15/15 | 15/15 | 14/15 (1 wrong) | 14/15 (1 wrong) | 14/15 (1 wrong) |
|
|
8869
|
+
| `blur1` (detail 1.58) | 12/15 (3 amb) | 12/15 (3 amb) | 13/15 (2 amb) | 12/15 (3 amb) | 12/15 (2 amb, 1 wrong) | 11/15 (1 amb, 3 wrong) | 11/15 (2 amb, 2 wrong) |
|
|
8845
8870
|
| `blur2` (detail 0.59) | 9/15 (5 amb, 1 wrong) | 9/15 (4 amb, 2 wrong) | 9/15 (4 amb, 2 wrong) | 8/15 (3 amb, 4 wrong) | 7/15 (3 amb, 5 wrong) | 6/15 (4 amb, 5 wrong) | 7/15 (3 amb, 5 wrong) |
|
|
8846
8871
|
| `flat` (detail 0.00) | 0/15 (14 amb, 1 wrong) | 0/15 (14 amb, 1 wrong) | 0/15 (13 amb, 2 wrong) | 0/15 (11 amb, 4 wrong) | 0/15 (13 amb, 2 wrong) | 0/15 (12 amb, 3 wrong) | 0/15 (12 amb, 3 wrong) |
|
|
8847
8872
|
|
|
@@ -8850,14 +8875,14 @@ The same trials, grouped by `detail`:
|
|
|
8850
8875
|
| detail | found | ambiguous | wrong | refused |
|
|
8851
8876
|
| --- | --- | --- | --- | --- |
|
|
8852
8877
|
| under 0.25 | 8/119 | 89 | 22 | 0 |
|
|
8853
|
-
| 0.25–0.5 |
|
|
8854
|
-
| 0.5–0.75 |
|
|
8878
|
+
| 0.25–0.5 | 0/3 | 2 | 1 | 0 |
|
|
8879
|
+
| 0.5–0.75 | 49/81 | 13 | 19 | 0 |
|
|
8855
8880
|
| 0.75–1 | 17/34 | 14 | 3 | 0 |
|
|
8856
8881
|
| 1–1.5 | 25/25 | 0 | 0 | 0 |
|
|
8857
|
-
| 1.5–2 | 34/48 |
|
|
8882
|
+
| 1.5–2 | 34/48 | 13 | 1 | 0 |
|
|
8858
8883
|
| 2–3 | 40/44 | 1 | 3 | 0 |
|
|
8859
8884
|
| 3–4 | 34/34 | 0 | 0 | 0 |
|
|
8860
|
-
| 4 and over |
|
|
8885
|
+
| 4 and over | 31/32 | 1 | 0 | 0 |
|
|
8861
8886
|
|
|
8862
8887
|
**Method.** The truth set is `examples/spineboy`: its setup pose and one frame of
|
|
8863
8888
|
`walk` (a third of the way in). For every trial the figure is rendered twice with one
|
|
@@ -8879,8 +8904,8 @@ part has a low per-pixel gradient and still places — and size alone has no
|
|
|
8879
8904
|
measurable effect across 24–192 px at any level.
|
|
8880
8905
|
|
|
8881
8906
|
**The edge**, derived by `deriveFloor` as the largest rung of a fixed ladder under
|
|
8882
|
-
which at most a tenth of the trials were found: **`detail` 0.5**. Under it, **
|
|
8883
|
-
of the trials were found (
|
|
8907
|
+
which at most a tenth of the trials were found: **`detail` 0.5**. Under it, **6.6%**
|
|
8908
|
+
of the trials were found (8/122); at or over it, **77.2%** (230/298). A part is below
|
|
8884
8909
|
the floor when its `detail` is under 0.5, or when its own longest side is under 24 px,
|
|
8885
8910
|
the smallest size measured (there, nothing measured says `pose` can place it).
|
|
8886
8911
|
|
|
@@ -8911,16 +8936,44 @@ blurred part now reported with a second placement at the same spot and another
|
|
|
8911
8936
|
scale, one of them with the truth itself as its best answer), for 43% more
|
|
8912
8937
|
refinement samples and the coarse pass untouched.
|
|
8913
8938
|
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8939
|
+
Since issue #886 the stopped polish tries **a quarter rung** (2^(1/12)) beside the
|
|
8940
|
+
half and keeps the better re-fit. The case was not a grid trial but §6's stationary
|
|
8941
|
+
post in [MOTION.md](MOTION.md): under `--scale 0.85,1.2` it came back at scale
|
|
8942
|
+
0.917, residual 0.0649, where the old placement at 0.975 still scores 0.0589. The
|
|
8943
|
+
half rung stepped from 0.917 to 1.029, where the best position scores 0.0980 — a part
|
|
8944
|
+
that fills its image pays for every pixel pushed past the figure, so above its truth
|
|
8945
|
+
the objective is a cliff, and half a rung crossed the basin onto it. With both, the
|
|
8946
|
+
post places at 0.971 (0.0593, 0.1 px from the old placement), and the grid goes from
|
|
8947
|
+
237 to 238 found and 8 to 6 misses (2 gained, 1 lost) for 16% more user CPU. The
|
|
8948
|
+
quarter alone found 234, losing the native arms #877 was made for. The one lost is a
|
|
8949
|
+
margin reading again: the blurred 32 px front shin (walk) now reports its truth as its
|
|
8950
|
+
best (0.07 px, 0.00968), with its old 0.51 px answer 0.0045 above it.
|
|
8951
|
+
|
|
8952
|
+
Issue #892 asked whether the coarse field, which keeps **one rotation per anchor
|
|
8953
|
+
cell**, loses the truth more often than on that post, and the answer is no. The
|
|
8954
|
+
tool now records, per trial, the coarse seed nearest the truth, the rotation the
|
|
8955
|
+
field kept for its cell and the field's own score there at the truth's rotation.
|
|
8956
|
+
Within 2.4 px of the truth that seed is a half turn off on 2 of the 238 found
|
|
8957
|
+
trials (a mouth at 48 px, both found anyway) and on none of the 6 misses, and
|
|
8958
|
+
every failed trial whose nearest seed is a quarter or half turn off but one is a
|
|
8959
|
+
flat part, none of them a miss. On the post itself, the upright rung scores 0.305
|
|
8960
|
+
at that cell against the half turn's 0.168, so a second rotation per cell would
|
|
8961
|
+
need a band 1.8 times wide to carry it. Re-gridding the rotation at the coarse level
|
|
8962
|
+
instead of the next one took the grid to 236 found (7 gained, 9 lost), and
|
|
8963
|
+
suppressing minima only within a rotation family took it to 231 (2 gained, 10
|
|
8964
|
+
lost). Both lose trials far from the truth, so neither shipped and the field is
|
|
8965
|
+
unchanged.
|
|
8966
|
+
|
|
8967
|
+
⚠️ **What this is and is not.** The grid is not a reliability line: six native cells
|
|
8968
|
+
place 14 or 15 of 15 and the trials at `detail` 3 and over place 65 of 66, but the
|
|
8969
|
+
goggles still place 13 of 42, and a threshold read off two dozen parts of one figure
|
|
8917
8970
|
would be a claim about that figure. What the grid can separate is **whose** failure a
|
|
8918
8971
|
failure is. `bun tools/pose_floor.ts` prints the residual at the truth for every
|
|
8919
8972
|
failed trial and marks it **missed** when the truth scores better than everything
|
|
8920
8973
|
reported and nothing reported is on it — a failure the search could fix. The other
|
|
8921
8974
|
failures are the objective preferring another placement (a blurred part shrunk into
|
|
8922
8975
|
its own region scores better than its truth) or the truth reported and tied, and no
|
|
8923
|
-
search can fix those. After #
|
|
8976
|
+
search can fix those. After #886, 6 of the 182 failed trials are misses, and 5 of
|
|
8924
8977
|
those sit within 3.1 px of the truth rather than on another hill; the `--from`
|
|
8925
8978
|
listing prints, for each, where the refinement left the truth level by level. All this was
|
|
8926
8979
|
measured on **ideal cuts**, the frame's own pixels, where a residual at the truth is
|
|
@@ -8935,7 +8988,10 @@ print the table, derive the edge and list the misses per cell. `PO22` in
|
|
|
8935
8988
|
no miss at all, and `PO23` places the 48 px fist #865 was made for; `PO28` and
|
|
8936
8989
|
`PO29` place the four trials #877 was made for and read where the shin survived the
|
|
8937
8990
|
cutoff, and `PO26` holds every polish to strictly descending residuals, read through
|
|
8938
|
-
the same trace.
|
|
8991
|
+
the same trace. `PO31` places §6's post at the old placement from the page's own
|
|
8992
|
+
input bytes, and `PO32` holds it to taking the quarter-rung escape and reading the same twice.
|
|
8993
|
+
`PO33` holds the coarse row the tool reads rotations from to the field each seed was
|
|
8994
|
+
picked from.
|
|
8939
8995
|
|
|
8940
8996
|
## 12. Reading the half of that picture `pose` refuses — `rigc chainfit`
|
|
8941
8997
|
|
package/docs/INGEST.md
CHANGED
|
@@ -370,6 +370,8 @@ rigc check --candidate examples/3-timing-and-spacing/export/3-timing-and-spacing
|
|
|
370
370
|
--frames ref3/light
|
|
371
371
|
```
|
|
372
372
|
|
|
373
|
+
**No run reproduces this:** abridged — the head's `atlas`, `frames`, `skin`, `scope`, `reference`, `content` and `in units` lines and its two ⚠️ notes are cut, so the `⤷ fit` line the run prints under `content` stands under `framed to`; the section's `frames` line and every `⤷` note are cut; and so is everything the run prints after `per-frame`
|
|
374
|
+
|
|
373
375
|
```
|
|
374
376
|
rigc check
|
|
375
377
|
candidate …/examples/3-timing-and-spacing/export/3-timing-and-spacing-ess.json
|
|
@@ -378,14 +380,14 @@ rigc check
|
|
|
378
380
|
declared frames.json's own box: TAKEN, coincident — a fit there asks for 0.00 px, under the 1 px that separates a candidate in the frames' coordinates from one in its own, over 21 frame(s).
|
|
379
381
|
|
|
380
382
|
── light — candidate animation "light", 12 fps ──
|
|
381
|
-
MAE mean 0.00 worst 0.00
|
|
382
|
-
slot drift worst 0.
|
|
383
|
+
MAE mean 0.00 worst 0.00 (exact: none of the 21 compared frame(s) differs from the reference) (0..255 over the union alpha; over the whole frame, mean 0.00)
|
|
384
|
+
slot drift worst 0.4 px "pendulum" at f0012
|
|
383
385
|
per-frame all 20 adjacent pair(s) change by as much as the reference's own frames do
|
|
384
386
|
```
|
|
385
387
|
|
|
386
388
|
Two things to take from the control, both of which you need before reading any real
|
|
387
389
|
number: the **framing** resolved to the frames' own box at 0.00 px, so the MAE is a
|
|
388
|
-
comparison of pictures rather than of framings; and **slot drift still reads 0.
|
|
390
|
+
comparison of pictures rather than of framings; and **slot drift still reads 0.4 px at
|
|
389
391
|
MAE 0.00**, which is that instrument's own floor rather than a difference.
|
|
390
392
|
|
|
391
393
|
⚠️ **`--texture-from` is not optional on ingest work, and the reason is structural.**
|
|
@@ -1339,7 +1341,9 @@ against one picture. A foreign export hands you a packed page instead, and point
|
|
|
1339
1341
|
`pose` at one is worse than useless — it treats the whole page as a single part and
|
|
1340
1342
|
answers confidently:
|
|
1341
1343
|
|
|
1342
|
-
```bash
|
|
1344
|
+
```bash setup
|
|
1345
|
+
rigc render --candidate examples/3-timing-and-spacing/export/3-timing-and-spacing-ess.json \
|
|
1346
|
+
--fps 4 --max 900 --out ref-big
|
|
1343
1347
|
mkdir -p packed-only
|
|
1344
1348
|
cp examples/3-timing-and-spacing/export/3-timing-and-spacing.png packed-only/
|
|
1345
1349
|
rigc pose --images packed-only --frame 'ref-big/light@4fps/f0002.png'
|
|
@@ -1350,12 +1354,12 @@ rigc pose
|
|
|
1350
1354
|
.. frame …/ref-big/light@4fps/f0002.png (900x409)
|
|
1351
1355
|
.. ground rgb(232, 232, 232) over 100% of the border ring
|
|
1352
1356
|
.. parts …/packed-only (1 png)
|
|
1353
|
-
.. search scale 0.5–2 in 7 step(s) · rotation -180°–180° step 15° · refuse above residual 0.25
|
|
1354
|
-
PLACE 3-timing-and-spacing.png x= 324.3 y= 188.
|
|
1355
|
-
found on a
|
|
1357
|
+
.. search scale 0.5–2 in 7 step(s) · rotation -180°–180° in 24 step(s) of 15° · refuse above residual 0.25
|
|
1358
|
+
PLACE 3-timing-and-spacing.png x= 324.3 y= 188.3 rot= -91.6° scale=0.630 residual=0.2085 unexplained= 30%
|
|
1359
|
+
found on a 14x7 anchor grid, step 4 at 16x reduction
|
|
1356
1360
|
```
|
|
1357
1361
|
|
|
1358
|
-
⚠️ **`residual=0.
|
|
1362
|
+
⚠️ **`residual=0.2085` is *under* the default 0.25 refusal bar**, so nothing refused
|
|
1359
1363
|
it, and `PLACE` rather than `AMBIG` means nothing flagged it either. With the same frame
|
|
1360
1364
|
and the two real loose parts, the answer is what it should be:
|
|
1361
1365
|
|
|
@@ -1365,12 +1369,15 @@ rigc pose --images examples/3-timing-and-spacing/images \
|
|
|
1365
1369
|
```
|
|
1366
1370
|
|
|
1367
1371
|
```
|
|
1372
|
+
rigc pose
|
|
1373
|
+
.. frame …/ref-big/light@4fps/f0002.png (900x409)
|
|
1374
|
+
.. ground rgb(232, 232, 232) over 100% of the border ring
|
|
1368
1375
|
.. parts …/examples/3-timing-and-spacing/images (2 png)
|
|
1369
|
-
.. search scale 0.3–0.6 in 4 step(s) · rotation -180°–180° step 15° · refuse above residual 0.25
|
|
1370
|
-
PLACE pendulum.png x= 319.3 y= 214.
|
|
1371
|
-
found on a
|
|
1372
|
-
PLACE square.png x= 437.
|
|
1373
|
-
found on a
|
|
1376
|
+
.. search scale 0.3–0.6 in 4 step(s) · rotation -180°–180° in 24 step(s) of 15° · refuse above residual 0.25
|
|
1377
|
+
PLACE pendulum.png x= 319.3 y= 214.6 rot= -88.9° scale=0.411 residual=0.0428 unexplained= 7%
|
|
1378
|
+
found on a 28x13 anchor grid, step 2 at 16x reduction
|
|
1379
|
+
PLACE square.png x= 437.1 y= 343.1 rot= 0.0° scale=0.410 residual=0.0334 unexplained= 4%
|
|
1380
|
+
found on a 113x51 anchor grid, step 2 at 4x reduction
|
|
1374
1381
|
```
|
|
1375
1382
|
|
|
1376
1383
|
⇒ **Check what is in `--images` before trusting a `pose` report on ingest work.** One
|