feat: one California as one pack, behind ?one=1
The nesting preview is gone and this replaces it. That one drew each metro's
built scene inside the state board's under a similarity transform; the transform
was right and two independently built terrains then occupied the same ground and
interpenetrated. `cities/unify.ts` is the version with no seam to stitch,
because the way to not have two grids is to not have two grids: one `City`
carrying the state's landform and both metros' detail, so the engine builds one
world, one lattice and one terrain mesh.
**The merge is mostly a union and twice it must not be.** Everything that
describes a place in a `City` is absolute lat/lng, so hills, districts,
landmarks, bridges, ports and airports concatenate. Two do not:
- `World.elevationAt` *blends* every hill covering a point, so leaving the
state's coarse hills under a metro's fine ones adds their heights and lifts
the whole Bay. 25 state hills are dropped where a metro replaces them.
- The state's 17 districts include coarse stand-ins for both metros against
the metros' 99 real ones, and both drawn is two cities in one place. 9 go.
Filtering is by centre-in-bounds, which is honest and not exact, and the file
says so rather than hiding it.
**The lattice was the whole question and the answer was measured, twice.**
`TODO.md` records a statewide lattice at metro fidelity as 23.7M points and
dead. That is true at San Francisco's own 45 m cell, because `buildAxis` refines
per *axis* — a plus, not a box — so two metros at opposite corners refine most
of the state. The blowup is a function of the fine cell and is gentle until 45 m,
so the first pass took 150 m / x8, or 1.23M points.
That rendered **1,114,226 triangles at the whole-board pose against a 440,000
cap**, and the useful part is where it did *not* come from: with every metro
building hidden, triangles fell by 43,000 and draw calls by 111. The buildings
were never the cost. Terrain was. So the fine cell is what a statewide board can
afford without terrain LOD, and that is **300 m / x16** — 0.18M points, 11.6x
finer than the state pack's 3,473 m cell and 6.7x coarser than San Francisco's
own board. Measured at that size: california 392,862 triangles of 440,000 and
california-drive 405,124 of 430,000, both green on desktop.
**And the detail LOD is the cheapest kind there is.** `createBlocks` now orders
every `detail` district's lots *last*, so hiding 99 districts' buildings is one
assignment to `InstancedMesh.count` — no second mesh, no second draw call, no
allocation, and nothing for `nightlights.ts` to learn, since it holds the same
mesh either way. Landmarks are one mesh each so theirs is a `visible` flag.
The reveal is two tests and needed both. Stand-off alone passes for the drive
chapter, whose camera sits a few tens of metres off the ground half way up the
state while being two hundred kilometres from the nearest building this governs
— measured, it failed `california-drive` on triangles for lots nobody could see.
So detail draws only when the camera is inside `DETAIL_STANDOFF_M` *and* its
**target** is within `DETAIL_REACH_M` of a detail district. The target rather
than the camera, because the target is what is being looked at.
`src/test/unify.test.ts` pins the two non-union merges, the detail marking and
the lattice size. Writing it turned up something worth keeping: **six hills are
named in both the state pack and a metro pack** — Marin Headlands, San Bruno
Mountain, Mount Diablo, Bolinas Ridge, Mount Gleason, Mount Wilson — so the
first version failed on San Francisco's own Marin Headlands, identified as a
state hill by its name. `ladder.ts` hit this with "Whole Board" on two boards.
A name is not an identity; the test keys on the object.
Known and not fixed: mobile draw calls are 428 of 415 and 315 of 280 on the
merged board, from the port, vessel and bridge layers that the state board never
carried before and that no LOD hides yet. That is why this is still a flag.
Default is untouched and the full budget passes with it off.
1,700 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* One California, as one pack.
|
||||
*
|
||||
* These assert the three things about `unifiedCalifornia` that a picture cannot
|
||||
* check and that a careless edit would silently undo: that the state stops
|
||||
* drawing what a metro now draws, that every metro lot is marked as detail so
|
||||
* the level of detail has something to act on, and that the lattice this all
|
||||
* rides on is the size the file claims it is. The last one is the whole reason
|
||||
* the merge is affordable, and it is one multiplication away from not being.
|
||||
*/
|
||||
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import {
|
||||
UNIFIED_COARSE_FACTOR,
|
||||
UNIFIED_FINE_METRES,
|
||||
unifiedCalifornia,
|
||||
} from "../cities/unify.ts";
|
||||
import CALIFORNIA from "../cities/california.ts";
|
||||
import SAN_FRANCISCO from "../cities/sf.ts";
|
||||
import SOCAL from "../cities/socal.ts";
|
||||
|
||||
const { city, report } = unifiedCalifornia();
|
||||
|
||||
/** `buildAxis`, restated — the lattice cost is the claim being checked. */
|
||||
function axisLength(min: number, max: number, fine: number, coarse: number, bands: number[][]): number {
|
||||
let n = 1;
|
||||
let x = min;
|
||||
const inFine = (v: number) => bands.some(([a, b]) => v >= (a as number) - coarse && v <= (b as number) + coarse);
|
||||
while (x < max) {
|
||||
x += inFine(x) ? fine : coarse;
|
||||
n += 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
describe("one California", () => {
|
||||
it("is still California, by id, because everything downstream keys on that", () => {
|
||||
// The fire gate, the ladder's region table, `?city=`, and the budget
|
||||
// harness's `data-board` assertion all name "california" already. A fourth
|
||||
// board id would mean teaching every one of them about a board that is the
|
||||
// same place.
|
||||
assert.equal(city.id, CALIFORNIA.id);
|
||||
assert.equal(city.bounds.minLat, CALIFORNIA.bounds.minLat);
|
||||
assert.equal(city.bounds.maxLat, CALIFORNIA.bounds.maxLat);
|
||||
});
|
||||
|
||||
it("stops drawing the state's coarse stand-ins where a metro now stands", () => {
|
||||
/*
|
||||
* Hills *sum*: `World.elevationAt` blends every hill covering a point, so a
|
||||
* coarse state hill left under a metro's fine ones lifts the whole Bay. And
|
||||
* the state's districts include coarse stand-ins for both metros, which
|
||||
* drawn together with the real ones is two cities in one place.
|
||||
*/
|
||||
assert.ok(report.hills.dropped > 0, "no state hill was cleared for a metro");
|
||||
assert.ok(report.districts.dropped > 0, "no state district was cleared for a metro");
|
||||
|
||||
const metroBounds = [SAN_FRANCISCO.bounds, SOCAL.bounds];
|
||||
const inside = (lat: number, lng: number) =>
|
||||
metroBounds.some((b) => lat >= b.minLat && lat <= b.maxLat && lng >= b.minLng && lng <= b.maxLng);
|
||||
|
||||
/*
|
||||
* By **identity**, not by name, and that is a finding rather than a style
|
||||
* choice: six hills are named in both the state pack and a metro pack —
|
||||
* Marin Headlands, San Bruno Mountain, Mount Diablo, Bolinas Ridge, Mount
|
||||
* Gleason, Mount Wilson — because two packs independently named the same
|
||||
* real hill. Keyed on the string, San Francisco's own Marin Headlands reads
|
||||
* as a state hill that survived inside a metro and fails this test for a
|
||||
* bug that is not there. `ladder.ts` hit the same thing with "Whole Board"
|
||||
* on two boards; the rule both times is that a name is not an identity.
|
||||
*
|
||||
* The merge spreads the arrays without copying their elements, so the state
|
||||
* pack's own hill objects are the ones to look for.
|
||||
*/
|
||||
const stateHills = new Set<unknown>(CALIFORNIA.hills);
|
||||
let checked = 0;
|
||||
for (const hill of city.hills) {
|
||||
if (!stateHills.has(hill)) continue;
|
||||
checked += 1;
|
||||
assert.ok(!inside(hill.lat, hill.lng), `state hill "${hill.name}" is still inside a metro`);
|
||||
}
|
||||
assert.ok(checked > 0, "no state hill survived at all, so this asserted nothing");
|
||||
});
|
||||
|
||||
it("marks every metro lot as detail, which is what the LOD acts on", () => {
|
||||
const detail = city.districts.filter((d) => d.detail === true);
|
||||
const base = city.districts.filter((d) => d.detail !== true);
|
||||
assert.equal(detail.length, SAN_FRANCISCO.districts.length + SOCAL.districts.length);
|
||||
assert.equal(base.length, report.districts.state - report.districts.dropped);
|
||||
// And the state's own districts are never marked, or the board would hide
|
||||
// California when you stood back from it.
|
||||
assert.ok(base.length > 0, "the state kept no districts of its own");
|
||||
});
|
||||
|
||||
it("keeps the lattice the size this whole merge depends on", () => {
|
||||
const cf = city.coarseFactor ?? 1;
|
||||
const lat = axisLength(
|
||||
city.bounds.minLat, city.bounds.maxLat, city.cellLat, city.cellLat * cf,
|
||||
(city.focusRegions ?? []).map((r) => [r.minLat, r.maxLat]),
|
||||
);
|
||||
const lng = axisLength(
|
||||
city.bounds.minLng, city.bounds.maxLng, city.cellLng, city.cellLng * cf,
|
||||
(city.focusRegions ?? []).map((r) => [r.minLng, r.maxLng]),
|
||||
);
|
||||
const points = lat * lng;
|
||||
/*
|
||||
* The ceiling, not a description. At 150 m / x8 this was 1.23M points and
|
||||
* the board rendered 1,114,226 triangles against a 440,000 cap — terrain,
|
||||
* not buildings. Anything that pushes this back over half a million points
|
||||
* is re-opening that, and should be measured rather than assumed.
|
||||
*/
|
||||
assert.ok(points < 500_000, `${points} lattice points — the terrain budget was found at ~180k`);
|
||||
assert.equal(UNIFIED_COARSE_FACTOR, cf);
|
||||
assert.ok(Math.abs(city.cellLat * 111_320 - UNIFIED_FINE_METRES) < 1);
|
||||
});
|
||||
|
||||
it("carries both metros' ports, which the state board never had", () => {
|
||||
// The most visible single consequence of the merge: the state board now has
|
||||
// a harbour on it, and `main.ts` attaches the vessel layer to any pack with
|
||||
// one. Before this, `sf.ts` and `california.ts` had zero berths between them.
|
||||
assert.ok((city.ports?.length ?? 0) >= (SOCAL.ports?.length ?? 0));
|
||||
assert.ok((city.ports?.length ?? 0) > (CALIFORNIA.ports?.length ?? 0));
|
||||
});
|
||||
|
||||
it("is memoised, because World builds one per mount", () => {
|
||||
assert.equal(unifiedCalifornia().city, city);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user