@manycore/aholo-splat-transform 1.2.7 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +120 -106
  2. package/COPYRIGHT.md +17 -0
  3. package/README.md +39 -39
  4. package/THIRD_PARTY_LICENSES.txt +1373 -0
  5. package/bin/cli.js +125 -118
  6. package/dist/SplatData.d.ts +67 -67
  7. package/dist/SplatData.js +167 -156
  8. package/dist/constant.d.ts +3 -3
  9. package/dist/constant.js +13 -13
  10. package/dist/file/IFile.d.ts +5 -5
  11. package/dist/file/IFile.js +1 -1
  12. package/dist/file/esz.d.ts +11 -0
  13. package/dist/file/esz.js +337 -0
  14. package/dist/file/index.d.ts +8 -7
  15. package/dist/file/index.js +7 -6
  16. package/dist/file/ksplat.d.ts +12 -12
  17. package/dist/file/ksplat.js +293 -232
  18. package/dist/file/lcc.d.ts +11 -11
  19. package/dist/file/lcc.js +161 -157
  20. package/dist/file/ply.d.ts +13 -13
  21. package/dist/file/ply.js +439 -388
  22. package/dist/file/sog.d.ts +80 -80
  23. package/dist/file/sog.js +525 -504
  24. package/dist/file/splat.d.ts +6 -6
  25. package/dist/file/splat.js +119 -99
  26. package/dist/file/spz.d.ts +11 -8
  27. package/dist/file/spz.js +597 -400
  28. package/dist/file/voxel.d.ts +43 -37
  29. package/dist/file/voxel.js +411 -280
  30. package/dist/index.d.ts +33 -33
  31. package/dist/index.js +54 -54
  32. package/dist/native/index.d.ts +54 -54
  33. package/dist/native/index.js +122 -128
  34. package/dist/native/utils.d.ts +1 -0
  35. package/dist/native/utils.js +54 -0
  36. package/dist/tasks/AutoChunkLodTask.d.ts +13 -13
  37. package/dist/tasks/AutoChunkLodTask.js +117 -117
  38. package/dist/tasks/AutoLodTask.d.ts +10 -10
  39. package/dist/tasks/AutoLodTask.js +20 -20
  40. package/dist/tasks/BaseTask.d.ts +15 -15
  41. package/dist/tasks/BaseTask.js +5 -5
  42. package/dist/tasks/FlexLodTask.d.ts +12 -12
  43. package/dist/tasks/FlexLodTask.js +54 -44
  44. package/dist/tasks/ModifyTask.d.ts +9 -9
  45. package/dist/tasks/ModifyTask.js +166 -156
  46. package/dist/tasks/ReadTask.d.ts +9 -9
  47. package/dist/tasks/ReadTask.js +29 -29
  48. package/dist/tasks/SkeletonLodTask.d.ts +10 -10
  49. package/dist/tasks/SkeletonLodTask.js +176 -156
  50. package/dist/tasks/VoxelTask.d.ts +35 -30
  51. package/dist/tasks/VoxelTask.js +40 -37
  52. package/dist/tasks/WriteTask.d.ts +12 -11
  53. package/dist/tasks/WriteTask.js +70 -70
  54. package/dist/utils/BufferReader.d.ts +12 -12
  55. package/dist/utils/BufferReader.js +45 -47
  56. package/dist/utils/Logger.d.ts +11 -11
  57. package/dist/utils/Logger.js +40 -38
  58. package/dist/utils/StreamChunkDecoder.d.ts +16 -16
  59. package/dist/utils/StreamChunkDecoder.js +31 -36
  60. package/dist/utils/index.d.ts +27 -27
  61. package/dist/utils/index.js +101 -101
  62. package/dist/utils/k-means.d.ts +4 -4
  63. package/dist/utils/k-means.js +340 -350
  64. package/dist/utils/math.d.ts +46 -46
  65. package/dist/utils/math.js +350 -351
  66. package/dist/utils/quantize-1d.d.ts +4 -4
  67. package/dist/utils/quantize-1d.js +164 -164
  68. package/dist/utils/sh-rotate.d.ts +2 -2
  69. package/dist/utils/sh-rotate.js +236 -175
  70. package/dist/utils/splat.d.ts +21 -20
  71. package/dist/utils/splat.js +397 -378
  72. package/dist/utils/voxel/binary.d.ts +8 -0
  73. package/dist/utils/voxel/binary.js +176 -0
  74. package/dist/utils/voxel/common.d.ts +178 -162
  75. package/dist/utils/voxel/common.js +1752 -1700
  76. package/dist/utils/voxel/coplanar-merge.d.ts +63 -63
  77. package/dist/utils/voxel/coplanar-merge.js +818 -819
  78. package/dist/utils/voxel/filter-cluster.d.ts +20 -0
  79. package/dist/utils/voxel/filter-cluster.js +628 -0
  80. package/dist/utils/voxel/gpu-dilation.d.ts +2 -2
  81. package/dist/utils/voxel/gpu-dilation.js +677 -665
  82. package/dist/utils/voxel/marching-cubes.d.ts +42 -42
  83. package/dist/utils/voxel/marching-cubes.js +1645 -1657
  84. package/dist/utils/voxel/mesh.d.ts +3 -3
  85. package/dist/utils/voxel/mesh.js +130 -130
  86. package/dist/utils/voxel/nav.d.ts +29 -29
  87. package/dist/utils/voxel/nav.js +1068 -1043
  88. package/dist/utils/voxel/postprocess.d.ts +23 -23
  89. package/dist/utils/voxel/postprocess.js +408 -375
  90. package/dist/utils/voxel/voxel-faces.d.ts +18 -18
  91. package/dist/utils/voxel/voxel-faces.js +662 -663
  92. package/dist/utils/voxel/voxelize.d.ts +34 -33
  93. package/dist/utils/voxel/voxelize.js +1208 -1193
  94. package/dist/utils/webgpu.d.ts +8 -8
  95. package/dist/utils/webgpu.js +122 -122
  96. package/package.json +37 -30
  97. package/dist/native/cpp/bin/linux/binding.node +0 -0
  98. package/dist/native/cpp/bin/windows/binding.node +0 -0
@@ -0,0 +1,8 @@
1
+ export type VoxelNodeEncoding = 'raw' | 'compact';
2
+ export interface DecodedVoxelBinary {
3
+ nodes: Uint32Array;
4
+ leafData: Uint32Array;
5
+ }
6
+ export declare function encodeRawVoxelBinary(nodes: Uint32Array, leafData: Uint32Array): Uint8Array;
7
+ export declare function encodeCompactVoxelBinary(nodes: Uint32Array, leafData: Uint32Array, numInteriorNodes: number, numMixedLeaves: number): Uint8Array;
8
+ export declare function decodeCompactVoxelBinary(binary: Uint8Array): DecodedVoxelBinary;
@@ -0,0 +1,176 @@
1
+ const SOLID_LEAF_MARKER = 0xff000000 >>> 0;
2
+ const COMPACT_MAGIC = 0x31424356; // "VCB1" little-endian
3
+ const COMPACT_VERSION = 1;
4
+ const HEADER_UINT32_COUNT = 8;
5
+ const HEADER_BYTES = HEADER_UINT32_COUNT * 4;
6
+ const TAG_MIXED = 0;
7
+ const TAG_SOLID = 1;
8
+ const TAG_INTERNAL = 2;
9
+ function popcount(n) {
10
+ n >>>= 0;
11
+ n -= (n >>> 1) & 0x55555555;
12
+ n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
13
+ return (((n + (n >>> 4)) & 0x0f0f0f0f) * 0x01010101) >>> 24;
14
+ }
15
+ function getTagByteLength(nodeCount) {
16
+ return Math.ceil(nodeCount / 4);
17
+ }
18
+ function align4(value) {
19
+ return (value + 3) & ~3;
20
+ }
21
+ function writeTag(tags, index, tag) {
22
+ const shift = (index & 3) << 1;
23
+ tags[index >> 2] = (tags[index >> 2] & ~(0x3 << shift)) | ((tag & 0x3) << shift);
24
+ }
25
+ function readTag(tags, index) {
26
+ const shift = (index & 3) << 1;
27
+ return (tags[index >> 2] >>> shift) & 0x3;
28
+ }
29
+ function toUint8Array(data) {
30
+ return data.byteOffset === 0 && data.byteLength === data.buffer.byteLength
31
+ ? data
32
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
33
+ }
34
+ export function encodeRawVoxelBinary(nodes, leafData) {
35
+ const binary = new Uint8Array((nodes.length + leafData.length) * 4);
36
+ const view = new Uint32Array(binary.buffer);
37
+ view.set(nodes, 0);
38
+ view.set(leafData, nodes.length);
39
+ return binary;
40
+ }
41
+ export function encodeCompactVoxelBinary(nodes, leafData, numInteriorNodes, numMixedLeaves) {
42
+ const nodeCount = nodes.length;
43
+ const tagBytes = getTagByteLength(nodeCount);
44
+ const tags = new Uint8Array(tagBytes);
45
+ const childMasks = new Uint8Array(numInteriorNodes);
46
+ let interiorCursor = 0;
47
+ let mixedCursor = 0;
48
+ for (let i = 0; i < nodeCount; i++) {
49
+ const node = nodes[i] >>> 0;
50
+ if (node === SOLID_LEAF_MARKER) {
51
+ writeTag(tags, i, TAG_SOLID);
52
+ continue;
53
+ }
54
+ const childMask = node >>> 24;
55
+ if (childMask === 0) {
56
+ const leafDataIndex = node & 0x00ffffff;
57
+ if (leafDataIndex !== mixedCursor) {
58
+ throw new Error(`compact voxel encoding requires mixed leaf indices to be BFS-sequential: ` +
59
+ `node ${i} has ${leafDataIndex}, expected ${mixedCursor}`);
60
+ }
61
+ writeTag(tags, i, TAG_MIXED);
62
+ mixedCursor++;
63
+ continue;
64
+ }
65
+ if (childMask === 0xff && (node & 0x00ffffff) === 0) {
66
+ throw new Error(`invalid voxel node ${i}: solid sentinel must be encoded as 0xFF000000`);
67
+ }
68
+ writeTag(tags, i, TAG_INTERNAL);
69
+ if (interiorCursor >= childMasks.length) {
70
+ throw new Error(`compact voxel encoding found more interior nodes than metadata (${numInteriorNodes})`);
71
+ }
72
+ childMasks[interiorCursor++] = childMask;
73
+ }
74
+ if (interiorCursor !== numInteriorNodes) {
75
+ throw new Error(`compact voxel encoding interior count mismatch: ${interiorCursor} !== ${numInteriorNodes}`);
76
+ }
77
+ if (mixedCursor !== numMixedLeaves) {
78
+ throw new Error(`compact voxel encoding mixed leaf count mismatch: ${mixedCursor} !== ${numMixedLeaves}`);
79
+ }
80
+ const leafBytes = toUint8Array(new Uint8Array(leafData.buffer, leafData.byteOffset, leafData.byteLength));
81
+ const leafOffset = align4(HEADER_BYTES + tagBytes + childMasks.byteLength);
82
+ const binary = new Uint8Array(leafOffset + leafBytes.byteLength);
83
+ const header = new DataView(binary.buffer, 0, HEADER_BYTES);
84
+ header.setUint32(0, COMPACT_MAGIC, true);
85
+ header.setUint32(4, COMPACT_VERSION, true);
86
+ header.setUint32(8, nodeCount, true);
87
+ header.setUint32(12, numInteriorNodes, true);
88
+ header.setUint32(16, numMixedLeaves, true);
89
+ header.setUint32(20, leafData.length, true);
90
+ header.setUint32(24, tagBytes, true);
91
+ header.setUint32(28, childMasks.byteLength, true);
92
+ binary.set(tags, HEADER_BYTES);
93
+ binary.set(childMasks, HEADER_BYTES + tagBytes);
94
+ binary.set(leafBytes, leafOffset);
95
+ return binary;
96
+ }
97
+ export function decodeCompactVoxelBinary(binary) {
98
+ if (binary.byteLength < HEADER_BYTES) {
99
+ throw new Error('compact voxel binary is too small for header');
100
+ }
101
+ const header = new DataView(binary.buffer, binary.byteOffset, HEADER_BYTES);
102
+ const magic = header.getUint32(0, true);
103
+ const version = header.getUint32(4, true);
104
+ if (magic !== COMPACT_MAGIC) {
105
+ throw new Error(`invalid compact voxel magic 0x${magic.toString(16)}`);
106
+ }
107
+ if (version !== COMPACT_VERSION) {
108
+ throw new Error(`unsupported compact voxel version ${version}`);
109
+ }
110
+ const nodeCount = header.getUint32(8, true);
111
+ const numInteriorNodes = header.getUint32(12, true);
112
+ const numMixedLeaves = header.getUint32(16, true);
113
+ const leafDataCount = header.getUint32(20, true);
114
+ const tagBytes = header.getUint32(24, true);
115
+ const childMaskBytes = header.getUint32(28, true);
116
+ if (tagBytes !== getTagByteLength(nodeCount)) {
117
+ throw new Error(`compact voxel tag byte count mismatch: ${tagBytes} !== ${getTagByteLength(nodeCount)}`);
118
+ }
119
+ if (childMaskBytes !== numInteriorNodes) {
120
+ throw new Error(`compact voxel child-mask byte count mismatch: ${childMaskBytes} !== ${numInteriorNodes}`);
121
+ }
122
+ const leafOffset = align4(HEADER_BYTES + tagBytes + childMaskBytes);
123
+ const expectedBytes = leafOffset + leafDataCount * 4;
124
+ if (binary.byteLength !== expectedBytes) {
125
+ throw new Error(`compact voxel byte length mismatch: ${binary.byteLength} !== ${expectedBytes}`);
126
+ }
127
+ const tags = new Uint8Array(binary.buffer, binary.byteOffset + HEADER_BYTES, tagBytes);
128
+ const childMasks = new Uint8Array(binary.buffer, binary.byteOffset + HEADER_BYTES + tagBytes, childMaskBytes);
129
+ const leafData = new Uint32Array(leafDataCount);
130
+ leafData.set(new Uint32Array(binary.buffer, binary.byteOffset + leafOffset, leafDataCount));
131
+ const nodes = new Uint32Array(nodeCount);
132
+ let levelStart = 0;
133
+ let levelEnd = nodeCount > 0 ? 1 : 0;
134
+ let childStart = levelEnd;
135
+ let interiorCursor = 0;
136
+ let mixedCursor = 0;
137
+ while (levelStart < levelEnd) {
138
+ let nextLevelEnd = childStart;
139
+ for (let i = levelStart; i < levelEnd; i++) {
140
+ const tag = readTag(tags, i);
141
+ if (tag === TAG_SOLID) {
142
+ nodes[i] = SOLID_LEAF_MARKER;
143
+ }
144
+ else if (tag === TAG_MIXED) {
145
+ nodes[i] = mixedCursor++;
146
+ }
147
+ else if (tag === TAG_INTERNAL) {
148
+ if (interiorCursor >= childMasks.length) {
149
+ throw new Error('compact voxel decode exhausted child masks');
150
+ }
151
+ const childMask = childMasks[interiorCursor++];
152
+ nodes[i] = ((childMask << 24) | childStart) >>> 0;
153
+ childStart += popcount(childMask);
154
+ nextLevelEnd = childStart;
155
+ if (childStart > nodeCount) {
156
+ throw new Error(`compact voxel child range exceeds node count (${childStart} > ${nodeCount})`);
157
+ }
158
+ }
159
+ else {
160
+ throw new Error(`compact voxel decode found reserved node tag ${tag} at node ${i}`);
161
+ }
162
+ }
163
+ levelStart = levelEnd;
164
+ levelEnd = nextLevelEnd;
165
+ }
166
+ if (levelEnd !== nodeCount) {
167
+ throw new Error(`compact voxel decode did not consume all nodes: ${levelEnd} !== ${nodeCount}`);
168
+ }
169
+ if (interiorCursor !== numInteriorNodes) {
170
+ throw new Error(`compact voxel decode interior count mismatch: ${interiorCursor} !== ${numInteriorNodes}`);
171
+ }
172
+ if (mixedCursor !== numMixedLeaves) {
173
+ throw new Error(`compact voxel decode mixed leaf count mismatch: ${mixedCursor} !== ${numMixedLeaves}`);
174
+ }
175
+ return { nodes, leafData };
176
+ }
@@ -1,162 +1,178 @@
1
- /** 3D Morton (Z-order) for integer block coordinates. */
2
- export declare const encodeMorton3: (x: number, y: number, z: number) => number;
3
- export declare const decodeMorton3: (m: number) => [number, number, number];
4
- export interface Bounds {
5
- min: {
6
- x: number;
7
- y: number;
8
- z: number;
9
- };
10
- max: {
11
- x: number;
12
- y: number;
13
- z: number;
14
- };
15
- }
16
- /** Voxel leaf edge length in voxels (4³ block). */
17
- export declare const LEAF_SIZE = 4;
18
- export declare const ALPHA_THRESHOLD: number;
19
- export declare const alignGridBounds: (bounds: Bounds, voxelResolution: number) => Bounds;
20
- /** Opacity-aware AABB half-extents from scale + unit quaternion. */
21
- export declare const extentsFromQuatScale: (sx: number, sy: number, sz: number, qx: number, qy: number, qz: number, qw: number, opacity?: number, opacityThreshold?: number) => {
22
- ex: number;
23
- ey: number;
24
- ez: number;
25
- };
26
- export declare class GaussianBVH {
27
- private static readonly MAX_LEAF_SIZE;
28
- private readonly x;
29
- private readonly y;
30
- private readonly z;
31
- private readonly extents;
32
- private readonly root;
33
- constructor(x: Float32Array, y: Float32Array, z: Float32Array, extents: Float32Array);
34
- queryOverlappingRaw(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[];
35
- queryOverlappingRawInto(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number, output: Uint32Array, offset?: number): number;
36
- private computeBounds;
37
- private buildNode;
38
- private queryNode;
39
- private queryNodeInto;
40
- }
41
- declare const SOLID_LO: number;
42
- declare const SOLID_HI: number;
43
- /**
44
- * Append-only buffer for streaming voxelization results.
45
- * Stores (linear blockIdx, voxel mask) pairs for non-empty 4x4x4 blocks.
46
- *
47
- * Block keys are linear block indices `bx + by*nbx + bz*nbx*nby` in the
48
- * producer's grid coordinate system. Producers and consumers must agree on
49
- * the grid dimensions; the buffer itself is dimension-agnostic.
50
- */
51
- export declare class BlockMaskBuffer {
52
- private solidIdx;
53
- private solidCountValue;
54
- private solidCap;
55
- private mixedIdx;
56
- private mixedCountValue;
57
- private mixedCap;
58
- private mixedMasks;
59
- addBlock(blockIdx: number, lo: number, hi: number): void;
60
- getMixedBlocks(): {
61
- blockIdx: Float64Array<ArrayBufferLike>;
62
- masks: Uint32Array<ArrayBufferLike>;
63
- };
64
- getSolidBlocks(): Float64Array<ArrayBufferLike>;
65
- get count(): number;
66
- get mixedCount(): number;
67
- get solidCount(): number;
68
- clear(): void;
69
- }
70
- declare const BLOCK_EMPTY = 0;
71
- declare const BLOCK_SOLID = 1;
72
- declare const BLOCK_MIXED = 2;
73
- declare const TYPE_MASK = 3;
74
- declare const BLOCKS_PER_WORD = 16;
75
- declare const EVEN_BITS: number;
76
- declare const readBlockType: (types: Uint32Array, blockIdx: number) => number;
77
- declare const writeBlockType: (types: Uint32Array, blockIdx: number, blockType: number) => void;
78
- declare class BlockMaskMap {
79
- keys: Int32Array;
80
- lo: Uint32Array;
81
- hi: Uint32Array;
82
- private _size;
83
- private _capacity;
84
- private _mask;
85
- constructor(initialCapacity?: number);
86
- slot(key: number): number;
87
- set(key: number, loVal: number, hiVal: number): void;
88
- removeAt(slot: number): void;
89
- clear(): void;
90
- get size(): number;
91
- releaseStorage(): void;
92
- clone(): BlockMaskMap;
93
- private _grow;
94
- }
95
- declare class SparseVoxelGrid {
96
- readonly nx: number;
97
- readonly ny: number;
98
- readonly nz: number;
99
- readonly nbx: number;
100
- readonly nby: number;
101
- readonly nbz: number;
102
- readonly bStride: number;
103
- types: Uint32Array;
104
- masks: BlockMaskMap;
105
- constructor(nx: number, ny: number, nz: number);
106
- getVoxel(ix: number, iy: number, iz: number): number;
107
- setVoxel(ix: number, iy: number, iz: number): void;
108
- orBlock(blockIdx: number, lo: number, hi: number): void;
109
- clear(): void;
110
- releaseStorage(): void;
111
- clone(): SparseVoxelGrid;
112
- cropTo(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
113
- cropToInverted(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
114
- static fromBuffer(acc: BlockMaskBuffer, nx: number, ny: number, nz: number): SparseVoxelGrid;
115
- toBuffer(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, defaultSolid?: boolean): BlockMaskBuffer;
116
- toBufferInverted(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number): BlockMaskBuffer;
117
- getOccupiedBlockBounds(onProgress?: (done: number, total: number) => void): {
118
- minBx: number;
119
- minBy: number;
120
- minBz: number;
121
- maxBx: number;
122
- maxBy: number;
123
- maxBz: number;
124
- } | null;
125
- getNavigableBlockBounds(onProgress?: (done: number, total: number) => void): {
126
- minBx: number;
127
- minBy: number;
128
- minBz: number;
129
- maxBx: number;
130
- maxBy: number;
131
- maxBz: number;
132
- } | null;
133
- static findNearestFreeCell(blocked: SparseVoxelGrid, seedIx: number, seedIy: number, seedIz: number, maxRadius: number): {
134
- ix: number;
135
- iy: number;
136
- iz: number;
137
- } | null;
138
- }
139
- export declare const SOLID_LEAF_MARKER: number;
140
- export declare const getChildOffset: (mask: number, octant: number) => number;
141
- interface BuildSparseOctreeOptions {
142
- consumeGrid?: boolean;
143
- dense?: boolean;
144
- }
145
- /**
146
- * Build a sparse octree from block masks using:
147
- * 1) mixed+solid SoA merge and Morton sort
148
- * 2) bottom-up level construction by parent Morton grouping
149
- * 3) BFS flatten to node/leafData arrays.
150
- */
151
- export declare const buildSparseOctree: (grid: SparseVoxelGrid, gridBounds: Bounds, sceneBounds: Bounds, voxelResolution: number, options?: BuildSparseOctreeOptions) => {
152
- gridBounds: Bounds;
153
- sceneBounds: Bounds;
154
- voxelResolution: number;
155
- leafSize: number;
156
- treeDepth: number;
157
- numInteriorNodes: number;
158
- numMixedLeaves: number;
159
- nodes: Uint32Array<ArrayBuffer>;
160
- leafData: Uint32Array<ArrayBuffer>;
161
- };
162
- export { BLOCK_EMPTY, BLOCK_SOLID, BLOCK_MIXED, BLOCKS_PER_WORD, TYPE_MASK, EVEN_BITS, readBlockType, writeBlockType, SOLID_LO, SOLID_HI, SparseVoxelGrid };
1
+ /** 3D Morton (Z-order) for integer block coordinates. */
2
+ export declare function encodeMorton3(x: number, y: number, z: number): number;
3
+ export declare function decodeMorton3(m: number): [number, number, number];
4
+ export interface Bounds {
5
+ min: {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ };
10
+ max: {
11
+ x: number;
12
+ y: number;
13
+ z: number;
14
+ };
15
+ }
16
+ /** Voxel leaf edge length in voxels (4³ block). */
17
+ export declare const LEAF_SIZE = 4;
18
+ export declare const ALPHA_THRESHOLD: number;
19
+ export declare function alignGridBounds(bounds: Bounds, voxelResolution: number): Bounds;
20
+ /**
21
+ * Max linear block index (signed 32-bit): BlockMaskMap keys, worker `blockIdx >>> 0`,
22
+ * and types bitmap indexing. Implies types bitmap <= ceil(MAX / 16) * 4 ~= 512 MB.
23
+ */
24
+ export declare const MAX_VOXEL_BLOCK_COUNT_INT32 = 2147483647;
25
+ /** Preflight hard grid limits before voxelization allocates the types bitmap. */
26
+ export declare function checkVoxelGridCapacity(gridBounds: Bounds, voxelResolution: number): void;
27
+ /** Opacity-aware AABB half-extents from scale + unit quaternion. */
28
+ export declare function extentsFromQuatScale(sx: number, sy: number, sz: number, qx: number, qy: number, qz: number, qw: number, opacity?: number, opacityThreshold?: number): {
29
+ ex: number;
30
+ ey: number;
31
+ ez: number;
32
+ };
33
+ export declare class GaussianBVH {
34
+ private static readonly MAX_LEAF_SIZE;
35
+ private readonly x;
36
+ private readonly y;
37
+ private readonly z;
38
+ private readonly extents;
39
+ private readonly root;
40
+ constructor(x: Float32Array, y: Float32Array, z: Float32Array, extents: Float32Array);
41
+ queryOverlappingRaw(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[];
42
+ queryOverlappingRawInto(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number, output: Uint32Array, offset?: number): number;
43
+ private computeBounds;
44
+ private buildNode;
45
+ private queryNode;
46
+ private queryNodeInto;
47
+ }
48
+ declare const SOLID_LO: number;
49
+ declare const SOLID_HI: number;
50
+ /**
51
+ * Append-only buffer for streaming voxelization results.
52
+ * Stores (linear blockIdx, voxel mask) pairs for non-empty 4x4x4 blocks.
53
+ *
54
+ * Block keys are linear block indices `bx + by*nbx + bz*nbx*nby` in the
55
+ * producer's grid coordinate system. Producers and consumers must agree on
56
+ * the grid dimensions; the buffer itself is dimension-agnostic.
57
+ */
58
+ export declare class BlockMaskBuffer {
59
+ private solidIdx;
60
+ private solidCountValue;
61
+ private solidCap;
62
+ private mixedIdx;
63
+ private mixedCountValue;
64
+ private mixedCap;
65
+ private mixedMasks;
66
+ addBlock(blockIdx: number, lo: number, hi: number): void;
67
+ getMixedBlocks(): {
68
+ blockIdx: Float64Array<ArrayBufferLike>;
69
+ masks: Uint32Array<ArrayBufferLike>;
70
+ };
71
+ getSolidBlocks(): Float64Array<ArrayBufferLike>;
72
+ get count(): number;
73
+ get mixedCount(): number;
74
+ get solidCount(): number;
75
+ clear(): void;
76
+ }
77
+ declare const BLOCK_EMPTY = 0;
78
+ declare const BLOCK_SOLID = 1;
79
+ declare const BLOCK_MIXED = 2;
80
+ declare const TYPE_MASK = 3;
81
+ declare const BLOCKS_PER_WORD = 16;
82
+ declare const EVEN_BITS: number;
83
+ declare function readBlockType(types: Uint32Array, blockIdx: number): number;
84
+ declare function writeBlockType(types: Uint32Array, blockIdx: number, blockType: number): void;
85
+ declare class BlockMaskMap {
86
+ keys: Int32Array;
87
+ lo: Uint32Array;
88
+ hi: Uint32Array;
89
+ private _size;
90
+ private _capacity;
91
+ private _mask;
92
+ constructor(initialCapacity?: number);
93
+ slot(key: number): number;
94
+ set(key: number, loVal: number, hiVal: number): void;
95
+ removeAt(slot: number): void;
96
+ clear(): void;
97
+ get size(): number;
98
+ releaseStorage(): void;
99
+ clone(): BlockMaskMap;
100
+ private _grow;
101
+ }
102
+ declare class SparseVoxelGrid {
103
+ readonly nx: number;
104
+ readonly ny: number;
105
+ readonly nz: number;
106
+ readonly nbx: number;
107
+ readonly nby: number;
108
+ readonly nbz: number;
109
+ readonly bStride: number;
110
+ types: Uint32Array;
111
+ masks: BlockMaskMap;
112
+ constructor(nx: number, ny: number, nz: number);
113
+ getVoxel(ix: number, iy: number, iz: number): number;
114
+ setVoxel(ix: number, iy: number, iz: number): void;
115
+ orBlock(blockIdx: number, lo: number, hi: number): void;
116
+ clear(): void;
117
+ releaseStorage(): void;
118
+ clone(): SparseVoxelGrid;
119
+ cropTo(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
120
+ cropToInverted(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, onProgress?: (done: number, total: number) => void): SparseVoxelGrid;
121
+ static fromBuffer(acc: BlockMaskBuffer, nx: number, ny: number, nz: number): SparseVoxelGrid;
122
+ toBuffer(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number, defaultSolid?: boolean): BlockMaskBuffer;
123
+ toBufferInverted(cropMinBx: number, cropMinBy: number, cropMinBz: number, cropMaxBx: number, cropMaxBy: number, cropMaxBz: number): BlockMaskBuffer;
124
+ getOccupiedBlockBounds(onProgress?: (done: number, total: number) => void): {
125
+ minBx: number;
126
+ minBy: number;
127
+ minBz: number;
128
+ maxBx: number;
129
+ maxBy: number;
130
+ maxBz: number;
131
+ } | null;
132
+ getNavigableBlockBounds(onProgress?: (done: number, total: number) => void): {
133
+ minBx: number;
134
+ minBy: number;
135
+ minBz: number;
136
+ maxBx: number;
137
+ maxBy: number;
138
+ maxBz: number;
139
+ } | null;
140
+ static findNearestFreeCell(blocked: SparseVoxelGrid, seedIx: number, seedIy: number, seedIz: number, maxRadius: number): {
141
+ ix: number;
142
+ iy: number;
143
+ iz: number;
144
+ } | null;
145
+ }
146
+ export declare const SOLID_LEAF_MARKER: number;
147
+ export declare const MAX_24BIT_OFFSET = 16777215;
148
+ export declare class SparseOctree24BitOverflowError extends Error {
149
+ kind: 'node' | 'mixed-leaf';
150
+ actual: number;
151
+ limit: number;
152
+ voxelResolution?: number;
153
+ constructor(kind: 'node' | 'mixed-leaf', actual: number, limit: number);
154
+ }
155
+ export interface SparseOctree {
156
+ gridBounds: Bounds;
157
+ sceneBounds: Bounds;
158
+ voxelResolution: number;
159
+ leafSize: number;
160
+ treeDepth: number;
161
+ numInteriorNodes: number;
162
+ numMixedLeaves: number;
163
+ nodes: Uint32Array;
164
+ leafData: Uint32Array;
165
+ }
166
+ export declare function getChildOffset(mask: number, octant: number): number;
167
+ interface BuildSparseOctreeOptions {
168
+ consumeGrid?: boolean;
169
+ dense?: boolean;
170
+ }
171
+ /**
172
+ * Build a sparse octree from block masks using:
173
+ * 1) mixed+solid SoA merge and Morton sort
174
+ * 2) bottom-up level construction by parent Morton grouping
175
+ * 3) BFS flatten to node/leafData arrays.
176
+ */
177
+ export declare function buildSparseOctree(grid: SparseVoxelGrid, gridBounds: Bounds, sceneBounds: Bounds, voxelResolution: number, options?: BuildSparseOctreeOptions): SparseOctree;
178
+ export { BLOCK_EMPTY, BLOCK_SOLID, BLOCK_MIXED, BLOCKS_PER_WORD, TYPE_MASK, EVEN_BITS, readBlockType, writeBlockType, SOLID_LO, SOLID_HI, SparseVoxelGrid, };