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