surroundings-probe

The Babylon half of surroundings — casting the rays that fill the read. The pure module answers questions about a measurement; this takes the measurement.

Separate file because surroundings must stay importable without a renderer (it is where the cover rules live, and they are worth testing against a world you type by hand). This one imports Babylon and is where the cost is.

What it costs, measured

One read is 12 bearings × 7 heights = 84 rays. Measured in Chrome against the demo arena, and again with the scene padded out with meshes nowhere near the character:

per read 11 meshes 311 1011
scene.pickWithRay 105µs 2809µs —
this 50µs 39µs 73µs

The padding was scattered over hundreds of metres and none of it was within reach. pickWithRay tested every mesh on every ray anyway, so a read got 27× more expensive because the level grew somewhere else. That is the shape of cost that kills a feature late: it benchmarks beautifully in a demo scene and falls over in a real level, by which time it is load-bearing.

Gathering the candidates ONCE per read — a bounding-sphere distance test, a subtract and a compare — makes the cost a function of what is near the character rather than of what exists. 92× the meshes for 1.4× the time, and the residual is the gather itself, which is the honest remaining O(n) and the place to put a spatial index if it ever matters.

Verified identical, not merely faster: at six positions around the arena, all 84 samples agreed with pickWithRay to within 2mm.

And the queries on top are free. Everything a character needs to know about cover — shelterFrom + stanceFor + exposure + inShelter + peekSide + muzzleClearance — benchmarks at 160ns, about 450× less than the read that feeds it. The rays are the cost; the thinking is not. Worth knowing before anyone optimises the wrong half.

So at the 10Hz the design asks for, cover discovery is ~0.7ms of CPU per character per second. Budgeting a tenth of a 60fps frame for it buys roughly 140 characters, all discovering cover, with the other 90% of the frame untouched.