← back to Quadrille Showroom
spec: 5 room types for showroom room-preview
2b90e02855f7bf4c6e188a02041727fdc9d7cfbb · 2026-06-30 19:33:41 -0700 · Steve
Files touched
A docs/ROOM-TYPES-SPEC.md
Diff
commit 2b90e02855f7bf4c6e188a02041727fdc9d7cfbb
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jun 30 19:33:41 2026 -0700
spec: 5 room types for showroom room-preview
---
docs/ROOM-TYPES-SPEC.md | 527 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 527 insertions(+)
diff --git a/docs/ROOM-TYPES-SPEC.md b/docs/ROOM-TYPES-SPEC.md
new file mode 100644
index 0000000..393c6fb
--- /dev/null
+++ b/docs/ROOM-TYPES-SPEC.md
@@ -0,0 +1,527 @@
+# ROOM_TYPES Spec — Quadrille 3D Showroom
+
+**Status:** DESIGN ONLY. No implementation. This is a registry spec for a future
+`ROOM_TYPES` object that would sit parallel to the existing `THEMES` / `MODES`
+registries. Nothing here edits `showroom.js`, `viewmodes.js`, or any code file.
+
+**Purpose:** Today the showroom is a single fixed environment — a 6.10 × 6.10 × 2.9 m
+PJ-style white-box gallery with a 50-board wingboard arc, one consultation nook, one
+olive tree, and a 3-point warm lighting rig (`showroom.js` lines ~692–939, ~963–993).
+This spec defines FIVE alternate *room presets* — **BEDROOM, OFFICE, HOTEL LOBBY,
+LIVING ROOM, ART GALLERY** — so a shopper can preview the clad Quadrille pattern in a
+realistic furnished context instead of only the sample-board arc. Each preset is a
+data record: room geometry, which surfaces get clad vs painted, floor/ceiling
+material + a matching ceiling fixture, a furniture set with concrete positions, a
+lighting rig, a default camera pose, and a hook for shifting the furniture palette to
+match the wallcovering's `hue` / `color_bucket`.
+
+---
+
+## 0. Grounding conventions (read before the records)
+
+These are the *actual* conventions the existing code uses. Every position/rotation in
+this spec is expressed in the same frame so a future implementer can drop values in
+without re-deriving them.
+
+**Coordinate frame (from `buildRoom`, `buildFurniture`, `buildAvatar`):**
+- Room is centered on the origin. `W = width (x)`, `D = depth (z)`, `H = height (y)`.
+- `x`: right = `+x`, left = `-x`. Half-width `= W/2`.
+- `z`: **the viewer faces `-z`.** The **back wall** (the primary feature surface, the
+ one the wing-arc hangs on) sits at `z = -D/2`. The **front wall** (doorway + DW
+ sign) sits at `z = +D/2`. So "deeper into the room / toward the feature wall" = more
+ negative z.
+- `y`: floor at `y = 0`, ceiling at `y = H`. Eye height ≈ 1.6 m.
+- Wall rotations (`addWall(x,y,z,w,h,rotY,mat)`): back `rotY=0`, left `rotY=π/2`,
+ right `rotY=-π/2`, front `rotY=π`.
+- `roomWalls[]` is the cladding registry — each entry `{ side, mesh, w, h, origMat }`.
+ Clicking a pattern re-maps `.map` on the clad walls; painted walls keep `origMat`.
+ `window._wallSides` is the canonical side list. **This spec's "clad vs painted"
+ column tells a future builder which `roomWalls[]` entries receive the pattern map
+ and which keep a flat paint material.**
+
+**Everything is a THREE primitive.** No GLTF. Floors/ceilings/walls are
+`PlaneGeometry`; furniture is composed from `BoxGeometry` / `CylinderGeometry` /
+`SphereGeometry` / `IcosahedronGeometry` groups. Every furniture record below is
+buildable from the primitive helpers already in the file (`capsuleMesh`,
+`buildConsultationNook`, `buildOliveTree`, `buildBookShelf`, plus the proto
+`sofa()` in `v9-walkin.html`).
+
+**Material library available now (`initMaterials`, lines ~375–416):**
+`MAT.floor` (warm oak), `MAT.ceiling` (warm plaster), `MAT.wall` / `MAT.brick`
+(photoreal limewash + normal/rough maps), `MAT.chrome` (brushed brass),
+`MAT.wood` (satin walnut), `MAT.chair` (cognac leather), `MAT.dark`, `MAT.frame`,
+`MAT.lightPanel` (emissive white), `MAT.baseboard`, `MAT.books[8]`.
+
+**Textures on disk (`public/textures/`):** `floor-oak.png` (+ normal/rough),
+`floor-stone.png`, `wall-limewash.png` (+ normal/rough). New floor looks
+(carpet / marble / polished-concrete) do NOT have a bundled texture yet — this spec
+flags them as **"needs texture or procedural fallback"** so they're honest about the
+asset gap. `floor-oak` and `floor-stone` are the only two floor albedos that exist.
+
+**Lighting rig shape today (lines ~895–939):** `AmbientLight` + `HemisphereLight`
+(both ~0.42) + a shadow-casting `DirectionalLight` KEY (1.05, warm) + a cool no-shadow
+`DirectionalLight` FILL (0.30) + a warm `DirectionalLight` RIM (0.22) + a
+`SpotLight` picture-light (0.55) grazing the feature wall. `MODES` already scales
+these per view (`Gallery` / `Evening`). Each record below re-tunes those five channels
+plus adds the fixture's own emissive.
+
+**Ceiling fixtures are emissive primitives, not real area lights** (matches the
+existing emissive cove-strip approach at lines ~726–754 — emissive `MeshBasicMaterial`
++ optional additive-glow quad = self-lit, zero light cost). A record's *fixture*
+gives the visible object; the *rig* gives the actual illumination. Where a fixture
+should also throw light (chandelier, pendant), the record adds one cheap `PointLight`
+co-located with the emissive mesh.
+
+---
+
+## 1. BEDROOM
+
+Intimate, warm, low-key. The pattern reads as a **behind-the-bed accent wall** — the
+classic residential wallcovering placement.
+
+| Field | Value |
+|---|---|
+| **Geometry (W×D×H)** | `4.6 × 5.0 × 2.7` m — smaller & lower than the square default; a real bedroom, cozier ceiling. |
+| **Clad surfaces** | **Back wall only** (`side:'back'`, the headboard wall) gets the pattern. Left/right/front = painted. |
+| **Painted surfaces** | Left/right/front walls = soft warm off-white (`MAT.wall` tinted, or a flat `0xece4d6`). |
+| **Floor** | Warm oak — `floor-oak.png` (exists), repeat ~2.0. Add a soft area rug under the bed (see furniture) so it doesn't read cold. |
+| **Ceiling** | Flat matte warm off-white (`0xf2eee5`, like current). |
+| **Ceiling fixture** | **Single pendant** dropped over the bed centerline — a slim brass stem (`CylinderGeometry` `MAT.chrome`) + a linen drum shade (`CylinderGeometry`, emissive `0xffe6c0` ~0.5). Co-locate one warm `PointLight` inside it. Position `(0, H-0.55, -D/2+1.4)`. |
+| **Mood** | Warm-dim. |
+
+**Furniture set + layout** (room-center origin, faces `-z`, back wall = headboard):
+- **Bed** — platform: `BoxGeometry(1.8, 0.35, 2.1)` mattress on a low walnut frame
+ (`MAT.wood`). Headboard: `BoxGeometry(1.9, 1.0, 0.12)` against the back wall.
+ Position bed center `(0, 0.35, -D/2 + 1.35)`, headboard `(0, 0.9, -D/2 + 0.35)`,
+ rotation `y=0` (headboard flush to the clad wall). Duvet = a slightly larger soft
+ box in bouclé cream (`0xe8e0d0`).
+- **Nightstands** ×2 — `BoxGeometry(0.5, 0.5, 0.4)` walnut, one each side of the bed:
+ `(-1.15, 0.25, -D/2 + 0.55)` and `(+1.15, 0.25, -D/2 + 0.55)`. A small emissive
+ table-lamp glow on each (echoes the proto lamp shade).
+- **Dresser** — `BoxGeometry(1.4, 0.85, 0.5)` walnut against the **left** wall:
+ `(-W/2 + 0.3, 0.42, 0.4)`, rotation `y=π/2`. Optional framed mirror above it.
+- **Area rug** — `CircleGeometry` or rounded box, `2.6 × 1.8`, muted wool
+ (`0xb9a88c`), under the foot of the bed `(0, 0.012, -D/2 + 2.6)`.
+
+**Lighting rig** (warm-dim):
+- Ambient `0xfff0dd` @ **0.30** (lower than default — intimate).
+- Hemisphere `0xfff1e0 / 0xe4d8c4` @ **0.28**.
+- KEY DirectionalLight `0xfff2e0` @ **0.75**, from `(1.6, H+0.8, 1.6)` targeting the
+ bed — soft, shadow on, wide PCF radius (~4).
+- FILL cool `0xdfe6ff` @ **0.18** (barely lifts shadows).
+- Pendant `PointLight` `0xffcaa0` @ **0.6**, range ~5, at the fixture position — the
+ dominant *felt* source, pooling warm light on the accent wall + bed.
+- No hard RIM; keep contrast gentle.
+
+**Camera framing:** stand near the foot of the bed looking at the headboard/accent
+wall. `position (0, 1.55, D/2 - 1.4)`, `lookAt (0, 1.4, -D/2 + 0.4)`, fov 55. Frames
+the clad back wall behind the bed with the pendant in the upper third.
+
+**Furniture-style-matching hook:** shift the **duvet + rug + one accent throw** to a
+tone drawn from the product. Read `color_bucket`; if warm (red/orange/gold/brown) push
+the duvet toward warm cream + a terracotta throw; if cool (blue/green/purple) push the
+rug toward greige + a slate throw. Bed frame + nightstands stay walnut (neutral
+anchor) so only the *soft goods* chase the hue — 60-30-10: walls (pattern) = 60,
+walnut = 30, textile accent tuned to `hue` = 10.
+
+---
+
+## 2. OFFICE
+
+Neutral-bright, crisp, productive. Pattern on the **wall behind the desk** (the
+video-call / focal wall).
+
+| Field | Value |
+|---|---|
+| **Geometry (W×D×H)** | `4.8 × 5.2 × 2.8` m — compact private office. |
+| **Clad surfaces** | **Back wall only** (the wall the desk faces away from / the focal wall behind the seated person). Others painted. |
+| **Painted surfaces** | Left/right/front = cool neutral white (`0xf1f1ee`). |
+| **Floor** | Polished concrete **(needs texture or procedural fallback — no `floor-concrete.png` yet)**; interim = `floor-stone.png` (exists) at low warmth, or a flat `MeshStandardMaterial(0x9a9a98, roughness 0.35)`. |
+| **Ceiling** | Flat off-white with **recessed / track grid** cue. |
+| **Ceiling fixture** | **Recessed troffers OR a track**: two emissive linear strips (reuse the existing cove-strip pattern, but cooler `0xf6f8ff` and brighter) running front→back at `x = ±W*0.22`, plus optional 3 small emissive downlight discs over the desk. Neutral-white emissive. |
+| **Mood** | Neutral-bright (highest overall illumination of the five). |
+
+**Furniture set + layout** (desk faces the viewer / `+z`, so the clad back wall is
+behind the seat):
+- **Desk** — top `BoxGeometry(1.6, 0.05, 0.75)` walnut (`MAT.wood`) at height 0.74,
+ two panel legs. Center `(0, 0.74, -D/2 + 1.1)`, rotation `y=0` (long edge parallel
+ to back wall). A slim emissive monitor plane + a couple swatch/paper boxes on top.
+- **Office chair** — swivel: `CylinderGeometry` 5-star base + gas column + a
+ `BoxGeometry` seat + curved back, cognac leather (`MAT.chair`). Position between
+ desk and back wall `(0, 0, -D/2 + 0.55)`, rotation `y=π` (faces `+z`, back to the
+ clad wall). Contact shadow under the base.
+- **Shelving** — reuse `buildBookShelf(x, z, rot, unitW)` verbatim. Place against the
+ **right** wall: `buildBookShelf(W/2 - 0.2, 0, -Math.PI/2, 2.4)`. `MAT.books[8]` give
+ color. Optionally a second unit on the left for symmetry.
+- Optional **guest chair** — one bouclé armchair (reuse the nook chair builder) in the
+ near corner `(W/2 - 0.9, 0, D/2 - 1.2)`, angled toward the desk.
+
+**Lighting rig** (neutral-bright):
+- Ambient `0xffffff` @ **0.5**.
+- Hemisphere `0xf4f6ff / 0xdedad2` @ **0.45**.
+- KEY DirectionalLight near-white `0xfff8f2` @ **1.0**, from `(2.0, H+1.0, 2.0)`,
+ shadow on, medium-soft radius (~2.5) — crisper contact than bedroom.
+- FILL cool `0xeef2ff` @ **0.35** — office fills are stronger so the room reads even
+ and flat-lit, no drama.
+- Recessed/track emissive strips carry the ceiling read; add one faint `PointLight`
+ `0xf6f8ff` @ 0.25 over the desk for a subtle pool.
+
+**Camera framing:** from the doorway looking across the desk at the clad focal wall.
+`position (0, 1.6, D/2 - 1.0)`, `lookAt (0, 1.35, -D/2 + 0.3)`, fov 58. Desk in mid-
+ground, pattern fills the back wall.
+
+**Furniture-style-matching hook:** the **desk + shelving stay walnut/neutral**
+(office reads professional, not costume-y). Chase the hue only in the **chair
+upholstery + the book-block colors**: if the product `color_bucket` is cool, bias the
+chair to a slate/charcoal fabric and re-weight `MAT.books` toward blues/greens; if
+warm, keep cognac leather and warm the book palette. Keep saturation *low* here — an
+office palette should be muted so the pattern is the only saturated element.
+
+---
+
+## 3. HOTEL LOBBY
+
+Dramatic, generous, double-height. This is the **large** preset. Pattern on a **tall
+feature wall behind the reception desk** — the money shot.
+
+| Field | Value |
+|---|---|
+| **Geometry (W×D×H)** | `8.0 × 8.0 × 4.2` m — noticeably larger + taller than the default; a lobby needs volume and a double-height feature wall. |
+| **Clad surfaces** | **Back wall (full height, behind reception)** is the hero clad surface. Optionally **also** clad the **front wall** as a secondary accent for a wrapped, enveloping feel. Left/right painted. |
+| **Painted surfaces** | Left/right = warm stone plaster (`MAT.wall`), lets the feature wall dominate. |
+| **Floor** | Polished stone / marble — `floor-stone.png` (exists) at ~2.4 repeat, high anisotropy for a reflective sheen; nudge `roughness` down (~0.3) for a lobby polish. True marble veining = **would benefit from a marble texture (not bundled)**; `floor-stone` is the honest interim. |
+| **Ceiling** | Coffered / recessed-cove; taller so it reads grand. |
+| **Ceiling fixture** | **Chandelier** — the statement piece. A brass ring/tiered cluster of small emissive spheres (`SphereGeometry`, emissive `0xffe6bd`) hung on a brass stem, centered over the seating group `(0, H-1.1, 0.2)`. Co-locate one warm `PointLight` @ ~0.9 range ~10. This is the one preset where the fixture is a focal object, not just a cue. |
+| **Mood** | Dramatic (highest contrast — bright feature wall, pooled warm seating, darker perimeter). |
+
+**Furniture set + layout** (larger room, origin center, reception against the clad
+back wall):
+- **Reception desk** — a long low curved/straight counter: `BoxGeometry(3.0, 1.1,
+ 0.7)` walnut front + a stone-cap top, against the back wall `(0, 0.55, -D/2 + 0.9)`,
+ rotation `y=0`. A backlit logo plane can sit on the clad wall behind it.
+- **Lobby sofa** — reuse the proto `sofa()` shape (2.2-wide base + back + arms +
+ cushions, `v9-walkin.html` lines ~338–351), scaled up or paired. Place a **facing
+ pair** framing a coffee table in the room center: sofa A `(0, 0, 1.2)` rot `y=π`
+ (faces `-z` toward reception), sofa B `(0, 0, -1.2)` rot `y=0`. Or an L-arrangement
+ in the near-right quadrant.
+- **Coffee table** — round stone/brass: `CylinderGeometry(0.6, 0.6, 0.4)` top on a
+ brass drum base, center `(0, 0.4, 0)`.
+- **Accents** — two olive/fig planters (`buildOliveTree`) flanking the reception
+ `(-2.4, 0, -D/2 + 0.8)` and `(+2.4, 0, -D/2 + 0.8)`; an area rug under the seating
+ group `(0, 0.012, 0)` ~4×3.
+- Optional **luggage bench** or pair of accent stools near the front wall.
+
+**Lighting rig** (dramatic):
+- Ambient `0x2a2620` @ **0.30** (low base = lets the pools read).
+- Hemisphere `0x4a4436 / 0x1a1712` @ **0.25**.
+- KEY DirectionalLight warm `0xfff1da` @ **1.15** grazing the feature wall from
+ `(3.0, H+1.5, 3.0)`, shadow on, wide radius — the hero-wall wash.
+- FILL warm-low `0xffd9a8` @ **0.20**.
+- RIM `0xffe6bd` @ **0.30** behind the reception to separate desk silhouette from the
+ clad wall.
+- Chandelier `PointLight` warm @ **0.9** pools the seating; a second `SpotLight`
+ (reuse picture-light params) accents the feature wall behind reception. High
+ key-to-fill ratio = the "dramatic" signature.
+
+**Camera framing:** wide establishing shot from near the front wall, low-ish, taking
+in seating foreground + reception + the tall clad feature wall + chandelier.
+`position (0.8, 1.6, D/2 - 1.5)`, `lookAt (0, 1.8, -D/2 + 0.9)`, **fov 65** (wider to
+capture the volume). This is the shot that sells the pattern at architectural scale.
+
+**Furniture-style-matching hook:** lobby is where the palette shift is boldest. Read
+`color_bucket` and set a **coordinated accent family** across sofa upholstery + rug +
+coffee-table accents: warm bucket → camel/cognac sofas, oxblood rug accent, brass
+warm; cool bucket → dove-grey sofas, teal/ink rug, cooler brass. Reception desk stays
+walnut+stone (permanent anchor). Because the room is big, tie the accent to the
+product's *dominant* `hue` and use a complementary for the rug so the seating group
+reads as intentionally styled to the wallcovering.
+
+---
+
+## 4. LIVING ROOM
+
+Warm, lived-in, residential. Ports the proto `v9-walkin.html` furnished scene
+directly. Pattern on the **sofa/back feature wall** (chimney-breast placement).
+
+| Field | Value |
+|---|---|
+| **Geometry (W×D×H)** | `6.10 × 6.10 × 2.9` m — the **default square** (this preset is the closest to the existing room, so it reuses the canonical dims). |
+| **Clad surfaces** | **Back wall** (behind the sofa) is clad. Optionally clad the flanking segment only, treating it as a chimney breast; simplest = full back wall. Others painted. |
+| **Painted surfaces** | Left/right/front = warm limewash (`MAT.wall`, current default). |
+| **Floor** | Warm oak (`floor-oak.png`, exists) + a large round wool rug under the seating (the proto already builds one). |
+| **Ceiling** | Flat warm off-white with slim cove strips (reuse the two existing emissive strips exactly). |
+| **Ceiling fixture** | **Flush / semi-flush mount** — a low warm dome: `SphereGeometry` hemisphere emissive `0xffe6c0` on a slim brass ring, centered `(0, H-0.18, 0)`. Understated (living rooms rarely have statement ceiling lights); the **floor lamp** does the mood work. |
+| **Mood** | Warm (warm-neutral, brighter than bedroom, softer than office). |
+
+**Furniture set + layout** (ported from `v9-walkin.html` `sofa()` IIFE, coords already
+in this frame — sofa against back wall facing `+z`/the viewer):
+- **Sofa** — proto build: base `BoxGeometry(2.2, 0.45, 0.95)`, back `(2.2,0.7,0.22)`,
+ seat cushion, two arms. Position `(0, 0, -D/2 + 0.78)` against the clad back wall,
+ rotation `y=0`. Cream (`0xcfc4b0`). Contact shadow `(0, -D/2+1.08)`.
+- **Coffee table** — add in front of the sofa (the proto omits one): round walnut
+ `CylinderGeometry(0.5, 0.5, 0.4)` top on a pedestal, `(0, 0.4, -D/2 + 1.9)`.
+- **Rug** — proto round rug: `CircleGeometry(1.7)` wool `0xb9a88c`, `(0, 0.012, -D/2 +
+ 1.7)`, receives shadow.
+- **Floor lamp** — proto lamp: pole `CylinderGeometry(0.02,0.02,1.5)` + emissive drum
+ shade `0xffe6c0` @ 0.6, at `(W*0.32, ·, -D*0.30)`. This is the warm key source's
+ visible body.
+- Optional **accent armchair** (reuse nook bouclé chair) angled in the near-left
+ corner `(-W*0.30, 0, D*0.20)` facing the sofa, and the olive planter (`buildOliveTree`)
+ in a back corner.
+
+**Lighting rig** (warm — closely mirrors the current default rig, which was tuned for
+exactly this warm residential feel):
+- Ambient `0xffe8cf` @ **0.30**.
+- Hemisphere `0xfff3e0 / 0x3a2f26` @ **0.40**.
+- KEY DirectionalLight `0xfff1da` @ **1.0** from `(2.4, H+1.2, 2.2)` targeting the sofa
+ wall, shadow on, soft radius.
+- FILL cool `0xdfe6ff` @ **0.25**.
+- Floor-lamp `PointLight` `0xffcaa0` @ **0.55**, range ~9, at the lamp shade — the
+ cozy corner glow that makes the room read lived-in (proto value).
+- Optional faint day-spill `PointLight` `0xfff4e0` @ 0.4 from a window direction if a
+ window plane is added.
+
+**Camera framing:** seated-guest eyeline looking at the sofa + clad wall.
+`position (0, 1.5, D/2 - 1.6)`, `lookAt (0, 1.3, -D/2 + 0.6)`, fov 58. Sofa +
+coffee table foreground, pattern fills the wall behind. (Very close to the proto's
+own default camera.)
+
+**Furniture-style-matching hook:** classic 60-30-10 residential styling. Walls
+(pattern) = 60; sofa neutral cream = 30 anchor; **throw pillows + rug border + lamp-
+shade tone = the 10**, tuned to `hue`. Warm `color_bucket` → ochre/rust pillows, warm
+rug; cool → indigo/sage pillows, greige rug. Sofa itself stays cream so any pattern
+sits against a neutral seat — this is the most "interior-designer-correct" of the five
+because it directly mirrors how a real designer would place a statement wallcovering
+in a living room.
+
+---
+
+## 5. ART GALLERY
+
+High-contrast, minimal, tall. The existing white-box arc room is spiritually a
+gallery, but this preset is the *black-box* gallery (see `v12-gallery-noir.html`):
+dark walls, spot-lit **single feature wall**, sculptural minimalism. Pattern is
+presented as *the artwork*.
+
+| Field | Value |
+|---|---|
+| **Geometry (W×D×H)** | `7.0 × 7.0 × 3.8` m — larger footprint and **noticeably taller** (gallery volume + breathing room around the feature wall). |
+| **Clad surfaces** | **One feature wall only** (`side:'back'`) is clad — the pattern is the exhibited piece. |
+| **Painted surfaces** | Left/right/front = near-black gallery wall (`0x161a22` matte, per the noir proto) — deliberately dark so the lit feature wall pops. |
+| **Floor** | Polished concrete **(needs texture — interim `floor-stone.png` desaturated, or flat `0x2a2a2c` roughness 0.4)**. Gallery floors are matte dark; no rug. |
+| **Ceiling** | Dark ceiling (`0x14161c`) so it disappears — only the track spots read. |
+| **Ceiling fixture** | **Track spots** — a slim brass/black track rail (`BoxGeometry`) across the ceiling parallel to the feature wall at `(0, H-0.12, -D/2 + 1.4)`, carrying 3–5 small barrel spot heads (`CylinderGeometry` `MAT.dark`), each with a real `SpotLight` aimed at a section of the clad wall. These are the ONLY meaningful lights. |
+| **Mood** | High-contrast (dark room, bright raked feature wall — the strongest key-to-ambient ratio of all five). |
+
+**Furniture set + layout** (sparse, sculptural — a gallery is mostly empty):
+- **Benches** ×1–2 — low minimalist slab: `BoxGeometry(1.6, 0.10, 0.45)` on two block
+ legs, dark oak or stone. Centered facing the feature wall `(0, 0.42, 1.2)`, rotation
+ `y=0`. Optional second bench `(0, 0.42, 2.2)`.
+- **Pedestals** ×2 — white/stone plinths `BoxGeometry(0.4, 1.1, 0.4)` flanking the
+ view axis `(-2.0, 0.55, -0.5)` and `(+2.0, 0.55, -0.5)`, each carrying a small
+ sculptural object (a turned form / a folded-fabric swatch display) so the room isn't
+ empty.
+- **Framed art** ×2 — on the **left** wall, two framed pieces (`BoxGeometry` frame
+ `MAT.frame` + an image plane) at eye height `(-W/2 + 0.05, 1.5, -1.0)` and
+ `(-W/2 + 0.05, 1.5, 1.0)`, rotation `y=π/2` — these can display *other* colorways of
+ the same pattern (a gallery wall of the collection).
+- A discreet wall label plaque beside the feature wall (small emissive/canvas plane)
+ with the pattern name — mirrors the DW sign approach.
+
+**Lighting rig** (high-contrast):
+- Ambient dark `0x161a22` @ **0.42** (per noir proto — this is a *dark* ambient, it
+ sets the black-box base without lifting it to grey).
+- Hemisphere — **omit or ~0.05** (galleries kill fill bounce for pure spot contrast).
+- KEY: replace the broad directional key with the **track SpotLights**. Each spot
+ `0xffe6bd`, intensity ~**1.4**, tight cone (`Math.PI/7.5`), penumbra 0.45, targeting
+ a band of the feature wall (per noir proto `spot` params, but ON). Shadow on the
+ primary center spot only (cost control).
+- FILL cool `0x6f7d96` @ **0.22** from the left (barely models the benches/pedestals).
+- RIM warm `0xffd9a0` @ **0.30** from behind-right to edge-light the pedestals.
+- Net effect: brilliant raked feature wall, near-black surroundings, sculptural pools
+ on the benches. **Do not** brighten the ambient — the contrast IS the aesthetic.
+
+**Camera framing:** centered, straight-on, reverent — the pattern as artwork.
+`position (0, 1.55, D/2 - 1.8)`, `lookAt (0, 1.6, -D/2 + 0.05)`, fov 52 (slightly
+tighter/longer lens = flatter, more "photographed artwork" framing). Bench in
+foreground, clad wall filling the frame under the track spots.
+
+**Furniture-style-matching hook:** the gallery deliberately does **not** color-match
+the furniture — benches/pedestals/floor stay achromatic (black/white/stone) so the
+pattern's `hue` is the *only* color in the room (maximum contrast, museum-neutral).
+The one place the hook applies: **tint the track-spot color temperature** slightly
+toward or away from the pattern's warmth (warm `color_bucket` → keep `0xffe6bd`; cool
+bucket → shift spots toward a neutral `0xfff4ec` so cool patterns don't go muddy), and
+optionally set the two **framed-art side pieces** to complementary colorways of the
+same SKU. Everything else stays monochrome by design.
+
+---
+
+## 6. Cross-cutting notes for the implementer
+
+- **Reuse before rebuild.** BEDROOM/OFFICE lean on `buildBookShelf` + the nook chair
+ + `buildOliveTree`; LIVING ROOM ports the proto `sofa()` almost verbatim; GALLERY
+ reuses the noir-proto spot params. Only the bed, desk, reception desk, chandelier,
+ and pedestals are genuinely new primitive builds.
+- **Cladding is a data flip, not new geometry.** Every preset builds all 4 walls as
+ `roomWalls[]` entries (as today); the record's "clad surfaces" column just selects
+ which entries receive the pattern `.map` on pattern-select and which keep their
+ `origMat` paint. This preserves the existing "click clads the wall" mechanism.
+- **Floor honesty.** Only `floor-oak` and `floor-stone` textures exist. OFFICE
+ (concrete), LOBBY (marble), GALLERY (dark concrete) are flagged as needing a texture
+ or a flat/procedural `MeshStandardMaterial` fallback — don't ship a preset claiming
+ a marble floor it can't render.
+- **Fixtures = emissive primitive (+ optional co-located PointLight).** Follows the
+ existing emissive cove-strip convention (zero shadow/light cost) so adding five
+ ceiling fixtures doesn't blow the FPS budget. Only chandelier / pendant / floor lamp
+ / track spots add real lights, and those are single cheap `PointLight` /
+ `SpotLight`s.
+- **Camera poses** are given as `position` + `lookAt` + `fov`; a future `ROOM_TYPES`
+ consumer would feed these into the same camera the `MODES` registry already drives.
+- **Palette hook is uniform in shape:** every record reads `product.color_bucket`
+ (coarse warm/cool/neutral) and `product.hue` (fine), then shifts only the *soft
+ goods / accents* (never the wood/stone/leather anchors), following 60-30-10 with the
+ pattern as the 60. GALLERY is the intentional exception (stays monochrome).
+
+---
+
+## 7. JS-shaped `ROOM_TYPES` sketch (drop-in parallel to THEMES / MODES)
+
+> Sketch only — illustrative literal, not wired to anything. Positions are in the
+> room-center frame (viewer faces `-z`, back wall at `z = -D/2`). `clad` lists the
+> `roomWalls[].side` values that receive the pattern; all other sides stay painted.
+> `fixture` / `furniture` entries are declarative descriptors a future builder maps to
+> the primitive helpers. Colors are hex ints to match `initMaterials`.
+
+```js
+// Parallel to THEMES / MODES. DESIGN SKETCH — not implemented.
+const ROOM_TYPES = {
+ bedroom: {
+ label: 'Bedroom',
+ room: { width: 4.6, depth: 5.0, height: 2.7 },
+ clad: ['back'], // headboard accent wall
+ paint: { color: 0xece4d6 }, // warm off-white
+ floor: { tex: 'floor-oak', repeat: 2.0 },
+ ceiling: { color: 0xf2eee5 },
+ fixture: { type: 'pendant', pos: [0, 'H-0.55', -1.1], emissive: 0xffe6c0,
+ light: { kind: 'point', color: 0xffcaa0, intensity: 0.6, range: 5 } },
+ furniture: [
+ { type: 'bed', pos: [0, 0.35, -1.15], rot: 0, size: [1.8, 0.35, 2.1] },
+ { type: 'nightstand', pos: [-1.15, 0.25, -1.95] },
+ { type: 'nightstand', pos: [ 1.15, 0.25, -1.95] },
+ { type: 'dresser', pos: ['-W/2+0.3', 0.42, 0.4], rot: 'PI/2', size: [1.4, 0.85, 0.5] },
+ { type: 'rug', pos: [0, 0.012, 0.0], size: [2.6, 1.8], color: 0xb9a88c }
+ ],
+ lights: { ambient: [0xfff0dd, 0.30], hemi: [0xfff1e0, 0xe4d8c4, 0.28],
+ key: { color: 0xfff2e0, intensity: 0.75, pos: [1.6, 'H+0.8', 1.6], shadow: true, radius: 4 },
+ fill:{ color: 0xdfe6ff, intensity: 0.18 } },
+ camera: { pos: [0, 1.55, 1.1], lookAt: [0, 1.4, -2.1], fov: 55 },
+ mood: 'warm-dim',
+ paletteHook: { anchor: ['bed', 'nightstand', 'dresser'], accent: ['rug', 'duvet', 'throw'] }
+ },
+
+ office: {
+ label: 'Office',
+ room: { width: 4.8, depth: 5.2, height: 2.8 },
+ clad: ['back'], // focal wall behind the seat
+ paint: { color: 0xf1f1ee }, // cool neutral white
+ floor: { tex: 'floor-stone', repeat: 2.2, fallback: { color: 0x9a9a98, roughness: 0.35 }, note: 'concrete pending' },
+ ceiling: { color: 0xf4f4f0, treatment: 'recessed-track' },
+ fixture: { type: 'track-recessed', strips: [['-W*0.22', 'H-0.02', 0], ['W*0.22', 'H-0.02', 0]],
+ emissive: 0xf6f8ff, downlights: 3,
+ light: { kind: 'point', color: 0xf6f8ff, intensity: 0.25 } },
+ furniture: [
+ { type: 'desk', pos: [0, 0.74, -1.5], rot: 0, size: [1.6, 0.05, 0.75], mat: 'wood' },
+ { type: 'office-chair', pos: [0, 0, -2.05], rot: 'PI', mat: 'chair' },
+ { type: 'bookshelf', pos: ['W/2-0.2', 0, 0], rot: '-PI/2', unitW: 2.4 }, // reuse buildBookShelf
+ { type: 'guest-chair', pos: ['W/2-0.9', 0, 1.2], rot: 2.6, mat: 'boucle' }
+ ],
+ lights: { ambient: [0xffffff, 0.50], hemi: [0xf4f6ff, 0xdedad2, 0.45],
+ key: { color: 0xfff8f2, intensity: 1.0, pos: [2.0, 'H+1.0', 2.0], shadow: true, radius: 2.5 },
+ fill:{ color: 0xeef2ff, intensity: 0.35 } },
+ camera: { pos: [0, 1.6, 1.6], lookAt: [0, 1.35, -2.3], fov: 58 },
+ mood: 'neutral-bright',
+ paletteHook: { anchor: ['desk', 'bookshelf'], accent: ['office-chair', 'books'], saturation: 'low' }
+ },
+
+ lobby: {
+ label: 'Hotel Lobby',
+ room: { width: 8.0, depth: 8.0, height: 4.2 }, // large + tall
+ clad: ['back'], // + optional 'front' for a wrap
+ paint: { mat: 'wall' }, // warm stone plaster
+ floor: { tex: 'floor-stone', repeat: 2.4, roughness: 0.3, note: 'marble pending' },
+ ceiling: { color: 0xece6da, treatment: 'coffered-cove' },
+ fixture: { type: 'chandelier', pos: [0, 'H-1.1', 0.2], emissive: 0xffe6bd,
+ light: { kind: 'point', color: 0xffe6bd, intensity: 0.9, range: 10 } },
+ furniture: [
+ { type: 'reception', pos: [0, 0.55, -3.1], rot: 0, size: [3.0, 1.1, 0.7], mat: 'wood' },
+ { type: 'sofa', pos: [0, 0, 1.2], rot: 'PI' }, // proto sofa()
+ { type: 'sofa', pos: [0, 0, -1.2], rot: 0 },
+ { type: 'coffee-table', pos: [0, 0.4, 0], r: 0.6 },
+ { type: 'olive', pos: [-2.4, 0, -3.2] }, // buildOliveTree
+ { type: 'olive', pos: [ 2.4, 0, -3.2] },
+ { type: 'rug', pos: [0, 0.012, 0], size: [4.0, 3.0] }
+ ],
+ lights: { ambient: [0x2a2620, 0.30], hemi: [0x4a4436, 0x1a1712, 0.25],
+ key: { color: 0xfff1da, intensity: 1.15, pos: [3.0, 'H+1.5', 3.0], shadow: true, radius: 4 },
+ fill:{ color: 0xffd9a8, intensity: 0.20 },
+ rim: { color: 0xffe6bd, intensity: 0.30 },
+ accentSpot: { color: 0xffe6bd, intensity: 0.6, target: 'featureWall' } },
+ camera: { pos: [0.8, 1.6, 2.5], lookAt: [0, 1.8, -3.1], fov: 65 },
+ mood: 'dramatic',
+ paletteHook: { anchor: ['reception'], accent: ['sofa', 'rug'], bold: true, complementaryRug: true }
+ },
+
+ living: {
+ label: 'Living Room',
+ room: { width: 6.10, depth: 6.10, height: 2.9 }, // canonical default dims
+ clad: ['back'], // chimney-breast / sofa wall
+ paint: { mat: 'wall' }, // warm limewash (current)
+ floor: { tex: 'floor-oak', repeat: 2.4 },
+ ceiling: { color: 0xf2eee5, coveStrips: true }, // reuse existing emissive strips
+ fixture: { type: 'flush-mount', pos: [0, 'H-0.18', 0], emissive: 0xffe6c0 },
+ furniture: [
+ { type: 'sofa', pos: [0, 0, -2.27], rot: 0, color: 0xcfc4b0 }, // proto sofa(): -D/2+0.78
+ { type: 'coffee-table', pos: [0, 0.4, -1.15], r: 0.5, mat: 'wood' },
+ { type: 'rug', pos: [0, 0.012, -1.35], r: 1.7, color: 0xb9a88c }, // proto round rug
+ { type: 'floor-lamp', pos: ['W*0.32', 0, '-D*0.30'], emissive: 0xffe6c0 }, // proto lamp
+ { type: 'armchair', pos: ['-W*0.30', 0, 'D*0.20'], rot: 2.4, mat: 'boucle' },
+ { type: 'olive', pos: [-2.2, 0, -2.2] }
+ ],
+ lights: { ambient: [0xffe8cf, 0.30], hemi: [0xfff3e0, 0x3a2f26, 0.40],
+ key: { color: 0xfff1da, intensity: 1.0, pos: [2.4, 'H+1.2', 2.2], shadow: true, radius: 3.5 },
+ fill:{ color: 0xdfe6ff, intensity: 0.25 },
+ lampGlow: { kind: 'point', color: 0xffcaa0, intensity: 0.55, range: 9, at: 'floor-lamp' } },
+ camera: { pos: [0, 1.5, 1.45], lookAt: [0, 1.3, -2.45], fov: 58 },
+ mood: 'warm',
+ paletteHook: { anchor: ['sofa'], accent: ['pillows', 'rug', 'lampshade'], rule: '60-30-10' }
+ },
+
+ gallery: {
+ label: 'Art Gallery',
+ room: { width: 7.0, depth: 7.0, height: 3.8 }, // large + tall
+ clad: ['back'], // single feature wall = the artwork
+ paint: { color: 0x161a22 }, // near-black gallery wall (noir proto)
+ floor: { tex: 'floor-stone', desaturate: true, fallback: { color: 0x2a2a2c, roughness: 0.4 }, note: 'dark concrete pending' },
+ ceiling: { color: 0x14161c },
+ fixture: { type: 'track-spots', rail: [0, 'H-0.12', -2.1], heads: 4, mat: 'dark',
+ spot: { color: 0xffe6bd, intensity: 1.4, angle: 'PI/7.5', penumbra: 0.45, target: 'featureWall' } },
+ furniture: [
+ { type: 'bench', pos: [0, 0.42, 1.2], rot: 0, size: [1.6, 0.10, 0.45] },
+ { type: 'bench', pos: [0, 0.42, 2.2], rot: 0, size: [1.6, 0.10, 0.45] },
+ { type: 'pedestal', pos: [-2.0, 0.55, -0.5], size: [0.4, 1.1, 0.4] },
+ { type: 'pedestal', pos: [ 2.0, 0.55, -0.5], size: [0.4, 1.1, 0.4] },
+ { type: 'framed-art', pos: ['-W/2+0.05', 1.5, -1.0], rot: 'PI/2', showsColorway: true },
+ { type: 'framed-art', pos: ['-W/2+0.05', 1.5, 1.0], rot: 'PI/2', showsColorway: true },
+ { type: 'wall-label', pos: [1.2, 1.4, -3.4] }
+ ],
+ lights: { ambient: [0x161a22, 0.42], hemi: [0x161a22, 0x0a0c10, 0.05],
+ key: 'track-spots', // the spots ARE the key
+ fill:{ color: 0x6f7d96, intensity: 0.22 },
+ rim: { color: 0xffd9a0, intensity: 0.30 } },
+ camera: { pos: [0, 1.55, 1.7], lookAt: [0, 1.6, -3.45], fov: 52 },
+ mood: 'high-contrast',
+ paletteHook: { monochromeFurniture: true, tune: 'spot-temperature', sidePiecesShowComplementaryColorway: true }
+ }
+};
+```
← 6c84fb0 add boot-walk + carousel screen-recording harnesses
·
back to Quadrille Showroom
·
showroom P1: remove angled/orbit/topdown, boot=walk-through- bc32b4a →