@splatwalk/core 0.3.0

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/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@splatwalk/core",
3
+ "version": "0.3.0",
4
+ "description": "SplatWalk WASM core: binary, hand-authored types, canonical FAST NAV preset, and a framework-agnostic floor module.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Eric Eisaman",
8
+ "homepage": "https://github.com/EricEisaman/splatwalk#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/EricEisaman/splatwalk.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/EricEisaman/splatwalk/issues"
15
+ },
16
+ "keywords": [
17
+ "gaussian-splatting",
18
+ "splat",
19
+ "wasm",
20
+ "webassembly",
21
+ "navmesh",
22
+ "navigation",
23
+ "recast",
24
+ "ply",
25
+ "spz",
26
+ "sog",
27
+ "glb",
28
+ "mesh",
29
+ "3d",
30
+ "babylonjs",
31
+ "webgl"
32
+ ],
33
+ "main": "./wasm_splatwalk.js",
34
+ "types": "./wasm_splatwalk.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./wasm_splatwalk.d.ts",
38
+ "import": "./wasm_splatwalk.js"
39
+ },
40
+ "./floor": {
41
+ "types": "./floor.d.ts",
42
+ "import": "./floor.js"
43
+ },
44
+ "./wasm": "./wasm_splatwalk_bg.wasm"
45
+ },
46
+ "files": [
47
+ "wasm_splatwalk.js",
48
+ "wasm_splatwalk.d.ts",
49
+ "wasm_splatwalk_bg.wasm",
50
+ "floor.js",
51
+ "floor.d.ts",
52
+ "README.md",
53
+ "LICENSE"
54
+ ],
55
+ "sideEffects": false,
56
+ "publishConfig": {
57
+ "access": "public"
58
+ }
59
+ }
@@ -0,0 +1,481 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /**
4
+ * Hand-authored TypeScript declarations for the SplatWalk WASM core.
5
+ *
6
+ * This file is a drop-in replacement for the `.d.ts` that wasm-bindgen generates,
7
+ * which types every settings argument and every result as `any`. It is published
8
+ * alongside the binary so binary-only integrators get the real settings and
9
+ * result shapes without re-deriving them from the TypeScript bridge.
10
+ *
11
+ * The shapes here are the canonical v2 data contract. `api_version` stays the hard
12
+ * compatibility gate (always `2`); `semver` and `capabilities` are additive so
13
+ * integrators can tolerate additive change instead of hard-failing on a bump.
14
+ * See `docs/wasm-api.md` for units, ranges, defaults, and the coordinate +
15
+ * progress-line contracts.
16
+ */
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Coordinate + shared shapes
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export interface CoordinateSpace {
23
+ /** `splatwalk_oriented` for default output, `engine_output` when an `output_space` conversion was applied. */
24
+ space: 'splatwalk_oriented' | 'engine_output' | string;
25
+ up_axis: 'y' | 'z' | string;
26
+ handedness: 'right' | 'left' | string;
27
+ }
28
+
29
+ /**
30
+ * Opt-in output coordinate convention for {@link MeshSettings.output_space}.
31
+ *
32
+ * When set, every mesh/basis/floor-plane result is converted from the default
33
+ * `splatwalk_oriented` space (right-handed, `+Y` up, CCW winding) into the
34
+ * requested convention and the reported `space` is updated to `engine_output`.
35
+ * Omitting it leaves all outputs in `splatwalk_oriented` space, unchanged.
36
+ * Per-cell ground-field scalars and `diagnostics` always stay in
37
+ * `splatwalk_oriented` space.
38
+ */
39
+ export interface OutputSpaceSettings {
40
+ /** `"y"` (default) or `"z"` (rotates `+Y`-up into `+Z`-up about X). */
41
+ up_axis?: 'y' | 'z';
42
+ /** `"right"` (default) or `"left"` (mirrors the Z axis). */
43
+ handedness?: 'right' | 'left';
44
+ /** `"auto"` (default; flips only when the basis is mirrored), `"ccw"`, or `"cw"`. */
45
+ winding?: 'auto' | 'ccw' | 'cw';
46
+ }
47
+
48
+ export interface MeshBuffers {
49
+ vertices: Float32Array;
50
+ indices: Uint32Array;
51
+ vertex_count: number;
52
+ face_count: number;
53
+ }
54
+
55
+ export interface FloorPlane {
56
+ normal: [number, number, number];
57
+ d: number;
58
+ }
59
+
60
+ export interface FieldBasis {
61
+ origin: [number, number, number];
62
+ tangent: [number, number, number];
63
+ bitangent: [number, number, number];
64
+ up: [number, number, number];
65
+ }
66
+
67
+ export type GroundFieldCellState =
68
+ | 'walkable'
69
+ | 'low_confidence'
70
+ | 'height_variance'
71
+ | 'obstacle'
72
+ | 'void'
73
+ | 'filled'
74
+ | 'eroded'
75
+ | 'discarded_component';
76
+
77
+ export interface GroundFieldCell {
78
+ height: number;
79
+ confidence: number;
80
+ variance: number;
81
+ normal_alignment: number;
82
+ obstacle_score: number;
83
+ primary_layer_height: number;
84
+ layer_count: number;
85
+ peak_density: number;
86
+ surface_confidence: number;
87
+ signed_distance: number;
88
+ gradient: [number, number];
89
+ component_id: number;
90
+ state: GroundFieldCellState;
91
+ }
92
+
93
+ /** Fields present on every v2 result. */
94
+ export interface ResultContract {
95
+ api_version: 2;
96
+ /** Semantic version of the WASM core build (tracks the crate version). */
97
+ semver: string;
98
+ /** Additive capability flags advertised by this build. */
99
+ capabilities: string[];
100
+ }
101
+
102
+ export interface ReconstructionDiagnostics {
103
+ api_version: 2;
104
+ region_min?: number[];
105
+ region_max?: number[];
106
+ oriented_min?: [number, number, number];
107
+ oriented_max?: [number, number, number];
108
+ floor_y_percentile_02?: number;
109
+ points_total: number;
110
+ points_invalid: number;
111
+ points_region_discarded: number;
112
+ points_after_filter: number;
113
+ ransac_inliers: number;
114
+ grid_width: number;
115
+ grid_height: number;
116
+ cell_size: number;
117
+ valid_vertices: number;
118
+ faces_generated: number;
119
+ faces_rejected_no_coverage: number;
120
+ faces_rejected_too_steep: number;
121
+ connected_components: number;
122
+ largest_component_faces: number;
123
+ holes_filled: number;
124
+ rejected_cells: number;
125
+ cells_rejected_low_confidence: number;
126
+ cells_rejected_height_variance: number;
127
+ cells_rejected_obstacle: number;
128
+ cells_void: number;
129
+ cells_filled: number;
130
+ cells_eroded: number;
131
+ cells_discarded_component: number;
132
+ selected_component_id: number;
133
+ selected_component_area: number;
134
+ floor_plane_source: string;
135
+ floor_plane_normal_y: number;
136
+ floor_plane_height: number;
137
+ floor_plane_used_fallback: boolean;
138
+ sdf_density_threshold: number;
139
+ sdf_vertical_cell_size: number;
140
+ sdf_profile_bins: number;
141
+ sdf_cells_with_surface: number;
142
+ sdf_cells_multi_layer: number;
143
+ sdf_cells_smoothed: number;
144
+ collision_voxel_size: number;
145
+ collision_grid_width: number;
146
+ collision_grid_height: number;
147
+ collision_grid_depth: number;
148
+ collision_occupied_voxels: number;
149
+ collision_cluster_kept_voxels: number;
150
+ collision_cluster_discarded_voxels: number;
151
+ collision_filled_voxels: number;
152
+ collision_carved_voxels: number;
153
+ collision_surface_faces: number;
154
+ collision_seed_used?: [number, number, number];
155
+ collision_seed_state: string;
156
+ collision_scene_type: string;
157
+ collision_mesh_mode: string;
158
+ collision_external_fill_leaked: boolean;
159
+ collision_failure_reason?: string;
160
+ floor_plane?: FloorPlane;
161
+ }
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // Settings
165
+ // ---------------------------------------------------------------------------
166
+
167
+ export interface MeshSettings {
168
+ mode: number;
169
+ voxel_target?: number;
170
+ sdf_cell_size?: number;
171
+ sdf_vertical_cell_size?: number;
172
+ sdf_density_threshold?: number;
173
+ sdf_max_layers?: number;
174
+ sdf_smoothing_radius?: number;
175
+ sdf_influence_radius_scale?: number;
176
+ collision_voxel_size?: number;
177
+ collision_opacity_threshold?: number;
178
+ collision_scene_type?: 'indoor' | 'outdoor' | 'object';
179
+ collision_seed?: number[];
180
+ collision_fill_size?: number;
181
+ collision_carve_height?: number;
182
+ collision_carve_radius?: number;
183
+ collision_mesh_mode?: 'faces' | 'smooth';
184
+ min_alpha?: number;
185
+ max_scale?: number;
186
+ normal_align?: number;
187
+ ransac_thresh?: number;
188
+ floor_projection_epsilon?: number;
189
+ height_projection_epsilon?: number;
190
+ obstacle_height_epsilon?: number;
191
+ obstacle_clearance_min?: number;
192
+ obstacle_clearance_max?: number;
193
+ max_local_height_variance?: number;
194
+ min_floor_confidence?: number;
195
+ hole_fill_radius?: number;
196
+ agent_radius_erode?: number;
197
+ component_mode?: 'largest' | 'nearest_region_center' | 'all';
198
+ region_min?: number[];
199
+ region_max?: number[];
200
+ /** Statistical outlier removal ("prune floaters"). Default `true`. */
201
+ prune_floaters?: boolean;
202
+ /** Neighbours sampled per splat for outlier removal (default 16). */
203
+ prune_floaters_k?: number;
204
+ /** Keep splats within `mean + std_ratio * stddev` (default 2.0). Lower = more aggressive. */
205
+ prune_floaters_std_ratio?: number;
206
+ rotation?: number[];
207
+ /**
208
+ * Opt-in output coordinate convention. Absent = default `splatwalk_oriented`
209
+ * output (right-handed, `+Y` up, CCW). See {@link OutputSpaceSettings}.
210
+ */
211
+ output_space?: OutputSpaceSettings;
212
+ flip_y?: boolean;
213
+ }
214
+
215
+ export interface SliceSettings {
216
+ /** Exported SH degree cap, 0..3 (default 3). */
217
+ sh_degree?: number;
218
+ /** shN k-means palette size (default 4096). */
219
+ sh_cluster_count?: number;
220
+ /** shN k-means refinement passes (default 10). */
221
+ sh_iterations?: number;
222
+ /** Target splats per LOD chunk (default 256000). */
223
+ chunk_count?: number;
224
+ /** Soft chunk extent in meters (default 16). */
225
+ chunk_extent?: number;
226
+ /** LOD levels, >= 1 (default 1). */
227
+ lod_levels?: number;
228
+ }
229
+
230
+ /** A single attempt in the optional WASM-side floor recovery ladder. */
231
+ export interface RoomFloorRecoveryStep {
232
+ label: string;
233
+ settings: Partial<MeshSettings>;
234
+ min_room_floor_area: number;
235
+ }
236
+
237
+ /** Settings for {@link build_room_floor_mesh} (a superset of {@link MeshSettings}). */
238
+ export interface RoomFloorSettings extends MeshSettings {
239
+ /** Minimum accepted floor area (m^2) for the base attempt. Default 4.0. */
240
+ min_room_floor_area?: number;
241
+ /** When true, also emit a GLB of the floor mesh in `glb`. Default false. */
242
+ emit_glb?: boolean;
243
+ /** Optional recovery ladder; when omitted a built-in default ladder is used. */
244
+ recovery?: RoomFloorRecoveryStep[];
245
+ }
246
+
247
+ // ---------------------------------------------------------------------------
248
+ // Results
249
+ // ---------------------------------------------------------------------------
250
+
251
+ export interface ReconstructionResult extends ResultContract {
252
+ mesh: MeshBuffers;
253
+ space: CoordinateSpace;
254
+ diagnostics: ReconstructionDiagnostics;
255
+ }
256
+
257
+ export interface SplatBounds extends ResultContract {
258
+ point_count: number;
259
+ oriented_min: [number, number, number];
260
+ oriented_max: [number, number, number];
261
+ floor_y_percentile_02: number;
262
+ space: CoordinateSpace;
263
+ }
264
+
265
+ export interface SuggestedRegion extends ResultContract {
266
+ region_min: [number, number, number];
267
+ region_max: [number, number, number];
268
+ floor_y: number;
269
+ sample_count: number;
270
+ clamped_height: boolean;
271
+ space: CoordinateSpace;
272
+ }
273
+
274
+ export interface NavmeshBasisResult extends ResultContract {
275
+ mesh: MeshBuffers;
276
+ space: CoordinateSpace;
277
+ basis: FieldBasis;
278
+ floor_plane: FloorPlane;
279
+ diagnostics: ReconstructionDiagnostics;
280
+ }
281
+
282
+ export interface WalkableGroundFieldResult extends ResultContract {
283
+ cells: GroundFieldCell[];
284
+ width: number;
285
+ height: number;
286
+ cell_size: number;
287
+ basis: FieldBasis;
288
+ floor_plane: FloorPlane;
289
+ space: CoordinateSpace;
290
+ diagnostics: ReconstructionDiagnostics;
291
+ }
292
+
293
+ /** Result of {@link build_room_floor_mesh}: a triangulated room-floor mesh. */
294
+ export interface RoomFloorMeshResult extends ResultContract {
295
+ mesh: MeshBuffers;
296
+ /** GLB bytes of the floor mesh, present only when `emit_glb` was set. */
297
+ glb?: Uint8Array;
298
+ space: CoordinateSpace;
299
+ basis: FieldBasis;
300
+ floor_plane: FloorPlane;
301
+ /** Selected floor area in square meters. */
302
+ selected_area: number;
303
+ /** Number of connected floor components considered. */
304
+ component_count: number;
305
+ selected_cell_count: number;
306
+ accepted_cell_count: number;
307
+ obstacle_cell_count: number;
308
+ rejected_cell_count: number;
309
+ /** Whether the relaxed mask / largest-island fallback was used. */
310
+ fallback_used: boolean;
311
+ /** Label of the recovery step that produced the floor. */
312
+ step_label: string;
313
+ diagnostics: ReconstructionDiagnostics;
314
+ }
315
+
316
+ /**
317
+ * Structured failure value rejected/thrown by {@link build_room_floor_mesh} when
318
+ * no recovery step yields a usable room floor. Branch on the stable `reason` code
319
+ * rather than string-matching `message`.
320
+ */
321
+ export interface RoomFloorFailure {
322
+ api_version: 2;
323
+ /** Stable machine code: the reason the last attempt failed. */
324
+ reason: 'no_component' | 'too_small' | 'empty_mesh' | 'no_steps' | string;
325
+ /** Human-readable summary across all attempted recovery steps. */
326
+ message: string;
327
+ /** Each attempted recovery step formatted as `label(reason)`. */
328
+ attempted: string[];
329
+ /** Largest usable floor area found, in square meters. */
330
+ selected_area: number;
331
+ /** Number of connected floor components considered. */
332
+ component_count: number;
333
+ /** Number of recovery steps attempted. */
334
+ steps: number;
335
+ }
336
+
337
+ /** Raw streamed-SOG / SOG manifest returned by {@link slice_splat} / {@link convert_to_sog}. */
338
+ export interface SliceManifest {
339
+ lodMetaPath: string;
340
+ lodMetaJson: string;
341
+ files: { path: string; contents: string }[];
342
+ binaries: { path: string; bytes: Uint8Array }[];
343
+ splatCount: number;
344
+ chunkCount: number;
345
+ }
346
+
347
+ // ---------------------------------------------------------------------------
348
+ // Entry points
349
+ // ---------------------------------------------------------------------------
350
+
351
+ export function init_splatwalk(): string;
352
+
353
+ // ---------------------------------------------------------------------------
354
+ // Cheap pre-flight introspection (no parse / field build required)
355
+ // ---------------------------------------------------------------------------
356
+
357
+ /** Semantic version of the WASM core build (tracks the crate version). */
358
+ export function splatwalk_version(): string;
359
+
360
+ /** Integer data-contract version (same value as every result's `api_version`). */
361
+ export function splatwalk_api_version(): number;
362
+
363
+ /** Additive capability flags advertised by this build. */
364
+ export function splatwalk_capabilities(): string[];
365
+
366
+ /**
367
+ * Register (or, with `undefined`, clear) an opt-in progress callback invoked as
368
+ * `callback(stage, fraction)` at the same boundaries as the `@progress` line
369
+ * protocol. The line protocol is still emitted as a fallback.
370
+ */
371
+ export function set_progress_callback(
372
+ callback?: (stage: string, fraction?: number) => void
373
+ ): void;
374
+
375
+ /**
376
+ * The canonical FAST NAV floor-field preset as a settings object. Pass it
377
+ * (merged with per-scene `rotation` / `flip_y` / `collision_seed` / `region_*`)
378
+ * to {@link build_walkable_ground_field} / {@link build_room_floor_mesh};
379
+ * the latter already applies it as a base layer automatically.
380
+ */
381
+ export function fast_nav_preset(): MeshSettings;
382
+
383
+ /** Reference FAST NAV agent dimensions (metres). */
384
+ export function recast_agent_defaults(): {
385
+ cs: number;
386
+ ch: number;
387
+ walkableHeight: number;
388
+ walkableRadius: number;
389
+ walkableClimb: number;
390
+ walkableSlopeAngle: number;
391
+ };
392
+
393
+ /**
394
+ * Convert metre-valued agent dimensions into Recast's integer voxel counts
395
+ * (`walkableHeight = ceil(h/ch)`, `walkableClimb = floor(climb/ch)`,
396
+ * `walkableRadius = ceil(r/cs)`) and suggest vertical-bounds padding. Inputs
397
+ * (all metres) default to {@link recast_agent_defaults} when omitted.
398
+ */
399
+ export function recast_config(settings?: {
400
+ cs?: number;
401
+ ch?: number;
402
+ walkableHeight?: number;
403
+ walkableClimb?: number;
404
+ walkableRadius?: number;
405
+ walkableSlopeAngle?: number;
406
+ /** Highest floor-cell Y (metres); when given, `suggestedBmaxY` is returned. */
407
+ maxFloorY?: number;
408
+ }): {
409
+ cs: number;
410
+ ch: number;
411
+ walkableHeight: number;
412
+ walkableClimb: number;
413
+ walkableRadius: number;
414
+ walkableSlopeAngle: number;
415
+ /** Suggested padding to add above the highest floor cell, in metres. */
416
+ bmaxYPadding: number;
417
+ /** `maxFloorY + bmaxYPadding`, or `null` when `maxFloorY` was omitted. */
418
+ suggestedBmaxY: number | null;
419
+ };
420
+
421
+ export function get_splat_bounds(data: Uint8Array, settings: MeshSettings): SplatBounds;
422
+
423
+ export function suggest_region(data: Uint8Array, settings: MeshSettings): SuggestedRegion;
424
+
425
+ export function convert_splat_to_mesh(data: Uint8Array, settings: MeshSettings): ReconstructionResult;
426
+
427
+ export function convert_splat_to_navmesh_basis(data: Uint8Array, settings: MeshSettings): NavmeshBasisResult;
428
+
429
+ export function build_walkable_ground_field(data: Uint8Array, settings: MeshSettings): WalkableGroundFieldResult;
430
+
431
+ /**
432
+ * Extract a triangulated room-floor mesh directly in WASM (the binary-side
433
+ * equivalent of the TypeScript FAST NAV floor path). The canonical FAST NAV
434
+ * preset is applied as a base layer automatically (your settings and the
435
+ * per-step recovery patch override it).
436
+ *
437
+ * On failure it throws/rejects with a structured {@link RoomFloorFailure} object
438
+ * (not a string): branch on `err.reason` for control flow and telemetry.
439
+ */
440
+ export function build_room_floor_mesh(data: Uint8Array, settings: RoomFloorSettings): RoomFloorMeshResult;
441
+
442
+ /**
443
+ * Serialize positions + indices into a minimal binary glTF (GLB) without
444
+ * standing up a 3D engine. Positions are xyz triplets; indices are `u32`.
445
+ */
446
+ export function mesh_to_glb(positions: Float32Array, indices: Uint32Array): Uint8Array;
447
+
448
+ /** Slice a `.ply`/`.spz` splat into a streamed-SOG bundle. */
449
+ export function slice_splat(data: Uint8Array, settings: SliceSettings): SliceManifest;
450
+
451
+ /** Convert a `.ply`/`.spz` splat into a single (non-LOD) SOG v2 bundle. */
452
+ export function convert_to_sog(data: Uint8Array, settings: SliceSettings): SliceManifest;
453
+
454
+ /** Convert a `.spz` (or `.ply`) splat to a full-fidelity binary little-endian 3DGS `.ply`. */
455
+ export function spz_to_ply(data: Uint8Array): Uint8Array;
456
+
457
+ // ---------------------------------------------------------------------------
458
+ // wasm-bindgen init plumbing (kept loose; matches the generated `--target web` glue)
459
+ // ---------------------------------------------------------------------------
460
+
461
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
462
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
463
+
464
+ export interface InitOutput {
465
+ readonly memory: WebAssembly.Memory;
466
+ readonly [exportName: string]: unknown;
467
+ }
468
+
469
+ /** Instantiate the module synchronously from already-fetched bytes/module. */
470
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
471
+
472
+ /**
473
+ * Default export: load + instantiate the wasm. Always await this (or `initSync`)
474
+ * before calling any named export.
475
+ */
476
+ export default function __wbg_init(
477
+ module_or_path?:
478
+ | { module_or_path: InitInput | Promise<InitInput> }
479
+ | InitInput
480
+ | Promise<InitInput>
481
+ ): Promise<InitOutput>;