@playcanvas/splat-transform
Version:
Library and CLI tool for 3D Gaussian splat format conversion and transformation
169 lines (168 loc) • 7.8 kB
TypeScript
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 };