PROCITY/docs/LANES/LANE_E_NOTES.md
m3ultra 447188a516 Lane E round 7 (E1): merge ped rigs to ONE draw each (gates roster flip)
Each of the 19 ped rigs carried 1-9 primitives / 1-3 materials (fleet 92 draws,
~116 at the 24-rig near cap). merge_ped.py (Blender) merges each to 1 primitive +
1 atlased material: join meshes -> pack material UVs into a non-overlapping atlas UV
-> EMIT-bake base-colours into one 1024 atlas -> single material. Skinning + skeleton
preserved (65 joints, walk/idle untouched, clips retarget unchanged). Fleet 92->19
draws (1/ped); near-cap 116->24 (79% cut). Verified in vendored GLTFLoader: all 19
load as SkinnedMesh + bind walk; man_suit poses byte-identical to original. Hands to
Lane D (D1) for full validation + full-density numbers, then F flips the roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 00:33:03 +10:00

138 lines
9.0 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 E — cross-lane notes
## Round 7
**→ Lane D (D1 — the flip gate): merged peds ready to validate.** `web/models/peds/*.glb` (19 rigs)
are merged to **ONE draw each** (1 primitive + 1 atlased material) — fleet **92→19 draws**, at the
24-rig near cap **116→24**. Method: Blender join + UV-pack + EMIT-bake all materials into one 1024
atlas (`pipeline/merge_ped.py`). **Skinning + skeleton preserved** — 65 joints intact on all 19,
`walk`/`idle` untouched, so clips retarget unchanged. I verified in the vendored GLTFLoader: all 19
load as SkinnedMesh + bind walk; `man_suit` poses to byte-identical dims vs the original (skin
deforms unchanged); `man_athletic` (3-mat) atlas eyeballed correct. Please do the full pass
(silhouettes/materials/impostor bake/identity variety) + the **full-density draws/tris numbers** for
F's flip. Pre-merge peds backed up (gitignored) at `pipeline/.peds_r6/` if you need a diff; per-ped
in `pipeline/_peds_merge.json`. **If any ped's atlas/silhouette reads wrong, name it — I re-run that
one** (per-ped `atlas` size is tunable; a couple with dense detail could go 2048).
**E2 (GODVERSE stock pack) — building against C's schema** (their task 1). Proposed index fields
below in case it helps C converge: `{id, title, artist, price, price_band, atlas, uv:[u0,v0,u1,v1]}`.
Adjusting to C's LANE_C_NOTES contract when posted.
## Round 6
**E1 done**`publish.py` now merges into `_published.json` (no more R5 clobber); `--verify` +
post-publish drift-check vs the live depot; `validate_manifest.py` fails if a manifest GLB isn't in
`_published.json`. Record verified 27==depot. All 27 procity GLBs stay live + recorded.
**→ Lane B / Lane C — I'm on-call for the props I shipped:**
- **B:** if `bus_shelter` / `bin` need a scale, origin, or facing tweak once placed on the street
graph, tell me the exact issue (current: bus_shelter 2.33×1.41 m / 2.4 m, bin 0.57×0.68 m / 1.0 m,
both base-origin minY=0). I can re-normalize + re-publish same-name (idempotent, merge-safe now).
- **C:** if `glass_case` / `magazine_rack` / `crate_stack` read wrong in-room (scale, the fal
glass_case's interior clutter, the magazine_rack density), flag it. A *broken*-prop fal re-gen is
pre-authorized ≤2 attempts (decision #5) — I'll log any spend in AUDIT. Footprints in the manifest;
all base-origin. Mapping guidance for the 3 orphans is in the Round-5 → Lane C section below.
## Round 5
### → Lane C: hero props BAKED to ≤8k tris — re-measure the record interior
The 6 heavy TRELLIS props are re-baked and **live on the depot** (same filenames, footprints
unchanged, so **no re-map needed** — they upgrade in place):
| prop | tris before → after |
|---|---|
| drinks_fridge | 77k → 8.0k |
| milkshake_mixer | 73k → 8.0k |
| listening_booth | 54k → 8.0k |
| counter_till | 32k → 8.0k |
| novelty_record | 26k → 8.0k |
| arcade_cabinet | 25k → 8.0k |
**Fleet 288k → 48k tris.** Method: voxel-remesh → decimate → Cycles base-colour bake (see
`pipeline/bake_lowpoly.py`, AUDIT R5). Verified loading in the vendored GLTFLoader; base colour
baked (no separate metallic/normal maps → also dodges the record_crate dangling-texture class).
**Please re-measure the record interior** (was ~273k tris in your R4 note) and record the new
number in LANE_C_GLB_VALIDATION.md — it should drop by ~most of the prop weight.
### → Lane C: 3 new fittings LIVE (fal Hunyuan) — glass_case + magazine_rack
The two remaining primitive-only fittings are now real GLBs on the depot (≤8k, base-colour baked):
- **`glass_case`** (`procity_fit_glass_case_01.glb`, 1.08×1.42 m, 1.0 m tall) — timber base + glass
panels + items inside. Registry ids `glass_case` (toy/dept) + `glass_cabinets` (pawn) both alias
to it. → add `glass_case`/`glassCase` (+ your pawn cabinet kind) → `'glass_case'` in `KIND_TO_GLB`.
- **`magazine_rack`** (`procity_fit_magazine_rack_01.glb`, 0.54×0.44 m, 1.2 m tall) — tiered timber
rack w/ magazines (milkbar/pawn). Registry `magazine_rack` aliases to it. → map your kind → `'magazine_rack'`.
- Both base-origin, verified loading in the vendored GLTFLoader. `manifest.fittingAliases` also maps
`fridge`→`drinks_fridge` and `listening_corner`→`listening_booth` if you iterate registry ids.
### → Lane B: new street props — `bus_shelter` + `bin`
- `procity_street_bus_shelter_01.glb` (`furniture.bus_shelter`, 2.33×1.41 m, 2.4 m, ≤8k, base-origin).
Solid painted-steel shelter (back wall + roof + bench) — place at bus-stop spots along the footpath.
- `procity_street_bin_01.glb` (`furniture.bin`, 0.57×0.68 m, 1.0 m, 3k) — red council wheelie bin, an
obvious town-furniture gap. Map `bin` in your furniture GLB-upgrade path if you want it on footpaths.
- **B3 resolved:** `novelty_record` is now **8k** (was 26.5k) via the E1 bake — re-measure the busy view.
All furniture GLBs base-origin + footprint-accurate; fail-soft as usual.
### → Lane C also: `crate_stack` for floor piles / dig
`procity_fit_crate_stack_01.glb` (`fittings.crate_stack`, 0.71×0.72 m, 0.9 m, 3k) — a stack of 3
plastic milk crates, good for record-store floor dressing or the dig scene. Optional; map a kind to
`'crate_stack'` if useful.
### → Fable: E1 (bake) + E3 (fal) status
- **E1 bake DONE + committed** — 6 props ≤8k, published. Feeds C's re-measure + your v1.1 tag.
- **E3 fal DONE** — glass_case + bus_shelter + magazine_rack generated on fal Hunyuan v2, **~$0.64
total** (log in AUDIT R5), ≤2 attempts each, all baked ≤8k + published. Guardrail held (nothing
else on fal). `validate --depot` 0 err. Last two primitive-only fittings retired.
- **E2 depot growth** next (v2-serving library props).
---
## Round 4
## → Lane D (task D2): decimated peds ready to validate
The 19 ped rigs in `web/models/peds/` are decimated and staged (committed `518678d`, ref
`lane-e/round4-peds`). Please validate rig binding + animation:
- **≤3k tris each** (range 15642805; per-ped before/after in `pipeline/_peds_decim.json`).
Fleet total **924k → 46.5k tris** (48.6k → 2.45k avg). At the 24-rig near cap ≈ **≤67k**.
- **Skinning preserved**: `JOINTS_0`/`WEIGHTS_0` intact; **skeleton unchanged** (nodes + 65
joints identical to source on every ped I checked), so the shared `walk.glb`/`idle.glb`
clips retarget unchanged. **`walk.glb`/`idle.glb` were NOT touched.**
- Method: `gltf-transform weld``simplify --ratio 0.05 --error 0.12` (meshoptimizer — works
because these are manifold skinned meshes, not R3 TRELLIS shell-soup). Contact sheet:
`docs/shots/laneE/peds_decimated.png` (silhouettes/textures clean at street distance; fingers
merge + faces flatten as expected at 3k, no melting).
- Originals backed up (gitignored) at `pipeline/.peds_orig/` if you need a before/after diff.
If any rig fails to bind/animate or a silhouette reads badly, tell me the file(s) and I'll
re-run that one with a gentler error (0.08 keeps ~50% more tris but still <5k). Then F re-measures
gate 3 after your sign-off.
## → Lane C: E2 asset re-exports
1. **`procity_fit_record_crate_01.glb` FIXED.** Root cause of your `undefined 'uri'` crash: the
material's `metallicRoughnessTexture` + `occlusionTexture` both pointed at a **sourceless
texture** (the packed AO/roughness map failed to encode to WebP during normalize; base-colour
+ normal were fine). Fix: `pipeline/fix_glb_textures.py` strips material slots that reference a
sourceless texture (orphaning it three.js loads textures lazily, so no crash). **Verified it
loads in the real vendored `GLTFLoader`** (meshes=1, tris=5000, textures ok) alongside a
bookshelf control. Re-published to the depot re-map `record_crate`/`recordBin` in `glb.js`
(they should already be mapped) and it'll upgrade instead of falling back.
2. **counter-with-till — LIVE.** New fitting `counter_till` (`procity_fit_counter_till_01.glb`):
**1.61 × 0.64 m footprint, 1.15 m tall**, timber counter + cabinet doors + period beige till on
top (flux_local concept trellis_mac, on-device). Fixes the R3 4 m till-less counter that
squashed. **Verified it loads in the vendored `GLTFLoader`** (32k tris TRELLIS shell-soup floor,
within decision-#2's 2577k for focal props) and **live on the depot** (`validate --depot` 0 err).
**In `glb.js` re-add `counter` to `KIND_TO_GLB` mapping to `'counter_till'`** (NOT the old
`counter` = balcao, which is a 4 m long bar counter kept for shops that want it). The manifest
`fittingAliases.counter` `counter_till` too. It's base-origin (minY=0), so your footprint-fit +
floor-plant works unchanged; at a 1.42.0 m counter slot it scales to a believable ~1.01.4 m
tall counter.
## → Fable: status
- **E1 (gate-3 critical path): DONE.** Peds 3k, committed + pinned. Unblocks D2 F3.
- **E2a record_crate: DONE + verified** (loads in vendored GLTFLoader). Re-published.
- **E2b counter: in progress** (local, on-device no fal spend per decision #3).
- Not doing: fal.ai spend (glass-case/bus-shelter stay parked), hero-prop bake-to-lowpoly.