export class GSplatOctreeInstance {
    /**
     * @param {GraphicsDevice} device - The graphics device.
     * @param {GSplatOctree} octree - The octree.
     * @param {GSplatPlacement} placement - The placement.
     */
    constructor(device: GraphicsDevice, octree: GSplatOctree, placement: GSplatPlacement);
    /** @type {GSplatOctree} */
    octree: GSplatOctree;
    /** @type {GSplatPlacement} */
    placement: GSplatPlacement;
    /** @type {Set<GSplatPlacement>} */
    activePlacements: Set<GSplatPlacement>;
    /** @type {boolean} */
    dirtyModifiedPlacements: boolean;
    /**
     * Set to true when placements are added or removed, signaling that the manager needs to
     * create a new world state and trigger a full work buffer rebuild.
     */
    dirtyPlacementSetChanged: boolean;
    /** @type {GraphicsDevice} */
    device: GraphicsDevice;
    /**
     * Array of NodeInfo instances, one per octree node.
     *
     * @type {NodeInfo[]}
     */
    nodeInfos: NodeInfo[];
    /**
     * Array of current placements per file. Index is fileIndex, value is GSplatPlacement or null.
     * Value null indicates file is not used / no placement.
     *
     * @type {(GSplatPlacement|null)[]}
     */
    filePlacements: (GSplatPlacement | null)[];
    /**
     * Set of pending file loads (file indices).
     *
     * @type {Set<number>}
     */
    pending: Set<number>;
    /**
     * Map of nodeIndex -> { oldFileIndex, newFileIndex } that needs to be decremented when the
     * new LOD resource loads. This ensures we decrement even if the node switches LOD again
     * before the new resource arrives.
     *
     * @type {Map<number, { oldFileIndex: number, newFileIndex: number }>}
     */
    pendingDecrements: Map<number, {
        oldFileIndex: number;
        newFileIndex: number;
    }>;
    /**
     * Files that became unused by this instance this update. Each entry represents a single decRef.
     *
     * @type {Set<number>}
     */
    removedCandidates: Set<number>;
    /**
     * Minimum allowed LOD index for this instance, clamped to valid octree bounds.
     */
    rangeMin: number;
    /**
     * Maximum allowed LOD index for this instance, clamped to valid octree bounds.
     */
    rangeMax: number;
    /**
     * Previous node position at which LOD was last updated. This is used to determine if LOD needs
     * to be updated as the octree splat moves.
     */
    previousPosition: Vec3;
    /**
     * Set when a resource has completed loading and LOD should be re-evaluated.
     */
    needsLodUpdate: boolean;
    /**
     * Tracks prefetched file indices that are being loaded without active placements.
     * When any completes, we trigger LOD re-evaluation to allow promotion.
     *
     * @type {Set<number>}
     */
    prefetchPending: Set<number>;
    /**
     * Tracks invisible->visible pending adds per node: nodeIndex -> fileIndex.
     * Ensures only a single pending placement exists for a node while it's not yet displayed.
     *
     * @type {Map<number, number>}
     */
    pendingVisibleAdds: Map<number, number>;
    /**
     * Returns the count of resources pending load or prefetch, including environment if loading.
     *
     * @type {number}
     */
    get pendingLoadCount(): number;
    /**
     * Environment placement.
     *
     * @type {GSplatPlacement|null}
     */
    environmentPlacement: GSplatPlacement | null;
    /**
     * Event handle for device lost event.
     *
     * @type {EventHandle|null}
     * @private
     */
    private _deviceLostEvent;
    /**
     * Reusable scratch for LOD distance thresholds.
     *
     * @type {Float32Array|null}
     * @private
     */
    private _lodMinDistThresholds;
    /**
     * Destroys this octree instance and clears internal references.
     *
     * @param {boolean} [skipRefCounting] - When true, skip decrementing file ref counts
     * on the octree. Used when the caller handles ref counting externally via pendingReleases
     * (e.g. during world state updates where decrements must be deferred).
     */
    destroy(skipRefCounting?: boolean): void;
    /**
     * Handles device lost event by releasing all loaded resources.
     *
     * @private
     */
    private _onDeviceLost;
    /**
     * Returns the file indices currently referenced by this instance that should be decremented
     * when the instance is destroyed.
     *
     * @returns {number[]} Array of file indices to decRef.
     */
    getFileDecrements(): number[];
    /**
     * Selects desired LOD index for a node using the underfill strategy. When underfill is enabled,
     * it prefers already-loaded LODs within [optimalLodIndex .. optimalLodIndex + lodUnderfillLimit].
     * If none are loaded, it selects the coarsest available LOD within the range.
     *
     * @param {import('./gsplat-octree-node.js').GSplatOctreeNode} node - The octree node.
     * @param {number} optimalLodIndex - Optimal LOD index based on camera/distance.
     * @param {number} maxLod - Maximum LOD index.
     * @param {number} lodUnderfillLimit - Allowed coarse range above optimal.
     * @returns {number} Desired LOD index to display.
     */
    selectDesiredLodIndex(node: import("./gsplat-octree-node.js").GSplatOctreeNode, optimalLodIndex: number, maxLod: number, lodUnderfillLimit: number): number;
    /**
     * Prefetch only the next-better LOD toward optimal. This stages loading in steps across all
     * nodes, avoiding intermixing requests before coarse is present.
     *
     * @param {import('./gsplat-octree-node.js').GSplatOctreeNode} node - The octree node.
     * @param {number} desiredLodIndex - Currently selected LOD for display (may be coarser than optimal).
     * @param {number} optimalLodIndex - Target optimal LOD.
     */
    prefetchNextLod(node: import("./gsplat-octree-node.js").GSplatOctreeNode, desiredLodIndex: number, optimalLodIndex: number): void;
    /**
     * Updates the octree instance when LOD needs to be updated.
     *
     * @param {GraphNode} cameraNode - The camera node.
     * @param {import('./gsplat-params.js').GSplatParams} params - Global gsplat parameters.
     */
    updateLod(cameraNode: GraphNode, params: import("./gsplat-params.js").GSplatParams): void;
    /**
     * Ensures the reusable threshold buffer can store indices 1 through maxLod and fills
     * buf[k] = d0 * m^(k-1) for k from 1 to maxLod (same distance bands as truncating 1 + log(d/d0) / log(m)).
     *
     * @param {number} maxLod - Maximum LOD index (>= 1).
     * @param {number} d0 - lodBaseDistance in FOV-adjusted distance space.
     * @param {number} m - lodMultiplier.
     * @returns {Float32Array} Buffer; index 0 unused; entries 1..maxLod set.
     * @private
     */
    private _ensureLodMinDistThresholds;
    /**
     * Evaluates optimal LOD indices for all nodes based on camera position and parameters.
     * This is Pass 1 of the LOD update process. Results are stored in nodeInfos array.
     *
     * Uses geometric LOD distances (lodBaseDistance * lodMultiplier^i) with FOV compensation
     * so that LOD transitions are perceptually uniform under perspective projection.
     *
     * @param {GraphNode} cameraNode - The camera node.
     * @param {number} maxLod - Maximum LOD index (lodLevels - 1).
     * @param {number} lodBaseDistance - Base distance for first LOD transition.
     * @param {number} lodMultiplier - Geometric ratio between successive LOD thresholds.
     * @param {number} rangeMin - Minimum allowed LOD index.
     * @param {number} rangeMax - Maximum allowed LOD index.
     * @param {import('./gsplat-params.js').GSplatParams} params - Global gsplat parameters.
     * @param {number} uniformScale - Uniform scale of the octree transform for world-space conversion.
     * @param {boolean} [accumulateSplats] - When true (default), sum splat counts for the chosen LOD per node and return the total (budget path). When false, skip counting (faster; return value unused).
     * @param {number} [globalMaxDistanceForBuckets] - When > 0, writes {@link NodeInfo.budgetBucket} using the same sqrt mapping as the budget balancer. Omit or pass 0 when not enforcing global budget.
     * @returns {number} Total number of splats that would be used by optimal LODs when accumulateSplats is true; otherwise 0.
     * @private
     */
    private evaluateNodeLods;
    /**
     * Evaluates optimal LOD for all nodes without applying changes.
     * Called by GSplatManager during phased global budget enforcement.
     *
     * @param {GraphNode} cameraNode - The camera node.
     * @param {import('./gsplat-params.js').GSplatParams} params - Global gsplat parameters.
     * @param {number} [budgetScale] - Dynamic scale applied to LOD parameters to shift
     * boundaries closer to the budget target. Applied to lodBaseDistance directly, and
     * gently to lodMultiplier via pow(budgetScale, -0.2). Defaults to 1.
     * @param {number} [globalMaxDistanceForBuckets] - When > 0, {@link NodeInfo.budgetBucket} is populated during LOD evaluation for budget balancing.
     * @returns {number} Total optimal splat count.
     */
    evaluateOptimalLods(cameraNode: GraphNode, params: import("./gsplat-params.js").GSplatParams, budgetScale?: number, globalMaxDistanceForBuckets?: number): number;
    /**
     * Applies calculated LOD changes and manages file placements.
     * This is Pass 2 of the LOD update process. Reads from nodeInfos array populated by evaluateNodeLods().
     *
     * @param {number} maxLod - Maximum LOD index (lodLevels - 1).
     * @param {import('./gsplat-params.js').GSplatParams} params - Global gsplat parameters.
     */
    applyLodChanges(maxLod: number, params: import("./gsplat-params.js").GSplatParams): void;
    /**
     * Increments reference count for a file and creates placement immediately.
     *
     * @param {number} fileIndex - The file index.
     * @param {number} nodeIndex - The octree node index.
     * @param {number} lodIndex - The LOD index for this node.
     */
    incrementFileRef(fileIndex: number, nodeIndex: number, lodIndex: number): void;
    /**
     * Decrements reference count for a file and removes placement if needed.
     *
     * @param {number} fileIndex - The file index.
     * @param {number} nodeIndex - The octree node index.
     */
    decrementFileRef(fileIndex: number, nodeIndex: number): void;
    /**
     * Updates existing placement with loaded resource and adds to manager.
     *
     * @param {number} fileIndex - The file index.
     * @returns {boolean} True if placement was updated and added to manager, false otherwise.
     */
    addFilePlacement(fileIndex: number): boolean;
    /**
     * Tests if the octree instance has moved by more than the provided LOD update distance.
     *
     * @param {number} threshold - Distance threshold to trigger an update.
     * @returns {boolean} True if the octree instance has moved by more than the threshold, false otherwise.
     */
    testMoved(threshold: number): boolean;
    /**
     * Updates the previous position of the octree instance.
     */
    updateMoved(): void;
    /**
     * Updates the octree instance each frame.
     *
     * @returns {boolean} True if octree instance is dirty, false otherwise.
     */
    update(): boolean;
    /**
     * Consumes and returns whether the active placement set membership changed (add/remove).
     *
     * @returns {boolean} True if placements were added or removed since last call.
     */
    consumePlacementSetChanged(): boolean;
    debugRender(scene: any): void;
    /**
     * Returns true if this instance requests LOD re-evaluation and resets the flag.
     *
     * @returns {boolean} True if LOD should be re-evaluated.
     */
    consumeNeedsLodUpdate(): boolean;
    /**
     * Polls prefetched file indices for completion and updates state.
     */
    pollPrefetchCompletions(): void;
}
/**
 * Stores LOD state for a single octree node.
 *
 * @ignore
 */
export class NodeInfo {
    /**
     * Current LOD index being rendered. -1 indicates node is not visible.
     */
    currentLod: number;
    /**
     * Optimal LOD index based on distance/visibility (before underfill).
     */
    optimalLod: number;
    /**
     * World-space distance from camera to this node.
     * Used for non-linear bucket mapping in budget enforcement.
     */
    worldDistance: number;
    /**
     * Accumulated camera translation for SH color update threshold tracking.
     */
    colorAccumulatedTranslation: number;
    /**
     * Back-reference to owning GSplatOctreeInstance.
     *
     * @type {GSplatOctreeInstance|null}
     */
    inst: GSplatOctreeInstance | null;
    /**
     * Cached reference to this node's LOD array for fast budget balancing.
     *
     * @type {Array|null}
     */
    lods: any[] | null;
    /**
     * Distance bucket index [0, NUM_BUCKETS - 1] for global budget balancing (sqrt mapping).
     * Written during {@link GSplatOctreeInstance.evaluateNodeLods} when a global max distance
     * is supplied (budget enforcement path only).
     *
     * @type {number}
     */
    budgetBucket: number;
    /**
     * Unique allocation identifier for persistent work buffer allocation tracking.
     *
     * @type {number}
     */
    allocId: number;
    /**
     * Resets all LOD values to -1 (invisible/uninitialized).
     */
    resetLod(): void;
}
import type { GSplatOctree } from './gsplat-octree.js';
import { GSplatPlacement } from './gsplat-placement.js';
import type { GraphicsDevice } from '../../platform/graphics/graphics-device.js';
import { Vec3 } from '../../core/math/vec3.js';
import type { GraphNode } from '../graph-node.js';
