Files
settled-reach/tooling/garment-qa
jpmschweitzerandClaude Fable 5 c765efd54e feat(assets): wardrobe wave 1 — per-body shells, 8 garments, try-on UI (T-1089)
Infra: offset-shell gains --per-body mode (each body's own segments, cut/mask
thresholds derived from that body's bone landmarks — reproduces the
hand-calibrated reference constants exactly on average_m); compositor prefers
<body>_mask.png with reference_mask.png fallback; tshirt re-authored per-body
on all 11 (the Q-060 torso poke-through class is GONE — residual flags are a
sleeve-hem epsilon artifact on thick arms, offset-insensitive, documented).

Garments (all per-body x 11, chromakey-gated <=150px worst, previewed):
hoodie (hood-down roll, kangaroo pocket, logo), button-down (collar/placket),
shorts, jeans (analytic denim field driving albedo+mask together; boundary
weld + open-rim flattening — real segment-splitter findings), formal pants,
jacket (over-shirt standoff, zip), suit_jacket_black (lapel region, tintable
shirt triangle — the hand-author proof), uniform_utility (11-segment
coverall, gap-free waist join by construction, 4-zone showcase, logo patch).

Try-on UI: creation screen shows per-region tint pickers (multi_region
garments) + logo picker (logo_capable + logos/*.png scan), data-driven off
manifest+coverage. Manifest merged by the lead: 12 clothing entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 00:35:20 +02:00
..

garment-qa — chromakey garment-clipping QA (T-1089)

Automatically detects clothing clip-through with a two-pass depth-proximity chromakey. Per view (clips × sampled frames × 4 camera yaws), the capture scene renders the SAME frozen animation frame twice: pass A paints the body segments a garment claims to cover (coverage.json hides) flat unshaded magenta, garment + head/hands normal; pass B is identical except the garment is flat cyan and every garment vertex is nudged clip_epsilon_m (default 3 cm) toward the camera. A body-key pixel that is magenta in A but cyan in B means the ε-shifted cloth now covers it — the body sat within ε in front of the cloth = poking through. This separates a true clip from a limb merely crossing in front of the torso, an open collar, or a bare arm over background (all of which stay magenta because the cloth behind them is > ε away).

Run: tooling/garment-qa/run-garment-qa [config.json] (defaults to configs/peasant.json). It launches Godot (~/bin/godot4, opengl3, xvfb-run when headless) on the capture scene, then runs the analyzer.

Config (path passed to the scene via GARMENT_QA_CONFIG): garments ({item_id,slot} catalogue items, or {glb,covers[]} for a raw WIP garment), body_types, clips, frames_per_clip, yaws, head_id/hair_id/eyebrow_id/skin_tone, out_dir.

Read the report: <out_dir>/report.json — the same summary prints to stdout. Two metrics per capture:

  • clip_through_pixels / largest_clip_component — key pixels the ε-shifted cloth covers (skin ≤ ε in front of cloth). This is the real defect and it gates: a capture fails when its largest connected clip blob ≥ --min-pixels (default 8, tolerating AA edges). clip_through_failures + the by_group clipfail/worstClip columns roll it up.
  • exposed_skin_pixels — key pixels the shift did NOT cover (skin well in front of any cloth: collar/sleeve/ankle gaps, a limb crossing the torso). Informational; does not gate.

Tune sensitivity with clip_epsilon_m in the config (smaller = only tighter pokes count) and --min-pixels on the analyzer. Failing/flagged frames are copied to <out_dir>/failures/*_HL.png with exposed_skin lime, clip_through filled red, and each clip blob boxed.

Note: the Godot scene lives at client/tools/garment_qa/chromakey_scene.gd (not here) because Godot res:// paths cannot leave the client project root.