1
0

perf: lot size is a ladder the camera climbs, not a constant

`DETAIL_LOT_METRES = 160` was one number for a board that stopped being
looked at from one distance, and it was wrong at both ends of the range
it is now looked at from. Measured with `scripts/cost-at.mjs` on the
merged board against a 400,000-triangle cap:

| pose | before | after | lot |
| --- | --- | --- | --- |
| Los Angeles, 13 km | **688,536** | 343,372 | 400 m |
| Los Angeles, 12.5 km | **678,546** | 343,372 | 400 m |
| Los Angeles, 11 km | **654,656** | 390,602 | 250 m |
| Los Angeles, 9 km | **635,806** | 380,762 | 250 m |
| **Los Angeles, 7.7 km** | **621,866** | **375,196** | 250 m |
| Los Angeles, 2.5 km | **415,780** | 345,340 | 200 m |
| Los Angeles, 0.9 km | 297,148 | 363,454 | 40 m |
| San Francisco, 7.7 km | 222,286 | 300,782 | 80 m |
| San Francisco, 2.5 km | 216,292 | 279,158 | 80 m |
| San Francisco, 0.6 km | 200,114 | 347,830 | 40 m |
| San Francisco, 400 km | 355,763 | 355,763 | — |
| San Francisco, 45 km | 270,377 | 270,377 | — |

**Six poses were over the cap and five of them had never been measured.**
Only the 7.7 km one was on record; 2.5 km over Los Angeles was at
415,780, and the whole band from 9 km up to where `DETAIL_STANDOFF_M`
switches the metros off at 13.3 km ran 635,806 to 688,536, because the
frustum there holds essentially the entire Southland. None of them is
over now. San Francisco goes the other way — 4.2x the buildings at the
poses the complaint was about, and 15,613 at the closest one against
849. No cap moved.

**Zero new draw calls, and that is a bound rather than a sample.** It is
the same `InstancedMesh`, the same geometry and the same material; a
district is built at 40, 80, 160, 200, 250 and 400 m, all six rungs live
in the store, and the live buffers hold whichever one the board chose.
Draws are unchanged to the digit at every pose above. A test asserts the
mesh identity across four rung changes.

The lever is a **lot count, not a lot size**, because a lot size is the
wrong thing to hang on the camera: at the same 22.6 km of engine
stand-off San Francisco has 1,987 lots in frustum and Los Angeles has
23,000, so any rule in metres of lot or kilometres of reach is a
different bill in the two cities. The board packs the finest rung whose
*visible* sum fits 19,000 lots, which is 400,000 minus the 184,000 to
205,000 triangles everything-but-the-city measured at across the whole
band this runs in — flat to 10%, which is why there is no stand-off ramp
and why the one that was here first came out.

Costs, honestly. `createBlocks` goes 264 ms -> 1,236 ms and its store
4.7 MiB -> 18.9 MiB, because every rung is walked and kept; the live
instance buffers get *smaller*, 59,166 -> 19,000, since the mesh no
longer has to be able to draw a rung nothing can afford. A rung change
pops — each rung is its own survey, not a subdivision — and cross-fading
would cost the draw call this board does not have. Los Angeles at 7.7 km
is visibly thinner than the 621,866-triangle version it replaces.

`TODO.md`'s LA section is rewritten around what is left: no budget cell
stands at any of these poses, which was the first item on it and still
is. 1,723 tests.
This commit is contained in:
2026-08-24 20:08:13 -07:00
parent 1049f942b8
commit 687c34d123
7 changed files with 872 additions and 160 deletions
+17 -1
View File
@@ -14,6 +14,11 @@
* one which does packs strictly less, that the pad is a pad, and that neither
* can ever pack more instances than the mesh has room for.
*
* `blocksLotLadder.test.ts` is the other half and came later: the frustum
* decides *which* districts are packed and the lot budget decides how finely
* each of them is. Everything here leaves the budget at its default, so what is
* measured below is the frustum on its own.
*
* The board is synthetic for the reason `seaAndTerrain.test.ts` gives: none of
* this is about California, and a real pack would couple this to a coastline.
*/
@@ -107,6 +112,16 @@ const REACH = 40; // scene units; both metros are inside this of their own centr
test("without a frustum the packing is exactly what it always was", async () => {
const world = await built();
const blocks = createBlocks(world);
/*
* Capacity stopped being "every lot that exists" when lot size became a
* ladder: the store holds every rung of every district and only one rung of
* each is ever drawn, so the mesh is allocated against a bound — the whole
* board at its finest reachable rung, or the lot budget, whichever is
* smaller, and never below the whole board at its coarsest. On this fixture
* the detail districts are far too large for a rung finer than the reference,
* so the board's finest reachable rung *is* the reference and the two
* statements below still measure exactly what they measured before.
*/
const capacity = (blocks.instanceMatrix.array.length / 16) | 0;
assert.ok(capacity > 200, `the fixture is too small to be a test: ${capacity} lots`);
@@ -124,7 +139,8 @@ test("without a frustum the packing is exactly what it always was", async () =>
const base = blocks.count;
assert.ok(base > 0, "the base district vanished");
// In reach of both: every lot on the board, in one contiguous run.
// In reach of both: every lot on the board, in one contiguous run — at the
// finest rung it has, which on this fixture is the only rung it has.
updateBlocksDetail(blocks, x, z, 1_000);
assert.equal(blocks.count, capacity, "reach alone must still be able to draw the whole board");
assert.ok(base < capacity, "the fixture has no detail lots to cull");