[object Object]

← back to Quadrille Showroom

V1 establishing arc (matches pj-dallas-showroom.png) + V2 step-driven conveyor + rail layout

5954106c4c41ae639622c48e7a7f550bded6fb4f · 2026-06-28 07:54:28 -0700 · Steve

- V1: wide establishing shot (high front-right, FOV 64) showing the sliver-packed
  corner arc + consultation nook + warm oak floor like the reference photo, instead of
  isolating one board. restoreBoards()+revertWalls()+open middle; boot defers to 1800ms
  so it wins the race vs the guided auto-focus (which was re-isolating to 1 board).
- V2 conveyor: real step controller (NOT auto-spin) — user dead-centre+stationary, the
  RACK yaws so each product rotates INTO centre; ArrowRight/Left + guided Next/Prev step
  one board at a time (capture-phase intercept while V2 active only), eased anim, idle =
  zero shadow rebakes. Verified: ArrowRight steps fwd, ArrowLeft steps back.
- setVersion now calls the prior version's exit() (conveyor key/click/frame cleanup).
- Rail layout: anchored top-right + max-height capped so it never collides with the
  bottom-right Chosen tray (was overlapping at 1600x900); collapse transform fixed.
- test-versions samples steady-state FPS (after settle) — all 10 versions hold 72fps;
  earlier sub-50 reads were camera-fly/texture-upload settling frames. 0 errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 5954106c4c41ae639622c48e7a7f550bded6fb4f
Author: Steve <steve@designerwallcoverings.com>
Date:   Sun Jun 28 07:54:28 2026 -0700

    V1 establishing arc (matches pj-dallas-showroom.png) + V2 step-driven conveyor + rail layout
    
    - V1: wide establishing shot (high front-right, FOV 64) showing the sliver-packed
      corner arc + consultation nook + warm oak floor like the reference photo, instead of
      isolating one board. restoreBoards()+revertWalls()+open middle; boot defers to 1800ms
      so it wins the race vs the guided auto-focus (which was re-isolating to 1 board).
    - V2 conveyor: real step controller (NOT auto-spin) — user dead-centre+stationary, the
      RACK yaws so each product rotates INTO centre; ArrowRight/Left + guided Next/Prev step
      one board at a time (capture-phase intercept while V2 active only), eased anim, idle =
      zero shadow rebakes. Verified: ArrowRight steps fwd, ArrowLeft steps back.
    - setVersion now calls the prior version's exit() (conveyor key/click/frame cleanup).
    - Rail layout: anchored top-right + max-height capped so it never collides with the
      bottom-right Chosen tray (was overlapping at 1600x900); collapse transform fixed.
    - test-versions samples steady-state FPS (after settle) — all 10 versions hold 72fps;
      earlier sub-50 reads were camera-fly/texture-upload settling frames. 0 errors.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/js/rack.js        |  4 +++-
 public/js/showroom.js    | 10 +++++-----
 public/showroom.html     |  4 ++--
 scripts/test-versions.js |  4 +++-
 4 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/public/js/rack.js b/public/js/rack.js
index 7be23f4..70e6b3f 100644
--- a/public/js/rack.js
+++ b/public/js/rack.js
@@ -28,7 +28,9 @@
   // Range chosen so the default (~62) lands on the photo's medium-thin slivers.
   function revealToRake(reveal) {
     const r = Math.max(0, Math.min(100, reveal));
-    return (30 + (r / 100) * 48) * Math.PI / 180;   // 30°..78°
+    // 38°..80° — at the default (~68) boards rake ~67° off dead-on so packed neighbours
+    // occlude all but a thin leading SLIVER, like the PJ fanned sample deck.
+    return (38 + (r / 100) * 42) * Math.PI / 180;
   }
 
   // Centre angle (radians, around the arc centre) of slot i of n boards.
diff --git a/public/js/showroom.js b/public/js/showroom.js
index 32b64d7..b0c9edd 100644
--- a/public/js/showroom.js
+++ b/public/js/showroom.js
@@ -19,9 +19,9 @@ const CONFIG = {
     // The rack is a gentle ARC wrapping a room corner/bay. Boards hang from a curved
     // brass rail, each hinged on its LEFT vertical edge, raked so packed they show only
     // a thin vertical SLIVER of each pattern (occlusion gives the sliver for free).
-    arcRadius: 3.2,                  // radius of the curved rail (m)
-    arcSpanDeg: 104,                 // total angular sweep of the arc (wraps the corner/bay)
-    arcCenter: { x: -0.3, z: -1.1 }, // arc centre in room space (boards face inward → viewer)
+    arcRadius: 3.3,                  // radius of the curved rail (m)
+    arcSpanDeg: 112,                 // total angular sweep of the arc (wraps the corner/bay)
+    arcCenter: { x: -0.3, z: -1.2 }, // arc centre in room space (boards face inward → viewer)
     sliverPitchScale: 1.0            // multiplier on the angular pitch (reveal slider can thin)
   },
   camera: { startPos: { x: 1.8, y: 1.65, z: 3.6 }, fov: 55 }
@@ -38,7 +38,7 @@ let controlsLocked = false, lockedCamPos = null, lockedCamTarget = null, previou
 let cameraAnim = null; // { startPos, endPos, startTarget, endTarget, progress, duration, onComplete }
 
 // Window paging across the full catalog (50 live wings at a time)
-let windowOffset = 0, windowTotal = 0, windowSize = 18;  // boards in the packed arc at once
+let windowOffset = 0, windowTotal = 0, windowSize = 22;  // boards in the packed arc at once
 let currentBrand = 'all', currentSort = 'natural', currentWallGroup = null;
 // Peruse (endless auto-tour) state
 let peruseActive = false, peruseIndex = 0, peruseTimer = null;
@@ -64,7 +64,7 @@ let VIEW_OPEN = (function () {
 // more boards in view). Persisted to localStorage like the Wing°/Boards sliders.
 let REVEAL = (function () {
   const v = parseFloat(localStorage.getItem('qh_reveal'));
-  return (v >= 0 && v <= 100) ? v : 62;   // default ≈ the photo's medium-thin slivers
+  return (v >= 0 && v <= 100) ? v : 70;   // default ≈ the photo's thin slivers (steep rake)
 })();
 
 // SHARED materials — key perf optimization
diff --git a/public/showroom.html b/public/showroom.html
index 0d493d2..f17a8d3 100644
--- a/public/showroom.html
+++ b/public/showroom.html
@@ -286,13 +286,13 @@
         <option value="book">Book</option>
       </select>
       <span id="density-wrap" title="Wings per wall">
-        <span>Boards</span><input type="range" id="density-range" min="8" max="24" step="2" value="18">
+        <span>Boards</span><input type="range" id="density-range" min="10" max="28" step="2" value="22">
       </span>
       <span id="density-wrap" title="Open-board angle (0°=flat, dead-on)">
         <span>Wing&deg;</span><input type="range" id="angle-range" min="0" max="90" step="5" value="8"><span id="angle-val">8&deg;</span>
       </span>
       <span id="density-wrap" title="How much of each closed board's pattern shows — wider edges = fewer boards, thinner slivers = more boards in the arc">
-        <span>Reveal</span><input type="range" id="reveal-range" min="0" max="100" step="5" value="62"><span id="reveal-val">62</span>
+        <span>Reveal</span><input type="range" id="reveal-range" min="0" max="100" step="5" value="70"><span id="reveal-val">70</span>
       </span>
     </div>
 
diff --git a/scripts/test-versions.js b/scripts/test-versions.js
index 43aa988..89caec1 100644
--- a/scripts/test-versions.js
+++ b/scripts/test-versions.js
@@ -68,7 +68,9 @@ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
   const perVersion = {};
   for (const key of order) {
     await page.click(`#ver-rail .ver-chip[data-version="${key}"]`);
-    await sleep(2600); // let the camera fly + the look settle
+    await sleep(3200); // let the camera fly + the look fully settle before sampling steady-state FPS
+    await sampleFps(key + '-warm'); // discard the first read (may catch a settling frame)
+    await sleep(900);
     const fps = await sampleFps(key);
     const cur = await page.evaluate(() => window._versions.current);
     perVersion[key] = { fps, applied: cur === key };

← f75fcc7 Perf + PJ-accurate isolate: hero stays AMID the sliver arc (  ·  back to Quadrille Showroom  ·  Add V1-vs-reference comparison + 10-version contact sheet; d e6c14ec →