Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Interface LODGroupEntry

    One LOD-group entry tracked by the registry.

    interface LODGroupEntry {
        path: string;
        groupObject: Object3D;
        children: LODGroupChild[];
        selector?: LodSelectorName;
        selectorMode: LODGroupSelectorMode;
        defaultLevel: number;
        activeChildIndex: number;
        displayedChildIndex?: number;
        heldDisplayChildIndex?: number;
        staleHoldSinceMs?: number;
        staleHoldExhausted?: boolean;
        offScreen?: boolean;
        desiredChildIndex?: number;
    }
    Index
    path: string

    Scene path (for diagnostics + UI lookup).

    groupObject: Object3D

    The lod_group's THREE container. World matrix lives here.

    children: LODGroupChild[]

    Children in coarsest→finest order (== insertion order on disk, == ascending coverageFraction).

    selector?: LodSelectorName

    Units of the children's coverageFraction thresholds (the on-disk group's selector attr): 'screen-area' compares them against the projected bbox rect's fraction of the viewport AREA (projectBoxAreaFraction); 'coverage' — the legacy diagonal metric (projectBoxDiagonalPx / (FILL_FACTOR × min(viewport.width, viewport.height)), the fitted screen axis) — is the default when absent, so older stores and test-constructed entries keep their behaviour.

    selectorMode: LODGroupSelectorMode

    Current selector mode ('auto' or { lockLevel: i }).

    defaultLevel: number

    Initial active level, used when nothing else has selected yet.

    activeChildIndex: number

    Index into children of the screen-DESIRED level (the aspiration). This is the hysteresis anchor and the level the auto-selector wants on screen. It is NOT necessarily what is displayed: when its committed geometry is stale for the current view version, the registry shows a coarser fresh level (displayedChildIndex) until the aspiration commits.

    displayedChildIndex?: number

    Index into children of the level ACTUALLY visible this frame. Equals activeChildIndex in steady state; during a re-slice it transiently points at the coarsest fresh level while the aspiration reloads, and during a never-downgrade hold it can also point at a FINER previously-displayed level while a coarser streaming aspiration catches up. During a stale hold it can instead remain on a finer STALE level while the next slice decodes. A per-frame transient written by evaluateEntry and read by enforceByteBudget (same synchronous evaluatePerFrame pass) so eviction never releases the on-screen level. undefined before the first evaluation ⇒ treated as activeChildIndex. Tracks what is ACTUALLY on screen every frame — including the coarse level shown while the group is off-screen — which is what eviction needs, but is therefore NOT the never-downgrade gate's memory (that is heldDisplayChildIndex).

    heldDisplayChildIndex?: number

    The last level displayed while the group was ON SCREEN — shared memory for the never-downgrade gate and stale hold. Distinct from displayedChildIndex because the off-screen gate transiently displays (and would otherwise record) the coarsest ready level; folding that into the gate memory would let a mere look-away-and-back clobber a held finer level and re-pop it to chunk-1 on return. Written by evaluateEntry only on frames where the group is on screen. undefined before the first on-screen evaluation ⇒ neither hold policy has a prior level.

    staleHoldSinceMs?: number

    Wall-clock ms at which the current stale-hold budget started — see staleHoldDisplayIndex. Set on the first eligible hold and retained when a later ratio check declines to hold, so the budget cannot restart during the same scrub. Cleared only when the aspiration recommits fresh or the budget is exhausted.

    staleHoldExhausted?: boolean

    True once a stale hold has exhausted STALE_HOLD_MS without the aspiration recommitting. Latches the coarse fallback for the rest of this scrub; cleared when the aspiration finally lands fresh.

    offScreen?: boolean

    Whether the auto-selector is currently holding this group at its coarsest-ready level because its world bounds are outside the camera frustum (the off-screen gate). false when on-screen or when a level is explicitly locked. Surfaced in the layers-panel readout as an "(off-screen)" hint so a coarse level on close inspection isn't mistaken for a selection bug. Updated each evaluatePerFrame.

    desiredChildIndex?: number

    The level index the selector WANTED this frame, recorded BEFORE the ready/freshness gates below it get a say. Written by evaluateEntry once a desired has been computed — the explicit lock and all three auto branches (off-screen hold, screen-area pick, legacy coverage pick). undefined (never evaluated) ⇒ read it as activeChildIndex.

    It is NOT rewritten on every frame: evaluateEntry returns before computing a desired when the entry has no registration cache or no world box, and evaluatePerFrame returns before reaching the entries at all on a zero-sized viewport or with fewer than two display dims. The field then keeps its previous value. That is benign — both early returns are stable properties of the entry/viewport rather than transient states, so a stale value cannot describe a level the selector has since moved off, and an entry that never got one reads as activeChildIndex (i.e. "nothing pending"), which is the right answer for a group the selector has never been able to evaluate.

    Purely diagnostic for the renderer — nothing about display reads it. It exists so an OFFLINE CAPTURE can tell "the selector wants a finer level it has not got yet" apart from "settled" (see LODGroupRegistry.isCaptureQuiescent). activeChildIndex alone cannot express that: the aspiration only ever advances ONTO A READY LEVEL, so in the frame where a lazy fine level's async load lands (the thunk sets ready=true and clears loading) the registry has not swapped yet — that happens on the NEXT selector pass. A quiescence predicate reading only loading / ready / displayedChildIndex would call that window "settled" and the capture would film the coarse level one frame before the swap, which is exactly the LOD pop this field exists to close.