import { BlockMaskBuffer } from './block-mask-buffer';
import { BlockMaskMap } from './block-mask-map';
declare const SOLID_LO: number;
declare const SOLID_HI: number;
declare const BLOCK_EMPTY = 0;
declare const BLOCK_SOLID = 1;
declare const BLOCK_MIXED = 2;
declare const FACE_MASKS_LO: number[];
declare const FACE_MASKS_HI: number[];
declare const BLOCKS_PER_WORD: number;
declare const TYPE_MASK: number;
declare const SOLID_WORD: number;
declare const EVEN_BITS: number;
/**
 * Read the 2-bit block type directly from a packed `types` Uint32Array.
 * Module-level so V8 can inline it into hot loops without method dispatch.
 * Equivalent to `grid.getBlockType(blockIdx)` when `types === grid.types`.
 *
 * @param types - Packed types array (16 blocks per word).
 * @param blockIdx - Linear block index.
 * @returns Block type: `BLOCK_EMPTY`, `BLOCK_SOLID`, or `BLOCK_MIXED`.
 */
declare const readBlockType: (types: Uint32Array, blockIdx: number) => number;
/**
 * Write the 2-bit block type directly into a packed `types` Uint32Array.
 * Module-level so V8 can inline it into hot loops without method dispatch.
 * Caller is responsible for keeping the grid's `masks` consistent (only
 * `MIXED` blocks should have a mask entry).
 *
 * @param types - Packed types array (16 blocks per word).
 * @param blockIdx - Linear block index.
 * @param value - Block type to set.
 */
declare const writeBlockType: (types: Uint32Array, blockIdx: number, value: number) => void;
declare class SparseVoxelGrid {
    readonly nx: number;
    readonly ny: number;
    readonly nz: number;
    readonly nbx: number;
    readonly nby: number;
    readonly nbz: number;
    readonly bStride: number;
    /**
     * Packed block types: 2 bits per block, 16 blocks per Uint32 word.
     * Length = ceil(totalBlocks / 16).
     */
    types: Uint32Array;
    /** Voxel masks for MIXED blocks, keyed on global block index. */
    masks: BlockMaskMap;
    constructor(nx: number, ny: number, nz: number);
    /**
     * Read the 2-bit block type at the given block index.
     *
     * @param blockIdx - Linear block index (`bx + by*nbx + bz*bStride`).
     * @returns Block type: `BLOCK_EMPTY`, `BLOCK_SOLID`, or `BLOCK_MIXED`.
     */
    getBlockType(blockIdx: number): number;
    /**
     * Write the 2-bit block type at the given block index. Caller is
     * responsible for keeping `masks` consistent (only `MIXED` blocks
     * should have a mask entry; `EMPTY`/`SOLID` should not).
     *
     * @param blockIdx - Linear block index.
     * @param value - Block type to set.
     */
    setBlockType(blockIdx: number, value: number): void;
    getVoxel(ix: number, iy: number, iz: number): number;
    setVoxel(ix: number, iy: number, iz: number): void;
    orBlock(blockIdx: number, lo: number, hi: number): void;
    clear(): void;
    /**
     * Release the large backing arrays once a grid has been consumed.
     */
    releaseStorage(): void;
    clone(): SparseVoxelGrid;
    static fromBuffer(acc: BlockMaskBuffer, nx: number, ny: number, nz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
    toBuffer(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): BlockMaskBuffer;
    /**
     * Crop this grid to a block-aligned sub-region. Returns a fresh grid of
     * size `(cropMaxBx-cropMinBx)*4 x (cropMaxBy-cropMinBy)*4 x (cropMaxBz-cropMinBz)*4`
     * containing the same data with origin shifted to (cropMinBx, cropMinBy, cropMinBz).
     *
     * Iterates only non-empty blocks of the source via word-level skipping.
     *
     * @param cropMinBx - Min block X (inclusive).
     * @param cropMinBy - Min block Y (inclusive).
     * @param cropMinBz - Min block Z (inclusive).
     * @param cropMaxBx - Max block X (exclusive).
     * @param cropMaxBy - Max block Y (exclusive).
     * @param cropMaxBz - Max block Z (exclusive).
     * @param onProgress - Optional progress callback over source `types` words.
     * @returns Newly allocated cropped grid.
     */
    cropTo(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
    /**
     * Crop this grid to a sub-region with inverted occupancy: source EMPTY
     * becomes destination SOLID, source SOLID becomes destination EMPTY,
     * source MIXED becomes destination MIXED with bitwise-inverted mask.
     *
     * The destination grid has dimensions matching the crop window. Used by
     * carve to flip the navigable region (1=navigable) into the runtime's
     * occupancy convention (1=blocked).
     *
     * Note: cropping the EMPTY-becomes-SOLID region is exact within the crop
     * window only. Since the source grid's EMPTY blocks become SOLID in the
     * output, the output's `types` for empty blocks must be set rather than
     * left at their default. We therefore initialize the entire output to
     * SOLID (word fill) and then patch any non-EMPTY source blocks.
     *
     * @param cropMinBx - Min block X (inclusive).
     * @param cropMinBy - Min block Y (inclusive).
     * @param cropMinBz - Min block Z (inclusive).
     * @param cropMaxBx - Max block X (exclusive).
     * @param cropMaxBy - Max block Y (exclusive).
     * @param cropMaxBz - Max block Z (exclusive).
     * @param onProgress - Optional progress callback over source `types` words.
     * @returns Newly allocated cropped + inverted grid.
     */
    cropToInverted(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
    /**
     * Get the bounding box of occupied blocks.
     *
     * @param onProgress - Optional progress callback over `types` words.
     * @returns Block coordinate bounds, or null if no blocks are occupied.
     */
    getOccupiedBlockBounds(onProgress?: (done: number, total: number) => void): {
        minBx: number;
        minBy: number;
        minBz: number;
        maxBx: number;
        maxBy: number;
        maxBz: number;
    } | null;
    /**
     * Get the bounding box of navigable (non-fully-solid) blocks. A block is
     * navigable if it is EMPTY or MIXED (i.e. contains at least one empty
     * voxel). Useful when the runtime treats out-of-grid as solid, so fully
     * solid blocks beyond the navigable region can be cropped away.
     *
     * @param onProgress - Optional progress callback over `types` words.
     * @returns Block coordinate bounds, or null if every block is solid.
     */
    getNavigableBlockBounds(onProgress?: (done: number, total: number) => void): {
        minBx: number;
        minBy: number;
        minBz: number;
        maxBx: number;
        maxBy: number;
        maxBz: number;
    } | null;
    /**
     * Find the nearest free (unblocked) voxel to a seed position using
     * expanding cube shells.
     *
     * @param blocked - Grid to search for free cells in.
     * @param seedIx - Seed voxel X coordinate.
     * @param seedIy - Seed voxel Y coordinate.
     * @param seedIz - Seed voxel Z coordinate.
     * @param maxRadius - Maximum search radius in voxels.
     * @returns Coordinates of the nearest free voxel, or null.
     */
    static findNearestFreeCell(blocked: SparseVoxelGrid, seedIx: number, seedIy: number, seedIz: number, maxRadius: number): {
        ix: number;
        iy: number;
        iz: number;
    } | null;
}
export { BLOCK_EMPTY, BLOCK_MIXED, BLOCK_SOLID, BLOCKS_PER_WORD, EVEN_BITS, FACE_MASKS_HI, FACE_MASKS_LO, SOLID_HI, SOLID_LO, SOLID_WORD, SparseVoxelGrid, TYPE_MASK, readBlockType, writeBlockType };
