@playcanvas/splat-transform 0.17.1 → 1.1.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.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.mjs +352 -5
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/index.cjs +5478 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.mjs +352 -5
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/lib/data-table/combine.d.ts +16 -0
  9. package/dist/lib/data-table/data-table.d.ts +48 -0
  10. package/dist/lib/data-table/summary.d.ts +33 -0
  11. package/dist/lib/data-table/transform.d.ts +19 -0
  12. package/dist/lib/index.d.cts +34 -0
  13. package/dist/lib/index.d.ts +4 -4
  14. package/dist/lib/io/read/index.d.ts +1 -1
  15. package/dist/lib/io/read/zip-file-system.d.ts +1 -1
  16. package/dist/lib/io/write/memory-file-system.d.ts +15 -0
  17. package/dist/lib/io/write/zip-file-system.d.ts +20 -0
  18. package/dist/lib/process.d.ts +96 -1
  19. package/dist/lib/read.d.ts +57 -1
  20. package/dist/lib/readers/read-ksplat.d.ts +11 -0
  21. package/dist/lib/readers/read-lcc.d.ts +13 -0
  22. package/dist/lib/readers/read-mjs.d.ts +12 -0
  23. package/dist/lib/readers/read-ply.d.ts +10 -0
  24. package/dist/lib/readers/read-sog.d.ts +1 -0
  25. package/dist/lib/readers/read-splat.d.ts +10 -0
  26. package/dist/lib/readers/read-spz.d.ts +12 -0
  27. package/dist/lib/types.d.ts +1 -0
  28. package/dist/lib/write.d.ts +57 -1
  29. package/dist/lib/writers/write-compressed-ply.d.ts +11 -0
  30. package/dist/lib/writers/write-csv.d.ts +10 -0
  31. package/dist/lib/writers/write-html.d.ts +10 -0
  32. package/dist/lib/writers/write-lod.d.ts +11 -0
  33. package/dist/lib/writers/write-ply.d.ts +10 -0
  34. package/dist/lib/writers/write-sog.d.ts +16 -1
  35. package/package.json +13 -4
package/dist/index.mjs CHANGED
@@ -1,5 +1,17 @@
1
1
  import { Vec3, Quat, Mat4, Mat3, BindGroupFormat, BindUniformBufferFormat, BindStorageBufferFormat, SHADERSTAGE_COMPUTE, Shader, UniformBufferFormat, SHADERLANGUAGE_WGSL, UniformFormat, UNIFORMTYPE_UINT, StorageBuffer, BUFFERUSAGE_COPY_DST, BUFFERUSAGE_COPY_SRC, Compute, FloatPacking, BoundingBox } from 'playcanvas';
2
2
 
3
+ /**
4
+ * A named column of typed array data within a DataTable.
5
+ *
6
+ * Columns store homogeneous numeric data efficiently using JavaScript typed arrays.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const positions = new Column('x', new Float32Array([1.0, 2.0, 3.0]));
11
+ * console.log(positions.name); // 'x'
12
+ * console.log(positions.dataType); // 'float32'
13
+ * ```
14
+ */
3
15
  class Column {
4
16
  name;
5
17
  data;
@@ -24,6 +36,32 @@ class Column {
24
36
  return new Column(this.name, this.data.slice());
25
37
  }
26
38
  }
39
+ /**
40
+ * A table of columnar data representing Gaussian splat properties.
41
+ *
42
+ * DataTable is the core data structure for splat data. Each column represents
43
+ * a property (e.g., position, rotation, color) as a typed array, and all columns
44
+ * must have the same number of rows.
45
+ *
46
+ * Standard columns include:
47
+ * - Position: `x`, `y`, `z`
48
+ * - Rotation: `rot_0`, `rot_1`, `rot_2`, `rot_3` (quaternion)
49
+ * - Scale: `scale_0`, `scale_1`, `scale_2` (log scale)
50
+ * - Color: `f_dc_0`, `f_dc_1`, `f_dc_2` (spherical harmonics DC)
51
+ * - Opacity: `opacity` (logit)
52
+ * - Spherical Harmonics: `f_rest_0` through `f_rest_44`
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * const table = new DataTable([
57
+ * new Column('x', new Float32Array([0, 1, 2])),
58
+ * new Column('y', new Float32Array([0, 0, 0])),
59
+ * new Column('z', new Float32Array([0, 0, 0]))
60
+ * ]);
61
+ * console.log(table.numRows); // 3
62
+ * console.log(table.numColumns); // 3
63
+ * ```
64
+ */
27
65
  class DataTable {
28
66
  columns;
29
67
  constructor(columns) {
@@ -115,7 +153,22 @@ class DataTable {
115
153
  }
116
154
  }
117
155
 
118
- // combine multiple DataTables into a single DataTable instance
156
+ /**
157
+ * Combines multiple DataTables into a single DataTable.
158
+ *
159
+ * Merges rows from all input tables. Columns are matched by name and type;
160
+ * columns that don't exist in all tables will have undefined values for
161
+ * rows from tables lacking that column.
162
+ *
163
+ * @param dataTables - Array of DataTables to combine.
164
+ * @returns A new DataTable containing all rows from all input tables.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * const combined = combine([tableA, tableB, tableC]);
169
+ * console.log(combined.numRows); // tableA.numRows + tableB.numRows + tableC.numRows
170
+ * ```
171
+ */
119
172
  const combine = (dataTables) => {
120
173
  if (dataTables.length === 1) {
121
174
  // nothing to combine
@@ -341,7 +394,25 @@ class RotateSH {
341
394
  const shNames$3 = new Array(45).fill('').map((_, i) => `f_rest_${i}`);
342
395
  const v = new Vec3();
343
396
  const q$1 = new Quat();
344
- // apply translation, rotation and scale to a data table
397
+ /**
398
+ * Applies a spatial transformation to splat data in-place.
399
+ *
400
+ * Transforms position, rotation, scale, and spherical harmonics data.
401
+ * The transformation is applied as: scale first, then rotation, then translation.
402
+ *
403
+ * @param dataTable - The DataTable to transform (modified in-place).
404
+ * @param t - Translation vector.
405
+ * @param r - Rotation quaternion.
406
+ * @param s - Uniform scale factor.
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * import { Vec3, Quat } from 'playcanvas';
411
+ *
412
+ * // Scale by 2x, rotate 90° around Y, translate up
413
+ * transform(dataTable, new Vec3(0, 5, 0), new Quat().setFromEulerAngles(0, 90, 0), 2.0);
414
+ * ```
415
+ */
345
416
  const transform = (dataTable, t, r, s) => {
346
417
  const mat = new Mat4().setTRS(t, r, new Vec3(s, s, s));
347
418
  const mat3 = new Mat3().setFromQuat(r);
@@ -460,6 +531,23 @@ const computeColumnStats = (data) => {
460
531
  infCount
461
532
  };
462
533
  };
534
+ /**
535
+ * Computes statistical summary for all columns in a DataTable.
536
+ *
537
+ * For each column, calculates min, max, median, mean, standard deviation,
538
+ * and counts of NaN/Infinity values. Useful for data validation and analysis.
539
+ *
540
+ * @param dataTable - The DataTable to analyze.
541
+ * @returns Summary data with per-column statistics.
542
+ *
543
+ * @example
544
+ * ```ts
545
+ * const summary = computeSummary(dataTable);
546
+ * console.log(summary.rowCount);
547
+ * console.log(summary.columns['x'].mean);
548
+ * console.log(summary.columns['opacity'].nanCount);
549
+ * ```
550
+ */
463
551
  const computeSummary = (dataTable) => {
464
552
  const columns = {};
465
553
  for (const column of dataTable.columns) {
@@ -918,6 +1006,17 @@ const COMPRESSION_MODES = [
918
1006
  }
919
1007
  ];
920
1008
  const HARMONICS_COMPONENT_COUNT$1 = [0, 9, 24, 45];
1009
+ /**
1010
+ * Reads a .ksplat file containing compressed Gaussian splat data.
1011
+ *
1012
+ * The .ksplat format (Kevin Kwok's format) uses spatial bucketing and
1013
+ * quantization to achieve high compression ratios while preserving quality.
1014
+ * Supports multiple compression modes and spherical harmonics bands.
1015
+ *
1016
+ * @param source - The read source providing access to the .ksplat file data.
1017
+ * @returns Promise resolving to a DataTable containing the splat data.
1018
+ * @ignore
1019
+ */
921
1020
  const readKsplat = async (source) => {
922
1021
  // Load complete file
923
1022
  const fileBuffer = await source.read().readAll();
@@ -1875,6 +1974,19 @@ const deserializeEnvironment = (raw, compressInfo, hasSH) => {
1875
1974
  }
1876
1975
  return new DataTable(columns);
1877
1976
  };
1977
+ /**
1978
+ * Reads an XGrids LCC format containing multi-LOD Gaussian splat data.
1979
+ *
1980
+ * The LCC format uses a quadtree spatial structure with multiple LOD levels.
1981
+ * Each LOD level is stored separately in data.bin with optional spherical
1982
+ * harmonics in shcoef.bin. Environment splats are stored in environment.bin.
1983
+ *
1984
+ * @param fileSystem - File system for reading the LCC files.
1985
+ * @param filename - Path to the meta.lcc file.
1986
+ * @param options - Options including LOD selection via `lodSelect`.
1987
+ * @returns Promise resolving to an array of DataTables, one per LOD level plus environment.
1988
+ * @ignore
1989
+ */
1878
1990
  const readLcc = async (fileSystem, filename, options) => {
1879
1991
  const lccData = await readFile$1(fileSystem, filename);
1880
1992
  const lccText = new TextDecoder().decode(lccData);
@@ -1949,6 +2061,18 @@ const readLcc = async (fileSystem, filename, options) => {
1949
2061
  return result;
1950
2062
  };
1951
2063
 
2064
+ /**
2065
+ * Reads splat data from a JavaScript module generator.
2066
+ *
2067
+ * The module must export a `Generator` class with a static `create(params)` method
2068
+ * that returns an object with `count`, `columnNames`, and `getRow(index, row)` properties.
2069
+ * This allows programmatic generation of splat data.
2070
+ *
2071
+ * @param moduleUrl - URL or path to the JavaScript module.
2072
+ * @param params - Parameters to pass to the generator's create method.
2073
+ * @returns Promise resolving to a DataTable containing the generated splat data.
2074
+ * @ignore
2075
+ */
1952
2076
  const readMjs = async (moduleUrl, params) => {
1953
2077
  const module = await import(moduleUrl);
1954
2078
  if (!module) {
@@ -2269,6 +2393,16 @@ const readExact = async (stream, buffer, offset, length) => {
2269
2393
  }
2270
2394
  return totalRead;
2271
2395
  };
2396
+ /**
2397
+ * Reads a PLY file containing Gaussian splat data.
2398
+ *
2399
+ * Supports both standard PLY files and compressed PLY format. The PLY format is
2400
+ * the standard output from 3D Gaussian Splatting training pipelines.
2401
+ *
2402
+ * @param source - The read source providing access to the PLY file data.
2403
+ * @returns Promise resolving to a DataTable containing the splat data.
2404
+ * @ignore
2405
+ */
2272
2406
  const readPly = async (source) => {
2273
2407
  const stream = source.read();
2274
2408
  // we don't support ply text header larger than 128k
@@ -2483,6 +2617,7 @@ const sigmoidInv = (y) => {
2483
2617
  * @param fileSystem - The file system to read from
2484
2618
  * @param filename - Path to meta.json (relative paths resolved from its directory)
2485
2619
  * @returns DataTable with Gaussian splat data
2620
+ * @ignore
2486
2621
  */
2487
2622
  const readSog = async (fileSystem, filename) => {
2488
2623
  const decoder = await WebPCodec.create();
@@ -2630,6 +2765,16 @@ const readSog = async (fileSystem, filename) => {
2630
2765
  return new DataTable(columns);
2631
2766
  };
2632
2767
 
2768
+ /**
2769
+ * Reads an Antimatter15 .splat file containing Gaussian splat data.
2770
+ *
2771
+ * The .splat format stores each splat as 32 bytes with position, scale, color,
2772
+ * opacity, and rotation data in a compact binary format.
2773
+ *
2774
+ * @param source - The read source providing access to the .splat file data.
2775
+ * @returns Promise resolving to a DataTable containing the splat data.
2776
+ * @ignore
2777
+ */
2633
2778
  const readSplat = async (source) => {
2634
2779
  // Load complete file
2635
2780
  const fileBuffer = await source.read().readAll();
@@ -2753,6 +2898,18 @@ function getFixed24(positionsView, elementIndex, memberIndex) {
2753
2898
  return fixed32;
2754
2899
  }
2755
2900
  const HARMONICS_COMPONENT_COUNT = [0, 9, 24, 45];
2901
+ /**
2902
+ * Reads a .spz file containing Niantic Labs compressed Gaussian splat data.
2903
+ *
2904
+ * The .spz format uses GZIP compression and fixed-point encoding to achieve
2905
+ * compact file sizes. Supports version 2 and 3 of the format.
2906
+ *
2907
+ * @see https://github.com/nianticlabs/spz
2908
+ *
2909
+ * @param source - The read source providing access to the .spz file data.
2910
+ * @returns Promise resolving to a DataTable containing the splat data.
2911
+ * @ignore
2912
+ */
2756
2913
  const readSpz = async (source) => {
2757
2914
  // Load complete file
2758
2915
  let fileBuffer = await source.read().readAll();
@@ -2989,6 +3146,19 @@ const logger = {
2989
3146
  }
2990
3147
  };
2991
3148
 
3149
+ /**
3150
+ * Determines the input format based on file extension.
3151
+ *
3152
+ * @param filename - The filename to analyze.
3153
+ * @returns The detected input format.
3154
+ * @throws Error if the file extension is not recognized.
3155
+ *
3156
+ * @example
3157
+ * ```ts
3158
+ * const format = getInputFormat('scene.ply'); // returns 'ply'
3159
+ * const format2 = getInputFormat('scene.splat'); // returns 'splat'
3160
+ * ```
3161
+ */
2992
3162
  const getInputFormat = (filename) => {
2993
3163
  const lowerFilename = filename.toLowerCase();
2994
3164
  if (lowerFilename.endsWith('.mjs')) {
@@ -3014,6 +3184,30 @@ const getInputFormat = (filename) => {
3014
3184
  }
3015
3185
  throw new Error(`Unsupported input file type: ${filename}`);
3016
3186
  };
3187
+ /**
3188
+ * Reads a Gaussian splat file and returns its data as one or more DataTables.
3189
+ *
3190
+ * Supports multiple input formats including PLY, splat, ksplat, spz, SOG, and LCC.
3191
+ * Some formats (like LCC) may return multiple DataTables for different LOD levels.
3192
+ *
3193
+ * @param readFileOptions - Options specifying the file to read and how to read it.
3194
+ * @returns Promise resolving to an array of DataTables containing the splat data.
3195
+ *
3196
+ * @example
3197
+ * ```ts
3198
+ * import { readFile, getInputFormat, UrlReadFileSystem } from '@playcanvas/splat-transform';
3199
+ *
3200
+ * const filename = 'scene.ply';
3201
+ * const fileSystem = new UrlReadFileSystem('https://example.com/');
3202
+ * const tables = await readFile({
3203
+ * filename,
3204
+ * inputFormat: getInputFormat(filename),
3205
+ * options: {},
3206
+ * params: [],
3207
+ * fileSystem
3208
+ * });
3209
+ * ```
3210
+ */
3017
3211
  const readFile = async (readFileOptions) => {
3018
3212
  const { filename, inputFormat, options, params, fileSystem } = readFileOptions;
3019
3213
  let result;
@@ -3208,7 +3402,7 @@ class CompressedChunk {
3208
3402
  }
3209
3403
  }
3210
3404
 
3211
- var version = "0.17.1";
3405
+ var version = "1.1.0";
3212
3406
 
3213
3407
  // sort the provided indices into morton order
3214
3408
  const sortMortonOrder = (dataTable, indices) => {
@@ -3327,6 +3521,17 @@ const vertexProps = [
3327
3521
  const shNames$2 = new Array(45).fill('').map((_, i) => `f_rest_${i}`);
3328
3522
  // Size of a chunk in the compressed PLY format (number of splats per chunk)
3329
3523
  const CHUNK_SIZE = 256;
3524
+ /**
3525
+ * Writes Gaussian splat data to compressed PLY format.
3526
+ *
3527
+ * Uses quantization and chunking to reduce file size while maintaining
3528
+ * compatibility with PLY-based viewers. Data is sorted using Morton order
3529
+ * for better compression and streaming performance.
3530
+ *
3531
+ * @param options - Options including filename and data table to write.
3532
+ * @param fs - File system for writing the output file.
3533
+ * @ignore
3534
+ */
3330
3535
  const writeCompressedPly = async (options, fs) => {
3331
3536
  const { filename, dataTable } = options;
3332
3537
  const shBands = { '9': 1, '24': 2, '-1': 3 }[shNames$2.findIndex(v => !dataTable.hasColumn(v))] ?? 0;
@@ -3400,6 +3605,16 @@ const writeCompressedPly = async (options, fs) => {
3400
3605
  await writer.close();
3401
3606
  };
3402
3607
 
3608
+ /**
3609
+ * Writes Gaussian splat data to a CSV text file.
3610
+ *
3611
+ * Useful for debugging, analysis, or importing into spreadsheet applications.
3612
+ * Each row represents one splat with all column values separated by commas.
3613
+ *
3614
+ * @param options - Options including filename and data table to write.
3615
+ * @param fs - File system for writing the output file.
3616
+ * @ignore
3617
+ */
3403
3618
  const writeCsv = async (options, fs) => {
3404
3619
  const { filename, dataTable } = options;
3405
3620
  const len = dataTable.numRows;
@@ -3471,6 +3686,21 @@ class MemoryWriter {
3471
3686
  };
3472
3687
  }
3473
3688
  }
3689
+ /**
3690
+ * A file system that writes files to in-memory buffers.
3691
+ *
3692
+ * Useful for generating output without writing to disk, such as when
3693
+ * creating data for download or further processing.
3694
+ *
3695
+ * @example
3696
+ * ```ts
3697
+ * const fs = new MemoryFileSystem();
3698
+ * await writeFile({ filename: 'output.ply', ... }, fs);
3699
+ *
3700
+ * // Get the generated data
3701
+ * const data = fs.results.get('output.ply');
3702
+ * ```
3703
+ */
3474
3704
  class MemoryFileSystem {
3475
3705
  results = new Map();
3476
3706
  createWriter(filename) {
@@ -3537,7 +3767,26 @@ class ZipEntryWriter {
3537
3767
  };
3538
3768
  }
3539
3769
  }
3540
- // FileSystem implementation that writes files into a zip archive
3770
+ /**
3771
+ * A file system that writes files into a ZIP archive.
3772
+ *
3773
+ * Creates a ZIP file containing all written files. Used internally
3774
+ * for bundled output formats like .sog files.
3775
+ *
3776
+ * @example
3777
+ * ```ts
3778
+ * const outputWriter = await fs.createWriter('bundle.zip');
3779
+ * const zipFs = new ZipFileSystem(outputWriter);
3780
+ *
3781
+ * // Write files into the zip
3782
+ * const writer = await zipFs.createWriter('data.json');
3783
+ * await writer.write(jsonData);
3784
+ * await writer.close();
3785
+ *
3786
+ * // Finalize the zip
3787
+ * await zipFs.close();
3788
+ * ```
3789
+ */
3541
3790
  class ZipFileSystem {
3542
3791
  close;
3543
3792
  createWriter;
@@ -4117,6 +4366,17 @@ const cluster1d = async (dataTable, iterations, device) => {
4117
4366
  };
4118
4367
  };
4119
4368
  let webPCodec;
4369
+ /**
4370
+ * Writes Gaussian splat data to the PlayCanvas SOG format.
4371
+ *
4372
+ * SOG (Splat Optimized Graphics) uses WebP lossless compression and k-means
4373
+ * clustering to achieve high compression ratios. Data is stored in textures
4374
+ * for efficient GPU loading.
4375
+ *
4376
+ * @param options - Options including filename, data, and compression settings.
4377
+ * @param fs - File system for writing output files.
4378
+ * @ignore
4379
+ */
4120
4380
  const writeSog = async (options, fs) => {
4121
4381
  const { filename: outputFilename, bundle, dataTable, iterations, createDevice } = options;
4122
4382
  // initialize output stream - use ZipFileSystem for bundled output
@@ -4355,6 +4615,16 @@ const toBase64 = (bytes) => {
4355
4615
  return btoa(binary);
4356
4616
  };
4357
4617
 
4618
+ /**
4619
+ * Writes Gaussian splat data as a self-contained HTML viewer.
4620
+ *
4621
+ * Creates an interactive 3D viewer that can be opened directly in a browser.
4622
+ * Uses the PlayCanvas SuperSplat viewer for rendering.
4623
+ *
4624
+ * @param options - Options including filename, data, and viewer settings.
4625
+ * @param fs - File system for writing output files.
4626
+ * @ignore
4627
+ */
4358
4628
  const writeHtml = async (options, fs) => {
4359
4629
  const { filename, dataTable, viewerSettingsJson, bundle, iterations, createDevice } = options;
4360
4630
  const pad = (text, spaces) => {
@@ -4650,6 +4920,17 @@ const binIndices = (parent, lod) => {
4650
4920
  recurse(parent);
4651
4921
  return result;
4652
4922
  };
4923
+ /**
4924
+ * Writes Gaussian splat data to multi-LOD format with spatial chunking.
4925
+ *
4926
+ * Creates a hierarchical structure with multiple LOD levels, each stored
4927
+ * in separate SOG files. Includes spatial indexing via a binary tree for
4928
+ * efficient streaming and view-dependent loading.
4929
+ *
4930
+ * @param options - Options including filename, data, and chunking parameters.
4931
+ * @param fs - File system for writing output files.
4932
+ * @ignore
4933
+ */
4653
4934
  const writeLod = async (options, fs) => {
4654
4935
  const { filename, dataTable, envDataTable, iterations, createDevice, chunkCount, chunkExtent } = options;
4655
4936
  const outputDir = dirname(filename);
@@ -4801,6 +5082,16 @@ const columnTypeToPlyType = (type) => {
4801
5082
  case 'uint32': return 'uint';
4802
5083
  }
4803
5084
  };
5085
+ /**
5086
+ * Writes Gaussian splat data to a binary PLY file.
5087
+ *
5088
+ * The PLY format is the standard output from 3D Gaussian Splatting training
5089
+ * and is widely supported by visualization tools.
5090
+ *
5091
+ * @param options - Options including filename and PLY data to write.
5092
+ * @param fs - File system for writing the output file.
5093
+ * @ignore
5094
+ */
4804
5095
  const writePly = async (options, fs) => {
4805
5096
  const { filename, plyData } = options;
4806
5097
  const header = [
@@ -4849,6 +5140,20 @@ const writePly = async (options, fs) => {
4849
5140
  await writer.close();
4850
5141
  };
4851
5142
 
5143
+ /**
5144
+ * Determines the output format based on file extension and options.
5145
+ *
5146
+ * @param filename - The filename to analyze.
5147
+ * @param options - Options that may affect format selection.
5148
+ * @returns The detected output format.
5149
+ * @throws Error if the file extension is not recognized.
5150
+ *
5151
+ * @example
5152
+ * ```ts
5153
+ * const format = getOutputFormat('scene.ply', {}); // returns 'ply'
5154
+ * const format2 = getOutputFormat('scene.sog', {}); // returns 'sog-bundle'
5155
+ * ```
5156
+ */
4852
5157
  const getOutputFormat = (filename, options) => {
4853
5158
  const lowerFilename = filename.toLowerCase();
4854
5159
  if (lowerFilename.endsWith('.csv')) {
@@ -4874,6 +5179,27 @@ const getOutputFormat = (filename, options) => {
4874
5179
  }
4875
5180
  throw new Error(`Unsupported output file type: ${filename}`);
4876
5181
  };
5182
+ /**
5183
+ * Writes Gaussian splat data to a file in the specified format.
5184
+ *
5185
+ * Supports multiple output formats including PLY, compressed PLY, CSV, SOG, LOD, and HTML.
5186
+ *
5187
+ * @param writeOptions - Options specifying the data and format to write.
5188
+ * @param fs - File system abstraction for writing files.
5189
+ *
5190
+ * @example
5191
+ * ```ts
5192
+ * import { writeFile, getOutputFormat, MemoryFileSystem } from '@playcanvas/splat-transform';
5193
+ *
5194
+ * const fs = new MemoryFileSystem();
5195
+ * await writeFile({
5196
+ * filename: 'output.sog',
5197
+ * outputFormat: getOutputFormat('output.sog', {}),
5198
+ * dataTable: myDataTable,
5199
+ * options: { iterations: 8 }
5200
+ * }, fs);
5201
+ * ```
5202
+ */
4877
5203
  const writeFile = async (writeOptions, fs) => {
4878
5204
  const { filename, outputFormat, dataTable, envDataTable, options, createDevice } = writeOptions;
4879
5205
  logger.log(`writing '${filename}'...`);
@@ -4981,7 +5307,28 @@ const filter = (dataTable, predicate) => {
4981
5307
  }
4982
5308
  return dataTable.permuteRows(indices.subarray(0, index));
4983
5309
  };
4984
- // process a data table with standard options
5310
+ /**
5311
+ * Applies a sequence of processing actions to splat data.
5312
+ *
5313
+ * Actions are applied in order and can include transformations (translate, rotate, scale),
5314
+ * filters (NaN, value, box, sphere, bands), and analysis (summary).
5315
+ *
5316
+ * @param dataTable - The input splat data.
5317
+ * @param processActions - Array of actions to apply in sequence.
5318
+ * @returns The processed DataTable (may be a new instance if filtered).
5319
+ *
5320
+ * @example
5321
+ * ```ts
5322
+ * import { Vec3 } from 'playcanvas';
5323
+ *
5324
+ * const processed = processDataTable(dataTable, [
5325
+ * { kind: 'scale', value: 0.5 },
5326
+ * { kind: 'translate', value: new Vec3(0, 1, 0) },
5327
+ * { kind: 'filterNaN' },
5328
+ * { kind: 'filterByValue', columnName: 'opacity', comparator: 'gt', value: 0.1 }
5329
+ * ]);
5330
+ * ```
5331
+ */
4985
5332
  const processDataTable = (dataTable, processActions) => {
4986
5333
  let result = dataTable;
4987
5334
  for (let i = 0; i < processActions.length; i++) {