/** * 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; 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; /** 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; /** 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; } /** 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.Material[] | THREE.Material, 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; /** 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); /** @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;