import { BatchedMesh, BufferGeometry, Material, Matrix4, Mesh, Object3D } from "three";
import { Context } from "../engine/engine_setup.js";
import type { Renderer } from "./Renderer.js";
declare class InstancingSetupArgs {
    rend: Renderer;
    foundMeshes: number;
    useMatrixWorldAutoUpdate: boolean;
}
/**
 * Handles instancing for Needle Engine.
 */
export declare class InstancingHandler {
    static readonly instance: InstancingHandler;
    /** This is the initial instance count when creating a new instancing structure.
     * Override this and the number of max instances that you expect for a given object.
     * The larger the value the more objects can be added without having to resize but it will also consume more memory.
     * (The instancing mesh renderer will grow x2 if the max instance count is reached)
     * @default 4
     * @returns The initial instance count
     */
    static getStartInstanceCount: (obj: Object3D) => number;
    objs: InstancedMeshRenderer[];
    setup(renderer: Renderer, obj: Object3D, context: Context, handlesArray: InstanceHandle[] | null, args: InstancingSetupArgs, level?: number): InstanceHandle[] | null;
    private tryCreateOrAddInstance;
    private autoUpdateInstanceMatrix;
}
/**
 * The instance handle is used to interface with the mesh that is rendered using instancing.
 */
export declare class InstanceHandle {
    static readonly all: InstanceHandle[];
    /** The name of the object */
    get name(): string;
    get isActive(): boolean;
    get vertexCount(): number;
    get maxVertexCount(): number;
    get reservedVertexCount(): number;
    get indexCount(): number;
    get maxIndexCount(): number;
    get reservedIndexCount(): number;
    /** The object that is being instanced */
    readonly object: Mesh;
    /** The instancer/BatchedMesh that is rendering this object*/
    readonly renderer: InstancedMeshRenderer;
    /** @internal */
    __instanceIndex: number;
    /** @internal */
    __reservedVertexRange: number;
    /** @internal */
    __reservedIndexRange: number;
    __geometryIndex: number;
    /** The mesh information of the object - this tries to also calculate the LOD info */
    readonly meshInformation: MeshInformation;
    constructor(originalObject: Mesh, instancer: InstancedMeshRenderer);
    /** Calculates the mesh information again
     * @returns true if the vertex count or index count has changed
     */
    updateMeshInformation(): boolean;
    /** Updates the matrix from the rendered object. Will also call updateWorldMatrix internally */
    updateInstanceMatrix(updateChildren?: boolean, updateMatrix?: boolean): void;
    /** Updates the matrix of the instance */
    setMatrix(matrix: Matrix4): void;
    /** Can be used to change the geometry of this instance */
    setGeometry(geo: BufferGeometry): boolean;
    /** Adds this object to the instancing renderer (effectively activating instancing) */
    add(): void;
    /** Removes this object from the instancing renderer
     * @param delete_ If true, the instance handle will be removed from the global list
    */
    remove(delete_: boolean): void;
}
declare class InstancedMeshRenderer {
    /** The three instanced mesh
     * @link https://threejs.org/docs/#api/en/objects/InstancedMesh
     */
    get batchedMesh(): BatchedMesh;
    get visible(): boolean;
    set visible(val: boolean);
    get castShadow(): boolean;
    set castShadow(val: boolean);
    set receiveShadow(val: boolean);
    /** If true, the instancer is allowed to grow when the max instance count is reached */
    allowResize: boolean;
    /** The name of the instancer */
    name: string;
    /** The added geometry */
    readonly geometry: BufferGeometry;
    /** The material used for the instanced mesh */
    readonly material: Material;
    /** The current number of instances */
    get count(): number;
    /** Update the bounding box and sphere of the instanced mesh
     * @param box If true, update the bounding box
     * @param sphere If true, update the bounding sphere
    */
    updateBounds(box?: boolean, sphere?: boolean): void;
    private _context;
    private _batchedMesh;
    private _handles;
    private _geometryIds;
    private _maxInstanceCount;
    private _currentInstanceCount;
    private _currentVertexCount;
    private _currentIndexCount;
    private _maxVertexCount;
    private _maxIndexCount;
    private static nullMatrix;
    /** Check if the geometry can be added to this instancer
     * @param geometry The geometry to check
     * @param material The material of the geometry
     * @returns true if the geometry can be added
     */
    canAdd(geometry: BufferGeometry, material: Material): boolean;
    private _needUpdateBounds;
    private _debugMaterial;
    private getBatchedMeshName;
    constructor(name: string, geo: BufferGeometry, material: Material, initialMaxCount: number, context: Context);
    dispose(): void;
    addInstance(obj: Mesh): InstanceHandle | null;
    add(handle: InstanceHandle): boolean;
    remove(handle: InstanceHandle, delete_: boolean): void;
    updateInstance(mat: Matrix4, index: number): void;
    updateGeometry(geo: BufferGeometry, geometryIndex: number): boolean;
    private onBeforeRender;
    private onAfterRender;
    private validateGeometry;
    private markNeedsUpdate;
    /**
     * @param geo The geometry to add (if none is provided it means the geometry is already added and just updated)
     */
    private mustGrow;
    private _growId;
    private grow;
    private tryEstimateVertexCountSize;
    private addGeometry;
    private removeGeometry;
}
declare type MeshInformation = {
    vertexCount: number;
    indexCount: number;
};
export {};
