The office learns where it stands, and the sky stops being a backdrop
**Aircraft actually move now, and the reason they did not is the headline.**
`HttpFlights` holds a frozen snapshot between network refreshes and is
polled at 1 Hz, so a live feed handed the layer the same position five to
fifteen times and then jumped. `span` therefore measured the poll interval
rather than the gap between the two positions that differ, the teleport
test saw an airliner covering 36 units in a "second" against a ceiling of
8, and **every live track's history was wiped on every refresh** — so no
aircraft on the deployed site could ever grow a trail, however long
TRAIL_POINTS was set. Skipping the repeat fixes the motion and the trail
at once. Trails then go to 72 points / 240 s, which is about seventy
seconds of flying.
Three more defects in the same file, found while looking: trail
truncation dropped the segments nearest the aircraft (leaving a streak
with no aeroplane attached), MAX_TRACKS was declared and never enforced,
and one missing target deleted its whole trail. The buffer now uploads
only what it wrote, rather than 46 MB/s of untouched array.
**You can get above the constellation.** Dome to 1.05 board *radii* and
the orbit to 2.0 spans. Radii, not spans: scene space is centred on the
city and the Bay Area board runs forty kilometres down the peninsula, so
the furthest corner is 0.94 spans out where the half-diagonal is 0.65 —
sized off the half-diagonal the dome sat inside its own city. The far
plane goes to 4 spans to stop clipping the sky from off-centre chapters,
and `PointsMaterial` defaults `fog: true`, which was quietly dimming the
whole constellation with the city's haze.
**An office can say where it stands.** `Office.site` — lat, lng, height
above the ground outside, and the compass bearing the pack's −Z points
along — and with one it gets the same sun the city does, a sky, and a
horizon at `-elevation`. CONTRACT §4 reserved this as "a later
refinement"; it is taken up rather than overturned, and `daylight.ts`
computes no light of its own. It does the two things a room needs that a
map does not: turn the sun into the building's frame, and move the fog
outdoors before it greys out the far wall.
Two buildings now, and they are deliberately unalike: Lumbridge HQ 188 m
up a Transbay tower facing 205°, and **Frontier Valley**, a startup in a
hangar at Alameda Point — one room, 54 x 30 m, nine metres to the
trusses, four metres above reclaimed ground.
Floor-to-floor in the reference pack is now 16.8 m: the interstitial is
ten times a real one, so the space between the slabs is somewhere things
can hang. It is frankly not architecture, `PLENUM` is the one number to
change, and the file says so.
Also fixed, all found by review rather than by looking at the screen:
- `sun.shadow.camera.updateProjectionMatrix()` was never called, so
three's default ±5 unit box has been in force this whole time and
every `shadowExtent` this repo passes — including the city's ±752 —
has been silently ignored.
- A missing aircraft was kept alive by the new grace period and *drawn*,
so it froze in mid-air at full opacity for 32 s.
- Frontier Valley's mezzanine was a `Room`, which carries no height: its
slab lay on the concrete, its chairs floated 4.4 m over it, and its
balustrade fenced off a patch of ground floor. It is a `Level`.
- Overlapping floor slabs z-fought. The format permits overlap and
resolves later-first, so `shell.ts` now lifts a slab a hair per
earlier slab it overlaps — and by nothing at all in a pack, like the
reference office, whose rooms only ever abut.
- `switchOffice` bypassed the `entering` guard (leaking a whole scene
per double-click) and tore down the old room before knowing the new
one would load, with no way back.
Known and not fixed: raising MAX_SPAN to 30 s doubles the worst-case
re-base snap when a feed's gap shortens. It is bounded, pre-existing in
kind, and the fix wants carrying the live head into the next leg.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+48
-3
@@ -194,14 +194,59 @@ export async function createScene(
|
||||
const [eastX, southZ] = world.project(city.bounds.minLat, city.bounds.maxLng);
|
||||
const boardSpan = Math.max(Math.abs(eastX - westX), Math.abs(southZ - northZ));
|
||||
|
||||
/**
|
||||
* How far the board reaches **from the scene origin**, which is not the same
|
||||
* as how big it is.
|
||||
*
|
||||
* Scene space is centred on `city.center` — the city — and the Bay Area board
|
||||
* runs forty kilometres down the peninsula from there, so the origin is
|
||||
* nowhere near the middle of it. The furthest corner is 0.94 spans out where
|
||||
* the half-diagonal is only 0.65, and anything sized off the half-diagonal is
|
||||
* therefore too small by half.
|
||||
*
|
||||
* The satellite dome is centred on the origin, because that is where its look
|
||||
* angles were computed for, so this is the radius it has to clear.
|
||||
*/
|
||||
const boardRadius = Math.max(
|
||||
Math.hypot(westX, northZ),
|
||||
Math.hypot(eastX, northZ),
|
||||
Math.hypot(westX, southZ),
|
||||
Math.hypot(eastX, southZ),
|
||||
);
|
||||
|
||||
const kit = createSceneKit({
|
||||
scene,
|
||||
dom: stage.renderer.domElement,
|
||||
fov: 42,
|
||||
near: 0.1,
|
||||
far: boardSpan * 3,
|
||||
/**
|
||||
* Everything, at the worst pose, plus room.
|
||||
*
|
||||
* The furthest thing from the camera is the back of the satellite dome seen
|
||||
* from a chapter at the far end of the board: `maxChapterOffset` (0.94
|
||||
* spans) + `maxDistance` (2.0) + the dome radius (about 0.99) — call it 3.9.
|
||||
* At 3.0 the sky was being clipped from any off-centre chapter, which is
|
||||
* most of them.
|
||||
*
|
||||
* It also now sits at the fog's far plane, which is the honest statement of
|
||||
* the invariant: nothing should be cut off before it has fully faded out.
|
||||
*/
|
||||
far: boardSpan * 4,
|
||||
minDistance: Math.max(4, boardSpan * 0.02),
|
||||
maxDistance: boardSpan * 1.5,
|
||||
/**
|
||||
* Far enough out to be **above the satellites**, which is what the extra
|
||||
* half-span buys.
|
||||
*
|
||||
* The satellite dome is at 0.7 spans (`engine/satellites.ts`), so at 1.5 the
|
||||
* camera was always inside the constellation and could only ever look up
|
||||
* through it. At 2.0 the far end of the zoom is outside it looking down, with
|
||||
* the whole dome in frame at this field of view and the board still filling
|
||||
* about two thirds of the screen.
|
||||
*
|
||||
* The far plane already covers it: the furthest thing from the camera is then
|
||||
* the back of the dome at 2.7 spans, against `far` at 3.0.
|
||||
*/
|
||||
maxDistance: boardSpan * 2.0,
|
||||
shadowExtent: boardSpan * 0.75,
|
||||
shadowFar: boardSpan * 2.2,
|
||||
});
|
||||
@@ -235,7 +280,7 @@ export async function createScene(
|
||||
|
||||
let satelliteLayer: SatelliteLayer | null = null;
|
||||
if (options.satellites) {
|
||||
satelliteLayer = createSatelliteLayer(boardSpan);
|
||||
satelliteLayer = createSatelliteLayer(boardRadius);
|
||||
scene.add(satelliteLayer.group);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user