@manycore/aholo-splat-transform 1.2.8 → 1.2.10
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.
- package/CHANGELOG.md +124 -113
- package/README.md +39 -39
- package/THIRD_PARTY_LICENSES.txt +1373 -1373
- package/bin/cli.js +125 -118
- package/dist/SplatData.d.ts +67 -67
- package/dist/SplatData.js +167 -150
- package/dist/constant.d.ts +3 -3
- package/dist/constant.js +13 -13
- package/dist/file/IFile.d.ts +5 -5
- package/dist/file/IFile.js +1 -1
- package/dist/file/esz.d.ts +11 -11
- package/dist/file/esz.js +337 -322
- package/dist/file/index.d.ts +8 -8
- package/dist/file/index.js +7 -7
- package/dist/file/ksplat.d.ts +12 -12
- package/dist/file/ksplat.js +293 -231
- package/dist/file/lcc.d.ts +11 -11
- package/dist/file/lcc.js +161 -158
- package/dist/file/ply.d.ts +13 -13
- package/dist/file/ply.js +439 -390
- package/dist/file/sog.d.ts +80 -80
- package/dist/file/sog.js +525 -494
- package/dist/file/splat.d.ts +6 -6
- package/dist/file/splat.js +119 -99
- package/dist/file/spz.d.ts +11 -11
- package/dist/file/spz.js +597 -583
- package/dist/file/voxel.d.ts +43 -37
- package/dist/file/voxel.js +411 -280
- package/dist/index.d.ts +33 -33
- package/dist/index.js +54 -54
- package/dist/native/index.d.ts +54 -54
- package/dist/native/index.js +122 -129
- package/dist/native/utils.d.ts +1 -0
- package/dist/native/utils.js +54 -0
- package/dist/tasks/AutoChunkLodTask.d.ts +13 -13
- package/dist/tasks/AutoChunkLodTask.js +117 -117
- package/dist/tasks/AutoLodTask.d.ts +10 -10
- package/dist/tasks/AutoLodTask.js +20 -20
- package/dist/tasks/BaseTask.d.ts +15 -15
- package/dist/tasks/BaseTask.js +5 -5
- package/dist/tasks/FlexLodTask.d.ts +12 -12
- package/dist/tasks/FlexLodTask.js +54 -44
- package/dist/tasks/ModifyTask.d.ts +9 -9
- package/dist/tasks/ModifyTask.js +166 -156
- package/dist/tasks/ReadTask.d.ts +9 -9
- package/dist/tasks/ReadTask.js +29 -29
- package/dist/tasks/SkeletonLodTask.d.ts +10 -10
- package/dist/tasks/SkeletonLodTask.js +176 -156
- package/dist/tasks/VoxelTask.d.ts +35 -30
- package/dist/tasks/VoxelTask.js +40 -37
- package/dist/tasks/WriteTask.d.ts +12 -12
- package/dist/tasks/WriteTask.js +70 -70
- package/dist/utils/BufferReader.d.ts +12 -12
- package/dist/utils/BufferReader.js +45 -45
- package/dist/utils/Logger.d.ts +11 -11
- package/dist/utils/Logger.js +40 -40
- package/dist/utils/StreamChunkDecoder.d.ts +16 -16
- package/dist/utils/StreamChunkDecoder.js +31 -31
- package/dist/utils/index.d.ts +27 -27
- package/dist/utils/index.js +101 -101
- package/dist/utils/k-means.d.ts +4 -4
- package/dist/utils/k-means.js +340 -341
- package/dist/utils/math.d.ts +46 -46
- package/dist/utils/math.js +350 -346
- package/dist/utils/quantize-1d.d.ts +4 -4
- package/dist/utils/quantize-1d.js +164 -164
- package/dist/utils/sh-rotate.d.ts +2 -2
- package/dist/utils/sh-rotate.js +236 -175
- package/dist/utils/splat.d.ts +21 -21
- package/dist/utils/splat.js +397 -387
- package/dist/utils/voxel/binary.d.ts +8 -0
- package/dist/utils/voxel/binary.js +176 -0
- package/dist/utils/voxel/common.d.ts +178 -162
- package/dist/utils/voxel/common.js +1752 -1682
- package/dist/utils/voxel/coplanar-merge.d.ts +63 -63
- package/dist/utils/voxel/coplanar-merge.js +818 -819
- package/dist/utils/voxel/filter-cluster.d.ts +20 -0
- package/dist/utils/voxel/filter-cluster.js +628 -0
- package/dist/utils/voxel/gpu-dilation.d.ts +2 -2
- package/dist/utils/voxel/gpu-dilation.js +677 -656
- package/dist/utils/voxel/marching-cubes.d.ts +42 -42
- package/dist/utils/voxel/marching-cubes.js +1645 -1657
- package/dist/utils/voxel/mesh.d.ts +3 -3
- package/dist/utils/voxel/mesh.js +130 -130
- package/dist/utils/voxel/nav.d.ts +29 -29
- package/dist/utils/voxel/nav.js +1068 -1043
- package/dist/utils/voxel/postprocess.d.ts +23 -23
- package/dist/utils/voxel/postprocess.js +408 -375
- package/dist/utils/voxel/voxel-faces.d.ts +18 -18
- package/dist/utils/voxel/voxel-faces.js +662 -663
- package/dist/utils/voxel/voxelize.d.ts +34 -33
- package/dist/utils/voxel/voxelize.js +1208 -1193
- package/dist/utils/webgpu.d.ts +8 -8
- package/dist/utils/webgpu.js +122 -122
- package/package.json +38 -39
- package/dist/native/cpp/bin/linux/binding.node +0 -0
- package/dist/native/cpp/bin/windows/binding.node +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { SparseVoxelGrid,
|
|
2
|
-
export type CollisionMeshShape = 'smooth' | 'faces';
|
|
3
|
-
export declare
|
|
1
|
+
import type { SparseVoxelGrid, Bounds } from './common.js';
|
|
2
|
+
export type CollisionMeshShape = 'smooth' | 'faces';
|
|
3
|
+
export declare function buildCollisionMesh(grid: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, shape?: CollisionMeshShape): Uint8Array | undefined;
|
package/dist/utils/voxel/mesh.js
CHANGED
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
import { coplanarMerge } from './coplanar-merge.js';
|
|
2
|
-
import { marchingCubes } from './marching-cubes.js';
|
|
3
|
-
import { voxelFaces } from './voxel-faces.js';
|
|
4
|
-
import { logger } from '../Logger.js';
|
|
5
|
-
|
|
6
|
-
const vertexCount = positions.length / 3;
|
|
7
|
-
const indexCount = indices.length;
|
|
8
|
-
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
9
|
-
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
10
|
-
for (let i = 0; i < positions.length; i += 3) {
|
|
11
|
-
const x = positions[i];
|
|
12
|
-
const y = positions[i + 1];
|
|
13
|
-
const z = positions[i + 2];
|
|
14
|
-
if (x < minX) {
|
|
15
|
-
minX = x;
|
|
16
|
-
}
|
|
17
|
-
if (y < minY) {
|
|
18
|
-
minY = y;
|
|
19
|
-
}
|
|
20
|
-
if (z < minZ) {
|
|
21
|
-
minZ = z;
|
|
22
|
-
}
|
|
23
|
-
if (x > maxX) {
|
|
24
|
-
maxX = x;
|
|
25
|
-
}
|
|
26
|
-
if (y > maxY) {
|
|
27
|
-
maxY = y;
|
|
28
|
-
}
|
|
29
|
-
if (z > maxZ) {
|
|
30
|
-
maxZ = z;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const positionsByteLength = positions.byteLength;
|
|
34
|
-
const indicesByteLength = indices.byteLength;
|
|
35
|
-
const totalBinSize = positionsByteLength + indicesByteLength;
|
|
36
|
-
const gltf = {
|
|
37
|
-
asset: { version: '2.0', generator: 'splat-transform' },
|
|
38
|
-
scene: 0,
|
|
39
|
-
scenes: [{ nodes: [0] }],
|
|
40
|
-
nodes: [{ mesh: 0 }],
|
|
41
|
-
meshes: [{ primitives: [{ attributes: { POSITION: 0 }, indices: 1 }] }],
|
|
42
|
-
accessors: [
|
|
43
|
-
{
|
|
44
|
-
bufferView: 0,
|
|
45
|
-
componentType: 5126,
|
|
46
|
-
count: vertexCount,
|
|
47
|
-
type: 'VEC3',
|
|
48
|
-
min: [minX, minY, minZ],
|
|
49
|
-
max: [maxX, maxY, maxZ]
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
bufferView: 1,
|
|
53
|
-
componentType: 5125,
|
|
54
|
-
count: indexCount,
|
|
55
|
-
type: 'SCALAR'
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
|
-
bufferViews: [
|
|
59
|
-
{ buffer: 0, byteOffset: 0, byteLength: positionsByteLength, target: 34962 },
|
|
60
|
-
{ buffer: 0, byteOffset: positionsByteLength, byteLength: indicesByteLength, target: 34963 }
|
|
61
|
-
],
|
|
62
|
-
buffers: [{ byteLength: totalBinSize }]
|
|
63
|
-
};
|
|
64
|
-
const jsonBytes = new TextEncoder().encode(JSON.stringify(gltf));
|
|
65
|
-
const jsonPadding = (4 - (jsonBytes.length % 4)) % 4;
|
|
66
|
-
const jsonChunkLength = jsonBytes.length + jsonPadding;
|
|
67
|
-
const binPadding = (4 - (totalBinSize % 4)) % 4;
|
|
68
|
-
const binChunkLength = totalBinSize + binPadding;
|
|
69
|
-
const totalLength = 12 + 8 + jsonChunkLength + 8 + binChunkLength;
|
|
70
|
-
const buffer = new ArrayBuffer(totalLength);
|
|
71
|
-
const view = new DataView(buffer);
|
|
72
|
-
const bytes = new Uint8Array(buffer);
|
|
73
|
-
let offset = 0;
|
|
74
|
-
view.setUint32(offset,
|
|
75
|
-
offset += 4;
|
|
76
|
-
view.setUint32(offset, 2, true);
|
|
77
|
-
offset += 4;
|
|
78
|
-
view.setUint32(offset, totalLength, true);
|
|
79
|
-
offset += 4;
|
|
80
|
-
view.setUint32(offset, jsonChunkLength, true);
|
|
81
|
-
offset += 4;
|
|
82
|
-
view.setUint32(offset,
|
|
83
|
-
offset += 4;
|
|
84
|
-
bytes.set(jsonBytes, offset);
|
|
85
|
-
offset += jsonBytes.length;
|
|
86
|
-
for (let i = 0; i < jsonPadding; i++) {
|
|
87
|
-
bytes[offset++] = 0x20;
|
|
88
|
-
}
|
|
89
|
-
view.setUint32(offset, binChunkLength, true);
|
|
90
|
-
offset += 4;
|
|
91
|
-
view.setUint32(offset,
|
|
92
|
-
offset += 4;
|
|
93
|
-
bytes.set(new Uint8Array(positions.buffer, positions.byteOffset, positionsByteLength), offset);
|
|
94
|
-
offset += positionsByteLength;
|
|
95
|
-
bytes.set(new Uint8Array(indices.buffer, indices.byteOffset, indicesByteLength), offset);
|
|
96
|
-
return bytes;
|
|
97
|
-
}
|
|
98
|
-
export
|
|
99
|
-
const nx = Math.round((gridBounds.max.x - gridBounds.min.x) / voxelResolution);
|
|
100
|
-
const ny = Math.round((gridBounds.max.y - gridBounds.min.y) / voxelResolution);
|
|
101
|
-
const nz = Math.round((gridBounds.max.z - gridBounds.min.z) / voxelResolution);
|
|
102
|
-
if (nx % 4 !== 0 || ny % 4 !== 0 || nz % 4 !== 0) {
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
logger.time('Build collision mesh');
|
|
106
|
-
let mesh;
|
|
107
|
-
if (shape === 'faces') {
|
|
108
|
-
mesh = voxelFaces(grid, gridBounds, voxelResolution);
|
|
109
|
-
logger.info(`collision mesh faces: ${mesh.positions.length / 3} vertices, ${mesh.indices.length / 3} triangles`);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
const preMerged = marchingCubes(grid, gridBounds, voxelResolution, { mergeFlatFaces: true });
|
|
113
|
-
logger.info(`collision mesh pre-merged: ${preMerged.positions.length / 3} vertices, ${preMerged.indices.length / 3} triangles`);
|
|
114
|
-
if (preMerged.indices.length < 3) {
|
|
115
|
-
mesh = preMerged;
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
mesh = coplanarMerge(preMerged, voxelResolution);
|
|
119
|
-
const reduction = (1 - mesh.indices.length / preMerged.indices.length) * 100;
|
|
120
|
-
logger.info(`collision mesh merged: ${mesh.positions.length / 3} vertices, ${mesh.indices.length / 3} triangles`);
|
|
121
|
-
logger.info(`collision mesh reduction: ${reduction.toFixed(0)}%`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
logger.timeEnd('Build collision mesh');
|
|
125
|
-
if (mesh.indices.length < 3) {
|
|
126
|
-
logger.warn('collision mesh: no triangles generated, skipping GLB output');
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
return encodeGlb(mesh.positions, mesh.indices);
|
|
130
|
-
}
|
|
1
|
+
import { coplanarMerge } from './coplanar-merge.js';
|
|
2
|
+
import { marchingCubes } from './marching-cubes.js';
|
|
3
|
+
import { voxelFaces } from './voxel-faces.js';
|
|
4
|
+
import { logger } from '../Logger.js';
|
|
5
|
+
function encodeGlb(positions, indices) {
|
|
6
|
+
const vertexCount = positions.length / 3;
|
|
7
|
+
const indexCount = indices.length;
|
|
8
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
9
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
10
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
11
|
+
const x = positions[i];
|
|
12
|
+
const y = positions[i + 1];
|
|
13
|
+
const z = positions[i + 2];
|
|
14
|
+
if (x < minX) {
|
|
15
|
+
minX = x;
|
|
16
|
+
}
|
|
17
|
+
if (y < minY) {
|
|
18
|
+
minY = y;
|
|
19
|
+
}
|
|
20
|
+
if (z < minZ) {
|
|
21
|
+
minZ = z;
|
|
22
|
+
}
|
|
23
|
+
if (x > maxX) {
|
|
24
|
+
maxX = x;
|
|
25
|
+
}
|
|
26
|
+
if (y > maxY) {
|
|
27
|
+
maxY = y;
|
|
28
|
+
}
|
|
29
|
+
if (z > maxZ) {
|
|
30
|
+
maxZ = z;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const positionsByteLength = positions.byteLength;
|
|
34
|
+
const indicesByteLength = indices.byteLength;
|
|
35
|
+
const totalBinSize = positionsByteLength + indicesByteLength;
|
|
36
|
+
const gltf = {
|
|
37
|
+
asset: { version: '2.0', generator: 'splat-transform' },
|
|
38
|
+
scene: 0,
|
|
39
|
+
scenes: [{ nodes: [0] }],
|
|
40
|
+
nodes: [{ mesh: 0 }],
|
|
41
|
+
meshes: [{ primitives: [{ attributes: { POSITION: 0 }, indices: 1 }] }],
|
|
42
|
+
accessors: [
|
|
43
|
+
{
|
|
44
|
+
bufferView: 0,
|
|
45
|
+
componentType: 5126,
|
|
46
|
+
count: vertexCount,
|
|
47
|
+
type: 'VEC3',
|
|
48
|
+
min: [minX, minY, minZ],
|
|
49
|
+
max: [maxX, maxY, maxZ],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
bufferView: 1,
|
|
53
|
+
componentType: 5125,
|
|
54
|
+
count: indexCount,
|
|
55
|
+
type: 'SCALAR',
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
bufferViews: [
|
|
59
|
+
{ buffer: 0, byteOffset: 0, byteLength: positionsByteLength, target: 34962 },
|
|
60
|
+
{ buffer: 0, byteOffset: positionsByteLength, byteLength: indicesByteLength, target: 34963 },
|
|
61
|
+
],
|
|
62
|
+
buffers: [{ byteLength: totalBinSize }],
|
|
63
|
+
};
|
|
64
|
+
const jsonBytes = new TextEncoder().encode(JSON.stringify(gltf));
|
|
65
|
+
const jsonPadding = (4 - (jsonBytes.length % 4)) % 4;
|
|
66
|
+
const jsonChunkLength = jsonBytes.length + jsonPadding;
|
|
67
|
+
const binPadding = (4 - (totalBinSize % 4)) % 4;
|
|
68
|
+
const binChunkLength = totalBinSize + binPadding;
|
|
69
|
+
const totalLength = 12 + 8 + jsonChunkLength + 8 + binChunkLength;
|
|
70
|
+
const buffer = new ArrayBuffer(totalLength);
|
|
71
|
+
const view = new DataView(buffer);
|
|
72
|
+
const bytes = new Uint8Array(buffer);
|
|
73
|
+
let offset = 0;
|
|
74
|
+
view.setUint32(offset, 0x46546c67, true);
|
|
75
|
+
offset += 4;
|
|
76
|
+
view.setUint32(offset, 2, true);
|
|
77
|
+
offset += 4;
|
|
78
|
+
view.setUint32(offset, totalLength, true);
|
|
79
|
+
offset += 4;
|
|
80
|
+
view.setUint32(offset, jsonChunkLength, true);
|
|
81
|
+
offset += 4;
|
|
82
|
+
view.setUint32(offset, 0x4e4f534a, true);
|
|
83
|
+
offset += 4;
|
|
84
|
+
bytes.set(jsonBytes, offset);
|
|
85
|
+
offset += jsonBytes.length;
|
|
86
|
+
for (let i = 0; i < jsonPadding; i++) {
|
|
87
|
+
bytes[offset++] = 0x20;
|
|
88
|
+
}
|
|
89
|
+
view.setUint32(offset, binChunkLength, true);
|
|
90
|
+
offset += 4;
|
|
91
|
+
view.setUint32(offset, 0x004e4942, true);
|
|
92
|
+
offset += 4;
|
|
93
|
+
bytes.set(new Uint8Array(positions.buffer, positions.byteOffset, positionsByteLength), offset);
|
|
94
|
+
offset += positionsByteLength;
|
|
95
|
+
bytes.set(new Uint8Array(indices.buffer, indices.byteOffset, indicesByteLength), offset);
|
|
96
|
+
return bytes;
|
|
97
|
+
}
|
|
98
|
+
export function buildCollisionMesh(grid, gridBounds, voxelResolution, shape = 'smooth') {
|
|
99
|
+
const nx = Math.round((gridBounds.max.x - gridBounds.min.x) / voxelResolution);
|
|
100
|
+
const ny = Math.round((gridBounds.max.y - gridBounds.min.y) / voxelResolution);
|
|
101
|
+
const nz = Math.round((gridBounds.max.z - gridBounds.min.z) / voxelResolution);
|
|
102
|
+
if (nx % 4 !== 0 || ny % 4 !== 0 || nz % 4 !== 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
logger.time('Build collision mesh');
|
|
106
|
+
let mesh;
|
|
107
|
+
if (shape === 'faces') {
|
|
108
|
+
mesh = voxelFaces(grid, gridBounds, voxelResolution);
|
|
109
|
+
logger.info(`collision mesh faces: ${mesh.positions.length / 3} vertices, ${mesh.indices.length / 3} triangles`);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const preMerged = marchingCubes(grid, gridBounds, voxelResolution, { mergeFlatFaces: true });
|
|
113
|
+
logger.info(`collision mesh pre-merged: ${preMerged.positions.length / 3} vertices, ${preMerged.indices.length / 3} triangles`);
|
|
114
|
+
if (preMerged.indices.length < 3) {
|
|
115
|
+
mesh = preMerged;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
mesh = coplanarMerge(preMerged, voxelResolution);
|
|
119
|
+
const reduction = (1 - mesh.indices.length / preMerged.indices.length) * 100;
|
|
120
|
+
logger.info(`collision mesh merged: ${mesh.positions.length / 3} vertices, ${mesh.indices.length / 3} triangles`);
|
|
121
|
+
logger.info(`collision mesh reduction: ${reduction.toFixed(0)}%`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
logger.timeEnd('Build collision mesh');
|
|
125
|
+
if (mesh.indices.length < 3) {
|
|
126
|
+
logger.warn('collision mesh: no triangles generated, skipping GLB output');
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
return encodeGlb(mesh.positions, mesh.indices);
|
|
130
|
+
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { SparseVoxelGrid, type Bounds } from './common.js';
|
|
2
|
-
interface NavSeed {
|
|
3
|
-
x: number;
|
|
4
|
-
y: number;
|
|
5
|
-
z: number;
|
|
6
|
-
}
|
|
7
|
-
type VoxelBackend = 'cpu' | 'gpu';
|
|
8
|
-
interface VoxelNavResult {
|
|
9
|
-
grid: SparseVoxelGrid;
|
|
10
|
-
gridBounds: Bounds;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Fill exterior-reachable space from boundary seeds and merge it back into
|
|
14
|
-
* occupancy after dilation. Returns cropped bounds around navigable volume.
|
|
15
|
-
*/
|
|
16
|
-
export declare function fillExterior(gridOriginal: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, dilation: number, seed: NavSeed, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
17
|
-
/**
|
|
18
|
-
* Carve navigable space for a capsule by:
|
|
19
|
-
* 1) dilating blocked voxels by capsule dimensions
|
|
20
|
-
* 2) flood filling reachable empty space from the seed
|
|
21
|
-
* 3) dilating and inverting to final occupancy representation.
|
|
22
|
-
*/
|
|
23
|
-
export declare function carve(grid: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, capsuleHeight: number, capsuleRadius: number, seed: NavSeed, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
24
|
-
/**
|
|
25
|
-
* Floor-fill via XZ dilate -> per-column upward walk -> XZ dilate -> OR.
|
|
26
|
-
* This mirrors upstream's block/bitmask walk instead of per-voxel getVoxel checks.
|
|
27
|
-
*/
|
|
28
|
-
export declare function fillFloor(gridOriginal: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, dilation?: number, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
29
|
-
export type { NavSeed, Bounds };
|
|
1
|
+
import { SparseVoxelGrid, type Bounds } from './common.js';
|
|
2
|
+
interface NavSeed {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
z: number;
|
|
6
|
+
}
|
|
7
|
+
type VoxelBackend = 'cpu' | 'gpu';
|
|
8
|
+
interface VoxelNavResult {
|
|
9
|
+
grid: SparseVoxelGrid;
|
|
10
|
+
gridBounds: Bounds;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fill exterior-reachable space from boundary seeds and merge it back into
|
|
14
|
+
* occupancy after dilation. Returns cropped bounds around navigable volume.
|
|
15
|
+
*/
|
|
16
|
+
export declare function fillExterior(gridOriginal: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, dilation: number, seed: NavSeed, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Carve navigable space for a capsule by:
|
|
19
|
+
* 1) dilating blocked voxels by capsule dimensions
|
|
20
|
+
* 2) flood filling reachable empty space from the seed
|
|
21
|
+
* 3) dilating and inverting to final occupancy representation.
|
|
22
|
+
*/
|
|
23
|
+
export declare function carve(grid: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, capsuleHeight: number, capsuleRadius: number, seed: NavSeed, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Floor-fill via XZ dilate -> per-column upward walk -> XZ dilate -> OR.
|
|
26
|
+
* This mirrors upstream's block/bitmask walk instead of per-voxel getVoxel checks.
|
|
27
|
+
*/
|
|
28
|
+
export declare function fillFloor(gridOriginal: SparseVoxelGrid, gridBounds: Bounds, voxelResolution: number, dilation?: number, backend?: VoxelBackend): Promise<VoxelNavResult>;
|
|
29
|
+
export type { NavSeed, Bounds };
|