IFClite TypeScript API
    Preparing search index...

    Interface BatchedMesh

    Batched mesh - groups multiple meshes with same color into single draw call Reduces draw calls from N meshes to ~100-500 batches

    When a single color group's geometry would exceed the GPU's maxBufferSize limit, the data is automatically split across multiple buckets at accumulation time. Each bucket gets a unique colorKey (base key or "base#N"), so the rest of the pipeline stays unchanged.

    interface BatchedMesh {
        bindGroup?: GPUBindGroup;
        bounds?: { max: [number, number, number]; min: [number, number, number] };
        color: [number, number, number, number];
        colorKey: string;
        expressIds: number[];
        finish?: Partial<Pick<Material, "metallic" | "roughness">>;
        gpuResident?: boolean;
        id: number;
        indexBuffer: GPUBuffer;
        indexCount: number;
        lod1IndexBuffer?: GPUBuffer;
        lod1IndexCount?: number;
        modelIndices?: (number | undefined)[];
        origin?: [number, number, number];
        quantized?: { min: [number, number, number]; step: number };
        uniformBuffer?: GPUBuffer;
        vertexBuffer: GPUBuffer;
    }
    Index
    bindGroup?: GPUBindGroup
    bounds?: { max: [number, number, number]; min: [number, number, number] }
    color: [number, number, number, number]
    colorKey: string
    expressIds: number[]
    finish?: Partial<Pick<Material, "metallic" | "roughness">>

    Finish shared by every piece: colorKey folds it in at 1/1000, so a batch never mixes finishes (#5582).

    gpuResident?: boolean

    GPU residency (issue #1682 phase 3a): false = evicted metadata shell — bounds/expressIds/counts remain valid for culling, picking-fallback and bookkeeping, but the GPU buffers are destroyed and MUST NOT be bound. The draw loop skips such batches and requests a rebuild via Scene.requestBatchResidency. undefined/true = resident.

    id: number
    indexBuffer: GPUBuffer
    indexCount: number
    lod1IndexBuffer?: GPUBuffer

    LOD1 (issue #1682 phase 5): simplified index range over the SAME vertex buffer, drawn instead of the full indices when the batch projects below the configured screen size. Absent = no LOD (draw full detail always).

    lod1IndexCount?: number
    modelIndices?: (number | undefined)[]

    Per-entry modelIndex, parallel to expressIds (same index = same source piece): batches group by colour (see Scene.bucketBaseKey), NOT by model, so two federated models sharing an expressId AND colour can land in the SAME batch as distinct entries. Picking must scope each entry by its own modelIndex here rather than treating the batch as single-model. Absent entries (or undefined values) mean "unscoped" for that entry — legacy batches built before this field existed, or single-model scenes.

    origin?: [number, number, number]

    Per-batch local-frame origin: stored vertex positions are RELATIVE to it, so this batch must be drawn with model = translate(origin) to land in world space (world = origin + position). Keeps f32 vertex coords element-small at building/georef scale (no fan collapse). [0,0,0] = absolute (legacy).

    quantized?: { min: [number, number, number]; step: number }

    12-byte lattice-quantized vertex buffer (issue #1682 phase 6): when present, vertexBuffer holds uint16x4+u32 records and the batch must draw through the quantized pipeline variants with these dequantization params in the uniform. Absent = 28-byte f32 layout (the default).

    uniformBuffer?: GPUBuffer
    vertexBuffer: GPUBuffer