Skip to content

fix(examples): redesign gltf-export-roundtrip as one crate under its re-imported wire cage - #273

Merged
TMHSDigital merged 1 commit into
mainfrom
fix/hero-gltf-export-roundtrip
Sep 26, 2026
Merged

TMHSDigital merged 1 commit into
mainfrom
fix/hero-gltf-export-roundtrip

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

What changed and why

The review found two identical crates with small floor text reading AUTHORED / ROUND-TRIP. That is the identical-copies failure mode: because a pass means the two crates look alike, there is nothing for the eye to find.

The hero is now one crate:

  • The solid crate is the authored one.
  • Laid over it is the actual re-imported mesh (the file's own triangles). It is drawn as a thin amber wire cage through a render-only Weld + Wireframe display stack and masked to the right of a vertical cut.
  • Neither object is moved. Both keep the identity transform that check 13 proves, and the camera does the turning.
  • The cage lands on every bevel, rivet and vent slat only because the importer undid the export_yup bake exactly and the file carried the evaluated (beveled) mesh.
  • If the axis conversion broke, the cage would sit a quarter turn off the crate. If the modifier contract broke, it would trace square corners.
  • The floor text is removed.

The crate itself has been upgraded:

  • It grows from 35 to 43 box shells: vent slats under each carry handle, and stiffening ribs across the lid.
  • The trim is a lighter gunmetal and the paint a warmer olive.
  • The authored copy gets noise-mottled paint and trim, on the render path only.

The render path now also runs gallery_asset_quality on the authored crate, with its exit 11 remapped to 23. The bevel is baked into the display mesh first, because the edge90 measure reads Object.data, which is still the square cage.

Also in this PR:

  • read_gltf now opens its JSON with encoding="utf-8".
  • scripts/asset_sheet.py gains a gltf-export-roundtrip SELECT row (^Crate\.Authored$).

Evidence

Framing: fill x=0.556, y=0.828 (band 0.70-0.90). Margins: left 0.222, right 0.222, bottom 0.078, top 0.094. framing_ok on 5.2.1 and 4.5.11.

Asset floors (authored crate): no default names, 3 materials (the floor applies only when parts >= 2; parts = 1), edge90 = 0.000. aq_ok.

Contact sheet, per criterion:

Criterion Candidate Calibration Verdict
Mean luminance 0.229 armature-bend 0.279, damped-track-aim 0.151, bmesh-gear 0.236 PASS, inside the range
Stage darkness 0.166 0.145-0.213 PASS
Wedge warmth +0.364 warm, like damped-track-aim +0.277 and bmesh-gear +0.303 PASS
Saturation 0.170 0.144-0.250 PASS
Thumbnail legibility At card size, the amber cage over the right half of the crate reads immediately - PASS

Asset sheet verdict: PASS, not the least-designed object in the lineup. The crate has more modeled parts and edge treatment than the hydrant and the well, though it is boxier than the drone and the shelf.

A note on the asset-sheet tool: its fit-to-extent camera frames the crate tightly, and the crate touches the edge of its panel. That is the shared tool's framing. The example itself is not affected.

Hero drift (measure_hero_drift.py --only): mean_abs 0.00834, verdict matches.

Check runs (check-only path)

Binary Reported version Check --no-yup falsifier
E:\Blender-Developer-Tools\.scratch\blender-5.2.1-windows-x64\blender.exe Blender 5.2.1 LTS exit 0 exit 9 (bbox deviates 8.700e-01)
E:\Blender-Developer-Tools\.scratch\blender-5.1.2-windows-x64\blender.exe Blender 5.1.2 exit 0 exit 9 (8.700e-01)
E:\Blender-Developer-Tools\.scratch\blender-4.5.11-windows-x64\blender.exe Blender 4.5.11 LTS exit 0 exit 9 (8.700e-01)

All three versions give the same measurements: verts=344, eval_loops=9288=disk_verts, tris=4644, pos_err 0.00e+00, nrm_err 6.35e-05, uv_err 3.11e-07. The render path also passes on 4.5.11 (EEVEE Next) with identical framing numbers.

Falsifiers

  • --no-yup (the existing contract falsifier): exit 9 on all three binaries, as shown above.
  • Asset-quality call site (new, exit 23): a temporary probe copy skipped the bevel bake. Result: aq_edge90 frac=1.000 (516/516) FAIL, exit 23. The probe was then deleted.
  • Visual witness: a temporary probe copy re-applied the missing quarter turn (rotation_euler.x = 90 deg) to the imported object before rendering.
    • With the framing gate left on, it exits 22 (bottom margin 0.000).
    • With the gate bypassed, the rendered cage falls through the floor, away from the solid crate.
    • The probe was then deleted.

Proven by live run vs established by inspection

Proven by live run:

  • Check and --no-yup on 5.2.1, 5.1.2 and 4.5.11
  • Render path, framing and asset-quality gates on 5.2.1 and 4.5.11
  • Both probes above
  • render_hero.py, contact_sheet.py, asset_sheet.py and measure_hero_drift.py on 5.2.1
  • build_gallery.py, after the rebase onto origin/main. The generated <img alt> in docs/gallery/index.html and docs/gallery/gltf-export-roundtrip/index.html was read.

Established by inspection only:

  • 5.1.2 render-path output (only the check-only path was run there)
  • CI smoke on 5.2 and 4.5, which is pending on this PR

🤖 Generated with Claude Code

…re-imported wire cage

The review found two identical crates labelled AUTHORED and ROUND-TRIP
in small floor text. Nothing differed between them, so the eye had
nothing to find.

The hero is now one crate. The solid crate is the authored one. Laid
over it is the actual re-imported mesh (the file's own triangles), drawn
as a thin amber wire cage through a render-only Weld + Wireframe display
stack, and masked to the right of a vertical cut. Neither object is
moved: both keep the identity transform that check 13 proves, and the
camera does the turning. The cage lands on every bevel, rivet and vent
slat only because the importer undid the +Y-up bake exactly. A probe
that puts back the missing quarter turn drops the cage through the
floor, and the framing gate fails too (bottom margin 0.000).

The crate grows from 35 to 43 box shells: vent slats under each carry
handle and stiffening ribs across the lid. The trim is a lighter
gunmetal and the paint a warmer olive. On the render path only, the
authored copy gets noise-mottled paint and trim. The check logic is
unchanged; its closed-form counts follow PARTS (344 cage verts, 9,288
evaluated loops).

The render path now also runs gallery_asset_quality on the authored
crate, with its 11 remapped to 23. The bevel is baked into the display
mesh first, because the edge measure reads Object.data, which is still
the square cage. The floor text is gone. read_gltf now opens the JSON
with encoding="utf-8". scripts/asset_sheet.py gains a SELECT row.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: TMHSDigital <[email protected]>
@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 c4f7d7d into main Sep 26, 2026
11 checks passed
@TMHSDigital
TMHSDigital deleted the fix/hero-gltf-export-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