Skip to content

fix(examples): redesign car-mirror-symmetry as a smooth-shaded stylized hatchback - #260

Merged
TMHSDigital merged 4 commits into
mainfrom
fix/hero-car-mirror-symmetry
Sep 26, 2026
Merged

TMHSDigital merged 4 commits into
mainfrom
fix/hero-car-mirror-symmetry

Conversation

@TMHSDigital

@TMHSDigital TMHSDigital commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

What and why

A gallery review judged the car-mirror-symmetry hero weak. It named four problems: a stray pink streak on the hood near the windshield, headlamps that looked like flat white stickers, a heavily faceted body that read as unfinished, and dull windows.

The streak came first. It is not a mirror-seam defect. I cast camera rays through the streak pixels on the committed code. Every hit landed on one face: authored face #37 (station 4, ring segment 5), seen on the mirrored half.

  • It sits at |x| 0.11–0.38, well away from the symmetry plane.
  • It is the thin panel where the old 9-point ring collapsed its greenhouse points onto the hood.
  • It was flat-shaded and faced the key light almost head on (n · −key = 0.967), so the clear-coated red blew toward pink.
  • All weld checks passed on that code (2n−c, on-plane count, manifold, Euler 2).

So there was no seam bug and no weld check to add. The redesigned ring cannot produce that thin panel.

Changes

  • Body loft, rebuilt. 52 placed stations × 13-point rings. Each ring blends from a hood layout into a cabin layout, which removes the thin panels. Other additions: round wheel arches around the wheels, flared black arch cladding and side skirts, a character line, black A- and B-pillars and drip rail, and a hatch.
  • Smooth shading. Sharp edges are set on the authored half by dihedral angle (35°) and material border. Edges on the plane take the angle to their own mirror image. There is no bevel or weighted-normal modifier, so the stack is still Mirror only and every count stays closed-form.
  • Parts. Headlamps, taillamps, grille, door mirrors and door handles are closed superellipse pods. Each has a chrome bezel and an inset lens, and a BVHTree ray cast seats it on the body surface. The wheels have five recessed spokes.
  • Glass. A dark, glossy dielectric whose colour ramps toward steel blue at grazing angles (Layer Weight → Color Ramp). On a near-black stage there is little for glass to reflect, so plain dark glass read as dull paint.
  • Grille welded across the plane (check extended). The grille is authored as a half whose end points lie exactly on x = 0, and the merge welds it into one part. The part check now takes a weld count per part: authored on-plane verts must equal weld, evaluated verts must equal 2n − weld, and evaluated on-plane verts must equal weld. Offset parts use weld = 0, so their check is unchanged (2n).
  • Render gates added. The render path now runs gallery_framing and gallery_asset_quality; it previously ran neither. Their exit codes are remapped to 17 / 18, because 10 and 11 are already check codes in this script.
  • Camera. It sits higher on the key side and looks down the hood centerline, so both headlamps, both mirrors, both A-pillars and the single centered grille read in the same view.

Before / after

Gate numbers (5.2.1 LTS, EEVEE)

  • Framing: fill x=0.734, y=0.789 (band 0.70–0.90). Margins: left 0.138, right 0.128, bottom 0.072, top 0.139. framing_ok.
  • Asset quality: no default names; 8 materials; edge90 0.035 (112/3174); compactness 16.5 (informational only). aq_ok.

Contact sheet, per criterion:

Criterion Candidate Calibration Verdict
Mean luminance 0.1730 armature-bend 0.2787, damped-track-aim 0.1511, bmesh-gear 0.3024 pass (within band)
Stage darkness 0.1652 0.145–0.236 pass
Wedge warmth +0.395 bmesh-gear +0.374 pass, warm pool behind the car
Saturation 0.262 highest of the four appropriate for a red hero
Subject fill see framing above pass
Thumbnail legibility (320×180) reads instantly as a red car with lamps, grille and wheels
  • Asset sheet verdict (new reference set): pass. Alone under neutral light, the car shows panel breaks, arch cladding, black pillars, bezelled lamps, one welded grille, mirrors, handles and spoked wheels. It is not the least-designed object in the lineup. It clearly clears the hydrant, and it is comparable to the wheelbarrow. The drone, the stone well and the apothecary shelf carry more fine-grained detail and material variety; the car's detail is broader and lower-frequency, by stylized game-asset design.
  • Hero drift: measure_hero_drift.py --only car-mirror-symmetry reports matches (mean_abs 0.00306, luma 0.1730/0.1728).

Check runs (check-only path, tests/smoke/run_example.py)

Binary Reported version Result
E:\Blender-Developer-Tools\.scratch\blender-5.2.1-windows-x64\blender.exe Blender 5.2.1 LTS PASS
E:\Blender-Developer-Tools\.scratch\blender-5.1.2-windows-x64\blender.exe Blender 5.1.2 PASS
E:\Blender-Developer-Tools\.scratch\blender-4.5.11-windows-x64\blender.exe Blender 4.5.11 LTS PASS

The check lines (body half=… / mirrored parts | …) are byte-identical across all three: body half 676/1289/614, 104 centerline verts; evaluated 1248/2474/1228, Euler 2, manifold, sym_dev 0.000e+00.

Falsifiers (5.2.1, each probe breaks one thing then runs check())

Probe Exit Measured
--no-mirror 5 676 verts ≠ 1248
body use_mirror_merge=False 5 1352 verts ≠ 1248
Mirror applied into data 3 datablock (1248, 2474, 1228) ≠ (676, 1289, 614)
one centerline vert moved to x=0.01 4 103 ≠ 104
Headlamp origin at x=0.01 12 origin x=0.01
new: grille merge off 14 (72, 52, 16) ≠ (64, 52, 8)
new: grille mirror axis off 14 (36, 26, 8) ≠ (64, 52, 8)
new: one grille end point at x=0.004 (beyond merge threshold) 13 on-plane 7 ≠ 8
front wheel mirror axis off 14 (390, 361) ≠ (780, 722)
new: framing band forced to 0.95–0.99 17 fill 0.789 FAIL
new: a hero part renamed Cube 18 default datablock names ['Cube']

Proven by live run

  • The streak diagnosis: ray-cast face mapping, x-range and normal·key on the committed code.
  • Check PASS on 5.2.1, 5.1.2 and 4.5.11, with byte-identical output.
  • Every falsifier above.
  • Framing and asset-quality numbers.
  • Hero and preview regenerated via render_hero.py, and the hero-drift match.
  • Contact sheet via contact_sheet.py, with its luma, stage, warmth and saturation.
  • Asset sheet rendered on 5.2.1 with the committed scripts/asset_sheet.py.
  • An unwelded body seam renders within 12/255 of the welded one (62 px > 10/255). This is recorded in the README as "not a pixel witness"; the count is what catches it.
  • build_gallery.py, with the new alt read in the generated docs/gallery/index.html and docs/gallery/car-mirror-symmetry/index.html.

Established by inspection only

  • The render path (--output) was run on 5.2.1 only, not on 5.1.2 or 4.5.11. It uses Coat Weight, Coat Roughness, ShaderNodeLayerWeight and ShaderNodeValToRGB, all present in 4.x Principled/node APIs. CI smoke does not pass --output.

🤖 Generated with Claude Code

…ed hatchback

The gallery review flagged a pink streak on the hood, sticker headlamps, a
faceted body that read unfinished, and dull windows. The streak was
investigated first: a camera ray cast maps it to one authored face (station
4, ring segment 5) on the mirrored half at |x| 0.11-0.38, far from the
plane, with every weld check passing. It was not a seam defect but a sliver
facet where the old ring's greenhouse points collapsed onto the hood,
flat-shaded and facing the key almost head on (n . -key = 0.967).

The loft is rebuilt: 52 placed stations x 13-point rings that lerp a hood
layout into a cabin layout (no slivers), round arches seated on the
wheels, flared arch cladding, a character line, and smooth shading with
sharp edges by angle and material set on the authored half (Mirror only in
the stack, so every count stays closed-form). Lamps, grille, door mirrors
and handles are chrome-bezelled pods seated on the skin by BVH ray cast;
glass ramps toward steel blue at grazing angles; wheels carry five
recessed spokes.

The grille is authored as a half across the plane and welded by the
merge, so the part check now takes a per-part weld count (2n - weld,
on-plane verts == weld) and falsifies both ways (merge off -> exit 14,
end point off the plane -> exit 13). The render path now runs the shared
framing and asset-quality gates, remapped to 17 and 18 because 10 and 11
are already check codes here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.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 and others added 3 commits September 25, 2026 20:15
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
…nce set

Adds the car's SELECT row to scripts/asset_sheet.py (body, wheels and the
fitted parts; stage excluded) and regenerates the asset sheet with the
committed tool against the reference set pinned in CLAUDE.md after #257:
collision-hull-proxy, socket-attach-points, vertex-color-ao, wheelbarrow,
apothecary-shelf. The old-car panel from the scratch sheet is dropped.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Keeps both asset-sheet SELECT rows (car-mirror-symmetry and
export-preset-axis); generated gallery pages regenerate unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
@TMHSDigital
TMHSDigital merged commit 784cda1 into main Sep 26, 2026
11 of 12 checks passed
@TMHSDigital
TMHSDigital deleted the fix/hero-car-mirror-symmetry 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