Skip to content
← Documentation

docs/camera-occlusion.md


Camera measured — exploration freedom, not a defect

Third result under renderer-as-laboratory. The camera differs from fog and light because the viewer controls it, so the measurement had to separate two things that look identical in a single frame.

tests/camera-occlusion.test.ts.


The task, defined before measuring

Can a user see that a given building exists?

  • Renderer claim failure — information that no reachable pose reveals.
  • Exploration freedom — information hidden now, recoverable by moving.

A building is reachable if at least one pose inside the control's own limits (minDistance 18, maxDistance 520, maxPolarAngle π/2.15) leaves it unoccluded. Occlusion is computed in closed form — perspective projection of box silhouettes, nearest-first — so no pixels are needed.

Result

18 buildings · 2 occluded at the default vantage (11.1%)
216 reachable poses sampled
unreachable from every pose: 0

Every building is reachable. The camera is exploration freedom, and removing or constraining it would remove freedom rather than a fault.

The 11.1% is a measured cost of the initial framing, which is a convention (worldscene-freedoms.md) — a number attached to a declared choice, not a defect.

The height bias exists and is weak

mean height — hidden 5.0, shown 5.2

Tall buildings do hide short ones, and height carries code-size, so the estate preferentially conceals small things. The mechanism is real; at this scale the effect is marginal. Recorded, not repaired, because the reachability result shows all of it is recoverable.

Classification, on the two axes

Freedom Semantic ownership Perceptual effect
initial camera pose conventional preserves — 11.1% concealed, all recoverable
interactive camera arbitrary preserves — measured, 0 unreachable
distance fog derived (was arbitrary) distorted — 36.3%, repaired to 0%
key light arbitrary preserves — 0 inversions
fill light arbitrary preserves — contrast only, −5.6%
material response arbitrary preserves — specular 116× too small

The camera is the case the two-axis scheme was needed for: arbitrary in ownership, harmless in effect. A single-axis scheme would have flagged it as an unowned claim and invited a repair that removed navigation.


A second finding: the fixture was degenerate

The first run reported zero occlusion, and the instrument guard refused it. Diagnosis:

atScale(10): extent x 0..990, z 0..0   heights 15.8..15.9   footprints 8

Every building on a line, at identical heights. The synthetic fixture cannot produce occlusion at all. The measurement was moved to deriveStructure, which is what the product actually renders — rings, slots, varying heights.

The guard is the reason this was caught rather than published. "No occlusion detected" is exactly the kind of clean-looking result that would have gone unquestioned.

And it forced a re-examination of the fog result

The fog measurement used the same degenerate fixture, so I checked whether 36.3% was an artifact of it:

Pearson r(depth, activity) = 0.080
as generated:        36.3% inverted
activity shuffled:   31.4% inverted

Depth and activity are essentially uncorrelated, and breaking any residual correlation leaves the same order of magnitude. The fog finding stands — it depends on depth spread and activity variance, both of which are real in that fixture, and not on the 2-D arrangement, which is not.

The real layout could not test it: with emptyFacts() there is only one distinct activity value, so there is nothing to invert. That is an unreachable state, not a refutation.


Standing

Measurable defect exposed? no — the camera is not one
Measurable improvement? no changes made, which is the result
Freedom removed without evidence? no
Prior finding re-verified? yes — fog survives a fixture challenge

What is still not established

  • 216 poses is a sample, at 15° azimuth × 3 elevations × 3 distances. Occlusion could persist in a gap between samples, though a building hidden across a 15° sweep and three distances would be unusual.
  • Occlusion is centre-point only. A building 90% covered counts as visible. The test answers "can a user see it exists", not "can a user read its height" — a stricter task would give a different number.
  • FOV is declared, not read. 50° is r3f's default and is not set in WorldScene.tsx; if a parent Canvas sets it, this measurement drifts.
  • The estate is 18 buildings from 9 synthetic repos. A denser real estate would occlude more, and reachability is the claim that would need re-testing.

215 → 219 tests, tsc clean.