UNPKG

@playcanvas/splat-transform

Version:

Library and CLI tool for 3D Gaussian splat format conversion and transformation

179 lines (178 loc) 6.61 kB
import { Vec3 } from 'playcanvas'; import { DataTable } from '../data-table'; /** * Axis-aligned bounding box for BVH nodes. */ interface BVHBounds { minX: number; minY: number; minZ: number; maxX: number; maxY: number; maxZ: number; } /** * BVH node for Gaussian AABBs. */ interface GaussianBVHNode { /** Number of Gaussians in this subtree */ count: number; /** Bounds of all Gaussian AABBs in this subtree */ bounds: BVHBounds; /** Gaussian indices (only for leaf nodes) */ indices?: Uint32Array; /** Left child (only for interior nodes) */ left?: GaussianBVHNode; /** Right child (only for interior nodes) */ right?: GaussianBVHNode; } /** * BVH (Bounding Volume Hierarchy) for efficient spatial queries on Gaussian AABBs. * * Unlike the centroid-based BTree, this BVH stores the full AABB for each node, * computed from position +/- extent for all Gaussians in the subtree. */ declare class GaussianBVH { /** Root node of the BVH */ root: GaussianBVHNode; /** Position data from the original DataTable */ private x; private y; private z; /** Extent data */ private extentX; private extentY; private extentZ; /** Maximum leaf size */ private static readonly MAX_LEAF_SIZE; /** * Construct a BVH from Gaussian data. * * @param dataTable - DataTable containing position (x, y, z) columns * @param extents - DataTable containing extent (extent_x, extent_y, extent_z) columns */ constructor(dataTable: DataTable, extents: DataTable); /** * Compute the AABB that bounds all Gaussian AABBs for the given indices. * * @param indices - Array of Gaussian indices * @returns The bounding box that contains all specified Gaussians */ private computeBounds; /** * Build a BVH node recursively. * * @param indices - Array of Gaussian indices to include in this subtree * @returns The constructed BVH node */ private buildNode; /** * Query all Gaussian indices whose AABBs overlap the given box. * * @param boxMin - Minimum corner of query box * @param boxMax - Maximum corner of query box * @returns Array of Gaussian indices that overlap the box */ queryOverlapping(boxMin: Vec3, boxMax: Vec3): number[]; /** * Query all Gaussian indices whose AABBs overlap the given box (using raw coordinates). * * @param minX - Minimum X of query box * @param minY - Minimum Y of query box * @param minZ - Minimum Z of query box * @param maxX - Maximum X of query box * @param maxY - Maximum Y of query box * @param maxZ - Maximum Z of query box * @returns Array of Gaussian indices that overlap the box */ queryOverlappingRaw(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[]; /** * Query all Gaussian indices whose AABBs intersect a view frustum * defined by 6 planes. Each plane is `(nx, ny, nz, d)` and points into * the frustum: a point is inside the frustum iff `n · p >= d` for every * plane. An AABB is rejected only when it lies fully on the negative * side of some plane. * * Writes matching indices into `result` starting at `offset`, stopping * if the buffer fills up. The total match count is still returned even * when the buffer is too small, so the caller can grow and retry. * Mirrors the `queryOverlappingRawInto` contract. * * @param planes - 24 floats (6 planes × 4 floats: nx, ny, nz, d). * @param result - Output buffer of Gaussian indices. * @param offset - Starting element offset in `result`. * @returns Number of matching Gaussian indices. */ queryFrustumRawInto(planes: Float32Array, result: Uint32Array, offset: number): number; /** * Recursive frustum-plane query helper. * * @param node - Current BVH node. * @param planes - 24 floats (6 planes × 4 floats). * @param result - Buffer to append matching indices into. * @param offset - Starting element offset in `result`. * @param count - Number of matches already written for this query. * @returns Updated match count. */ private queryFrustumNode; /** * Query overlapping Gaussian indices directly into a caller-provided buffer. * * Returns the total number of matches even if the target buffer is too * small; in that case only the prefix that fits is written and the caller * can grow the buffer then retry. * * @param minX - Minimum X of query box * @param minY - Minimum Y of query box * @param minZ - Minimum Z of query box * @param maxX - Maximum X of query box * @param maxY - Maximum Y of query box * @param maxZ - Maximum Z of query box * @param result - Buffer to append matching Gaussian indices into. * @param offset - Starting element offset in `result`. * @returns Number of matching Gaussian indices. */ queryOverlappingRawInto(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number, result: Uint32Array, offset: number): number; /** * Recursive query helper. * * @param node - Current BVH node to query * @param minX - Query box minimum X * @param minY - Query box minimum Y * @param minZ - Query box minimum Z * @param maxX - Query box maximum X * @param maxY - Query box maximum Y * @param maxZ - Query box maximum Z * @param result - Array to append matching indices to */ private queryNode; /** * Recursive typed-buffer query helper. * * @param node - Current BVH node to query * @param minX - Query box minimum X * @param minY - Query box minimum Y * @param minZ - Query box minimum Z * @param maxX - Query box maximum X * @param maxY - Query box maximum Y * @param maxZ - Query box maximum Z * @param result - Buffer to append matching indices into * @param offset - Starting element offset in `result` * @param count - Number of matches already found for this query * @returns Updated match count */ private queryNodeInto; /** * Get the total number of Gaussians in the BVH. * * @returns The total count of Gaussians */ get count(): number; /** * Get the bounds of the entire scene. * * @returns The scene bounding box */ get sceneBounds(): BVHBounds; } export { GaussianBVH, GaussianBVHNode, BVHBounds };