import type { BufferElement, RenderMaterial, ViralutionElement } from "../..";
import type { ViralViewerApi } from "../../viral-viewer-api";
import { WorkerThreadPool } from "./base/worker-pool";
export type SpatialRebuildStrategy = "none" | "overlap" | "min-parts";
export declare class LoadBatchedElementWorker {
    viralViewerApi: ViralViewerApi;
    workerPool: WorkerThreadPool;
    workerPool2: WorkerThreadPool;
    /**
     * Feature flag: when true, uses ViralBatchedMeshV3 (Three.js BatchedMesh)
     * instead of ViralBatchedMesh (V1) for batched geometry.
     *
     * V3 benefits: per-element frustum culling, automatic depth sorting,
     * GPU-native visibility, O(1) raycast lookup.
     */
    useBatchedMeshV3: boolean;
    /**
     * Spatial rebuild strategy applied after all buffers are flushed.
     *
     * - `'none'`      — No spatial rebuild; keep meshes as-is from streaming order.
     * - `'overlap'`   — Only rebuild meshes whose bounding box covers ≥ `spatialOverlapThreshold`
     *                    of the model's total bounding box volume (meaning they're spatially scattered).
     * - `'min-parts'` — Force every material group to be split into at least
     *                    `spatialMinParts` spatially coherent meshes.
     */
    spatialRebuildStrategy: SpatialRebuildStrategy;
    /**
     * When `spatialRebuildStrategy` is `'overlap'`, a mesh is considered scattered
     * if its bounding box volume is ≥ this fraction of the model's total bounding box volume.
     * Range: 0–1. Default: 0.6 (60%)
     */
    spatialOverlapThreshold: number;
    /**
     * When `spatialRebuildStrategy` is `'min-parts'`, each material's elements
     * will be divided into at least this many spatially coherent meshes.
     * Default: 4
     */
    spatialMinParts: number;
    /**
     * Maximum number of instanced mesh draw calls before the post-load
     * re-balance pass demotes low-efficiency instanced types to batched meshes.
     * Set to 0 to disable re-balancing. Default: 128 (per D-02).
     */
    drawCallBudget: number;
    private lastRenderTime;
    private elementBuffer;
    private readonly BATCH_THRESHOLD_VERTICES;
    private readonly BATCH_THRESHOLD_OBJECTS;
    constructor(viralViewerApi: ViralViewerApi);
    /**
     * Initialize model with materials
     * @param materials
     * @returns modelId
     */
    initial(materials: RenderMaterial[]): number;
    /**
     * Main load method - automatically routes to spatial or traditional approach
     */
    loadElement(modelId: number, elements: ViralutionElement[], callbackOnSuccess?: () => void, globalTranslation?: {
        x: number;
        y: number;
        z: number;
    } | null): void;
    /**
     * Promise-based load method - routes elements to batched/instanced workers
     * and resolves when all workers have finished processing.
     */
    loadElementAsync(modelId: number, elements: ViralutionElement[], globalTranslation?: {
        x: number;
        y: number;
        z: number;
    } | null): Promise<void>;
    /**
     * Register additional materials for a model after initial() has been called.
     * Used by the IFC loader when streaming discovers colors not in DEFAULT_MATERIALS.
     */
    registerMaterials(modelId: number, materials: RenderMaterial[], startIndex: number): void;
    /**
     * Directly ingest pre-converted BufferElement[] from the IFC loader,
     * bypassing the geometry worker pipeline. Used when geometry is already
     * in BufferElement format (ifc-lite produces flat Float32Array positions directly).
     */
    loadBufferElementsDirect(modelId: number, bufferElements: BufferElement[]): void;
    private loadInstancedElementAsync;
    private loadBatchedElementAsync;
    private computeBatchLimits;
    /** Split elements to chunks that satisfy both vertex and object limits. */
    private splitByLimits;
    /**
     * Compute the centroid of a BufferElement's geometry from its position buffer.
     */
    private computeElementCentroid;
    /**
     * Split elements into spatially coherent chunks using recursive longest-axis bisection.
     *
     * Instead of arbitrarily chunking elements in arrival order, this:
     * 1. Computes each element's centroid
     * 2. Finds the longest spatial axis of the element set
     * 3. Sorts by that axis and splits at the midpoint
     * 4. Recurses until each chunk fits within vertex/object limits
     *
     * Result: each batched mesh covers a compact spatial region, enabling
     * effective frustum culling on zoom/rotation.
     */
    private splitBySpatialPartition;
    /**
     * Split elements into exactly `minParts` spatially coherent chunks
     * using recursive longest-axis bisection, regardless of vertex limits.
     */
    private splitByMinParts;
    private minPartsSplitRecursive;
    private spatialSplitRecursive;
    /**
     * Create single merged mesh (traditional implementation)
     */
    private createSingleMergedMesh;
    /**
     * Create single merged mesh using Three.js BatchedMesh (V3).
     * Per-element frustum culling, automatic depth sorting, GPU-native visibility.
     */
    private createSingleMergedMeshV3;
    private createSingleInstancedMesh;
    /**
     * Create optimized material for merging with per-element opacity support
     * Uses onBeforeCompile to inject custom shader code for RGBA vertex colors
     */
    private createOptimizedMaterial;
    /**
     * 🎨 Inject custom shader modifications for per-element opacity
     * This modifies the material's shaders to support RGBA vertex colors
     * where the alpha channel controls per-element transparency
     */
    private injectPerElementOpacityShader;
    /**
     * Create optimized material for V3 (Three.js BatchedMesh).
     * Unlike V1, V3 doesn't use vertexColors — it uses BatchedMesh's per-instance colors.
     * Alpha is injected via custom shader reading from batchingColorTexture.
     */
    private createOptimizedMaterialV3;
    /**
     * Throttled render to avoid excessive render calls
     */
    private throttledRender;
    /**
     * 🚀 Add elements to buffer and batch when threshold is reached
     */
    private addToBuffer;
    /**
     * 🚀 Flush accumulated elements for a specific material
     */
    private flushBuffer;
    /**
     * V3 flush: appends elements to existing ViralBatchedMeshV3 or creates a new one.
     * No 500K vertex limit — BatchedMesh handles capacity internally.
     */
    private flushBufferV3;
    /**
     * 🚀 Flush all remaining buffers (call this when loading is complete).
     *
     * Buffer flushing is synchronous so geometry is visible immediately.
     * Post-load optimizations (draw-call rebalance, spatial rebuild) run
     * asynchronously to avoid blocking the main thread.
     */
    flushAllBuffers(): void;
    private runPostLoadOptimizations;
    private rebuildSelectables;
    /**
     * 🌍 Rebuild all V1 batched meshes using spatial partitioning.
     *
     * During streaming, elements arrive in arbitrary order and get batched by
     * sequential vertex limits. This means each mesh contains geometry scattered
     * across the entire model — frustum culling becomes ineffective because every
     * mesh's bounding box overlaps every camera view.
     *
     * This method:
     * 1. Collects all V1 meshes per material
     * 2. Extracts their buffer elements
     * 3. Disposes the original meshes
     * 4. Re-partitions elements into spatially coherent chunks
     * 5. Creates new meshes from the spatial chunks
     *
     * Result: each mesh covers a compact spatial region, so frustum culling
     * can skip entire meshes when the camera is zoomed into one area.
     */
    private spatialRebuildAllMeshes;
}
