Validated Lane E's 9 fitting GLBs in real rooms. 5 good, now live behind useGLB (wire_shelf, clothes_rack, bookshelf, cube_shelf_wide, work_table); record_crate broken (won't load) + counter too long/no-till fall back to primitive. Report: docs/LANES/LANE_C_GLB_VALIDATION.md. glb.js: real-metre scale clamped to footprint, per-kind yaw for Z-major assets (+90deg) per manifest facing convention, manifest.localBase for offline validation, awaitable upgrades. interiors.js: room.glbReady. interior_test.html: GLB toggle. Soak useGLB on (50 rooms): throws 0, pathFail 0, detFail 0, leakGeo 0, leakTex 0, worst 10.5ms, 256 upgrades. qa.sh --strict green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.1 KiB
LANE C — GLB validation report (round 3) → for Lane E + Fable
PROCITY-C, 2026-07-14. Round-3 task "GLB path visual validation" (ROUND3_INSTRUCTIONS §Lane C).
Validated Lane E's 9 fitting GLBs from pipeline/_normalized/ in real interior rooms via the
interiors/glb.js upgrade path (useGLB on). Verdict below; the 5 "good" assets are live.
How validated
- Served the 9
procity_fit_*.glblocally (web/assets/_local_glb/, copied frompipeline/_normalized/) and pointedglb.jsat them via a newmanifest.localBase(loads before/without the depot, per the round-3 instruction). Production still usesdepot:<file>unchanged. - Toggle GLB props on the interior test page (
web/interior_test.html) rebuilds every shop type with the GLBs and re-renders once they load; a headless sweep+soak checks throws/leaks/perf. - Convention followed:
glb_law(metres, +Y up, base at origin) ✓ every asset measuredminY≈0;facing("Lane B/C rotate directional props") — Lane C now applies per-kind yaw inglb.js.
Result — soak with useGLB on (50 rooms, all types)
throws 0 · pathFail 0 · determinismFail 0 · leakGeo 0 · leakTex 0 · worst build 10.5ms (<50) · 256 GLB upgrades applied. GLB textures/geometries dispose leak-free on room exit (loader-cached
- clone-shared; baseline taken after warmup). Acceptance met.
✅ Good — live now (5 assets)
| id / file | native (x·y·z m) | notes |
|---|---|---|
wire_shelf · procity_fit_wire_shelf_01.glb |
1.17 · 1.8 · 0.44 | clean, full height, faces right (yaw 0) |
clothes_rack · procity_fit_clothes_rack_01.glb |
1.34 · 1.5 · 0.43 | garments hang correctly, casters read well |
bookshelf · procity_fit_bookshelf_01.glb |
0.2 · 2.0 · 1.02 | needs +90° yaw — modelled wide along Z; Lane C rotates it. Then spines face the aisle ✓ |
work_table · procity_fit_work_table_01.glb |
0.44 · 0.75 · 1.04 | needs +90° yaw (Z-major); goods sit on top ✓ |
cube_shelf_wide · procity_fit_cube_shelf_wide_01.glb |
0.75 · 1.1 · 1.24 | needs +90° yaw. ⚠ 1.24 wide → in narrow (2-col ≈0.84m) cube slots it clamps to ~0.75m tall. Fine in wide slots. Optional: a ~0.8m-wide cube variant. |
Lane C applies the +90° yaw for the three Z-major assets (per the facing convention — no action needed
from Lane E unless you want to re-bake them Z-forward). All plant on the floor; no z-fighting with the
procedural stock/decor that rides on top.
⚠ Mismatches to fix (2 assets)
procity_fit_record_crate_01.glb— BROKEN, will not load.GLTFLoader.loadAsyncthrowsTypeError: Cannot read properties of undefined (reading 'uri'). The file has valid glTF magic and is 858 KB, but references an undefineduri(missing embedded image/buffer, or an extension the shipping barecore/loaders.jsGLTFLoader can't resolve — it is the only one of the 16 that fails that loader; the other 8 fittings + street furniture load fine). Impact: record bins/crates fall back to primitives (fail-soft, no crash). Please re-export (and if it uses KTX2/meshopt, flag it — the core loader has no KTX2/meshopt/Draco decoder configured).procity_fit_counter_01.glb— too large for the interior counter slot; no till. It's a real 4.02 m-long × 1.1 m counter. Interior counter slots are ~1.4–2.2 m, so fitting to the slot squashes it to ~0.6 m tall, and it has no till/register modelled. Lane C therefore keeps the counter primitive (correct height + till + keeper stand). If you want a GLB counter for interiors, a ~2 m-long counter with a till would drop straight in (re-addcountertoKIND_TO_GLB).
Notes for Lane E's local-depot mode (your round-3 §2)
When ?localdepot=1 / core/loaders.js resolves depot:<file> → local, Lane C needs no change:
glb.js uses depot:<file> by default and only used localBase as a standalone validation shim. Point
your local resolver at pipeline/_normalized/ and my useGLB path works through it as-is.
Screenshot evidence: docs/shots/laneC/glb_validation_grid.jpg.