Skip to content

fix(examples): redesign gltf-skin-roundtrip as a mech scorpion standoff - #265

Merged
TMHSDigital merged 2 commits into
mainfrom
fix/hero-gltf-skin-roundtrip
Sep 26, 2026
Merged

TMHSDigital merged 2 commits into
mainfrom
fix/hero-gltf-skin-roundtrip

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Why

The gallery review singled out this hero. It showed two near-identical scorpions built from untextured orange boxes, with legs clipping into each other and the floor, and no readable design. It also fell into the identical-copies trap: a pass meant "they look the same", so the eye had nothing to compare.

What changed

The model was rebuilt from scratch as a designed mech scorpion:

  • a lofted gunmetal chassis under a crowned carapace with five shingled tergite plates, a sensor brow and chelicerae;
  • eight jointed legs, with painted femur armour, hydraulic rams and knee drums, planted on rubber pads at z = 0;
  • three-bone claws: arm, swollen chela, and a movable finger;
  • a five-collar armoured tail on rubber bellows, ending in a telson with a venom band and a chrome needle.

It uses 5 materials (hazard paint, gunmetal, chrome, rubber, venom glow). Emission is used only on the eyes and the venom band.

The rig grows from 7 bones to 21. Bones now point +Y, -Y and ±X, so the rest-matrix round-trip is exercised off the old single axis. Weights are rigid on the plates. There are two-bone smoothstep blends in the rubber boots at every flexing joint: 840 disk vertices carry two influences.

The composition witnesses the skin. On the left, the authored rig holds the guard pose the check compares: tail coiled, claws tucked. On the right is the actual re-imported mesh, driven through its imported armature into a different strike pose: tail reared, claws raised, pincers gaping. A file that lost the skin, the joints or the weights could not follow that pose. Posing uses rest-space axes in quaternions, so the same call drives both rigs; the glTF importer leaves its bones in quaternion mode. No text labels.

The render path is now gated. It calls gallery_framing (exit 10) and gallery_asset_quality (exit 11); the old render path called neither.

Two check-protocol bugs were fixed. Both make the check stricter.

  1. The "straddle-safe" neighbour lookup never worked. It added ±1e-4 without re-rounding, and 0.3601 + 1e-4 in floating point is not the key 0.3602, so only exact keys matched. When the redesign put a vertex on a rounding boundary, it reported a phantom weight loss (exit 18, w_err 1.0, measured on 5.2.1). Lookups now use keys_near(): the exact key first, then 26 rounded neighbours.
  2. A corrupted split copy could hide behind a good twin. got_w kept only the last re-imported vertex per position. The exporter splits vertices per normal, and each copy has its own JOINTS_0/WEIGHTS_0. The weight falsifier (one weight nudged to 0.99) fell through to exit 19 instead of 18. Every copy is now compared.

Asset-sheet tooling: scripts/asset_sheet.py gains a SELECT row for this example. scripts/asset_sheet_panel.py now bakes an Armature-deformed asset's staged pose before it removes the rig; without the bake, a skinned asset renders in rest pose (the scorpion with its tail stretched flat). None of the five current references is skinned, so their panels are unchanged.

Gates

Framing (5.2.1 and 4.5.11): fill x 0.856, y 0.589, minimum margin 0.072. No deviation.

Asset floors: no default names; 5 materials; edge90 0.001 (16/10946); no degenerate faces.

Contact sheet: docs/gallery/contact-sheets/gltf-skin-roundtrip-contact-sheet.webp

tile luma stage warmth sat
after 0.231 0.204 +0.147 0.210
before (old hero) 0.200 0.193 +0.217 0.136
armature-bend 0.279 0.213 -0.428 0.144
damped-track-aim 0.151 0.145 +0.277 0.231
bmesh-gear 0.236 0.177 +0.303 0.250

Per-criterion verdicts:

  • Stage darkness: pass. 0.204 is inside the set. It first measured 0.236 against the re-rendered bmesh-gear, so the lights were trimmed.
  • Wedge warmth: pass. A contained warm pool on the wall behind the pair.
  • Subject fill: pass (0.856 x).
  • Saturation: pass. The hazard paint carries it, far above the old 0.136.
  • Thumbnail legibility: pass. At 427×240 it reads as two mech scorpions squaring off, one coiled and one rearing.

Asset sheet: docs/gallery/asset-sheets/gltf-skin-roundtrip.webp. The scorpion is shown against the current reference set (collision-hull-proxy, socket-attach-points, vertex-color-ao, wheelbarrow, apothecary-shelf). Verdict: passes, mid-lineup.

  • It is more articulated than the hydrant and level with the drone for part density.
  • Its weakest aspect is surface finish: flat paint, with no wear or tone variation like the timber pieces carry.

Drift: measure_hero_drift.py --only gltf-skin-roundtrip gives mean_abs 0.0037: matches.

Generated HTML: the card <img alt> and detail page carry the full new alt. The witnesses callout carries "21 bones … 6.0e-07" untruncated.

Check runs (exact binaries, versions they report)

Binaries:

  • E:\Blender-Developer-Tools\.scratch\blender-4.5.11-windows-x64\blender.exe, which reports Blender 4.5.11 LTS
  • ...blender-5.1.2-windows-x64\blender.exe, which reports Blender 5.1.2
  • ...blender-5.2.1-windows-x64\blender.exe, which reports Blender 5.2.1 LTS
default --no-skins --output
4.5.11 0 5 0
5.1.2 0 5 (not run)
5.2.1 0 5 0 (via render_hero.py)

Measured values are identical on all three binaries:

  • bones=21, verts=6190, eval_loops=21892, disk_verts=11932 (welded 9960), blended_disk_verts=840
  • sum_err 2.98e-08, rest_err 2.32e-06, w_err 0, pos_err 5.96e-07

tests/smoke/run_example.py --forbid-skip gives PASS on 5.2.1 and 4.5.11.

Falsifiers

Each probe is a scratch copy with one line broken, run on 4.5.11, 5.1.2 and 5.2.1 with identical results:

probe exit measured
export_skins=False (--no-skins) 5 0 skins on disk
one re-imported weight set to 0.99 18 w_err 9.900e-01 (fell to 19 before fix 2)
re-imported Leg_R3 rest tail moved 1 mm 14 rest_err 3.866e-03
re-imported Tail_3 posed +10° 19 pos_err 1.319e-01
old un-rounded lookup, restored (5.2.1 only) 18 phantom w_err 1.0: the bug fixed

Proven by live run vs inspection only

Proven by live run:

  • all check exits and falsifiers above
  • framing and asset floors on 5.2.1 and 4.5.11
  • the contact-sheet and asset-sheet metrics
  • the drift match and the gallery build

Inspection only:

  • the thumbnail-legibility and asset-sheet verdicts (by eye, full size and 427×240);
  • the 5.1.2 --output path (not run);
  • the unchanged reference panels. The bake only touches objects with an Armature modifier, and I confirmed no reference asset has one by reading the SELECT targets, not by diffing panels.

🤖 Generated with Claude Code

TMHSDigital and others added 2 commits September 25, 2026 20:42
The review singled this hero out: two near-identical scorpions built from
untextured orange boxes, with legs clipping into each other and the floor.
The image gave the eye nothing to compare, because a pass meant "they look
the same".

The model is rebuilt from scratch. It has a lofted gunmetal chassis under a
crowned carapace and five shingled tergite plates. Eight jointed legs have
painted femur armour, hydraulic rams and knee drums, and they plant on
rubber pads. Each claw has three bones (arm, swollen chela, movable finger).
The tail has five armoured collars on rubber bellows, and a telson with a
venom band and a chrome needle. There are 5 materials, and emission is used
only on the eyes and the venom band. The rig grows from 7 bones to 21, with
bones pointing +Y, -Y and +/-X, so the rest-matrix round-trip is exercised
off the old single axis.

The composition now witnesses the skin. The authored rig holds the guard
pose the check compares. The actual re-imported mesh is driven through its
IMPORTED armature into a different strike pose. A file that lost the skin,
the joints or the weights could not follow that pose. The render path now
runs gallery_framing (exit 10) and gallery_asset_quality (exit 11).

Two check-protocol bugs were found and fixed; both make the check stricter:
- The "straddle-safe" neighbour lookup added +/-1e-4 without re-rounding,
  so only the exact key could ever match. It reported a phantom weight
  loss (exit 18, 1.0) once the redesign put a vertex on a rounding
  boundary.
- got_w kept only the last re-imported vertex per position. A corrupted
  split copy hid behind its twin, and the weight falsifier fell through to
  exit 19 instead of 18.

Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tion sets

After the rebase onto main, two things changed. #258 re-rendered
bmesh-gear, which darkened the contact-sheet calibration, and #257 raised
the asset-sheet reference set. The scorpion stage measured 0.236, brighter
than every calibration tile, so the key, fill, rim and wedge come down
until the stage sits inside the set (0.204). Luma is now 0.231.

The committed asset-sheet tool gains a row for this example, and it now
bakes an Armature-deformed asset's staged pose before it removes the rig.
Without that bake a skinned asset falls back to its rest pose, and the
scorpion rendered with its tail stretched flat. None of the five
references is skinned, so their panels are unchanged.

Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added examples Runnable smoke-gated examples under examples/ documentation Improvements or additions to documentation labels Sep 26, 2026
@TMHSDigital
TMHSDigital merged commit e173e9d into main Sep 26, 2026
11 checks passed
@TMHSDigital
TMHSDigital deleted the fix/hero-gltf-skin-roundtrip branch September 26, 2026 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation examples Runnable smoke-gated examples under examples/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant