PROCITY/docs/LANES/LANE_C_GLB_VALIDATION.md
m3ultra fe40ea7d0a Lane C: round-3 GLB hero-prop validation (useGLB path)
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>
2026-07-14 16:18:12 +10:00

54 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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_*.glb` locally (`web/assets/_local_glb/`, copied from `pipeline/_normalized/`)
and pointed `glb.js` at them via a new `manifest.localBase` (loads before/without the depot, per the
round-3 instruction). Production still uses `depot:<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 measured `minY≈0`;
`facing` ("Lane B/C rotate directional props") — Lane C now applies per-kind yaw in `glb.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)
1. **`procity_fit_record_crate_01.glb` — BROKEN, will not load.**
`GLTFLoader.loadAsync` throws `TypeError: Cannot read properties of undefined (reading 'uri')`.
The file has valid glTF magic and is 858 KB, but references an undefined `uri` (missing embedded
image/buffer, or an extension the shipping bare `core/loaders.js` GLTFLoader 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).
2. **`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.42.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-add `counter` to `KIND_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`](../shots/laneC/glb_validation_grid.jpg).