/**
 * One-call scene import: every static mesh of an Object3D (e.g. a loaded glTF scene) becomes VirtualGeometry geometry.
 *
 * Meshes are grouped by (geometry, geometry group, material, render flags), so repeated geometry becomes one
 * VirtualMesh with one instance per occurrence (InstancedMesh instances included). Each unique geometry range
 * is built once. Skinned and morphing meshes, points, lines and sprites are left alone and keep rendering.
 */
import * as THREE from 'three/webgpu';
import { type VirtualGeometryCachedBuildOptions } from '../io/cache.js';
import { type VirtualMeshBuildOptions, type VirtualMeshData, type VirtualMeshSource } from '../preprocess/buildVirtualMesh.js';
import type { VirtualGeometry } from '../runtime/VirtualGeometry.js';
import type { VirtualMesh, VirtualMeshOptions } from '../runtime/VirtualMesh.js';
/** Builds one DAG. Same signature as `buildVirtualMesh`, so a caching builder drops in here or via `options.builder`. */
export type VirtualGeometryBuilder = (source: VirtualMeshSource, options?: VirtualMeshBuildOptions) => Promise<VirtualMeshData>;
export interface VirtualGeometryImportOptions {
    /**
     * DAG build options for every geometry (`onProgress` is driven by the import; use `onProgress` below), including
     * `cache` options for the default cached builder, e.g. `{ cache: { maxBytes: 2 * 1024 ** 3 } }`.
     */
    build?: Omit<VirtualGeometryCachedBuildOptions, 'onProgress'>;
    /** Options for each created VirtualMesh (e.g. `maxDrawDistance`), or a function returning them per group. */
    mesh?: VirtualMeshOptions | ((group: VirtualGeometryImportGroup) => VirtualMeshOptions | undefined);
    /** Return false to leave a mesh as it is (it keeps rendering normally). Called for every compatible mesh. */
    filter?: (mesh: THREE.Mesh) => boolean;
    /**
     * true (default): the VirtualMeshes are added to `object` and the converted meshes stop rendering (their
     * leaf meshes are taken out of the graph, meshes with children stay with their layers cleared; `dispose()`
     * restores both). false: nothing in the scene changes; add `result.object` yourself.
     */
    replace?: boolean;
    /** Overall progress in 0..1 while building. May be async (awaited), e.g. to let the page repaint. */
    onProgress?: (fraction: number) => void | Promise<void>;
    /** Converts a source material. Default: node materials are cloned, classic mesh materials go through `toNodeMaterial`. */
    material?: (material: THREE.Material, group: VirtualGeometryImportGroup) => THREE.NodeMaterial | null;
    /** DAG builder (default `buildVirtualMesh`), e.g. a cached one with the same signature. */
    builder?: VirtualGeometryBuilder;
}
/** Meshes that share geometry, geometry range, material and render flags: one VirtualMesh. */
export interface VirtualGeometryImportGroup {
    geometry: THREE.BufferGeometry;
    /** Index range (vertex range for non-indexed geometry) this group draws: one entry of `geometry.groups`, clipped to the draw range. */
    range: {
        start: number;
        count: number;
    };
    material: THREE.Material;
    /** Column-major world matrix per instance (16 floats each), in the order of `instances`. */
    matrices: Float32Array;
    /** rgba per instance, from `InstancedMesh.instanceColor` (null when no source has instance colors). */
    colors: Float32Array | null;
    /** Source of each instance: the mesh, and the instance index for an InstancedMesh (else -1). */
    instances: {
        object: THREE.Mesh;
        index: number;
    }[];
    /** Per-vertex colors are used (`material.vertexColors` and a `color` attribute), like three would. */
    vertexColors: boolean;
    castShadow: boolean;
    receiveShadow: boolean;
    /** False when the mesh or one of its ancestors is hidden. */
    visible: boolean;
    renderOrder: number;
    layers: number;
    /** From the first source mesh. */
    name: string;
    userData: Record<string, unknown>;
}
/** Why a mesh is left alone, or null when it can be converted. */
export declare function incompatibility(mesh: THREE.Object3D): string | null;
/**
 * Collects the convertible meshes under `root` into instance groups (pure CPU work, no GPU, testable in Node).
 * World matrices are read after updating them, so the result matches what three would render now.
 */
export declare function collectVirtualGeometryGroups(root: THREE.Object3D, filter?: (mesh: THREE.Mesh) => boolean): {
    groups: VirtualGeometryImportGroup[];
    meshes: THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material<THREE.MaterialEventMap>[] | THREE.Material<THREE.MaterialEventMap>, THREE.Object3DEventMap>[];
    skipped: {
        object: THREE.Object3D;
        reason: string;
    }[];
};
/** Result of `VirtualGeometry.add()`: the created meshes, and how to undo the import. */
export declare class VirtualGeometryImport {
    private readonly context;
    /** Holds every created VirtualMesh. Added to the imported object unless `replace: false`. */
    readonly object: THREE.Group<THREE.Object3DEventMap>;
    /** One VirtualMesh per entry of `groups`. */
    readonly meshes: VirtualMesh[];
    groups: VirtualGeometryImportGroup[];
    /** Meshes that were left alone, and why. */
    readonly skipped: {
        object: THREE.Object3D;
        reason: string;
    }[];
    readonly stats: {
        sourceMeshes: number;
        instances: number;
        uniqueGeometries: number;
        buildMs: number;
    };
    private readonly hidden;
    /** Converted leaf meshes taken out of the graph, with their former parent (restored by `dispose`). */
    private readonly detached;
    constructor(context: VirtualGeometry, collected: ReturnType<typeof collectVirtualGeometryGroups>);
    /** @internal Stops the given source meshes from rendering (restored by `dispose`). */
    hide(meshes: THREE.Mesh[], root: THREE.Object3D): void;
    /** World matrix of a source object, also when it (or its ancestors) were taken out of the graph. */
    private worldMatrixOf;
    /**
     * Re-reads every source mesh's current world matrix into the instances (call after moving the imported
     * object or animating its nodes). Instances are baked in world space at import time otherwise.
     */
    syncTransforms(): void;
    /** Removes the VirtualMeshes and lets the source meshes render again. */
    dispose(): void;
}
/**
 * Converts every compatible mesh under `object` to VirtualGeometry geometry. See `VirtualGeometry.add`.
 */
export declare function virtualMeshesFromObject3D(context: VirtualGeometry, object: THREE.Object3D, options?: VirtualGeometryImportOptions): Promise<VirtualGeometryImport>;
