import type { Vec3, RenderBounds, BoundsSpec } from "./bounds.js"; import type { BoundsCache } from "./bounds.js"; import type { CameraVisibilityContext, CameraKind } from "./camera.js"; import type { SpatialIndex } from "./spatialIndex.js"; import type { CullingSettings, ObjectVisibilityOverrides } from "./settings.js"; import type { OcclusionTester } from "./occlusion.js"; import type { VisibilityStats } from "./diagnostics.js"; /** * A scene object the visibility system considers. A normal game object already carries a * position and a version counter, so it becomes cullable automatically — no separate * "cullable" component. Everything else is optional override. */ export interface Renderable { readonly id: string; readonly position: Vec3; /** Bumps when transform, geometry, bounds, or overrides change — gates bounds/override recompute. */ readonly version: number; readonly bounds?: BoundsSpec; readonly overrides?: ObjectVisibilityOverrides; readonly layer?: string; /** Fast-path exemption for UI, skyboxes, debug overlays, camera-attached, marked always-visible. */ readonly alwaysVisible?: boolean; /** Asset ids this object needs loaded; feeds the streaming preload/retain sets. */ readonly assets?: readonly string[]; } export interface VisibilitySystemOptions { readonly renderables: () => Iterable; readonly cameras: () => readonly CameraVisibilityContext[]; readonly settings?: Partial; readonly sceneOverrides?: ObjectVisibilityOverrides; readonly globalOverrides?: ObjectVisibilityOverrides; readonly layerOverrides?: (layer: string) => ObjectVisibilityOverrides | undefined; readonly occlusion?: OcclusionTester; /** Injected shared index. Defaults to an internally-owned uniform 3D hash. */ readonly index?: SpatialIndex; readonly boundsCache?: BoundsCache; readonly now?: () => number; } export interface VisibilityResult { /** Objects to submit to the renderer this frame. Valid until the next `update()` (reused set). */ readonly visible: ReadonlySet; /** Objects within the preload region — load their assets, whether or not they render. */ readonly preload: ReadonlySet; readonly stats: VisibilityStats; } export interface VisibilityDebugSnapshot { cameras: { id: string; kind: CameraKind; corners: number[]; preloadMargin: number; }[]; bounds: { id: string; minX: number; minY: number; minZ: number; maxX: number; maxY: number; maxZ: number; visible: boolean; }[]; partitions: { key: string; count: number; minX: number; minY: number; minZ: number; maxX: number; maxY: number; maxZ: number; }[]; culled: string[]; stats: VisibilityStats; } export interface VisibilitySystem { update(): VisibilityResult; isVisible(id: string): boolean; isPreloaded(id: string): boolean; boundsOf(id: string): RenderBounds | undefined; settings(): CullingSettings; setSettings(patch: Partial): void; stats(): VisibilityStats; /** Assets required by the preload set — hand to an AssetStreamingSystem. */ requiredAssets(): ReadonlySet; index(): SpatialIndex; debugSnapshot(): VisibilityDebugSnapshot; clear(): void; } export declare function createVisibilitySystem(options: VisibilitySystemOptions): VisibilitySystem;