The phone can reach the plan, read the disclosure, and see the room
Three things, all on the door people actually open. office.lumbridgecorp.com is a link you send somebody, and a link somebody is sent is opened on a phone. **The plan had no way in.** The stylesheet builds it a whole bottom-sheet layout below 600px — full width above the rail, 38dvh tall, hover-only text dropped — and the only thing that could open it was the `M` key, which on a phone is not a control that is hard to find but a control that does not exist. The comment above that layout says "it is still behind `M`, so it costs nothing until it is asked for", and on a phone it could not be asked for. So there is a button, in the one cluster a thumb reaches, at every width rather than only the narrow ones — a control only a keyboard can reach is a control some people do not have, and that is as true at 1920 as at 390. It is glyph-only, because the `M` hint beside it already carries the word and two controls labelled "plan" in one bar is one too many, and it carries `aria-pressed` for the same reason the chapter buttons do: a toggle that does not look like its state is a button that appears to do nothing on every second press. **The disclosure was behind a hamburger.** "Sample occupancy — these people are invented" lived on `#office-badge` inside `#panel`, and on a phone `#panel` is a sheet that starts closed. The one sentence standing between twenty-five invented people at real desks and a screenshot presented as a staff list was hidden, on the device most likely to take the screenshot. It moves to `#source`, which is where this page already says what on screen is and is not real, is fixed and always drawn, and which the phone stylesheet itself calls "the one caption that is never allowed to be dropped for space". It replaces the city's liveness line while you are inside rather than joining it, because the markers, the sky and the traffic are facts about a board behind you — and "live data" printed over invented colleagues is the exact species of lie that wording was rewritten to stop telling. It also needed a rule of its own: `.source` on a phone is one nowrap ellipsised line, which rendered this as "sample occupancy · these people …", a truncation that removes the only word that mattered. A disclosure cut off mid-clause is worse than none, because it looks like a caption somebody bothered to write and nobody goes looking for the rest. **The room did not fit.** `camera.fov` is vertical, so visible width is `distance * tan(fov/2) * aspect`, and a phone held upright has an aspect near 0.5 against the 16:9 those viewpoints were framed by eye against. At the same distance that is a third of the width: the arrival shot put a thirty-four-metre floor plate off the corner of the screen under a frame full of empty sky. The pack was not wrong and the renderer was not wrong — the number meant something else on that screen. `poseFor` now preserves the width the author framed, which is the thing they were choosing; "everything in this building is somewhere in this frame" is a statement about width, and the extra height a tall screen throws in costs nothing. It only ever pushes back, never pulls in, so a window wider than 16:9 is untouched. The correction scales the whole offset from the target and not the ground distance alone, and that is the entire fix rather than a refinement. Multiplying only the distance does not step back from a shot, it flattens it: 32 m out and 14 m up became ninety-odd metres out and still fourteen up, a near-horizontal squint at the edge of a floor plate stranded near the horizon. I built that first and it was worse than the bug. Checked on an iPhone 13 viewport and at 1920x1080 and 1440x900. Phone: the whole floor centred at the authored angle with people at the benches, the disclosure on two lines and complete, the button tapped open and the plan sheet up with eight rooms named. Desktop 16:9 is pixel-identical — the correction is exactly 1 there — and the console is clean on all three.
This commit is contained in:
@@ -292,16 +292,67 @@ export function createOfficeScene(office: Office, options: OfficeSceneOptions):
|
||||
const floorY = plan.level(viewpoint.levelId)?.floorY ?? 0;
|
||||
const focus = viewpoint.focus;
|
||||
const TARGET_Y = 1.2;
|
||||
/**
|
||||
* The correction scales the whole offset from the target, not the ground
|
||||
* distance alone, and the difference is the entire fix.
|
||||
*
|
||||
* Pushing the camera back while leaving `height` where it was does not step
|
||||
* away from the shot, it *flattens* it: the reference pack's establishing
|
||||
* view is 32 m out and 14 m up, a comfortable look down onto the floor, and
|
||||
* multiplying only the 32 leaves the camera ninety-odd metres away and still
|
||||
* fourteen up — a near-horizontal squint at the edge of a floor plate,
|
||||
* stranded near the horizon with the bottom half of the frame empty. Tried
|
||||
* it; it was worse than the bug. Scaling both preserves the elevation angle
|
||||
* exactly, so the shot is the one the author framed, from further away.
|
||||
*/
|
||||
const k = widthCorrection();
|
||||
const above = Math.max(focus.height, TARGET_Y + 0.3) - TARGET_Y;
|
||||
return {
|
||||
target: new THREE.Vector3(focus.at.x, floorY + TARGET_Y, focus.at.z),
|
||||
position: new THREE.Vector3(
|
||||
focus.at.x + Math.sin(focus.rotation) * focus.distance,
|
||||
floorY + Math.max(focus.height, TARGET_Y + 0.3),
|
||||
focus.at.z + Math.cos(focus.rotation) * focus.distance,
|
||||
focus.at.x + Math.sin(focus.rotation) * focus.distance * k,
|
||||
floorY + TARGET_Y + above * k,
|
||||
focus.at.z + Math.cos(focus.rotation) * focus.distance * k,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The aspect ratio a pack's `distance` was written against.
|
||||
*
|
||||
* Every viewpoint in `lumbridge-hq.ts` was framed by eye in a landscape
|
||||
* browser, which makes 16:9 the honest reading of what those numbers mean —
|
||||
* and this is the only place that reading is written down, so a pack author
|
||||
* who wants to know what `distance: 32` promises can find out.
|
||||
*/
|
||||
const AUTHORED_ASPECT = 16 / 9;
|
||||
|
||||
/**
|
||||
* How much further back a narrow viewport has to stand.
|
||||
*
|
||||
* `camera.fov` is *vertical*, so the width you can see is
|
||||
* `distance * tan(fov / 2) * aspect` — and a phone held upright has an aspect
|
||||
* near 0.5 against the 1.78 the pack was written for. At the same distance
|
||||
* that is a third of the width, which is exactly what the arrival shot looked
|
||||
* like: a thirty-four-metre floor plate shoved off the corner of the screen
|
||||
* with the top of the frame full of empty sky. The pack was not wrong and the
|
||||
* renderer was not wrong; the number simply meant something else on that
|
||||
* screen.
|
||||
*
|
||||
* So the correction preserves the *width* the author framed, which is the
|
||||
* thing they were actually choosing — "everything in this building is
|
||||
* somewhere in this frame" is a statement about width, and the extra height a
|
||||
* tall screen throws in for free costs nothing. It only ever pushes back,
|
||||
* never pulls in: a viewport wider than 16:9 already shows more than was asked
|
||||
* for, and creeping closer to trim it would crop an establishing shot on a
|
||||
* desktop to make a rule tidy.
|
||||
*/
|
||||
function widthCorrection(): number {
|
||||
const aspect = kit.camera.aspect;
|
||||
if (!(aspect > 0) || !Number.isFinite(aspect)) return 1;
|
||||
return Math.max(1, AUTHORED_ASPECT / aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where you arrive when the pack declares no viewpoints at all.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user