From 34926324bd8e0b43124cee528b3fc7d3745b2580 Mon Sep 17 00:00:00 2001 From: m3ultra Date: Tue, 14 Jul 2026 18:44:09 +1000 Subject: [PATCH] Lane C R4: hero props into rooms (arcade/booth/fridge/mixer/register) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-4 §Lane C — map the 4 new hero props + cash_register (manifest now 14 fittings), validate, measure, clean up. - glb.js: map listening_booth→listeningCorner (record), drinks_fridge→fridge (milkbar), arcade_cabinet→new arcadeCabinet primitive (video focal prop). New attachCounterTop() places cash_register on every counter's till slot (hides the primitive till) + milkshake_mixer on the milk-bar benchtop; counter primitive + keeper stand untouched. All yaw 0 (no correction). - fittings.js: new arcadeCabinet primitive (footprint/height matched to the GLB); counter exposes counterTop attach points + tags the primitive till. - theme.js: arcadeCabinet in the video recipe; the 3 focal props (arcade, listeningCorner already, +) raised to priority 6 + placed first so the door-counter path loop can't pull them → 24/24 appearance. - interiors.js: thread recipe.key to upgradeRoom (gates milkshake_mixer to milk bars). - interior_test.html: load GLBs via the live depot: path (drop the deleted _local_glb localBase shim; ?localdepot=1 still works offline). Validated (all via live depot): primitive sweep 810 {throws 0, pathFail 0, detFail 0}; GLB-on soak {throws 0, path 0, det 0, leakGeo 0, leakTex 0, worst 7.3ms}; all 5 new props render planted/scaled/facing right (contact sheet docs/shots/laneC/glb_heroprops_r4.jpg). Room tris measured: milk-bar GLB-on ~468k (drinks_fridge 77k + milkshake_mixer 73k) — reported to Lane E as the #1 bake-pass target (not fixed, per integrator decision #2; interiors render one-at-a-time so gate 3 is unaffected). record_crate still broken + counter still oversized — both await Lane E re-export (C task 5). Deleted the stale web/assets/_local_glb/ validation copy. qa.sh --strict GREEN. Co-Authored-By: Claude Opus 4.8 --- C-progress.md | 29 +++++++++++- docs/LANES/LANE_C_GLB_VALIDATION.md | 57 +++++++++++++++++++++- docs/shots/laneC/glb_heroprops_r4.jpg | Bin 0 -> 54718 bytes web/interior_test.html | 6 +-- web/js/interiors/fittings.js | 32 +++++++++++-- web/js/interiors/glb.js | 65 ++++++++++++++++++++++++-- web/js/interiors/interiors.js | 4 +- web/js/interiors/theme.js | 3 +- 8 files changed, 180 insertions(+), 16 deletions(-) create mode 100644 docs/shots/laneC/glb_heroprops_r4.jpg diff --git a/C-progress.md b/C-progress.md index 4f1bce3..43970b1 100644 --- a/C-progress.md +++ b/C-progress.md @@ -3,7 +3,34 @@ *Status: **v1 complete & verified**. Standalone interiors library + test page. Every shop door opens into a unique, seeded, themed interior, generated on demand in ~4ms, byte-identical every revisit.* -Last updated: 2026-07-14 (round 3) · owner: PROCITY-C · reviewer: Fable +Last updated: 2026-07-14 (round 4) · owner: PROCITY-C · reviewer: Fable + +--- + +## Update 2026-07-14 (round 4) — hero props into rooms + +Round-4 task (ROUND4_INSTRUCTIONS §Lane C): map the 4 new hero props + cash_register (manifest now 14 +fittings), sweep/soak with them on, screenshot each, delete the stale `_local_glb/`, measure a hero +room. **All done.** Full report for Lane E: [LANE_C_GLB_VALIDATION.md](docs/LANES/LANE_C_GLB_VALIDATION.md); +contact sheet [docs/shots/laneC/glb_heroprops_r4.jpg](docs/shots/laneC/glb_heroprops_r4.jpg). + +- **New mappings** (`glb.js`): `arcade_cabinet`→new `arcadeCabinet` primitive (video focal prop), + `listening_booth`→`listeningCorner` (record), `drinks_fridge`→`fridge` (milkbar). All load, `glb_law` + compliant, yaw 0 (no correction). A new **counter-top attach** (`attachCounterTop`) puts `cash_register` + on every counter's till slot (hides the primitive till) and `milkshake_mixer` on the milk-bar benchtop — + the counter primitive + keeper stand are untouched. +- **Focal-prop reliability fix**: the door-counter path loop was pulling priority-4 focal props (arcade + appeared in only 5/24 video rooms). Raised the 3 focal props to priority 6 + placed-first → + **24/24 appearance**, still 0 carves / 0 path-fails. +- **Validation**: primitive sweep 810 builds `{throws 0, pathFail 0, detFail 0}`; GLB-on soak + `{throws 0, path 0, det 0, leakGeo 0, leakTex 0, worst 7.3ms}`; all 5 new props confirmed in-room. +- **Room tris measured** (task 4): milk-bar GLB-on ≈ **468k tris** (over budget) driven by `drinks_fridge` + (77k) + `milkshake_mixer` (73k) — **reported to Lane E** as the #1 bake-pass target (not fixed, per + integrator decision #2; interiors render one-at-a-time so gate 3 / the street budget is unaffected). +- **Cleanup**: deleted `web/assets/_local_glb/` (R3 validation copy); test page now loads GLBs via the + live `depot:` path (`?localdepot=1` still works for offline). `localBase` hook kept in `glb.js`. +- **Standby (C task 5)**: when Lane E re-exports `record_crate` (broken) + a ~2 m counter-with-till, I + re-map both. Not landed at commit time. --- diff --git a/docs/LANES/LANE_C_GLB_VALIDATION.md b/docs/LANES/LANE_C_GLB_VALIDATION.md index 096631b..cc84a0e 100644 --- a/docs/LANES/LANE_C_GLB_VALIDATION.md +++ b/docs/LANES/LANE_C_GLB_VALIDATION.md @@ -1,4 +1,59 @@ -# LANE C — GLB validation report (round 3) → for Lane E + Fable +# LANE C — GLB validation report → for Lane E + Fable + +## ROUND 4 update (2026-07-14) — the 4 new hero props + cash_register + +Mapped and validated the 5 round-4 hero GLBs (manifest now 14 fittings). Loaded via the **live +`depot:` path** (all published, HTTP 200); the R3 `_local_glb/` copy is deleted. Screenshot evidence: +[`docs/shots/laneC/glb_heroprops_r4.jpg`](../shots/laneC/glb_heroprops_r4.jpg). + +**All 5 load cleanly** (unlike the still-broken `record_crate`), follow `glb_law` (minY≈0, real metres), +and match their manifest footprints — **no per-kind yaw correction needed (yaw 0)**: + +| id / file | native x·y·z (m) | tris | maps to | placement | +|---|---|---|---|---| +| `arcade_cabinet` | 0.75·1.70·0.85 | 25,142 | **new** `arcadeCabinet` primitive (video recipe) | floor, aisle zone, focal | +| `listening_booth` | 0.88·1.60·0.71 | 53,502 | `listeningCorner` (record) | floor, window zone, focal | +| `drinks_fridge` | 0.85·1.60·0.96 | 77,047 | `fridge` (milkbar) | floor, against wall | +| `milkshake_mixer` | 0.38·0.50·0.27 | 73,492 | counter-top (milkbar) | ON counter benchtop (left slot) | +| `cash_register` | 0.42·0.35·0.34 | 5,999 | counter-top (all types) | ON counter benchtop (till slot); hides primitive till | + +New mechanism: **counter-top GLB attach** (`glb.js attachCounterTop`) — cash_register replaces the +primitive till on every counter; milkshake_mixer sits on the milk-bar benchtop. The counter primitive +(correct height + keeper stand) is kept; only the till mesh is hidden. Focal props made reliable +(priority 6 + placed first): **24/24 appearance** across seeds, 0 carves, 0 path-fails. + +**Sweep + soak with all R4 mappings on**: `throws 0 · pathFail 0 · determinismFail 0 · leakGeo 0 · +leakTex 0 · worst build 7.3 ms`. GLB clones share cached geometry (SkeletonUtils.clone) → per-room +dispose is leak-free (baseline taken after a full 9-type warmup). + +### ⚠ Interior tris — one room over budget (task 4 report, NOT fixed per integrator decision #2) + +Per-room triangles, single interior rendered alone (primitives vs GLB-on), seed 1990: + +| room | prims tris | GLB-on tris | GLB-on draws | note | +|---|---|---|---|---| +| pawn | 812 | 7,019 | 161 | fine | +| opshop | 2,476 | 58,230 | 706 | fine | +| video | 5,712 | 61,669 | 461 | arcade 25k dominates — fine | +| book | 6,372 | 102,998 | 1,249 | high **draws** (≈600 primitive spines) | +| record | 2,530 | 115,867 | 337 | listening_booth 53k — fine | +| **milkbar** | 1,662 | **468,106** | 578 | **OVER** — `drinks_fridge` (77k) ×up-to-3 + `milkshake_mixer` (73k) | + +**→ Lane E bake-pass priority (future, not v1):** `drinks_fridge` (77k) and `milkshake_mixer` (73k) are +grossly over-tessellated for their visual role (a fridge and a bench appliance). Baking these two to +~5–10k would drop the milk-bar room from ~468k to well under 150k. `cash_register` (6k) and +`arcade_cabinet` (25k) are already reasonable. Interiors render one-at-a-time (Lane F swaps scenes, the +street is not drawn behind them), so this does **not** affect gate 3 (street budget) or the v1 tag — but +it's the #1 candidate for the bake pass. Not blocking; reporting per task 4. + +### Still open (Lane E) +- `record_crate` — STILL fails to load (`Cannot read ...'uri'`); record bins/crates stay primitive. Re-export. +- `counter` — still the 4 m till-less asset; interiors keep the primitive counter. A ~2 m counter-with-till + would let me drop cash_register's separate attach and map `counter` directly. When both land I re-map (C task 5). + +--- + +## ROUND 3 report (superseded above where they overlap) → 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 diff --git a/docs/shots/laneC/glb_heroprops_r4.jpg b/docs/shots/laneC/glb_heroprops_r4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41564d87a3f9596e18a3e91836e6798cfb5b4935 GIT binary patch literal 54718 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�(QT`H4=w)dt0*! zX=8I%rUKA2-h_#JOAq^$tT0zv{}5k7=efYjT;l`)3yRf|#eu~)Eb-IvCypp}jaf-~ zDysvE49i)0qF!aphBR&=mU=5Y)DFa2h(-B<%cT~)nVj5k!}HeOjQfUnWrP~dmZqg; zSg!V(dDt(hZ@d4)k3*}Xp2Ne8Ef^+BH@$g)oUH?YOH6*spi;bAa+7MwG_pJ_hD<09 zEu^gsX^`S1?0jMhHxt$NU(bKTVibSF^4S@RiOlf%^Mm0o4vtAIk?O8xa5ft*CK>g!3TgoH4aTwVhi;5vmf z3FRLE-AB4ReAcg}PhS)otQXfd=g1{6nyJBLs~MFJQB99X3;IOFsV#~;N|Jdi>iw%` zHGZe30OaVac`*$&><}~9eVoVrr>Y&zDh0vSrUQ8V<%}l5c287lR$3&h@Tie1y6D)} zhd={O+@{Ygq{!itC+Wqd!6*V@YiReJf{c-C&&*Iz)z({;*RvW#kQ;3~=3llaYlGJ- zm$I`zE5UGhhCB#9wj^qWM+jP>wOUKvf+p*TaHj`1AkPA zDv?>TNfKs>?P{GEJ&t7oG@pOig%2*cow_#|T$kPPqzN0L4Yw;P?6S%4y%3&&HMLu4(MXTS+c}s=S!{iqF@WTIj@kFj@-G{juYFKK&8}b z3&nGh&jU51!0-7MWfyengw{3;yH;MYr);y8)Y|+$12&ueB8H48TiE5;c%KOPs>hO@ z@H}~|u(tK{;vD_^ke9*@gat}1&zY+1{6`(~&eZzb>l)ozfQ9?Me znH>dh)YAday}_IAvo@D~6|ykLrm9I?{wHQyAMBte0T$|NHo!ioxj;x{$CGNA!L`4Z z3m>F`hKyYnmPDF+R%zbf8S-B~j4DS}L@YBA59Wt9p13c)iAUvyUE7F0vS-EAQH;8- zk0I32HtkzALZu#WXFfMtg6Sl#h@2XS+;sic zgCcl(X0D@Q=8iep1(AsLG_|Bn?~w-@;3Mz$5;Um5*42ROJY`y)kyNh_9{B(L z1dgl!=3iAyGEa$%33O0JRJu0|bKme|SG9|m;Wxw=SGKM7+VXNWL^cUcCzdhoTf(pt zF$SuNRE&LII{Yg%JWjDE{*$vOc(bz6rYW2vXDONUy_3`Z(A-wPzW!RPbZu_ukyjn) zi|*buaha{1YATaW6->3@nQ#kPO%q8&1t7=e+pxX9f9z|kK!Vo&;nvnn9*QWqL@FAx z>XJ%Ys7myDbfxwNDS z%xV0jg@_&WaN<7DRZG>hu7B`~;WwNxUU2u|(W%Gva(7E{?IlluG(l}{;aBdM9tQht zV@so2hs?%y9@6nK8hNl( zDDc=4`v&GfdavfOrqvy_xyzcPY;kW%)+AxxgiE96j-XPWpg27i&sBW%eXMy{U#1`4 zCz9r`=Af9;3UE1k{F~fjbEb^Tfidh2*Tv*$n9ZTmpK)zv6aQ^{ZT)Z52k_7qQ{t+} zx?lzQTDn=ow~R4~?0r-)IcCm))eXGbrkd}mP)6 zhnOeDM7c~oG0+R0mtPKR|&6+mhyfr0b|K> zbf?EAEO)g4vC=n_-Bd_KtouGy%GW4ZK1`mk`BQpqmks;6Eeh}j&l7*~fsZBI$St|{H=Xws}1#mDDZrixW#$B3^o@e znLj87{5r})2t8 zC~f`GzOwwP{_?V47IMWo^4jav0=+?NwK%^2aa9Sy|69XhBh+4Rl=!OqVsc@m|CPc2 z|0n)>bpO`}kQQ2cYE?Rpz@$LXBwstW7<-<#cgKVO3cruUFH4J!>zyrBlR+C^70h1nQO$CsR{I0+_59v>N@kOE z=5RX;0fB35M^~Y(NBsVlwy=MEeUIb0wt7|$p@8R~+277X(A?#NB*0?Fzt~h+%i_U& z(ckNS0T7((f68xFDgRPe7Y{D!*E{OhjsBss{#&VL2d@4Hn~HOfW4SheR{ctSRS=0a z{7ZfH4$cys5&j44$_u$dYwhP*{p%Hqw+(**uo{P1Xi@*(qAErJM`dm7AL6R=|2+))`5$_1^-&SdKWx}Y(AMDB_}bL{be0!@VjZF*qWv{raVzUAQ!S!-0NLiz-uB&^UoJ|YjxGR*%pM-?b_X6 zADU*CIk+Nta9J$%w7GC&E)<9s^YV6DaccMV(Z|sZ=$;Pcd@wR{=RycR7U$?v2J}}i z*}FU`cm-aMG226U0mIln8{*J-!B0zU(xjtT_=BG zB4GR#qH8!t=-)^sv7J`H)STZugk2lFp$d^yItXF+`z+hqz+bw%)+8YfF|O}FlG0A^ zLT}U&z5a?8j{mo;uK8CKO?aKRRRetSzrTXN$^I>kBC(q{MXG6j6Y*ctzw3zq_pASu z)jtyc6>{Za;VASov)g3|6}y?JE8!FWR$nQTX<;44L{>N7TxUCjqwi zDP7k~0WWb|0Z>;Ll_guY!v!Wg`L@B7pv}D1DC~U0*nnxWrhx0_#x2`g*8+GdXU`wlL*byMgS5F6Aa7p4NnCm;2HlLPTgt#ijm^!}!ck ze0jN(C&^34Ex1+1X*3@ZluOFA_=Vr3vd@;y`|qskHh=R*+W!IQL4GRjxvW07bohuU zn4A1k&qkq(rR->FB7}evbn%GK7Ysp-;z4!|{670$B&zx8@)cygDyusUH@wtG?gWd= zUP*gn;Tqda>i;pGwh+EV`+WNH@D8&5!Z(sWZf8vh zT%3RsX#ZRAbt{JOC5H54d$y;;=6y1&s+O*{@u05>xpQAQU8M52ezUi!j4ua3AQv`u zM8{fmaSIR_Im@Gl|IY@@Zu3UnZ26(3UG+NQYmun5zs(4IJ~VuNbB+DLu(dQUrX0`L z7JT~Kf`41Gd~%#FL5b!mP{T!jsq1PTLK+|WmpJ}f8isz$7N_96fzy8`p!@Ql#{Exu zO~sY81<29(+13i5^Phu~$DroDGziwb17+{im3Gp+G=?Z|IbjOOO*$`=9{&*!25$T> ziyY0-RFdLf7WrjGU;kGDYer}0-n)7IcHMaAx}wy}%(R8e!LvUA-D(JkomuM|VUEb} zr_n2roLH%>*L*~YAgSV#)TP-?hzpzfVg78rx5jE+MR(Y1EMqn)5r>4W_93tF-nw>P z{^<<5UbfiVeDpeVD&&FB0{2_rC-NsrUnla_h)c7*&ujOO{H}(bW_GbbF;=#+0J!i{ zRncK6$JT&ph-sbD{&n%QQkUa<9K>GMMag}I0FqqWWfho zI#|ZZbM@f3TVdJ!cAfUhSHVGRHa#L0SF`4u4cxdSEh}V-724Og`kcocSJ=b1})*_=d*6> zhGWPZq$-J9-5E0SY*NbKXi8NA8|asCDmT9FC7kDALwiZ`z5}auLt9==%l;cmhW=H~%^>oR>s+WZuoio1qY_RtGjH0vs!@b0b3LHw_?VhvwPep7-htcFJ7o3G0 zMT5Dkl=gytmjvWgJi5Rhdbi|W^{)HQR=U_Rn2_*RQIie@ja)6)dYT{d zZp;~WnhXHArHbFm1JS{_I%w>>{%XkPN)2ouo+lsX_09R;@-sLvOAx+L9`M-{1N1|Q zR5y6MbS~_<9SD~v8<(q}DKmN92#98|b{ti8J?v2hw(=588wM^@nr7}X>k}IZDUU$T zO94zB5>Nh^zNFV)5tSH=^=|sLyXh6yvsM;McsXy@QmVfYP6WJtnCITzz2=S;a^%D1 zVWEz$G@FIq(-z>=+bFf=gW$WYfXX~?3veZ#JA9G`zGt*zIb3&N4 z>;^&+Rv9#Qlv$YIi5|%4MQ3;L=()|>QKc6+>*IJesS4XNw_HHhe0t_7v+h@b6PLpc z1dkHptwv$=mdNzb-~W(~YWmayxE4xHao5q@Jvit(YfnijDQ$|Q0417yra55yqJ_dwU|0ZF6SZ$!UdOr#GptC`&R?v}d0lkHL) z7PsA>$={X#daj@O;Yrr(0_trx)R}vY_2W1zy3Kq~#=|?1#hL08K&WX}hU1{;qX&60 zbQRGcX!Zu~XYtc_E5l1`YUGKj2SZT(ZW5_9ki}dd3fpjN9t#+n#p$I(8R_W2dCrn@ zc?^Pc+~FDtS9$$OQOWLN{b|yX_qMF&kpTocL`effW;~|-Ud*48O@p{Vm8uP;8D*n7 zObRK5QnTcYDAbV>PK@m8-IBDC(4a10a2T`DbiBeVorgG~XkCx;_T-8jHY=5tD&nWH z8`hl0Pra<++ACMvwOezuB&7qQY4tcE)p)%yy7XXY&ngjRT(=a9GrZeh(B6hYte zcy}u5&l93Cy;HHI&y?1dYU{%cKiv|S=p)w0u^QP+PZONVXzl5V0?*zMO9ecwooS~x zW@JoE(#v2FV6MdWC3+_iApJ1w!^pI-d_VHQHdj8%xb+8+$d)!msA|*{3GJj7oQ1T> zW0hVghZI&QjH_ujl`vfZXWBR{rrMXM-Ys=~wEuZClnPI^vC*l{LIBJzQXH+%iZ^bE z{Kf%kL`iK~F>y%K?hZSkY^=?CbNF|mp1%dTVVY>iN=Mvd-^?ma3;*fo% zZ+wQ3ACprbmlxwV4MR)rTpVlB-L-&|vzLMUV!tuycm6}q3C+2T9%bJ~kK;Zb_oxsK z1=L}Yq=jUIR!98RiSrv~cXgx*(OYeNkJJT7ogb16>Sm-~PSl@sA5!m1hU2Ex)ANG4 zL(EGupX|k7YM$l&clK3wCSFf(f2Ff39c_}b(W~c%iTr%O`l29SuN?sTvZTkJgJXZ_ z%D5S8%j=2;vmzHzC6QovO7?Q9@+{FLMi+}?U*`KhUv3^Xr^o(rQwcYl9?^w*EkmI&IQEsZZ2Q<}7T@FNXQo3f5179h+&a}7$&?Tnx-7-Y|LAH_+vR}dm)I<# zU*92WY<{(tbfMMrXjvX|`YxhbAtP)jyNTpLwvhM0Aygam^)S<|L^_=EphVnw<1mZA z#(#C4yge`kQAh^%0eoqpCX4K8K7UUVok`#W(`)=MpSDl zq>ww-qfzLJ zul(D92Mf^4%<(ge1)rYq9cb)hXv0oR&1G=%xwdxoBd3wFEr0i2|u;7k@AZ8*w+!w5_z`Jr@&cfuJEsiiV?g~v@E(3EJXL$ms*Yv@J4wOqU zJ|p%bx8p6>gVs#>LVKg?%aCb6>+2o}9vgp&*XgsGA@rdX$cJ$-&HJtw^&ubmM&&vb z-FK?O1Bl-8^?dA&p23nvqTe3oBlBKkSl#H9;tzGp2RaY za%_W~(%rebNwt#po@oCtpOD6&-R`@H&6aD>EOuipDLF^p(#>+Mqk%dE9-mkz^L%1@ zAl=_8V@vvO%rFI_o|P!)wcX*@DTF^42mH5qPN~2_r_+b;5RxMtF&f5wrL(s$wC#Gg za>$>++=3jm`H8&uTJKCNJ#nfXk8et6Vm7yPq93SJRy6qqOD%YvA<@ZHCX!-}=;-Kr z9_5F8hH&YGp1fYuR7v8p5h|LhDI4Cl_w7_h<0rNv4loCLnkmIgJ()0e)bTx_A0zHB z7-YGIQ5|wsMLZ25mU^h^*xEe9fEjlu9aN8K%&OWgcP4|pM+_o^(j3xM z@?mrZ(%PQsJs`80rMS<)8qI{O86J^=*2ZUdCFwr^m&l15Xf4dCCuIvL<|qEI`n~65NA3L4vzG1ealu;2PZB-Q8_)cXzko z?hXOIJ9)o-_TJ~zId$sZx;0h9)AUr+%<5jfp7pHt|CJ;2SHP`EV%2riPYLo3oLH0)Qs>78e;DTA!aTRL<8 zK1zM4uek?N7dM2s{j%Vyr?fdFYTGLK8{uWa#h@+hx&7A-<;@HEVjuIWL538x^oOW} zhuT(Aa$!6>JWjkByYvPKQR%}VurIKuE0zCS11XF0MN^{HfsjDy_81WlH;=FcHaRb( z(T-;puP{Uj=dwn#uJsf^RGO5IP@08!u^*Z0Ux8NPp`QL>0BCiT<5|Tjuz&6_ZmdkS zW;b_}Sn-{%P)liNVIoncfsQ*fM=E1-QP(%~+&qP7lgkDElT8iYv+|*;Rj>TWiFLjU ze9V%aCQFA2cpXQ(){Qp2=qWQ_>kDWR>}k`gXN`2X`?}?(ojAIJ}6^_(>Dy_@b=BtCUwk-}3-@ z$kJezsP}ygNd{@jZKbLPIYUqrbb~0SZ?!`zn(^|q+)YF!=cSIweqqnvSjaA>2_sn1 zYl^RbYQ8aWY`A)d)fjVsGsZRWfWi1L)AuTh+ywv`K%{ijnJ_l@VFe0vx7O-9R_kB$yX z6EfFXS|v1fSMm;1Do729(l(#!54Q4tctk{L zxIlt)S0=KOhehs3euor8@5jqtjY_7m*Aw!#P^UH+$dP`B^sJgmK^hxyB*eE;f@}}* zeeMqxhax6Vj%drij)s9AtgAhC?Qrn~_lN2i8!?g<7ACB$46-dPgkaA6T=dsDBD|>Q zYX{tUBMIeY+$EV!~mN|c(`6sKI0#*=-xrk!Zt>~wk+=}aCF)< z_mY^0}n6s{Pl7cEI{h<{`IU5 zr2N5s?{+2;vN)e?*|Ze#7p7Ezb912dfMqUdk}ApL37?p z@@oA9vX%kKvM5zEISM>2^}GWhQ>wiGoKh`yKiTd;N=@tzp38^Kb)7Iri6^mp{voz)L9lIFw za(7=6KjdpF6=qNx`}wrIBNoa4?}dOeM~|XFrStBIK^UEfL)WIeA&VgDPp@%Y;E=< zmRv{lMa31NU}KcnPuivH)u;}d>x&YIxoHHEMh#VJD#Ur@=T>XYO2&+GmSyo}x9X^qzjY`~wO63EmbaLkmQ}OysSb}Q9<7c-JSq`kGx-JFf=vz<8(d&|mfY5El>ZA3x_M9U`rN5}a8WT;x6|Lgbl- zqO!kR#^N8VC^+_$?p+i=v8YbnkpXDxYI23*cILe@_5*dTsSrbr@e!uGFv?iM%z6!A zHFZtKDNF~V0xOyKhhp@D*$**UgvOs~0hQt7l*8^1H8&ufn9hm`at0 z_RN^KAaFMB?W1)9qllP<)Wm7Sc05FbCFD3by#_)Y?c+g6wO?MXRaI4=5=rolz4&89 z9wjR6wX0Lg}#Uh-C`uJA6RlN z#d!+%v7(hXl_EkyP*`!s1!yvTgBzsBxN6v8JRi^WK9#g4 z*9J<5rO%IMMrLJRceLcYGLq|j1dAdU6hNtjl8wsvSXX`7`<(3F{Lz9w(Q@c6i95{5nLYC^b(2je0+b~0Rn=C@m?$I%=E^L8gl*ez+qVDDs zejx1PoOfYyXT$em|IQI-wfKX)1o7NR-@!Q)!Y0 zQ%CS+*Xq!&W-Q+Fko3~h_}hxd-M^sL8z4)WU`S8M6Xw&}~Ja^6Y_dIb3w{`h~hMdVC>$P1hC{BnXSfXfQ)A@;mMq zB!YoWlkM#yZ-eB-NcL7Ow00wAAwCbQOXp->bS<_LuJW|1rX{Qm%~;ld(0^6BxZVym z%;_%c`Mv3LYquVe7ZpIMvr4RPvFW@BbLuzcZ@XjJ|MnnZE}*1YkO>T*)V8)jdDX(5f&W(9t1@Yg zT5oW_(zddjF$yH#j++c5@jftziYAmyuePp0IiM+Di0;2X1c;@d?*~?z%+d8>9p_4Q zbexy{82}RDv7#<&H}ZEu3S7twYP*0CIFS~5vgoi=r5F7z2*+XKjCR{%>3J6Wj``cH zhNd%6LMuIZWWZS9n3QrJ!~N+lTCB#SyJKEy^kBrfWt>8XGtFQ!-_ys+6@9wSs30^d zWKr#dJ>~f>M5VMDwTr|PG&SiG$i;{`rEDLeos9hj`GkQ@b^PGE@dt0U5#xMf!>3CU z?$}L6aN?niPU;(2c?Uo*rl5jOHFBcIj*jTUb`AjJQV03Hc8HI9mDv#ZC`%}h^L{*x znO-jZisd*vu?wsuA!LaHF83yiQI(4DJ)-9473Q@R`^K6-YUu!9KxJd-)AlGD!2f2fMFvTdqtiYehBS>?Ry@wmv?y|tO7=>7_ztsO(NpD`FzJ);Q<#?A zBUTaPZym>?7vTAnOdQ?Gs5q^HCG}RWm8>|1y4BO?WJYb9jJk9YY5P_xCe>ec?7uG@ z?y}1?)NK}|{(Oo2w+#5gej`m?ybWTQ^9IH{$JMVONG(GNQ+vk@;;s(j zlWl6OyRYYC!K>QU`^wptC)f3#zkP^!NiNHfN!>@k-VHoSNHa9#4Yn%0DDOxt_^(`s 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 N-=3}iUje=e{t0gPK!N}O literal 0 HcmV?d00001 diff --git a/web/interior_test.html b/web/interior_test.html index 482cc37..27db6d3 100644 --- a/web/interior_test.html +++ b/web/interior_test.html @@ -101,9 +101,9 @@ for (const a of ARCHETYPE_KEYS) archSel.appendChild(new Option(a, a)); let current = null; // the live interior let gridHelper = null, pathHelper = null; let wire = false, showGrid = false, showPath = false, useGLB = false; -let glbManifest = null; // Lane E manifest + localBase → validate GLB props vs locally-served copies -fetch('assets/manifest.json').then(r => r.ok ? r.json() : null) - .then(m => { if (m) { m.localBase = 'assets/_local_glb/'; glbManifest = m; } }).catch(() => {}); +let glbManifest = null; // Lane E manifest → GLB props load via the live depot: path (all 22 GLBs published). +fetch('assets/manifest.json').then(r => r.ok ? r.json() : null) // for local-only testing add ?localdepot=1 to the URL + .then(m => { if (m) glbManifest = m; }).catch(() => {}); function parseLot(v) { const m = String(v).match(/(\d+(?:\.\d+)?)\s*[x×,\s]\s*(\d+(?:\.\d+)?)/); diff --git a/web/js/interiors/fittings.js b/web/js/interiors/fittings.js index 381bef8..b0d9845 100644 --- a/web/js/interiors/fittings.js +++ b/web/js/interiors/fittings.js @@ -167,6 +167,27 @@ function vhsAisle(ctx, o = {}, r) { return { group: g, footprint: { w, d }, height: h, slots, places: [] }; } +// Upright arcade cabinet — the video-store focal prop (GLB `arcade_cabinet` upgrades it). +// Built facing +Z (screen toward the room), footprint/height matched to the manifest so the GLB drops in. +function arcadeCabinet(ctx, o = {}, r) { + const g = new ctx.THREE.Group(); + const w = o.w || 0.72, h = o.h || 1.7, d = o.d || 0.82; + const body = ctx.mat(['#7a2a3a', '#2a3a7a', '#2a6a4a', '#6a3a2a'][(r() * 4) | 0], 0.6); + const black = MAT.black(ctx); + ctx.box(w, h, d * 0.55, body, 0, h / 2, -d * 0.2, g); // tall body (set back) + ctx.box(w, h * 0.5, d * 0.45, body, 0, h * 0.25, d * 0.05, g); // lower front (kickplate) + ctx.box(w + 0.04, 0.2, 0.14, ctx.mat('#f0e070', 0.4, { emissive: new ctx.THREE.Color('#403a10') }), 0, h - 0.1, 0.02, g); // lit marquee + const scr = ctx.box(w - 0.14, 0.52, 0.04, ctx.mat('#0a0e14', 0.25, { emissive: new ctx.THREE.Color('#0c1626') }), 0, h * 0.7, 0.16, g); + scr.rotation.x = 0.22; // slanted dark screen, faces +Z + const cp = ctx.box(w - 0.06, 0.34, 0.05, black, 0, h * 0.46, d * 0.22, g); cp.rotation.x = -1.0; // control panel + ctx.cyl(0.018, 0.13, MAT.chrome(ctx), -0.15, h * 0.5, d * 0.24, g); + ctx.cyl(0.018, 0.13, MAT.chrome(ctx), 0.15, h * 0.5, d * 0.24, g); + [['#e04a3a', -0.02], ['#f0b428', 0.05], ['#4ac04a', 0.12]].forEach(([c, bx]) => ctx.cyl(0.02, 0.03, ctx.mat(c, 0.4), bx, h * 0.51, d * 0.27, g)); + ctx.box(0.22, 0.16, 0.02, ctx.mat('#c8a13a', 0.4), 0, h * 0.14, d * 0.28, g); // coin door + g.userData = { kind: 'prop', interactable: true }; + return { group: g, footprint: { w, d }, height: h, slots: [], places: [g] }; +} + // Spinner rack — rotating wire stand (paperbacks / postcards). function spinnerRack(ctx, o = {}, r) { const g = new ctx.THREE.Group(); @@ -222,12 +243,17 @@ function counter(ctx, o = {}, r) { const wood = MAT.wood(ctx), dark = MAT.darkwood(ctx); const body = ctx.box(w, h, d, wood, 0, h / 2, 0, g); ctx.box(w + 0.1, 0.06, d + 0.1, dark, 0, h, 0, g); // benchtop - ctx.box(0.34, 0.22, 0.28, MAT.black(ctx), w / 2 - 0.35, h + 0.15, 0, g); // till + const till = ctx.box(0.34, 0.22, 0.28, MAT.black(ctx), w / 2 - 0.35, h + 0.15, 0, g); // till const scr = ctx.plane(0.14, 0.1, ctx.mat('#0a1a0a', 0.4, { emissive: new ctx.THREE.Color('#123') }), g); scr.position.set(w / 2 - 0.35, h + 0.28, 0.14); scr.rotation.x = -0.5; + till.userData = { tillPrimitive: true }; // glb.js hides these when cash_register lands + scr.userData = { tillPrimitive: true }; body.userData = { kind: 'counter', interactable: true }; g.userData = { kind: 'counter', interactable: true }; - return { group: g, footprint: { w: w + 0.1, d: d + 0.1 }, height: h + 0.3, slots: [], places: [g] }; + // Counter-top attach points (local space, on the benchtop top surface) for GLB counter-top props + // (cash_register on the till spot; milkshake_mixer on the free left spot). y = benchtop top. + const counterTop = { y: h + 0.03, till: { x: w / 2 - 0.35, z: 0 }, appliance: { x: -w / 2 + 0.4, z: -0.02 } }; + return { group: g, footprint: { w: w + 0.1, d: d + 0.1 }, height: h + 0.3, slots: [], places: [g], counterTop }; } // Glass display case — timber base + tinted glass top, a few "treasures" inside. @@ -352,7 +378,7 @@ function artFrame(ctx, o = {}, r) { export const FITTINGS = { recordBin, crate, listeningCorner, - wallShelf, metalShelf, cubeShelf, bookshelf, vhsAisle, spinnerRack, + wallShelf, metalShelf, cubeShelf, bookshelf, vhsAisle, spinnerRack, arcadeCabinet, clothesRack, trestleTable, counter, glassCase, pegboard, fridge, magazineRack, armchair, barredWindow, returnsSlot, escalator, artFrame, diff --git a/web/js/interiors/glb.js b/web/js/interiors/glb.js index 419f208..c5660d7 100644 --- a/web/js/interiors/glb.js +++ b/web/js/interiors/glb.js @@ -24,6 +24,10 @@ const KIND_TO_GLB = { bookshelf: 'bookshelf', cubeShelf: 'cube_shelf_wide', trestleTable: 'work_table', + // Round-4 hero props (manifest now 14 fittings): + listeningCorner: 'listening_booth', // record store focal prop + fridge: 'drinks_fridge', // milk bar drinks fridge + arcadeCabinet: 'arcade_cabinet', // video store focal prop }; // Per-kind facing correction (radians, about +Y). The GLBs follow glb_law (metres, +Y up, base at origin) @@ -34,8 +38,20 @@ const KIND_TO_YAW = { bookshelf: Math.PI / 2, cubeShelf: Math.PI / 2, trestleTable: Math.PI / 2, + // new hero props — tuned on-screen in R4 (see LANE_C_GLB_VALIDATION.md) + listeningCorner: 0, + fridge: 0, + arcadeCabinet: 0, }; +// Counter-top GLB props: sit ON the primitive counter's benchtop (not a floor swap). Each targets a +// counterTop attach slot exposed by the counter fitting. cash_register replaces the primitive till on +// every counter; milkshake_mixer only on milk-bar counters. +const COUNTERTOP = [ + { id: 'cash_register', slot: 'till', hideTill: true, types: null, yaw: 0, maxFoot: 0.42 }, + { id: 'milkshake_mixer', slot: 'appliance', hideTill: false, types: ['milkbar'], yaw: 0, maxFoot: 0.42 }, +]; + let _manifestP = null; // Fetch + cache the manifest. Returns null (not throw) if absent/unreachable → primitives everywhere. export function preloadManifest(url = 'assets/manifest.json') { @@ -81,9 +97,48 @@ export function upgradeFitting(ctx, fitting, kind, manifest) { }); } -// Upgrade every placed fitting in a room. Called from buildInterior when GLB mode is on. -// Returns a promise resolving once all in-room fittings' GLB swaps have settled. -export function upgradeRoom(ctx, placed, manifest) { - if (!manifest) return Promise.resolve(); - return Promise.all(placed.filter(p => !p.removed).map(p => upgradeFitting(ctx, p.fitting, p.kind, manifest))); +// Place counter-top GLB props (cash_register, milkshake_mixer) onto a counter fitting's benchtop. +// Additive: does NOT hide the counter primitive (correct height + keeper stand stay); cash_register +// hides just the primitive till it replaces. Fail-soft: unreachable/missing GLB → primitive stays. +export function attachCounterTop(ctx, fitting, manifest, shopType) { + const ct = fitting.counterTop; + if (!ct || !manifest || !manifest.fittings) return Promise.resolve(); + const jobs = []; + for (const spec of COUNTERTOP) { + if (spec.types && !spec.types.includes(shopType)) continue; + const entry = manifest.fittings[spec.id]; + if (!entry || !entry.file) continue; + const ref = manifest.localBase ? `${manifest.localBase}${entry.file}` : `depot:${entry.file}`; + jobs.push(loadGLB(ref).then(gltf => { + if (!gltf || ctx._disposed || !fitting.group.parent) return; + const THREE = ctx.THREE; + const inst = skeletonClone(gltf.scene); + inst.rotation.y = spec.yaw || 0; + const bb = new THREE.Box3().setFromObject(inst); + const size = new THREE.Vector3(); bb.getSize(size); + const glbW = Math.max(size.x, size.z) || 1; + const s = Math.min(1, spec.maxFoot / glbW); // clamp to the benchtop slot; never inflate + inst.scale.setScalar(s); + const at = ct[spec.slot]; + inst.position.set(at.x, ct.y - bb.min.y * s, at.z); // plant base on the benchtop surface + if (spec.hideTill) for (const c of fitting.group.children) if (c.userData && c.userData.tillPrimitive) c.visible = false; + inst.userData = { glbUpgrade: true, kind: spec.id, counterTop: true }; + fitting.group.add(inst); + })); + } + return Promise.all(jobs); +} + +// Upgrade every placed fitting in a room. Called from buildInterior when GLB mode is on. +// `shopType` gates counter-top props (e.g. milkshake_mixer → milk bar only). +// Returns a promise resolving once all in-room fittings' GLB swaps have settled. +export function upgradeRoom(ctx, placed, manifest, shopType) { + if (!manifest) return Promise.resolve(); + const jobs = []; + for (const p of placed) { + if (p.removed) continue; + jobs.push(upgradeFitting(ctx, p.fitting, p.kind, manifest)); + if (p.fitting.counterTop) jobs.push(attachCounterTop(ctx, p.fitting, manifest, shopType)); + } + return Promise.all(jobs); } diff --git a/web/js/interiors/interiors.js b/web/js/interiors/interiors.js index cd6b6ae..89e34ce 100644 --- a/web/js/interiors/interiors.js +++ b/web/js/interiors/interiors.js @@ -85,9 +85,9 @@ export function buildInterior(shop, THREE, opts) { let glbReady = Promise.resolve(); // resolves when GLB upgrades settle (immediately if off) if (opts.useGLB) { const manifest = opts.manifest || (glbManifest && glbManifest.__resolved) || null; - if (manifest) glbReady = upgradeRoom(ctx, lay.placed, manifest); + if (manifest) glbReady = upgradeRoom(ctx, lay.placed, manifest, recipe.key); else glbReady = preloadManifest(opts.manifestUrl).then(m => { - if (m && !ctx._disposed) { glbManifest = { __resolved: m }; return upgradeRoom(ctx, lay.placed, m); } + if (m && !ctx._disposed) { glbManifest = { __resolved: m }; return upgradeRoom(ctx, lay.placed, m, recipe.key); } }); } diff --git a/web/js/interiors/theme.js b/web/js/interiors/theme.js index 14d54f0..f088d7d 100644 --- a/web/js/interiors/theme.js +++ b/web/js/interiors/theme.js @@ -34,10 +34,10 @@ const RECIPES = { clutter: 0.85, counterPos: 'corner', fittings: [ + { kind: 'listeningCorner', zone: 'window', min: 1, max: 1, priority: 6 }, // focal hero prop — placed first + high priority { kind: 'recordBin', zone: 'aisle', min: 2, max: 5, priority: 5 }, { kind: 'crate', zone: 'centre', min: 1, max: 3, priority: 3 }, { kind: 'wallShelf', zone: 'wall', min: 1, max: 3, priority: 3 }, - { kind: 'listeningCorner', zone: 'window', min: 1, max: 1, priority: 4 }, { kind: 'counter', zone: 'counter', min: 1, max: 1, priority: 9 }, ], stockKind: 'sleeves', @@ -110,6 +110,7 @@ const RECIPES = { clutter: 0.85, counterPos: 'door', fittings: [ + { kind: 'arcadeCabinet', zone: 'aisle', min: 1, max: 1, priority: 6 }, // focal hero prop — placed first + high priority so the door-counter path loop won't pull it { kind: 'vhsAisle', zone: 'aisle', min: 2, max: 4, priority: 5 }, { kind: 'vhsAisle', zone: 'wall', min: 1, max: 2, priority: 4 }, { kind: 'returnsSlot', zone: 'counter', min: 1, max: 1, priority: 4 },