The store renderer placed every decal at raw pos_x/y/z with raw rotation, ignoring preferred_wall/snap/
object_type — so wall art (pos with one in-plane axis, perpendicular=0, rotation 0) floated in mid-room on
the wrong axis. Ported WowPlatter public/js/virtual/decals.js snapToWallAndOrient: a space decal (rotation
all-zero or snap=wall) keeps its in-plane axis, the perpendicular axis is pushed flat to its named wall
(north z=-D/2 yaw0 · south z=D/2 yawpi · east x=W/2 yaw-pi/2 · west x=-W/2 yaw+pi/2 · floor/ceiling lie
flat), yawed to face into the room; non-zero rotation = free manual placement, respected. Wall conventions
already matched the room's walls. Fixes booth (31 decals) + entry-hall (6) automatically. Verified the snap
math against real data (all land on-axis, in-bounds, facing in). Still TODO: crate_type(5)/rack(4) logo
decals (backend only fetches object_type=space; need the face-snap port) + hiphop room has no decals authored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scene was dumping all 3 rooms' racks/crates/lights into one room, and the
served decals + portals were never rendered (trapped in booth-room).
- /virtual/scene scopes to ONE room (?space=, default = is_default space);
filters racks/crates/lights/cameras/portals/decals/covers by space_id
- render decals (image + canvas-text planes) and portal doorways; walk into
a portal -> loads the linked room
- portal links_to_id is the PAIRED portal's id, not a space — resolve through
it to the destination room (to_space)
- copy the 29 referenced decal webp/svg into webstore/assets (self-contained,
served /store/assets); rewrite WP /wp-content/uploads/ paths in the scene API
- skip the 17MB logo .glb mesh decal (flat logo-blue.webp covers branding)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dig.js: enter a crate → records stand packed in a bin; scroll/drag riffles a damped
cursor through them; each sleeve hinges forward at its bottom edge as you pass (smoothstep
wave); tap the front sleeve to pull it out and inspect (price/condition/add-to-cart panel).
Depth-LOD cover loading (±8 around cursor). Procedural fwip/thunk audio, no asset files.
Wired into index.html: click crate → dig scene; render loop branches on dig.active.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>