/** * OctreeLODSystem.ts * * Octree-based Level-of-Detail system for Gaussian Splatting scenes. * Implements the Octree-GS approach (TPAMI 2025): anchor Gaussians assigned * to octree levels with camera-distance LOD selection and budget-aware capping. * * Key design decisions: * - Anchor Gaussians are stored at the octree level matching their detail scale * - Camera distance determines which LOD levels contribute to rendering * - Power-law (Levy flight) transition thresholds replace linear spacing * - Budget enforcement drops deepest LOD levels first when over cap * - VR mode reserves fixed budget per avatar (W.034: 60K each, max 3) * * Research references: * W.032 - Octree-GS LOD (anchor-based level selection, TPAMI 2025) * W.034 - VR Gaussian budget (~180K total on Quest 3 at 72fps) * P.030.01 - Hierarchical LOD Gaussian Architecture pattern * P.030.05 - VR Gaussian Budget Management pattern * * @module spatial */ import { Vector3 } from './SpatialTypes'; /** * Gaussian anchor: a representative Gaussian at a specific octree level. * At rendering time, only anchors from selected LOD levels are drawn. */ export interface GaussianAnchor { /** Unique identifier for this anchor Gaussian */ id: string; /** World-space position (center of the Gaussian) */ position: Vector3; /** Gaussian scale (max axis determines effective radius for octree insertion) */ scale: number; /** LOD level this anchor belongs to (0 = coarsest/root, higher = finer detail) */ lodLevel: number; /** Number of Gaussians this anchor represents (for budget accounting) */ gaussianCount: number; /** Optional: index into the original splat array for rendering */ splatIndex?: number; /** V11: Perceptual importance (0-1, default 0.5). Higher = kept under budget pressure */ importance?: number; } /** * Configuration for the octree LOD system. */ export interface OctreeLODConfig { /** Maximum octree depth (number of LOD levels). 4-8 typical for city-scale. */ maxDepth: number; /** * Power-law exponent for transition threshold spacing. * Controls how distance thresholds grow with LOD level. * - 1.0 = linear spacing (uniform) * - 1.5 = moderate power-law (recommended for indoor/room-scale) * - 2.0 = aggressive power-law (recommended for outdoor/city-scale) * Levy flight research (W.030) suggests power-law distributions match * natural depth trajectory patterns in camera movement. */ powerLawExponent: number; /** Base distance for LOD level 0 transition (in world units) */ baseDistance: number; /** Maximum distance for the outermost LOD level (in world units) */ maxDistance: number; /** VR mode: enable hard budget enforcement */ vrMode: boolean; /** Total Gaussian budget (0 = unlimited). VR default: 180000 (Quest 3 at 72fps) */ gaussianBudget: number; /** Per-avatar Gaussian reservation (0 = no avatar reservations) */ perAvatarReservation: number; /** Maximum number of avatars with reserved budgets */ maxAvatars: number; /** Maximum anchors per node before subdivision */ maxAnchorsPerNode: number; } /** * Result of an LOD selection query: which levels and anchors to render. */ export interface LODSelectionResult { /** LOD levels selected for rendering (0 = coarsest, higher = finer) */ selectedLevels: number[]; /** Total Gaussians selected across all levels */ totalGaussians: number; /** Whether the budget cap was applied (some levels were dropped) */ budgetCapped: boolean; /** Number of LOD levels dropped due to budget cap */ levelsDropped: number; /** Anchor Gaussians to render (flattened from selected levels) */ anchors: GaussianAnchor[]; /** Camera distance to scene center */ cameraDistance: number; /** Computed transition thresholds (for debugging/visualization) */ thresholds: number[]; /** Available Gaussian budget after avatar reservations */ availableBudget: number; } /** * Per-level statistics for the octree. */ export interface LODLevelStats { level: number; anchorCount: number; gaussianCount: number; nodeCount: number; } /** * Metrics snapshot for the entire OctreeLOD system. */ export interface OctreeLODMetrics { /** Total anchor count across all levels */ totalAnchors: number; /** Total Gaussian count across all levels */ totalGaussians: number; /** Per-level breakdown */ levels: LODLevelStats[]; /** Octree depth (actual, may be less than maxDepth) */ actualDepth: number; /** Number of active avatar reservations */ activeAvatarReservations: number; /** Total nodes in the octree */ totalNodes: number; } /** * Octree-based Level-of-Detail system for Gaussian Splatting scenes. * * Architecture (based on Octree-GS, TPAMI 2025): * * 1. **Octree Construction**: Scene bounding box is recursively subdivided * into 8 children up to maxDepth levels. Each level corresponds to an * LOD level (depth 0 = coarsest overview, depth N = finest detail). * * 2. **Anchor Assignment**: Gaussian splats are assigned to the octree level * matching their detail scale. Coarse/large Gaussians go to shallow levels; * fine/small Gaussians go to deep levels. This is the "anchor" concept * from Octree-GS. * * 3. **LOD Selection**: Given a camera position, compute distance to each * octree voxel. Use power-law transition thresholds to determine which * LOD levels are active. Closer voxels activate deeper (finer) levels. * * 4. **Budget Enforcement**: Sum Gaussian counts across selected levels. * If total exceeds the budget, drop the deepest (finest) levels first. * This preserves scene overview while sacrificing fine detail under pressure. * * 5. **VR Mode**: Reserves fixed Gaussian budget per avatar (e.g., 60K each), * then allocates remaining budget to scene LOD selection. * * Usage: * ```typescript * const lod = new OctreeLODSystem({ * maxDepth: 6, * powerLawExponent: 1.5, * baseDistance: 2.0, * maxDistance: 200.0, * vrMode: true, * gaussianBudget: 180000, * perAvatarReservation: 60000, * maxAvatars: 3, * }); * * // Build octree from scene bounds * lod.initialize(0, 0, 0, 100); // center + halfSize * * // Insert anchor Gaussians at appropriate LOD levels * lod.insertAnchor({ id: 'a0', x: 10, y: 0, z: 5, scale: 2.0, lodLevel: 0, gaussianCount: 500 }); * lod.insertAnchor({ id: 'a1', x: 10, y: 0, z: 5, scale: 0.1, lodLevel: 4, gaussianCount: 50 }); * * // Select LOD levels for current camera * const selection = lod.selectLOD(cameraX, cameraY, cameraZ); * // selection.anchors contains the Gaussians to render this frame * ``` */ export declare class OctreeLODSystem { private root; private config; private thresholds; private anchorCount; private totalGaussianCount; private activeAvatars; private nodeCount; /** Scene center for distance calculations */ private sceneCenter; constructor(config?: Partial); /** * Initialize the octree with scene bounds. * Must be called before inserting anchors. */ initialize(centerX: number, centerY: number, centerZ: number, halfSize: number): void; /** * Initialize from a bounding box (min/max corners). */ initializeFromBounds(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): void; /** * Compute power-law transition thresholds for LOD level selection. * * Power-law spacing (Levy flight-inspired, W.030): * threshold[i] = baseDistance * ((i + 1) / maxDepth) ^ exponent * (maxDistance / baseDistance) * * This produces thresholds that are tightly spaced near the camera * (where detail matters most) and widely spaced at far distances * (where coarse LOD suffices). */ private computeThresholds; /** * Get the computed transition thresholds (read-only). */ getThresholds(): readonly number[]; /** * Insert an anchor Gaussian into the octree at its designated LOD level. * Returns true if successfully inserted. */ insertAnchor(anchor: GaussianAnchor): boolean; private insertIntoNode; /** * Remove an anchor by ID. */ removeAnchor(id: string): boolean; private removeFromNode; /** * Bulk-insert anchors (more efficient than individual inserts for large scenes). * Anchors are sorted by LOD level for efficient tree traversal. */ bulkInsert(anchors: GaussianAnchor[]): number; /** * Select LOD levels and anchors to render based on camera position. * * Algorithm: * 1. Compute camera distance to scene center * 2. Walk thresholds to find the deepest (finest) LOD level visible * 3. Select all levels from 0 (coarsest) through the deepest visible level * 4. Collect anchors from selected levels * 5. If budget mode, drop deepest levels until under budget * 6. In VR mode, subtract avatar reservations from available budget */ selectLOD(cameraX: number, cameraY: number, cameraZ: number, avatarCount?: number): LODSelectionResult; /** * Recursively collect anchors from the octree that belong to the selected levels. */ private collectAnchors; /** * Set the number of active avatars (for VR budget reservation). */ setActiveAvatars(count: number): void; /** * Get the number of active avatar reservations. */ getActiveAvatars(): number; /** * Get the scene-available Gaussian budget after avatar reservations. */ getAvailableSceneBudget(): number; /** * Compute the appropriate LOD level for a Gaussian based on its scale. * * Larger Gaussians (coarse detail) -> lower LOD levels (shallow octree nodes) * Smaller Gaussians (fine detail) -> higher LOD levels (deep octree nodes) * * Uses logarithmic mapping: level = floor(log2(maxScale / scale)) * Clamped to [0, maxDepth-1]. */ computeLODLevelFromScale(scale: number, maxScaleInScene: number): number; private createNode; private subdivideNode; private containsPoint; /** * Get comprehensive metrics about the octree state. */ getMetrics(): OctreeLODMetrics; private collectMetrics; /** * Get the total number of anchors. */ getAnchorCount(): number; /** * Get the total Gaussian count across all anchors. */ getTotalGaussianCount(): number; /** * Get the current configuration. */ getConfig(): Readonly; /** * Update configuration (recomputes thresholds). */ updateConfig(config: Partial): void; /** * Clear all anchors and reset the octree. * Preserves configuration. */ clear(): void; /** * Check if the system has been initialized. */ isInitialized(): boolean; } //# sourceMappingURL=OctreeLODSystem.d.ts.map