The never-downgrade display gate for the LODGroupRegistry selector —
pure policy over commit-time stamps, no THREE import (structural node
shapes only), unit-testable in isolation like its sibling
lod-freshness.ts (which supplies the leaf-stamp primitives).
A lazy substitutive level flips ready after its FIRST additive chunk
commits, so an ungated swap to a fresh-but-still-streaming level pops
displayed quality down to chunk-1 (on zoom in, zoom out, or after a scrub
settles) and climbs back over the following passes.
shouldHoldPreviousDisplay holds the previously-displayed level
while the streaming aspiration is strictly worse than what is shown, and
releases on ladder completion, the committed-energy threshold (stamped
datasets, UPGRADE direction only: committed e(k) ≥
ENERGY_RELEASE_THRESHOLD — the primary, much earlier release on
zoom-in), committed-count crossover (the unstamped fallback, and the sole
early release on a downgrade), ladder failure, or the previous level losing
freshness — never blocking a
swap when nothing better is on screen (fast first paint is preserved).
Committed state only. The gate reads the per-mesh commit stamps
(visible*Count, loadedViewVersion, committedLadderComplete — written
by the commit helpers, see data/scene-loader/commit/stamp-view-version.ts),
never the loaders' live hasMoreLODs getters. Live getters flip the moment
the final LOD's fetch resolves, frames before its processing + commit land;
the stamps flip in the same synchronous call that writes the final count,
so the gate can never see "complete" paired with a stale partial count.
(The registry's refinement-kick logic deliberately keeps using the live
getter — kicking MORE loading wants live loader state; displaying wants
committed state.)
Nested-group levels. A lod_group child can be a whole subtree (e.g. the
overview recipe's fine kind=partition branch, or hand-authored
lod-of-lod nestings) rather than a single stamped leaf. Such a child has no
direct stamps; subtreeDisplayProgress folds its visible stamped
leaves into one aggregate (count sum / all-complete / all-fresh), which the
gate consumes exactly like a leaf's stamps. The walk respects descendant
visible flags — an inner lod_group keeps toggling its own levels while
the outer placeholder is hidden, so the aggregate counts precisely what
would render — but ignores the ROOT's own flag (the registry itself hides
the placeholder of a not-displayed child).
The never-downgrade display gate for the
LODGroupRegistryselector — pure policy over commit-time stamps, no THREE import (structural node shapes only), unit-testable in isolation like its siblinglod-freshness.ts(which supplies the leaf-stamp primitives).A lazy substitutive level flips
readyafter its FIRST additive chunk commits, so an ungated swap to a fresh-but-still-streaming level pops displayed quality down to chunk-1 (on zoom in, zoom out, or after a scrub settles) and climbs back over the following passes. shouldHoldPreviousDisplay holds the previously-displayed level while the streaming aspiration is strictly worse than what is shown, and releases on ladder completion, the committed-energy threshold (stamped datasets, UPGRADE direction only: committed e(k) ≥ ENERGY_RELEASE_THRESHOLD — the primary, much earlier release on zoom-in), committed-count crossover (the unstamped fallback, and the sole early release on a downgrade), ladder failure, or the previous level losing freshness — never blocking a swap when nothing better is on screen (fast first paint is preserved).Committed state only. The gate reads the per-mesh commit stamps (
visible*Count,loadedViewVersion,committedLadderComplete— written by the commit helpers, seedata/scene-loader/commit/stamp-view-version.ts), never the loaders' livehasMoreLODsgetters. Live getters flip the moment the final LOD's fetch resolves, frames before its processing + commit land; the stamps flip in the same synchronous call that writes the final count, so the gate can never see "complete" paired with a stale partial count. (The registry's refinement-kick logic deliberately keeps using the live getter — kicking MORE loading wants live loader state; displaying wants committed state.)Nested-group levels. A lod_group child can be a whole subtree (e.g. the
overviewrecipe's finekind=partitionbranch, or hand-authored lod-of-lod nestings) rather than a single stamped leaf. Such a child has no direct stamps; subtreeDisplayProgress folds its visible stamped leaves into one aggregate (count sum / all-complete / all-fresh), which the gate consumes exactly like a leaf's stamps. The walk respects descendantvisibleflags — an inner lod_group keeps toggling its own levels while the outer placeholder is hidden, so the aggregate counts precisely what would render — but ignores the ROOT's own flag (the registry itself hides the placeholder of a not-displayed child).