@loaders.gl/splats 5.0.0-alpha.1 → 5.0.0-alpha.11

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 (45) hide show
  1. package/LICENSE +14 -3
  2. package/dist/dist.dev.js +36757 -17782
  3. package/dist/dist.min.js +68 -7
  4. package/dist/index.cjs +2769 -838
  5. package/dist/index.cjs.map +3 -4
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/ksplat-loader-types.js +1 -1
  11. package/dist/ksplat-loader-types.js.map +1 -1
  12. package/dist/lib/parse-rad-chunk.js +3 -3
  13. package/dist/lib/parse-rad-chunk.js.map +1 -1
  14. package/dist/lib/parse-rad.d.ts +23 -7
  15. package/dist/lib/parse-rad.d.ts.map +1 -1
  16. package/dist/lib/parse-rad.js +10 -135
  17. package/dist/lib/parse-rad.js.map +1 -1
  18. package/dist/lib/parse-spz.d.ts.map +1 -1
  19. package/dist/lib/parse-spz.js +153 -4
  20. package/dist/lib/parse-spz.js.map +1 -1
  21. package/dist/rad-loader-types.js +1 -1
  22. package/dist/rad-loader-types.js.map +1 -1
  23. package/dist/rad-metadata.schema.json +133 -0
  24. package/dist/rad-source-loader.js +1 -1
  25. package/dist/rad-source-loader.js.map +1 -1
  26. package/dist/rad-zod-schema.cjs +81 -0
  27. package/dist/rad-zod-schema.cjs.map +6 -0
  28. package/dist/rad-zod-schema.d.ts +88 -0
  29. package/dist/rad-zod-schema.d.ts.map +1 -0
  30. package/dist/rad-zod-schema.js +70 -0
  31. package/dist/rad-zod-schema.js.map +1 -0
  32. package/dist/radc-metadata.schema.json +112 -0
  33. package/dist/splat-loader-types.js +1 -1
  34. package/dist/splat-loader-types.js.map +1 -1
  35. package/dist/spz-loader-types.js +1 -1
  36. package/dist/spz-loader-types.js.map +1 -1
  37. package/dist/types.d.ts +6 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/package.json +17 -8
  40. package/src/index.ts +4 -1
  41. package/src/lib/parse-rad-chunk.ts +3 -3
  42. package/src/lib/parse-rad.ts +46 -167
  43. package/src/lib/parse-spz.ts +190 -5
  44. package/src/rad-zod-schema.ts +83 -0
  45. package/src/types.ts +7 -0
package/dist/index.cjs CHANGED
@@ -5,8 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ var __esm = (fn, res, err2) => function __init() {
9
+ if (err2) throw err2[0];
10
+ try {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ } catch (e) {
13
+ throw err2 = [e], e;
14
+ }
10
15
  };
11
16
  var __export = (target, all) => {
12
17
  for (var name in all)
@@ -76,481 +81,2296 @@ var init_splats_format = __esm({
76
81
  }
77
82
  });
78
83
 
79
- // dist/lib/splat-utils.js
80
- function convertColorByteToSphericalHarmonicDc(colorByte) {
81
- return (colorByte / 255 - 0.5) / SH_C0;
84
+ // ../loader-utils/src/lib/log-utils/log.ts
85
+ function createLog() {
86
+ const log2 = new import_log.Log({ id: "loaders.gl" });
87
+ globalThis.loaders ||= {};
88
+ globalThis.loaders.log = log2;
89
+ globalThis.loaders.version = version;
90
+ globalThis.probe ||= {};
91
+ globalThis.probe.loaders = log2;
92
+ return log2;
93
+ }
94
+ var import_log, VERSION, version, log;
95
+ var init_log = __esm({
96
+ "../loader-utils/src/lib/log-utils/log.ts"() {
97
+ "use strict";
98
+ import_log = require("@probe.gl/log");
99
+ VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
100
+ version = VERSION[0] >= "0" && VERSION[0] <= "9" ? `v${VERSION}` : "";
101
+ log = createLog();
102
+ }
103
+ });
104
+
105
+ // ../loader-utils/src/lib/javascript-utils/is-type.ts
106
+ var isObject, isPureObject, isSharedArrayBuffer;
107
+ var init_is_type = __esm({
108
+ "../loader-utils/src/lib/javascript-utils/is-type.ts"() {
109
+ "use strict";
110
+ isObject = (value) => value !== null && typeof value === "object";
111
+ isPureObject = (value) => isObject(value) && value.constructor === {}.constructor;
112
+ isSharedArrayBuffer = (value) => typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
113
+ }
114
+ });
115
+
116
+ // ../loader-utils/src/lib/option-utils/merge-options.ts
117
+ function mergeOptions(baseOptions, newOptions) {
118
+ return mergeOptionsRecursively(baseOptions || {}, newOptions);
119
+ }
120
+ function mergeOptionsRecursively(baseOptions, newOptions, level = 0) {
121
+ if (level > 3) {
122
+ return newOptions;
123
+ }
124
+ const options = { ...baseOptions };
125
+ for (const [key, newValue] of Object.entries(newOptions)) {
126
+ if (isPureObject(newValue)) {
127
+ options[key] = mergeOptionsRecursively(
128
+ options[key] || {},
129
+ newOptions[key],
130
+ level + 1
131
+ );
132
+ } else {
133
+ options[key] = newOptions[key];
134
+ }
135
+ }
136
+ return options;
82
137
  }
83
- function convertAlphaByteToLinearOpacity(alphaByte) {
84
- return Math.min(Math.max(alphaByte / 255, 0), 1);
138
+ var init_merge_options = __esm({
139
+ "../loader-utils/src/lib/option-utils/merge-options.ts"() {
140
+ "use strict";
141
+ init_is_type();
142
+ }
143
+ });
144
+
145
+ // ../loader-utils/src/lib/module-utils/js-module-utils.ts
146
+ function registerJSModules(modules) {
147
+ globalThis.loaders ||= {};
148
+ globalThis.loaders.modules ||= {};
149
+ Object.assign(globalThis.loaders.modules, modules);
85
150
  }
86
- function normalizeQuaternion(w, x, y, z) {
87
- const length = Math.hypot(w, x, y, z);
88
- if (!Number.isFinite(length) || length <= Number.EPSILON) {
89
- return [1, 0, 0, 0];
151
+ function getJSModule(name, caller) {
152
+ var _a, _b;
153
+ const module2 = (_b = (_a = globalThis.loaders) == null ? void 0 : _a.modules) == null ? void 0 : _b[name];
154
+ if (!module2) {
155
+ throw new Error(`${caller}: ${name} library not installed`);
90
156
  }
91
- return [w / length, x / length, y / length, z / length];
157
+ return module2;
92
158
  }
93
- function decodeQuaternionByte(byte) {
94
- return (byte - 128) / 128;
159
+ function getJSModuleOrNull(name) {
160
+ var _a, _b;
161
+ const module2 = (_b = (_a = globalThis.loaders) == null ? void 0 : _a.modules) == null ? void 0 : _b[name];
162
+ return module2 || null;
95
163
  }
96
- function decodeFloat16(value) {
97
- const sign = value & 32768 ? -1 : 1;
98
- const exponent = value >> 10 & 31;
99
- const fraction = value & 1023;
100
- if (exponent === 0) {
101
- return sign * Math.pow(2, -14) * (fraction / 1024);
164
+ var init_js_module_utils = __esm({
165
+ "../loader-utils/src/lib/module-utils/js-module-utils.ts"() {
166
+ "use strict";
102
167
  }
103
- if (exponent === 31) {
104
- return fraction ? Number.NaN : sign * Number.POSITIVE_INFINITY;
168
+ });
169
+
170
+ // ../loader-utils/src/lib/binary-utils/array-buffer-utils.ts
171
+ function concatenateArrayBuffers(...sources) {
172
+ return concatenateArrayBuffersFromArray(sources);
173
+ }
174
+ function concatenateArrayBuffersFromArray(sources) {
175
+ const sourceArrays = sources.map(
176
+ (source2) => source2 instanceof ArrayBuffer ? new Uint8Array(source2) : source2
177
+ );
178
+ const byteLength = sourceArrays.reduce((length, typedArray) => length + typedArray.byteLength, 0);
179
+ const result = new Uint8Array(byteLength);
180
+ let offset = 0;
181
+ for (const sourceArray of sourceArrays) {
182
+ result.set(sourceArray, offset);
183
+ offset += sourceArray.byteLength;
184
+ }
185
+ return result.buffer;
186
+ }
187
+ var init_array_buffer_utils = __esm({
188
+ "../loader-utils/src/lib/binary-utils/array-buffer-utils.ts"() {
189
+ "use strict";
105
190
  }
106
- return sign * Math.pow(2, exponent - 15) * (1 + fraction / 1024);
191
+ });
192
+
193
+ // ../loader-utils/src/lib/iterators/async-iteration.ts
194
+ async function concatenateArrayBuffersAsync(asyncIterator) {
195
+ const arrayBuffers = [];
196
+ for await (const chunk of asyncIterator) {
197
+ arrayBuffers.push(copyToArrayBuffer(chunk));
198
+ }
199
+ return concatenateArrayBuffers(...arrayBuffers);
107
200
  }
108
- var SH_C0;
109
- var init_splat_utils = __esm({
110
- "dist/lib/splat-utils.js"() {
201
+ function copyToArrayBuffer(chunk) {
202
+ if (chunk instanceof ArrayBuffer) {
203
+ return chunk;
204
+ }
205
+ if (ArrayBuffer.isView(chunk)) {
206
+ const { buffer, byteOffset, byteLength } = chunk;
207
+ return copyFromBuffer(buffer, byteOffset, byteLength);
208
+ }
209
+ return copyFromBuffer(chunk);
210
+ }
211
+ function copyFromBuffer(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
212
+ const view = new Uint8Array(buffer, byteOffset, byteLength);
213
+ const copy = new Uint8Array(view.length);
214
+ copy.set(view);
215
+ return copy.buffer;
216
+ }
217
+ var init_async_iteration = __esm({
218
+ "../loader-utils/src/lib/iterators/async-iteration.ts"() {
111
219
  "use strict";
112
- SH_C0 = 0.28209479177387814;
220
+ init_array_buffer_utils();
113
221
  }
114
222
  });
115
223
 
116
- // dist/lib/splats-arrow-table.js
117
- function makeGaussianSplatsArrowTable(splats) {
118
- const columns = {};
119
- const fields = [];
120
- const schemaFields = [];
121
- addColumn(columns, fields, schemaFields, "POSITION", makeFixedSizeListVector(splats.positions, 3), {
122
- type: "fixed-size-list",
123
- listSize: 3,
124
- children: [{ name: "value", type: "float32" }]
125
- });
126
- const colorCoefficients = getColorCoefficients(splats);
127
- addScalarColumn(columns, fields, schemaFields, "f_dc_0", colorCoefficients[0], {
128
- "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
129
- "loaders_gl.gaussian_splats.component": "0",
130
- "loaders_gl.gaussian_splats.encoding": "coefficient"
131
- });
132
- addScalarColumn(columns, fields, schemaFields, "f_dc_1", colorCoefficients[1], {
133
- "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
134
- "loaders_gl.gaussian_splats.component": "1",
135
- "loaders_gl.gaussian_splats.encoding": "coefficient"
136
- });
137
- addScalarColumn(columns, fields, schemaFields, "f_dc_2", colorCoefficients[2], {
138
- "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
139
- "loaders_gl.gaussian_splats.component": "2",
140
- "loaders_gl.gaussian_splats.encoding": "coefficient"
224
+ // ../loader-utils/src/lib/request-utils/authentication.ts
225
+ function resolveCredentials(credentials, authentications = []) {
226
+ if (credentials.every(isAuthentication)) return credentials;
227
+ return credentials.map((credential, index) => {
228
+ if (isAuthentication(credential)) return credential;
229
+ const AuthenticationClass = authentications.find(
230
+ (authentication2) => authentication2.type === (credential == null ? void 0 : credential.type)
231
+ );
232
+ if (!AuthenticationClass) {
233
+ throw new Error(`No authentication class registered for credential at index ${index}.`);
234
+ }
235
+ let authentication;
236
+ try {
237
+ authentication = new AuthenticationClass(credential);
238
+ } catch {
239
+ throw new Error(`Invalid authentication configuration at index ${index}.`);
240
+ }
241
+ if (!isAuthentication(authentication)) {
242
+ throw new Error(`Authentication class returned an invalid credential at index ${index}.`);
243
+ }
244
+ return authentication;
141
245
  });
142
- addScalarColumn(columns, fields, schemaFields, "opacity", splats.opacities, {
143
- "loaders_gl.gaussian_splats.semantic": "opacity",
144
- "loaders_gl.gaussian_splats.encoding": "linear"
246
+ }
247
+ function resolveAuthenticationOptions(options) {
248
+ var _a, _b;
249
+ if (!((_b = (_a = options.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length)) return options;
250
+ const credentials = resolveCredentials(options.core.credentials, options.core.authentications);
251
+ if (credentials === options.core.credentials) return options;
252
+ return { ...options, core: { ...options.core, credentials } };
253
+ }
254
+ function isAuthentication(credential) {
255
+ if (!credential || typeof credential !== "object") return false;
256
+ if (typeof credential.id !== "string" || !Array.isArray(credential.origins)) return false;
257
+ if (credential.type === "request") return typeof credential.authenticate === "function";
258
+ return (credential.type === "header" || credential.type === "query-parameter") && typeof credential.name === "string" && (typeof credential.token === "string" || typeof credential.token === "function") && Array.isArray(credential.refreshStatusCodes);
259
+ }
260
+ var init_authentication = __esm({
261
+ "../loader-utils/src/lib/request-utils/authentication.ts"() {
262
+ "use strict";
263
+ }
264
+ });
265
+
266
+ // ../loader-utils/src/lib/request-utils/request-credentials.ts
267
+ function createAuthenticatedFetch(options) {
268
+ const suppliedFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
269
+ const existingMetadata = suppliedFetch[AUTHENTICATED_FETCH];
270
+ const credentialResolutions = new Map(existingMetadata == null ? void 0 : existingMetadata.credentialResolutions);
271
+ const resolvedCredentials = resolveCredentials(
272
+ options.credentials.map((credential) => credentialResolutions.get(credential) || credential),
273
+ options.authentications
274
+ );
275
+ options.credentials.forEach((credential, index) => {
276
+ credentialResolutions.set(credential, resolvedCredentials[index]);
145
277
  });
146
- addVectorComponents(columns, fields, schemaFields, "scale", splats.scales, 3, {
147
- "loaders_gl.gaussian_splats.semantic": "scale",
148
- "loaders_gl.gaussian_splats.encoding": "linear"
278
+ if (!options.fetchOptions && (!resolvedCredentials.length || (existingMetadata == null ? void 0 : existingMetadata.credentials.length) === resolvedCredentials.length && resolvedCredentials.every(
279
+ (credential, index) => credential === existingMetadata.credentials[index]
280
+ )))
281
+ return suppliedFetch;
282
+ const baseFetch = (existingMetadata == null ? void 0 : existingMetadata.fetch) || suppliedFetch;
283
+ const credentials = existingMetadata ? [.../* @__PURE__ */ new Set([...resolvedCredentials, ...existingMetadata.credentials])] : resolvedCredentials;
284
+ const fetchOptions = mergeFetchOptions(
285
+ (existingMetadata == null ? void 0 : existingMetadata.fetchOptions) || {},
286
+ options.fetchOptions
287
+ );
288
+ const tokenCredentials = credentials.filter(
289
+ (credential) => credential.type !== "request"
290
+ );
291
+ const requestCredentials = credentials.filter(
292
+ (credential) => credential.type === "request"
293
+ );
294
+ for (const credential of requestCredentials) normalizeRequestOrigins(credential.origins);
295
+ const authenticatedFetch = async (url, requestOptions = {}) => {
296
+ var _a, _b, _c, _d, _e, _f, _g;
297
+ requestOptions = mergeFetchOptions(fetchOptions, requestOptions);
298
+ if ((_a = requestOptions.signal) == null ? void 0 : _a.aborted) throw createAbortError();
299
+ if (!credentials.length) return baseFetch(url, requestOptions);
300
+ const resolvedURL = parseHTTPURL(url);
301
+ const authorization = resolvedURL ? await authorizeRequest(resolvedURL, requestOptions, tokenCredentials) : { url, options: requestOptions, credentials: [] };
302
+ const signedRequest = await authenticateRequest(authorization, requestCredentials, "request");
303
+ const response = await baseFetch(signedRequest.url, signedRequest.options);
304
+ const refreshableCredentials = [];
305
+ for (const resolvedCredential of authorization.credentials) {
306
+ const { credential } = resolvedCredential;
307
+ if (typeof credential.token === "function" && (isReplayableRequest(requestOptions) || ((_b = credential.canReplayRequest) == null ? void 0 : _b.call(credential, url, requestOptions))) && (isReplayableRequest(signedRequest.options) || ((_c = credential.canReplayRequest) == null ? void 0 : _c.call(credential, signedRequest.url, signedRequest.options))) && (credential.refreshStatusCodes.includes(response.status) || await ((_d = credential.shouldRefresh) == null ? void 0 : _d.call(credential, response))))
308
+ refreshableCredentials.push(resolvedCredential);
309
+ }
310
+ const shouldRetrySignature = isReplayableRequest(requestOptions) && isReplayableRequest(signedRequest.options) && signedRequest.credentials.some(
311
+ (credential) => {
312
+ var _a2;
313
+ return (_a2 = credential.refreshStatusCodes) == null ? void 0 : _a2.includes(response.status);
314
+ }
315
+ );
316
+ if (!refreshableCredentials.length && !shouldRetrySignature) return response;
317
+ if ((_e = requestOptions.signal) == null ? void 0 : _e.aborted) throw createAbortError();
318
+ const refreshedTokens = /* @__PURE__ */ new Map();
319
+ await Promise.all(
320
+ refreshableCredentials.map(async ({ credential }) => {
321
+ const token = await refreshCredential(credential, url, response);
322
+ if (token) refreshedTokens.set(credential, token);
323
+ })
324
+ );
325
+ if (!refreshedTokens.size && !shouldRetrySignature) return response;
326
+ await ((_f = response.body) == null ? void 0 : _f.cancel().catch(() => {
327
+ }));
328
+ if ((_g = requestOptions.signal) == null ? void 0 : _g.aborted) throw createAbortError();
329
+ const replayAuthorization = resolvedURL ? await authorizeRequest(
330
+ resolvedURL,
331
+ requestOptions,
332
+ tokenCredentials,
333
+ refreshedTokens,
334
+ authorization.credentials
335
+ ) : { url, options: requestOptions };
336
+ const replayRequest = await authenticateRequest(
337
+ replayAuthorization,
338
+ requestCredentials,
339
+ "retry",
340
+ response
341
+ );
342
+ return baseFetch(replayRequest.url, replayRequest.options);
343
+ };
344
+ Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
345
+ value: {
346
+ fetch: baseFetch,
347
+ credentials,
348
+ credentialResolutions,
349
+ fetchOptions
350
+ }
149
351
  });
150
- addVectorComponents(columns, fields, schemaFields, "rot", splats.rotations, 4, {
151
- "loaders_gl.gaussian_splats.semantic": "rotation",
152
- "loaders_gl.gaussian_splats.encoding": "quaternion"
352
+ return authenticatedFetch;
353
+ }
354
+ function getAuthenticatedFetch(options = {}) {
355
+ var _a, _b, _c;
356
+ const fetchOption = options.fetch ?? ((_a = options.core) == null ? void 0 : _a.fetch);
357
+ let fetchFunction;
358
+ if (typeof fetchOption === "function") {
359
+ fetchFunction = fetchOption;
360
+ } else {
361
+ fetchFunction = (url, requestOptions) => fetch(url, requestOptions);
362
+ }
363
+ return createAuthenticatedFetch({
364
+ fetch: fetchFunction,
365
+ fetchOptions: typeof fetchOption === "object" && fetchOption ? fetchOption : void 0,
366
+ credentials: ((_b = options.core) == null ? void 0 : _b.credentials) || [],
367
+ authentications: (_c = options.core) == null ? void 0 : _c.authentications
153
368
  });
154
- if (splats.sphericalHarmonics && splats.sphericalHarmonicsComponentCount) {
155
- addSphericalHarmonicRestColumns(columns, fields, schemaFields, splats.sphericalHarmonics, splats.sphericalHarmonicsComponentCount);
156
- }
157
- const metadata = /* @__PURE__ */ new Map([
158
- ["loaders_gl.semantic_type", "gaussian-splats"],
159
- ["loaders_gl.gaussian_splats.version", "1"],
160
- ["loaders_gl.gaussian_splats.source_format", splats.format],
161
- ["topology", "point-list"],
162
- ["mode", "0"]
163
- ]);
164
- const arrowSchema = new arrow.Schema(fields, metadata);
165
- const schema = {
166
- fields: schemaFields,
167
- metadata: Object.fromEntries(metadata)
168
- };
169
- return {
170
- shape: "arrow-table",
171
- schema,
172
- data: new arrow.Table(arrowSchema, columns),
173
- topology: "point-list",
174
- loaderData: splats.loaderData
175
- };
176
369
  }
177
- function addVectorComponents(columns, fields, schemaFields, prefix, values, size, metadata) {
178
- for (let component = 0; component < size; component++) {
179
- const componentValues = new Float32Array(values.length / size);
180
- for (let rowIndex = 0; rowIndex < componentValues.length; rowIndex++) {
181
- componentValues[rowIndex] = values[rowIndex * size + component];
182
- }
183
- addScalarColumn(columns, fields, schemaFields, `${prefix}_${component}`, componentValues, {
184
- ...metadata,
185
- "loaders_gl.gaussian_splats.component": String(component)
370
+ function mergeFetchOptions(defaultOptions, requestOptions) {
371
+ const mergedOptions = { ...defaultOptions, ...requestOptions };
372
+ if (defaultOptions.headers || (requestOptions == null ? void 0 : requestOptions.headers)) {
373
+ const headers = new Headers(defaultOptions.headers);
374
+ new Headers(requestOptions == null ? void 0 : requestOptions.headers).forEach((value, key) => headers.set(key, value));
375
+ mergedOptions.headers = headers;
376
+ }
377
+ return mergedOptions;
378
+ }
379
+ async function authenticateRequest(request, credentials, reason, response) {
380
+ const appliedCredentials = [];
381
+ const signal = request.options.signal;
382
+ for (const credential of credentials) {
383
+ const origin = getRequestOrigin(request.url);
384
+ if (!origin || !normalizeRequestOrigins(credential.origins).includes(origin)) continue;
385
+ if (signal == null ? void 0 : signal.aborted) throw createAbortError();
386
+ const authenticatedRequest = await credential.authenticate({
387
+ url: request.url,
388
+ options: { ...request.options, headers: new Headers(request.options.headers) },
389
+ reason,
390
+ response: response ? { status: response.status, headers: new Headers(response.headers) } : void 0
186
391
  });
392
+ if (!authenticatedRequest || typeof authenticatedRequest.url !== "string" || !authenticatedRequest.options || typeof authenticatedRequest.options !== "object") {
393
+ throw new Error("Authentication callback returned an invalid request.");
394
+ }
395
+ request = {
396
+ url: authenticatedRequest.url,
397
+ options: { ...authenticatedRequest.options, ...signal ? { signal } : {} }
398
+ };
399
+ appliedCredentials.push(credential);
187
400
  }
401
+ if (signal == null ? void 0 : signal.aborted) throw createAbortError();
402
+ return { ...request, credentials: appliedCredentials };
188
403
  }
189
- function addSphericalHarmonicRestColumns(columns, fields, schemaFields, sphericalHarmonics, componentCount) {
190
- for (let component = 0; component < componentCount; component++) {
191
- const componentValues = new Float32Array(sphericalHarmonics.length / componentCount);
192
- for (let rowIndex = 0; rowIndex < componentValues.length; rowIndex++) {
193
- componentValues[rowIndex] = sphericalHarmonics[rowIndex * componentCount + component];
404
+ function getRequestOrigin(url) {
405
+ try {
406
+ const parsedURL = new URL(url);
407
+ if (!parsedURL.host || parsedURL.username || parsedURL.password) return null;
408
+ return parsedURL.origin !== "null" ? parsedURL.origin : `${parsedURL.protocol}//${parsedURL.host}`;
409
+ } catch {
410
+ return null;
411
+ }
412
+ }
413
+ function normalizeRequestOrigins(origins) {
414
+ if (!origins.length)
415
+ throw new Error("Request authentication requires at least one exact origin.");
416
+ return origins.map((origin) => {
417
+ const resolvedOrigin = getRequestOrigin(origin);
418
+ let url;
419
+ try {
420
+ url = new URL(origin);
421
+ } catch {
422
+ throw new Error("Invalid request authentication origin.");
194
423
  }
195
- addScalarColumn(columns, fields, schemaFields, `f_rest_${component}`, componentValues, {
196
- "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_rest",
197
- "loaders_gl.gaussian_splats.component": String(component),
198
- "loaders_gl.gaussian_splats.encoding": "coefficient"
199
- });
424
+ if (!resolvedOrigin || url.pathname && url.pathname !== "/" || url.search || url.hash) {
425
+ throw new Error("Invalid request authentication origin.");
426
+ }
427
+ return resolvedOrigin;
428
+ });
429
+ }
430
+ async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
431
+ const url = new URL(sourceURL);
432
+ const headers = new Headers(requestOptions.headers);
433
+ const resolvedCredentials = [];
434
+ const previousTokens = new Map(
435
+ previousCredentials.map(({ credential, token }) => [credential, token])
436
+ );
437
+ for (const credential of credentials) {
438
+ if (!credential.origins.includes(url.origin)) continue;
439
+ const overrideToken = tokenOverrides.get(credential);
440
+ const previousToken = previousTokens.get(credential);
441
+ const ownsQueryParameter = credential.type === "query-parameter" && previousToken !== void 0;
442
+ const ownsHeader = credential.type === "header" && previousToken !== void 0;
443
+ if (credential.type === "query-parameter" && url.searchParams.has(credential.name) && !ownsQueryParameter || credential.type === "header" && headers.has(credential.name) && !ownsHeader) {
444
+ continue;
445
+ }
446
+ const token = overrideToken ?? previousToken ?? await resolveToken(credential.token, { url: sourceURL.toString(), reason: "request" });
447
+ if (!token) continue;
448
+ if (credential.type === "query-parameter") {
449
+ url.searchParams.set(credential.name, token);
450
+ } else {
451
+ headers.set(credential.name, `${credential.prefix || ""}${token}`);
452
+ }
453
+ resolvedCredentials.push({ credential, token });
200
454
  }
455
+ return {
456
+ url: url.toString(),
457
+ options: { ...requestOptions, headers },
458
+ credentials: resolvedCredentials
459
+ };
201
460
  }
202
- function addScalarColumn(columns, fields, schemaFields, name, values, metadata) {
203
- addColumn(columns, fields, schemaFields, name, arrow.makeVector(values), "float32", metadata);
461
+ async function refreshCredential(credential, url, response) {
462
+ const existingPromise = refreshPromises.get(credential);
463
+ if (existingPromise) return existingPromise;
464
+ const tokenProvider = credential.token;
465
+ const promise = Promise.resolve(
466
+ tokenProvider({
467
+ url,
468
+ reason: "refresh",
469
+ response: { status: response.status, headers: response.headers }
470
+ })
471
+ ).finally(() => refreshPromises.delete(credential));
472
+ refreshPromises.set(credential, promise);
473
+ return promise;
474
+ }
475
+ async function resolveToken(token, context) {
476
+ return typeof token === "function" ? token(context) : token;
477
+ }
478
+ function parseHTTPURL(url) {
479
+ try {
480
+ const parsedURL = new URL(url);
481
+ return ["http:", "https:"].includes(parsedURL.protocol) ? parsedURL : null;
482
+ } catch {
483
+ return null;
484
+ }
204
485
  }
205
- function addColumn(columns, fields, schemaFields, name, column, schemaType, metadata = {}) {
206
- columns[name] = column;
207
- fields.push(new arrow.Field(name, column.type, false, new Map(Object.entries(metadata))));
208
- schemaFields.push({ name, type: schemaType, nullable: false, metadata });
486
+ function isReplayableRequest(options) {
487
+ const method = (options.method || "GET").toUpperCase();
488
+ if (!["GET", "HEAD", "OPTIONS", "PUT", "DELETE"].includes(method)) return false;
489
+ return !(options.body && typeof ReadableStream !== "undefined" && options.body instanceof ReadableStream);
209
490
  }
210
- function makeFixedSizeListVector(value, size) {
211
- const values = arrow.makeVector(value);
212
- const child = values.data[0];
213
- const type = new arrow.FixedSizeList(size, new arrow.Field("value", child.type, false));
214
- const data = new arrow.Data(type, 0, value.length / size, 0, {}, [child]);
215
- return new arrow.Vector([data]);
491
+ function createAbortError() {
492
+ return new DOMException("The operation was aborted.", "AbortError");
216
493
  }
217
- function getColorCoefficients(splats) {
218
- const rowCount = splats.splatCount;
219
- const fdc0 = new Float32Array(rowCount);
220
- const fdc1 = new Float32Array(rowCount);
221
- const fdc2 = new Float32Array(rowCount);
222
- for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
223
- if (splats.sphericalHarmonicDcs) {
224
- fdc0[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 0];
225
- fdc1[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 1];
226
- fdc2[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 2];
227
- } else {
228
- fdc0[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 0]);
229
- fdc1[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 1]);
230
- fdc2[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 2]);
494
+ var AUTHENTICATED_FETCH, refreshPromises;
495
+ var init_request_credentials = __esm({
496
+ "../loader-utils/src/lib/request-utils/request-credentials.ts"() {
497
+ "use strict";
498
+ init_authentication();
499
+ AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
500
+ refreshPromises = /* @__PURE__ */ new WeakMap();
501
+ }
502
+ });
503
+
504
+ // ../loader-utils/src/lib/path-utils/file-aliases.ts
505
+ function resolvePath(filename) {
506
+ for (const alias in fileAliases) {
507
+ if (filename.startsWith(alias)) {
508
+ const replacement = fileAliases[alias];
509
+ filename = filename.replace(alias, replacement);
231
510
  }
232
511
  }
233
- return [fdc0, fdc1, fdc2];
512
+ if (!filename.startsWith("http://") && !filename.startsWith("https://")) {
513
+ filename = `${pathPrefix}${filename}`;
514
+ }
515
+ return filename;
234
516
  }
235
- var arrow;
236
- var init_splats_arrow_table = __esm({
237
- "dist/lib/splats-arrow-table.js"() {
517
+ var pathPrefix, fileAliases;
518
+ var init_file_aliases = __esm({
519
+ "../loader-utils/src/lib/path-utils/file-aliases.ts"() {
238
520
  "use strict";
239
- arrow = __toESM(require("apache-arrow"), 1);
240
- init_splat_utils();
521
+ pathPrefix = "";
522
+ fileAliases = {};
241
523
  }
242
524
  });
243
525
 
244
- // dist/lib/parse-splat.js
245
- function parseSPLAT(data) {
246
- return makeGaussianSplatsArrowTable(parseSPLATToGaussianSplats(data));
247
- }
248
- function parseSPLATToGaussianSplats(data) {
249
- if (data.byteLength % SPLAT_ROW_BYTE_LENGTH !== 0) {
250
- throw new Error(`SPLATLoader: byte length must be a multiple of ${SPLAT_ROW_BYTE_LENGTH}.`);
526
+ // ../loader-utils/src/lib/binary-utils/memory-conversion-utils.ts
527
+ function ensureArrayBuffer(bufferSource) {
528
+ if (bufferSource instanceof ArrayBuffer) {
529
+ return bufferSource;
251
530
  }
252
- const splatCount = data.byteLength / SPLAT_ROW_BYTE_LENGTH;
253
- const dataView = new DataView(data);
254
- const positions = new Float32Array(splatCount * 3);
255
- const scales = new Float32Array(splatCount * 3);
256
- const rotations = new Float32Array(splatCount * 4);
257
- const colors = new Uint8Array(splatCount * 3);
258
- const opacities = new Float32Array(splatCount);
259
- for (let splatIndex = 0; splatIndex < splatCount; splatIndex++) {
260
- const byteOffset = splatIndex * SPLAT_ROW_BYTE_LENGTH;
261
- const positionOffset = splatIndex * 3;
262
- const rotationOffset = splatIndex * 4;
263
- positions[positionOffset + 0] = dataView.getFloat32(byteOffset + 0, true);
264
- positions[positionOffset + 1] = dataView.getFloat32(byteOffset + 4, true);
265
- positions[positionOffset + 2] = dataView.getFloat32(byteOffset + 8, true);
266
- scales[positionOffset + 0] = dataView.getFloat32(byteOffset + 12, true);
267
- scales[positionOffset + 1] = dataView.getFloat32(byteOffset + 16, true);
268
- scales[positionOffset + 2] = dataView.getFloat32(byteOffset + 20, true);
269
- colors[positionOffset + 0] = dataView.getUint8(byteOffset + 24);
270
- colors[positionOffset + 1] = dataView.getUint8(byteOffset + 25);
271
- colors[positionOffset + 2] = dataView.getUint8(byteOffset + 26);
272
- opacities[splatIndex] = convertAlphaByteToLinearOpacity(dataView.getUint8(byteOffset + 27));
273
- const [w, x, y, z] = normalizeQuaternion(decodeQuaternionByte(dataView.getUint8(byteOffset + 28)), decodeQuaternionByte(dataView.getUint8(byteOffset + 29)), decodeQuaternionByte(dataView.getUint8(byteOffset + 30)), decodeQuaternionByte(dataView.getUint8(byteOffset + 31)));
274
- rotations[rotationOffset + 0] = w;
275
- rotations[rotationOffset + 1] = x;
276
- rotations[rotationOffset + 2] = y;
277
- rotations[rotationOffset + 3] = z;
531
+ if (isSharedArrayBuffer(bufferSource)) {
532
+ return copyToArrayBuffer2(bufferSource);
278
533
  }
279
- return {
280
- format: "splat",
281
- splatCount,
282
- positions,
283
- scales,
284
- rotations,
285
- colors,
286
- opacities,
287
- loaderData: {
288
- format: "splat",
289
- splatCount,
290
- rowByteLength: SPLAT_ROW_BYTE_LENGTH
291
- }
292
- };
534
+ const { buffer, byteOffset, byteLength } = bufferSource;
535
+ if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {
536
+ return buffer;
537
+ }
538
+ return copyToArrayBuffer2(buffer, byteOffset, byteLength);
293
539
  }
294
- var SPLAT_ROW_BYTE_LENGTH;
295
- var init_parse_splat = __esm({
296
- "dist/lib/parse-splat.js"() {
540
+ function copyToArrayBuffer2(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
541
+ const view = new Uint8Array(buffer, byteOffset, byteLength);
542
+ const copy = new Uint8Array(view.length);
543
+ copy.set(view);
544
+ return copy.buffer;
545
+ }
546
+ var init_memory_conversion_utils = __esm({
547
+ "../loader-utils/src/lib/binary-utils/memory-conversion-utils.ts"() {
297
548
  "use strict";
298
- init_splats_arrow_table();
299
- init_splat_utils();
300
- SPLAT_ROW_BYTE_LENGTH = 32;
549
+ init_is_type();
301
550
  }
302
551
  });
303
552
 
304
- // dist/splat-loader.js
305
- var splat_loader_exports = {};
306
- __export(splat_loader_exports, {
307
- SPLATLoaderWithParser: () => SPLATLoaderWithParser
308
- });
309
- var _SPLATLoaderPreload, SPLATLoaderMetadataWithoutPreload, SPLATLoaderWithParser;
310
- var init_splat_loader = __esm({
311
- "dist/splat-loader.js"() {
553
+ // ../loader-utils/src/lib/sources/data-source.ts
554
+ function getFetchFunction(options) {
555
+ return getAuthenticatedFetch(options);
556
+ }
557
+ function getSourceLoaderOptions(options) {
558
+ var _a;
559
+ if (options.loadOptions !== void 0 || ((_a = options.core) == null ? void 0 : _a.loadOptions) !== void 0) {
560
+ throw new Error(
561
+ "Source loadOptions and core.loadOptions were removed. Use core and root loader namespaces directly."
562
+ );
563
+ }
564
+ const loadOptions = { ...options };
565
+ if (options == null ? void 0 : options.core) {
566
+ loadOptions.core = { ...options.core };
567
+ const parserCore = loadOptions.core;
568
+ for (const key of ["type", "attributions", "loaders", "onError", "loadOptions"]) {
569
+ delete parserCore[key];
570
+ }
571
+ if (Object.keys(parserCore).length === 0) {
572
+ delete loadOptions.core;
573
+ }
574
+ }
575
+ const topLevelBaseUri = typeof loadOptions.baseUri === "string" ? loadOptions.baseUri : void 0;
576
+ const topLevelBaseUrl = typeof loadOptions.baseUrl === "string" ? loadOptions.baseUrl : void 0;
577
+ if (topLevelBaseUri !== void 0 || topLevelBaseUrl !== void 0) {
578
+ loadOptions.core ||= {};
579
+ if (loadOptions.core.baseUrl === void 0) {
580
+ loadOptions.core.baseUrl = topLevelBaseUrl ?? topLevelBaseUri;
581
+ }
582
+ delete loadOptions.baseUri;
583
+ delete loadOptions.baseUrl;
584
+ }
585
+ return loadOptions;
586
+ }
587
+ function normalizeError(error, message) {
588
+ if (error instanceof Error) {
589
+ return error;
590
+ }
591
+ if (typeof error === "string") {
592
+ return new Error(error);
593
+ }
594
+ return new Error(message);
595
+ }
596
+ function unavailableCoreApiMethod(methodName) {
597
+ return () => {
598
+ throw new Error(
599
+ `CoreAPI.${methodName} is unavailable. Use @loaders.gl/core.createDataSource().`
600
+ );
601
+ };
602
+ }
603
+ var UNAVAILABLE_CORE_API, DataSource;
604
+ var init_data_source = __esm({
605
+ "../loader-utils/src/lib/sources/data-source.ts"() {
312
606
  "use strict";
313
- init_parse_splat();
314
- init_splat_loader_types();
315
- ({ preload: _SPLATLoaderPreload, ...SPLATLoaderMetadataWithoutPreload } = SPLATLoader);
316
- SPLATLoaderWithParser = {
317
- ...SPLATLoaderMetadataWithoutPreload,
318
- parse: async (arrayBuffer) => parseSPLAT(arrayBuffer),
319
- parseSync: (arrayBuffer) => parseSPLAT(arrayBuffer)
607
+ init_merge_options();
608
+ init_file_aliases();
609
+ init_log();
610
+ init_request_credentials();
611
+ init_authentication();
612
+ UNAVAILABLE_CORE_API = {
613
+ fetchFile: unavailableCoreApiMethod("fetchFile"),
614
+ parse: unavailableCoreApiMethod("parse"),
615
+ parseFile: unavailableCoreApiMethod("parseFile"),
616
+ parseSync: unavailableCoreApiMethod("parseSync"),
617
+ parseInBatches: unavailableCoreApiMethod("parseInBatches"),
618
+ load: unavailableCoreApiMethod("load"),
619
+ loadInBatches: unavailableCoreApiMethod("loadInBatches")
620
+ };
621
+ DataSource = class _DataSource {
622
+ static defaultOptions = {
623
+ core: {
624
+ type: "auto",
625
+ attributions: [],
626
+ loaders: [],
627
+ onError: void 0
628
+ }
629
+ };
630
+ optionsType;
631
+ options;
632
+ data;
633
+ url;
634
+ /** Shared parser options derived from the source options, excluding source-only core controls. */
635
+ loadOptions;
636
+ /** A resolved fetch function extracted from the shared core options. */
637
+ fetch;
638
+ /** Shared source-level runtime hooks, when supplied by the source factory. */
639
+ coreApi;
640
+ /** Whether a real CoreAPI instance was injected by the integration layer. */
641
+ hasCoreApi;
642
+ _needsRefresh = true;
643
+ constructor(data, options, defaultOptions, coreApi) {
644
+ this.options = mergeOptions(
645
+ mergeOptions(_DataSource.defaultOptions, defaultOptions || {}),
646
+ options
647
+ );
648
+ this.data = data;
649
+ this.url = typeof data === "string" ? resolvePath(data) : "";
650
+ const loadOptions = resolveAuthenticationOptions(getSourceLoaderOptions(this.options));
651
+ this.loadOptions = loadOptions;
652
+ const fetch2 = getFetchFunction(loadOptions);
653
+ this.coreApi = coreApi || UNAVAILABLE_CORE_API;
654
+ this.hasCoreApi = Boolean(coreApi);
655
+ this.fetch = fetch2;
656
+ }
657
+ setProps(options) {
658
+ const mergedOptions = mergeOptions(this.options, options);
659
+ const loadOptions = resolveAuthenticationOptions(getSourceLoaderOptions(mergedOptions));
660
+ this.options = mergedOptions;
661
+ this.loadOptions = loadOptions;
662
+ this.fetch = getFetchFunction(loadOptions);
663
+ this.setNeedsRefresh();
664
+ }
665
+ /** Mark this data source as needing a refresh (redraw) */
666
+ setNeedsRefresh() {
667
+ this._needsRefresh = true;
668
+ }
669
+ /**
670
+ * Does this data source need refreshing?
671
+ * @note The specifics of the refresh mechanism depends on type of data source
672
+ */
673
+ getNeedsRefresh(clear = true) {
674
+ const needsRefresh = this._needsRefresh;
675
+ if (clear) {
676
+ this._needsRefresh = false;
677
+ }
678
+ return needsRefresh;
679
+ }
680
+ /** Reports a source-level failure through the configured callback or the shared logger. */
681
+ reportError(error, message) {
682
+ var _a;
683
+ const normalizedError = normalizeError(error, message);
684
+ const callback = (_a = this.options.core) == null ? void 0 : _a.onError;
685
+ if (callback) {
686
+ callback(normalizedError, this);
687
+ } else {
688
+ log.warn(`${this.constructor.name}: ${normalizedError.message}`)();
689
+ }
690
+ return normalizedError;
691
+ }
320
692
  };
321
693
  }
322
694
  });
323
695
 
324
- // dist/splat-loader-types.js
325
- async function preload() {
326
- const { SPLATLoaderWithParser: SPLATLoaderWithParser2 } = await Promise.resolve().then(() => (init_splat_loader(), splat_loader_exports));
327
- return SPLATLoaderWithParser2;
328
- }
329
- var VERSION, SPLATLoader;
330
- var init_splat_loader_types = __esm({
331
- "dist/splat-loader-types.js"() {
696
+ // ../loader-utils/src/index.ts
697
+ var init_src = __esm({
698
+ "../loader-utils/src/index.ts"() {
332
699
  "use strict";
333
- init_splats_format();
334
- VERSION = true ? "5.0.0-alpha.1" : "latest";
335
- SPLATLoader = {
336
- dataType: null,
337
- batchType: null,
338
- ...SPLATFormat,
339
- version: VERSION,
340
- options: {
341
- splats: {
342
- shape: "arrow-table"
700
+ init_js_module_utils();
701
+ init_js_module_utils();
702
+ init_async_iteration();
703
+ init_memory_conversion_utils();
704
+ init_data_source();
705
+ }
706
+ });
707
+
708
+ // ../compression/src/lib/compression.ts
709
+ var CompressionTransform, Compressor, Decompressor, Compression;
710
+ var init_compression = __esm({
711
+ "../compression/src/lib/compression.ts"() {
712
+ "use strict";
713
+ init_src();
714
+ CompressionTransform = class {
715
+ /** Preloads any dynamic libraries. May enable sync functions */
716
+ async preload(modules = {}) {
717
+ registerJSModules(modules);
718
+ return void 0;
719
+ }
720
+ // HELPERS
721
+ concatenate(asyncIterator) {
722
+ return concatenateArrayBuffersAsync(asyncIterator);
723
+ }
724
+ improveError(error) {
725
+ if (!error.message.includes(this.name)) {
726
+ error.message = `${this.name} ${error.message}`;
343
727
  }
344
- },
345
- preload
728
+ return error;
729
+ }
730
+ };
731
+ Compressor = class extends CompressionTransform {
732
+ constructor(options) {
733
+ super();
734
+ this.compressBatches = this.compressBatches.bind(this);
735
+ }
736
+ /** Asynchronously compresses data. */
737
+ async compress(input) {
738
+ await this.preload();
739
+ return this.compressSync(input);
740
+ }
741
+ /** Synchronously compresses data. */
742
+ compressSync(input) {
743
+ throw new Error(`${this.name}: sync compression not supported`);
744
+ }
745
+ /** Compresses batches. */
746
+ async *compressBatches(asyncIterator) {
747
+ const input = await this.concatenate(asyncIterator);
748
+ yield this.compress(input);
749
+ }
750
+ };
751
+ Decompressor = class extends CompressionTransform {
752
+ constructor(options) {
753
+ super();
754
+ this.decompressBatches = this.decompressBatches.bind(this);
755
+ }
756
+ /** Asynchronously decompresses data. */
757
+ async decompress(input, size) {
758
+ await this.preload();
759
+ return this.decompressSync(input, size);
760
+ }
761
+ /** Synchronously decompresses data. */
762
+ decompressSync(input, size) {
763
+ throw new Error(`${this.name}: sync decompression not supported`);
764
+ }
765
+ /** Decompresses batches. */
766
+ async *decompressBatches(asyncIterator) {
767
+ const input = await this.concatenate(asyncIterator);
768
+ yield this.decompress(input);
769
+ }
770
+ };
771
+ Compression = class extends Compressor {
772
+ constructor(options) {
773
+ super(options);
774
+ this.decompressBatches = this.decompressBatches.bind(this);
775
+ }
776
+ /** Asynchronously decompresses data. */
777
+ async decompress(input, size) {
778
+ await this.preload();
779
+ return this.decompressSync(input, size);
780
+ }
781
+ /** Synchronously decompresses data. */
782
+ decompressSync(input, size) {
783
+ throw new Error(`${this.name}: sync decompression not supported`);
784
+ }
785
+ /** Decompresses batches. */
786
+ async *decompressBatches(asyncIterator) {
787
+ const input = await this.concatenate(asyncIterator);
788
+ yield this.decompress(input);
789
+ }
346
790
  };
347
791
  }
348
792
  });
349
793
 
350
- // dist/lib/parse-ksplat.js
351
- function parseKSPLAT(data) {
352
- return makeGaussianSplatsArrowTable(parseKSPLATToGaussianSplats(data));
794
+ // ../compression/src/lib/compression-stream.ts
795
+ async function compressWithNativeCompressionStream(input, format) {
796
+ const outputBatches = compressBatchesWithNativeCompressionStream([input], format);
797
+ return outputBatches ? await concatenateBatches(outputBatches) : null;
353
798
  }
354
- function parseKSPLATToGaussianSplats(data) {
355
- if (data.byteLength < HEADER_BYTE_LENGTH) {
356
- throw new Error(`KSPLATLoader: file must contain a ${HEADER_BYTE_LENGTH}-byte header.`);
799
+ function compressBatchesWithNativeCompressionStream(inputBatches, format) {
800
+ const compressionStream = createNativeCompressionStream(format);
801
+ return compressionStream ? transformBatches(inputBatches, compressionStream) : null;
802
+ }
803
+ function createNativeCompressionStream(format) {
804
+ if (typeof globalThis.CompressionStream === "undefined") {
805
+ return null;
357
806
  }
358
- const header = parseKSPLATHeader(data);
359
- checkKSPLATVersion(header);
360
- const sections = parseKSPLATSections(data, header);
361
- const splatCount = getTotalSplatCount(header, sections);
362
- const sphericalHarmonicsComponentCount = Math.max(0, ...sections.slice(0, getActiveSectionCount(header)).map((section) => getSphericalHarmonicsComponentCount(section.sphericalHarmonicsDegree)));
363
- const positions = new Float32Array(splatCount * 3);
364
- const scales = new Float32Array(splatCount * 3);
365
- const rotations = new Float32Array(splatCount * 4);
366
- const colors = new Uint8Array(splatCount * 3);
367
- const opacities = new Float32Array(splatCount);
368
- const sphericalHarmonics = sphericalHarmonicsComponentCount ? new Float32Array(splatCount * sphericalHarmonicsComponentCount) : void 0;
369
- let outputSplatIndex = 0;
370
- for (const section of sections.slice(0, getActiveSectionCount(header))) {
371
- validateSectionBounds(data, section);
372
- for (let localSplatIndex = 0; localSplatIndex < section.splatCount && outputSplatIndex < splatCount; localSplatIndex++) {
373
- decodeKSPLATSplat(data, header, section, localSplatIndex, outputSplatIndex, positions, scales, rotations, colors, opacities, sphericalHarmonics, sphericalHarmonicsComponentCount);
374
- outputSplatIndex++;
807
+ try {
808
+ const CompressionStreamConstructor = globalThis.CompressionStream;
809
+ return new CompressionStreamConstructor(format);
810
+ } catch (error) {
811
+ if (error instanceof TypeError || (error == null ? void 0 : error.name) === "TypeError") {
812
+ return null;
375
813
  }
814
+ throw error;
376
815
  }
377
- return {
378
- format: "ksplat",
379
- splatCount,
380
- positions,
381
- scales,
382
- rotations,
383
- colors,
384
- opacities,
385
- sphericalHarmonics,
386
- sphericalHarmonicsComponentCount,
387
- loaderData: {
388
- format: "ksplat",
389
- ...header,
390
- sections: sections.slice(0, getActiveSectionCount(header)).map((section) => ({
391
- splatCount: section.splatCount,
392
- maxSplatCount: section.maxSplatCount,
393
- sphericalHarmonicsDegree: section.sphericalHarmonicsDegree
394
- }))
816
+ }
817
+ async function* transformBatches(inputBatches, compressionStream) {
818
+ const writer = compressionStream.writable.getWriter();
819
+ const reader = compressionStream.readable.getReader();
820
+ const writePromise = writeBatches(inputBatches, writer);
821
+ writePromise.catch(() => {
822
+ });
823
+ let outputCompleted = false;
824
+ try {
825
+ while (true) {
826
+ const { done, value } = await reader.read();
827
+ if (done) {
828
+ outputCompleted = true;
829
+ break;
830
+ }
831
+ yield new Uint8Array(value).buffer;
395
832
  }
396
- };
833
+ await writePromise;
834
+ } finally {
835
+ if (!outputCompleted) {
836
+ await reader.cancel().catch(() => {
837
+ });
838
+ await writer.abort().catch(() => {
839
+ });
840
+ await writePromise.catch(() => {
841
+ });
842
+ }
843
+ reader.releaseLock();
844
+ }
397
845
  }
398
- function decodeKSPLATSplat(data, header, section, localSplatIndex, outputSplatIndex, positions, scales, rotations, colors, opacities, sphericalHarmonics, sphericalHarmonicsComponentCount) {
399
- const layout = COMPRESSION_LAYOUTS[header.compressionLevel];
400
- const splatBase = section.dataBase + section.bytesPerSplat * localSplatIndex;
401
- const positionOffset = outputSplatIndex * 3;
402
- const rotationOffset = outputSplatIndex * 4;
403
- const bucketCenter = getBucketCenter(data, section, localSplatIndex);
404
- positions[positionOffset + 0] = decodeKSPLATCenterComponent(data, splatBase, 0, header, section, bucketCenter[0]);
405
- positions[positionOffset + 1] = decodeKSPLATCenterComponent(data, splatBase, 1, header, section, bucketCenter[1]);
406
- positions[positionOffset + 2] = decodeKSPLATCenterComponent(data, splatBase, 2, header, section, bucketCenter[2]);
407
- scales[positionOffset + 0] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 0, header.compressionLevel);
408
- scales[positionOffset + 1] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 1, header.compressionLevel);
409
- scales[positionOffset + 2] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 2, header.compressionLevel);
410
- const [w, x, y, z] = normalizeQuaternion(readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 3, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 4, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 5, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 6, header.compressionLevel));
411
- rotations[rotationOffset + 0] = w;
412
- rotations[rotationOffset + 1] = x;
413
- rotations[rotationOffset + 2] = y;
414
- rotations[rotationOffset + 3] = z;
415
- const colorBase = splatBase + layout.colorOffsetBytes;
416
- const colorView = new Uint8Array(data, colorBase, 4);
417
- colors[positionOffset + 0] = colorView[0];
418
- colors[positionOffset + 1] = colorView[1];
419
- colors[positionOffset + 2] = colorView[2];
420
- opacities[outputSplatIndex] = convertAlphaByteToLinearOpacity(colorView[3]);
421
- if (sphericalHarmonics && sphericalHarmonicsComponentCount) {
422
- decodeSphericalHarmonics(data, splatBase + layout.sphericalHarmonicsOffsetBytes, header, section, outputSplatIndex, sphericalHarmonics, sphericalHarmonicsComponentCount);
846
+ async function writeBatches(inputBatches, writer) {
847
+ try {
848
+ for await (const inputBatch of inputBatches) {
849
+ await writer.write(new Uint8Array(inputBatch));
850
+ }
851
+ await writer.close();
852
+ } catch (error) {
853
+ await writer.abort(error).catch(() => {
854
+ });
855
+ throw error;
423
856
  }
424
857
  }
425
- function parseKSPLATHeader(data) {
426
- const dataView = new DataView(data, 0, HEADER_BYTE_LENGTH);
427
- const compressionLevel = dataView.getUint16(20, true);
428
- if (compressionLevel !== 0 && compressionLevel !== 1 && compressionLevel !== 2) {
429
- throw new Error(`KSPLATLoader: unsupported compression level ${compressionLevel}.`);
858
+ async function concatenateBatches(batches) {
859
+ const output = [];
860
+ let byteLength = 0;
861
+ for await (const batch of batches) {
862
+ const bytes = new Uint8Array(batch);
863
+ output.push(bytes);
864
+ byteLength += bytes.byteLength;
430
865
  }
431
- return {
432
- versionMajor: dataView.getUint8(0),
433
- versionMinor: dataView.getUint8(1),
434
- maxSectionCount: dataView.getUint32(4, true),
435
- sectionCount: dataView.getUint32(8, true),
436
- maxSplatCount: dataView.getUint32(12, true),
437
- splatCount: dataView.getUint32(16, true),
438
- compressionLevel,
439
- minSphericalHarmonicsCoeff: dataView.getFloat32(36, true) || -DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE,
440
- maxSphericalHarmonicsCoeff: dataView.getFloat32(40, true) || DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE
441
- };
866
+ const result = new Uint8Array(byteLength);
867
+ let offset = 0;
868
+ for (const batch of output) {
869
+ result.set(batch, offset);
870
+ offset += batch.byteLength;
871
+ }
872
+ return result.buffer;
442
873
  }
443
- function checkKSPLATVersion(header) {
444
- if (header.versionMajor === CURRENT_MAJOR_VERSION ? header.versionMinor >= CURRENT_MINOR_VERSION : header.versionMajor > CURRENT_MAJOR_VERSION) {
445
- return;
874
+ var init_compression_stream = __esm({
875
+ "../compression/src/lib/compression-stream.ts"() {
876
+ "use strict";
446
877
  }
447
- throw new Error(`KSPLATLoader: version ${header.versionMajor}.${header.versionMinor} is not supported.`);
878
+ });
879
+
880
+ // ../compression/src/lib/decompression-stream.ts
881
+ async function decompressWithNativeDecompressionStream(input, format) {
882
+ const outputBatches = decompressBatchesWithNativeDecompressionStream([input], format);
883
+ return outputBatches ? await concatenateNativeDecompressionBatches(outputBatches) : null;
448
884
  }
449
- function parseKSPLATSections(data, header) {
450
- if (data.byteLength < HEADER_BYTE_LENGTH + header.maxSectionCount * SECTION_HEADER_BYTE_LENGTH) {
451
- throw new Error("KSPLATLoader: file does not contain all section headers.");
885
+ function decompressBatchesWithNativeDecompressionStream(inputBatches, format) {
886
+ const decompressionStream = createNativeDecompressionStream(format);
887
+ return decompressionStream ? transformBatchesWithNativeDecompressionStream(inputBatches, decompressionStream) : null;
888
+ }
889
+ function isNativeDecompressionSupported(format) {
890
+ return Boolean(createNativeDecompressionStream(format));
891
+ }
892
+ function createNativeDecompressionStream(format) {
893
+ var _a, _b;
894
+ if (typeof globalThis.DecompressionStream === "undefined") {
895
+ return null;
452
896
  }
453
- const sections = [];
454
- let sectionBase = HEADER_BYTE_LENGTH + header.maxSectionCount * SECTION_HEADER_BYTE_LENGTH;
455
- let splatCountOffset = 0;
456
- for (let sectionIndex = 0; sectionIndex < header.maxSectionCount; sectionIndex++) {
457
- const sectionHeaderBase = HEADER_BYTE_LENGTH + sectionIndex * SECTION_HEADER_BYTE_LENGTH;
458
- const dataView = new DataView(data, sectionHeaderBase, SECTION_HEADER_BYTE_LENGTH);
459
- const splatCount = dataView.getUint32(0, true);
460
- const maxSplatCount = dataView.getUint32(4, true);
461
- const bucketSize = dataView.getUint32(8, true);
462
- const bucketCount = dataView.getUint32(12, true);
463
- const bucketBlockSize = dataView.getFloat32(16, true);
464
- const bucketStorageSizeBytes = dataView.getUint16(20, true);
465
- const compressionScaleRange = dataView.getUint32(24, true) || COMPRESSION_LAYOUTS[header.compressionLevel].scaleRange;
466
- const fullBucketCount = dataView.getUint32(32, true);
467
- const partiallyFilledBucketCount = dataView.getUint32(36, true);
468
- const sphericalHarmonicsDegree = dataView.getUint16(40, true);
469
- const bytesPerSplat = getBytesPerSplat(header.compressionLevel, sphericalHarmonicsDegree);
470
- const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;
471
- const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;
472
- const storageSizeBytes = bytesPerSplat * maxSplatCount + bucketsStorageSizeBytes;
473
- sections.push({
474
- bytesPerSplat,
475
- splatCountOffset,
476
- splatCount: splatCount || maxSplatCount,
477
- maxSplatCount,
478
- bucketSize,
479
- bucketCount,
480
- bucketStorageSizeBytes,
481
- bucketsStorageSizeBytes,
482
- compressionScaleRange,
483
- compressionScaleFactor: bucketBlockSize / 2 / compressionScaleRange,
484
- base: sectionBase,
485
- bucketsBase: sectionBase + bucketsMetaDataSizeBytes,
486
- dataBase: sectionBase + bucketsStorageSizeBytes,
487
- fullBucketCount,
488
- partiallyFilledBucketCount,
489
- sphericalHarmonicsDegree
897
+ if (((_b = (_a = globalThis.process) == null ? void 0 : _a.release) == null ? void 0 : _b.name) === "node" && typeof globalThis.Buffer === "undefined") {
898
+ return null;
899
+ }
900
+ try {
901
+ const DecompressionStreamConstructor = globalThis.DecompressionStream;
902
+ return new DecompressionStreamConstructor(format);
903
+ } catch (error) {
904
+ if (error instanceof TypeError || (error == null ? void 0 : error.name) === "TypeError") {
905
+ return null;
906
+ }
907
+ throw error;
908
+ }
909
+ }
910
+ async function* transformBatchesWithNativeDecompressionStream(inputBatches, decompressionStream) {
911
+ const writer = decompressionStream.writable.getWriter();
912
+ const reader = decompressionStream.readable.getReader();
913
+ const writePromise = writeBatchesToNativeDecompressionStream(inputBatches, writer);
914
+ writePromise.catch(() => {
915
+ });
916
+ let outputCompleted = false;
917
+ try {
918
+ while (true) {
919
+ const { done, value } = await reader.read();
920
+ if (done) {
921
+ outputCompleted = true;
922
+ break;
923
+ }
924
+ yield copyExactArrayBuffer(value);
925
+ }
926
+ await writePromise;
927
+ } finally {
928
+ if (!outputCompleted) {
929
+ await reader.cancel().catch(() => {
930
+ });
931
+ await writer.abort().catch(() => {
932
+ });
933
+ await writePromise.catch(() => {
934
+ });
935
+ }
936
+ reader.releaseLock();
937
+ }
938
+ }
939
+ async function concatenateNativeDecompressionBatches(outputBatches) {
940
+ const batches = [];
941
+ let byteLength = 0;
942
+ for await (const outputBatch of outputBatches) {
943
+ const bytes = new Uint8Array(outputBatch);
944
+ batches.push(bytes);
945
+ byteLength += bytes.byteLength;
946
+ }
947
+ const output = new Uint8Array(byteLength);
948
+ let byteOffset = 0;
949
+ for (const batch of batches) {
950
+ output.set(batch, byteOffset);
951
+ byteOffset += batch.byteLength;
952
+ }
953
+ return output.buffer;
954
+ }
955
+ function copyExactArrayBuffer(value) {
956
+ return new Uint8Array(value).buffer;
957
+ }
958
+ async function writeBatchesToNativeDecompressionStream(inputBatches, writer) {
959
+ try {
960
+ for await (const inputBatch of inputBatches) {
961
+ await writer.write(new Uint8Array(inputBatch));
962
+ }
963
+ await writer.close();
964
+ } catch (error) {
965
+ await writer.abort(error).catch(() => {
490
966
  });
491
- sectionBase += storageSizeBytes;
492
- splatCountOffset += maxSplatCount;
967
+ throw error;
493
968
  }
494
- return sections;
495
969
  }
496
- function decodeKSPLATCenterComponent(data, splatBase, component, header, section, bucketCenter) {
497
- const value = readCompressedCenterValue(data, splatBase, component, header.compressionLevel);
498
- return header.compressionLevel >= 1 ? (value - section.compressionScaleRange) * section.compressionScaleFactor + bucketCenter : value;
970
+ var init_decompression_stream = __esm({
971
+ "../compression/src/lib/decompression-stream.ts"() {
972
+ "use strict";
973
+ }
974
+ });
975
+
976
+ // ../compression/src/lib/native-decompressor.ts
977
+ var native_decompressor_exports = {};
978
+ __export(native_decompressor_exports, {
979
+ NativeDecompressor: () => NativeDecompressor
980
+ });
981
+ var NativeDecompressor;
982
+ var init_native_decompressor = __esm({
983
+ "../compression/src/lib/native-decompressor.ts"() {
984
+ "use strict";
985
+ init_compression();
986
+ init_decompression_stream();
987
+ NativeDecompressor = class extends Decompressor {
988
+ name;
989
+ extensions;
990
+ contentEncodings;
991
+ isSupported = true;
992
+ /** Runtime stream format used for every operation. */
993
+ format;
994
+ constructor(metadata, format, options = {}) {
995
+ super(options);
996
+ this.name = metadata.name;
997
+ this.extensions = [...metadata.extensions];
998
+ this.contentEncodings = [...metadata.contentEncodings];
999
+ this.format = format;
1000
+ }
1001
+ /** Decompresses one buffer with the runtime-provided stream. */
1002
+ async decompress(input) {
1003
+ const output = await decompressWithNativeDecompressionStream(input, this.format);
1004
+ if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
1005
+ return output;
1006
+ }
1007
+ /** Decompresses batches incrementally with the runtime-provided stream. */
1008
+ async *decompressBatches(inputBatches) {
1009
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, this.format);
1010
+ if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
1011
+ yield* output;
1012
+ }
1013
+ };
1014
+ }
1015
+ });
1016
+
1017
+ // ../compression/src/lib/lazy-compression.ts
1018
+ function mergeModules(options, modules) {
1019
+ return { ...options, modules: { ...options.modules, ...modules } };
1020
+ }
1021
+ var LazyDecompressor;
1022
+ var init_lazy_compression = __esm({
1023
+ "../compression/src/lib/lazy-compression.ts"() {
1024
+ "use strict";
1025
+ init_compression();
1026
+ init_decompression_stream();
1027
+ LazyDecompressor = class extends Decompressor {
1028
+ name;
1029
+ extensions;
1030
+ contentEncodings;
1031
+ isSupported = true;
1032
+ /** Constructor options retained until a concrete implementation is selected. */
1033
+ options;
1034
+ /** Built-in stream format to probe, or null when the format has no built-in path. */
1035
+ nativeFormat;
1036
+ /** Returns whether built-in selection remains eligible for the merged preload options. */
1037
+ shouldUseNative;
1038
+ /** Dynamically imports the balanced fallback constructor. */
1039
+ loadFallback;
1040
+ /** Selected concrete implementation after preload completes. */
1041
+ implementation = null;
1042
+ /** Shared in-flight selection used by concurrent asynchronous calls. */
1043
+ implementationPromise = null;
1044
+ constructor(metadata, loadFallback, options = {}, nativeFormat = null, shouldUseNative = () => true) {
1045
+ super(options);
1046
+ this.name = metadata.name;
1047
+ this.extensions = [...metadata.extensions];
1048
+ this.contentEncodings = [...metadata.contentEncodings];
1049
+ this.options = options;
1050
+ this.nativeFormat = nativeFormat;
1051
+ this.shouldUseNative = shouldUseNative;
1052
+ this.loadFallback = loadFallback;
1053
+ }
1054
+ /** Selects and returns the built-in or dynamically imported fallback decompressor. */
1055
+ async preload(modules = {}) {
1056
+ if (this.implementation) return this.implementation;
1057
+ const options = mergeModules(this.options, modules);
1058
+ this.implementationPromise ||= this.loadImplementation(options);
1059
+ try {
1060
+ this.implementation = await this.implementationPromise;
1061
+ return this.implementation;
1062
+ } catch (error) {
1063
+ this.implementationPromise = null;
1064
+ throw error;
1065
+ }
1066
+ }
1067
+ /** Loads the selected concrete decompressor. */
1068
+ async loadImplementation(options) {
1069
+ if (options.useNative !== false && this.nativeFormat && this.shouldUseNative(options) && isNativeDecompressionSupported(this.nativeFormat)) {
1070
+ const { NativeDecompressor: NativeDecompressor2 } = await Promise.resolve().then(() => (init_native_decompressor(), native_decompressor_exports));
1071
+ return new NativeDecompressor2(this, this.nativeFormat, options);
1072
+ }
1073
+ const Decompressor2 = await this.loadFallback();
1074
+ const implementation = new Decompressor2({ ...options, useNative: false });
1075
+ await implementation.preload(options.modules);
1076
+ return implementation;
1077
+ }
1078
+ /** Decompresses after lazily selecting the default implementation. */
1079
+ async decompress(input, size) {
1080
+ return (await this.preload()).decompress(input, size);
1081
+ }
1082
+ /** Decompresses synchronously after an implementation has been preloaded. */
1083
+ decompressSync(input, size) {
1084
+ if (!this.implementation) {
1085
+ throw new Error(`${this.name}: call preload() before decompressSync()`);
1086
+ }
1087
+ return this.implementation.decompressSync(input, size);
1088
+ }
1089
+ /** Decompresses batches after lazily selecting the default implementation. */
1090
+ async *decompressBatches(inputBatches) {
1091
+ yield* (await this.preload()).decompressBatches(inputBatches);
1092
+ }
1093
+ };
1094
+ }
1095
+ });
1096
+
1097
+ // ../compression/src/lib/fflate/index.ts
1098
+ function inflateSync(data, out) {
1099
+ return inflt(data, out);
1100
+ }
1101
+ function gunzipSync(data, out) {
1102
+ return inflt(data.subarray(gzs(data), -8), out || new u8(gzl(data)));
1103
+ }
1104
+ function unzlibSync(data, out) {
1105
+ return inflt((zlv(data), data.subarray(2, -4)), out);
1106
+ }
1107
+ var u8, u16, u32, fleb, fdeb, clim, freb, fl, revfl, fd, revfd, rev, hMap, flt, fdt, flrm, fdrm, max, bits, bits16, shft, slc, ec, err, inflt, gzs, gzl, zlv, Inflate, Gunzip, Unzlib;
1108
+ var init_fflate = __esm({
1109
+ "../compression/src/lib/fflate/index.ts"() {
1110
+ "use strict";
1111
+ u8 = Uint8Array;
1112
+ u16 = Uint16Array;
1113
+ u32 = Uint32Array;
1114
+ fleb = new u8([
1115
+ 0,
1116
+ 0,
1117
+ 0,
1118
+ 0,
1119
+ 0,
1120
+ 0,
1121
+ 0,
1122
+ 0,
1123
+ 1,
1124
+ 1,
1125
+ 1,
1126
+ 1,
1127
+ 2,
1128
+ 2,
1129
+ 2,
1130
+ 2,
1131
+ 3,
1132
+ 3,
1133
+ 3,
1134
+ 3,
1135
+ 4,
1136
+ 4,
1137
+ 4,
1138
+ 4,
1139
+ 5,
1140
+ 5,
1141
+ 5,
1142
+ 5,
1143
+ 0,
1144
+ /* unused */
1145
+ 0,
1146
+ 0,
1147
+ /* impossible */
1148
+ 0
1149
+ ]);
1150
+ fdeb = new u8([
1151
+ 0,
1152
+ 0,
1153
+ 0,
1154
+ 0,
1155
+ 1,
1156
+ 1,
1157
+ 2,
1158
+ 2,
1159
+ 3,
1160
+ 3,
1161
+ 4,
1162
+ 4,
1163
+ 5,
1164
+ 5,
1165
+ 6,
1166
+ 6,
1167
+ 7,
1168
+ 7,
1169
+ 8,
1170
+ 8,
1171
+ 9,
1172
+ 9,
1173
+ 10,
1174
+ 10,
1175
+ 11,
1176
+ 11,
1177
+ 12,
1178
+ 12,
1179
+ 13,
1180
+ 13,
1181
+ /* unused */
1182
+ 0,
1183
+ 0
1184
+ ]);
1185
+ clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
1186
+ freb = (eb, start) => {
1187
+ const b = new u16(31);
1188
+ for (let i = 0; i < 31; ++i) {
1189
+ b[i] = start += 1 << eb[i - 1];
1190
+ }
1191
+ const r = new u32(b[30]);
1192
+ for (let i = 1; i < 30; ++i) {
1193
+ for (let j = b[i]; j < b[i + 1]; ++j) {
1194
+ r[j] = j - b[i] << 5 | i;
1195
+ }
1196
+ }
1197
+ return [b, r];
1198
+ };
1199
+ [fl, revfl] = freb(fleb, 2);
1200
+ fl[28] = 258, revfl[258] = 28;
1201
+ [fd, revfd] = freb(fdeb, 0);
1202
+ rev = new u16(32768);
1203
+ for (let i = 0; i < 32768; ++i) {
1204
+ let x = (i & 43690) >>> 1 | (i & 21845) << 1;
1205
+ x = (x & 52428) >>> 2 | (x & 13107) << 2;
1206
+ x = (x & 61680) >>> 4 | (x & 3855) << 4;
1207
+ rev[i] = ((x & 65280) >>> 8 | (x & 255) << 8) >>> 1;
1208
+ }
1209
+ hMap = (cd, mb, r) => {
1210
+ const s = cd.length;
1211
+ let i = 0;
1212
+ const l = new u16(mb);
1213
+ for (; i < s; ++i) {
1214
+ if (cd[i]) ++l[cd[i] - 1];
1215
+ }
1216
+ const le = new u16(mb);
1217
+ for (i = 0; i < mb; ++i) {
1218
+ le[i] = le[i - 1] + l[i - 1] << 1;
1219
+ }
1220
+ let co;
1221
+ if (r) {
1222
+ co = new u16(1 << mb);
1223
+ const rvb = 15 - mb;
1224
+ for (i = 0; i < s; ++i) {
1225
+ if (cd[i]) {
1226
+ const sv = i << 4 | cd[i];
1227
+ const r2 = mb - cd[i];
1228
+ let v = le[cd[i] - 1]++ << r2;
1229
+ for (const m = v | (1 << r2) - 1; v <= m; ++v) {
1230
+ co[rev[v] >>> rvb] = sv;
1231
+ }
1232
+ }
1233
+ }
1234
+ } else {
1235
+ co = new u16(s);
1236
+ for (i = 0; i < s; ++i) {
1237
+ if (cd[i]) {
1238
+ co[i] = rev[le[cd[i] - 1]++] >>> 15 - cd[i];
1239
+ }
1240
+ }
1241
+ }
1242
+ return co;
1243
+ };
1244
+ flt = new u8(288);
1245
+ for (let i = 0; i < 144; ++i) flt[i] = 8;
1246
+ for (let i = 144; i < 256; ++i) flt[i] = 9;
1247
+ for (let i = 256; i < 280; ++i) flt[i] = 7;
1248
+ for (let i = 280; i < 288; ++i) flt[i] = 8;
1249
+ fdt = new u8(32);
1250
+ for (let i = 0; i < 32; ++i) fdt[i] = 5;
1251
+ flrm = /* @__PURE__ */ hMap(flt, 9, 1);
1252
+ fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
1253
+ max = (a) => {
1254
+ let m = a[0];
1255
+ for (let i = 1; i < a.length; ++i) {
1256
+ if (a[i] > m) m = a[i];
1257
+ }
1258
+ return m;
1259
+ };
1260
+ bits = (d, p, m) => {
1261
+ const o = p / 8 | 0;
1262
+ return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
1263
+ };
1264
+ bits16 = (d, p) => {
1265
+ const o = p / 8 | 0;
1266
+ return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
1267
+ };
1268
+ shft = (p) => (p + 7) / 8 | 0;
1269
+ slc = (v, s, e) => {
1270
+ if (s == null || s < 0) s = 0;
1271
+ if (e == null || e > v.length) e = v.length;
1272
+ const n = new (v.BYTES_PER_ELEMENT == 2 ? u16 : v.BYTES_PER_ELEMENT == 4 ? u32 : u8)(e - s);
1273
+ n.set(v.subarray(s, e));
1274
+ return n;
1275
+ };
1276
+ ec = [
1277
+ "unexpected EOF",
1278
+ "invalid block type",
1279
+ "invalid length/literal",
1280
+ "invalid distance",
1281
+ "stream finished",
1282
+ "no stream handler",
1283
+ ,
1284
+ // determined by compression function
1285
+ "no callback",
1286
+ "invalid UTF-8 data",
1287
+ "extra field too long",
1288
+ "date not in range 1980-2099",
1289
+ "filename too long",
1290
+ "stream finishing",
1291
+ "invalid zip data"
1292
+ // determined by unknown compression method
1293
+ ];
1294
+ err = (ind, msg, nt) => {
1295
+ const e = new Error(msg || ec[ind]);
1296
+ e.code = ind;
1297
+ if (Error.captureStackTrace) Error.captureStackTrace(e, err);
1298
+ if (!nt) throw e;
1299
+ return e;
1300
+ };
1301
+ inflt = (dat, buf, st) => {
1302
+ const sl = dat.length;
1303
+ if (!sl || st && st.f && !st.l) return buf || new u8(0);
1304
+ const noBuf = !buf || st;
1305
+ const noSt = !st || st.i;
1306
+ if (!st) st = {};
1307
+ if (!buf) buf = new u8(sl * 3);
1308
+ const cbuf = (l) => {
1309
+ let bl = buf.length;
1310
+ if (l > bl) {
1311
+ const nbuf = new u8(Math.max(bl * 2, l));
1312
+ nbuf.set(buf);
1313
+ buf = nbuf;
1314
+ }
1315
+ };
1316
+ let final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
1317
+ const tbts = sl * 8;
1318
+ do {
1319
+ if (!lm) {
1320
+ final = bits(dat, pos, 1);
1321
+ const type = bits(dat, pos + 1, 3);
1322
+ pos += 3;
1323
+ if (!type) {
1324
+ const s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
1325
+ if (t > sl) {
1326
+ if (noSt) err(0);
1327
+ break;
1328
+ }
1329
+ if (noBuf) cbuf(bt + l);
1330
+ buf.set(dat.subarray(s, t), bt);
1331
+ st.b = bt += l, st.p = pos = t * 8, st.f = final;
1332
+ continue;
1333
+ } else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
1334
+ else if (type == 2) {
1335
+ const hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
1336
+ const tl = hLit + bits(dat, pos + 5, 31) + 1;
1337
+ pos += 14;
1338
+ const ldt = new u8(tl);
1339
+ const clt = new u8(19);
1340
+ for (let i = 0; i < hcLen; ++i) {
1341
+ clt[clim[i]] = bits(dat, pos + i * 3, 7);
1342
+ }
1343
+ pos += hcLen * 3;
1344
+ const clb = max(clt), clbmsk = (1 << clb) - 1;
1345
+ const clm = hMap(clt, clb, 1);
1346
+ for (let i = 0; i < tl; ) {
1347
+ const r = clm[bits(dat, pos, clbmsk)];
1348
+ pos += r & 15;
1349
+ const s = r >>> 4;
1350
+ if (s < 16) {
1351
+ ldt[i++] = s;
1352
+ } else {
1353
+ let c = 0, n = 0;
1354
+ if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
1355
+ else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;
1356
+ else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;
1357
+ while (n--) ldt[i++] = c;
1358
+ }
1359
+ }
1360
+ const lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
1361
+ lbt = max(lt);
1362
+ dbt = max(dt);
1363
+ lm = hMap(lt, lbt, 1);
1364
+ dm = hMap(dt, dbt, 1);
1365
+ } else err(1);
1366
+ if (pos > tbts) {
1367
+ if (noSt) err(0);
1368
+ break;
1369
+ }
1370
+ }
1371
+ if (noBuf) cbuf(bt + 131072);
1372
+ const lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
1373
+ let lpos = pos;
1374
+ for (; ; lpos = pos) {
1375
+ const c = lm[bits16(dat, pos) & lms], sym = c >>> 4;
1376
+ pos += c & 15;
1377
+ if (pos > tbts) {
1378
+ if (noSt) err(0);
1379
+ break;
1380
+ }
1381
+ if (!c) err(2);
1382
+ if (sym < 256) buf[bt++] = sym;
1383
+ else if (sym == 256) {
1384
+ lpos = pos, lm = void 0;
1385
+ break;
1386
+ } else {
1387
+ let add = sym - 254;
1388
+ if (sym > 264) {
1389
+ const i = sym - 257, b = fleb[i];
1390
+ add = bits(dat, pos, (1 << b) - 1) + fl[i];
1391
+ pos += b;
1392
+ }
1393
+ const d = dm[bits16(dat, pos) & dms], dsym = d >>> 4;
1394
+ if (!d) err(3);
1395
+ pos += d & 15;
1396
+ let dt = fd[dsym];
1397
+ if (dsym > 3) {
1398
+ const b = fdeb[dsym];
1399
+ dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
1400
+ }
1401
+ if (pos > tbts) {
1402
+ if (noSt) err(0);
1403
+ break;
1404
+ }
1405
+ if (noBuf) cbuf(bt + 131072);
1406
+ const end = bt + add;
1407
+ for (; bt < end; bt += 4) {
1408
+ buf[bt] = buf[bt - dt];
1409
+ buf[bt + 1] = buf[bt + 1 - dt];
1410
+ buf[bt + 2] = buf[bt + 2 - dt];
1411
+ buf[bt + 3] = buf[bt + 3 - dt];
1412
+ }
1413
+ bt = end;
1414
+ }
1415
+ }
1416
+ st.l = lm, st.p = lpos, st.b = bt, st.f = final;
1417
+ if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;
1418
+ } while (!final);
1419
+ return bt == buf.length ? buf : slc(buf, 0, bt);
1420
+ };
1421
+ gzs = (d) => {
1422
+ if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, "invalid gzip data");
1423
+ const flg = d[3];
1424
+ let st = 10;
1425
+ if (flg & 4) st += d[10] | (d[11] << 8) + 2;
1426
+ for (let zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]) ;
1427
+ return st + (flg & 2);
1428
+ };
1429
+ gzl = (d) => {
1430
+ const l = d.length;
1431
+ return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;
1432
+ };
1433
+ zlv = (d) => {
1434
+ if ((d[0] & 15) != 8 || d[0] >>> 4 > 7 || (d[0] << 8 | d[1]) % 31) err(6, "invalid zlib data");
1435
+ if (d[1] & 32) err(6, "invalid zlib data: preset dictionaries not supported");
1436
+ };
1437
+ Inflate = class {
1438
+ /**
1439
+ * Creates an inflation stream
1440
+ * @param cb The callback to call whenever data is inflated
1441
+ */
1442
+ constructor(cb) {
1443
+ this.ondata = cb;
1444
+ }
1445
+ /** Persistent bit-reader and Huffman decoding state. */
1446
+ s = {};
1447
+ /** Compression options or retained output window for this stream. */
1448
+ o;
1449
+ /** Compressed bytes pending decoding. */
1450
+ p = new u8(0);
1451
+ /** Whether the stream has received its final chunk. */
1452
+ d;
1453
+ /**
1454
+ * The handler to call whenever data is available
1455
+ */
1456
+ ondata;
1457
+ /** Appends pending input after checking stream lifecycle. */
1458
+ e(c) {
1459
+ if (!this.ondata) err(5);
1460
+ if (this.d) err(4);
1461
+ const l = this.p.length;
1462
+ const n = new u8(l + c.length);
1463
+ n.set(this.p), n.set(c, l), this.p = n;
1464
+ }
1465
+ /** Decodes pending input and retains the sliding window. */
1466
+ c(final) {
1467
+ this.d = this.s.i = final || false;
1468
+ const bts = this.s.b;
1469
+ const dt = inflt(this.p, this.o, this.s);
1470
+ this.ondata(slc(dt, bts, this.s.b), this.d);
1471
+ this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;
1472
+ this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;
1473
+ }
1474
+ /**
1475
+ * Pushes a chunk to be inflated
1476
+ * @param chunk The chunk to push
1477
+ * @param final Whether this is the final chunk
1478
+ */
1479
+ push(chunk, final) {
1480
+ this.e(chunk), this.c(final);
1481
+ }
1482
+ };
1483
+ Gunzip = class extends Inflate {
1484
+ /** Whether the stream header still needs to be emitted or consumed. */
1485
+ v = 1;
1486
+ /**
1487
+ * Creates a GUNZIP stream
1488
+ * @param cb The callback to call whenever data is inflated
1489
+ */
1490
+ constructor(cb) {
1491
+ super(cb);
1492
+ }
1493
+ /**
1494
+ * Pushes a chunk to be GUNZIPped
1495
+ * @param chunk The chunk to push
1496
+ * @param final Whether this is the last chunk
1497
+ */
1498
+ push(chunk, final) {
1499
+ Inflate.prototype.e.call(this, chunk);
1500
+ if (this.v) {
1501
+ const s = this.p.length > 3 ? gzs(this.p) : 4;
1502
+ if (s >= this.p.length && !final) return;
1503
+ this.p = this.p.subarray(s), this.v = 0;
1504
+ }
1505
+ if (final) {
1506
+ if (this.p.length < 8) err(6, "invalid gzip data");
1507
+ this.p = this.p.subarray(0, -8);
1508
+ }
1509
+ Inflate.prototype.c.call(this, final);
1510
+ }
1511
+ };
1512
+ Unzlib = class extends Inflate {
1513
+ /** Whether the stream header still needs to be emitted or consumed. */
1514
+ v = 1;
1515
+ /**
1516
+ * Creates a Zlib decompression stream
1517
+ * @param cb The callback to call whenever data is inflated
1518
+ */
1519
+ constructor(cb) {
1520
+ super(cb);
1521
+ }
1522
+ /**
1523
+ * Pushes a chunk to be unzlibbed
1524
+ * @param chunk The chunk to push
1525
+ * @param final Whether this is the last chunk
1526
+ */
1527
+ push(chunk, final) {
1528
+ Inflate.prototype.e.call(this, chunk);
1529
+ if (this.v) {
1530
+ if (this.p.length < 2 && !final) return;
1531
+ this.p = this.p.subarray(2), this.v = 0;
1532
+ }
1533
+ if (final) {
1534
+ if (this.p.length < 4) err(6, "invalid zlib data");
1535
+ this.p = this.p.subarray(0, -4);
1536
+ }
1537
+ Inflate.prototype.c.call(this, final);
1538
+ }
1539
+ };
1540
+ }
1541
+ });
1542
+
1543
+ // ../compression/src/lib/fflate-stream.ts
1544
+ async function* transformFflateBatches(processor, inputBatches) {
1545
+ const chunks = [];
1546
+ processor.ondata = (data) => {
1547
+ chunks.push(data.slice().buffer);
1548
+ };
1549
+ for await (const batch of inputBatches) {
1550
+ processor.push(new Uint8Array(batch), false);
1551
+ yield* chunks.splice(0);
1552
+ }
1553
+ processor.push(new Uint8Array(0), true);
1554
+ yield* chunks;
1555
+ }
1556
+ var init_fflate_stream = __esm({
1557
+ "../compression/src/lib/fflate-stream.ts"() {
1558
+ "use strict";
1559
+ }
1560
+ });
1561
+
1562
+ // ../compression/src/gzip-decompressor-fflate.ts
1563
+ var GZipFflateDecompressor;
1564
+ var init_gzip_decompressor_fflate = __esm({
1565
+ "../compression/src/gzip-decompressor-fflate.ts"() {
1566
+ "use strict";
1567
+ init_fflate();
1568
+ init_compression();
1569
+ init_fflate_stream();
1570
+ GZipFflateDecompressor = class extends Decompressor {
1571
+ name = "gzip";
1572
+ extensions = ["gz", "gzip"];
1573
+ contentEncodings = ["gzip", "x-gzip"];
1574
+ isSupported = true;
1575
+ constructor(options = {}) {
1576
+ super(options);
1577
+ }
1578
+ /** Decompresses one GZIP payload synchronously. */
1579
+ decompressSync(input) {
1580
+ return gunzipSync(new Uint8Array(input)).slice().buffer;
1581
+ }
1582
+ /** Decompresses GZIP batches incrementally. */
1583
+ async *decompressBatches(inputBatches) {
1584
+ yield* transformFflateBatches(new Gunzip(), inputBatches);
1585
+ }
1586
+ };
1587
+ }
1588
+ });
1589
+
1590
+ // ../compression/src/gzip-decompressor.ts
1591
+ var gzip_decompressor_exports = {};
1592
+ __export(gzip_decompressor_exports, {
1593
+ GZipDecompressor: () => GZipDecompressor
1594
+ });
1595
+ var GZipDecompressor;
1596
+ var init_gzip_decompressor = __esm({
1597
+ "../compression/src/gzip-decompressor.ts"() {
1598
+ "use strict";
1599
+ init_gzip_decompressor_fflate();
1600
+ init_decompression_stream();
1601
+ GZipDecompressor = class extends GZipFflateDecompressor {
1602
+ options;
1603
+ constructor(options = {}) {
1604
+ super(options);
1605
+ this.options = options;
1606
+ }
1607
+ /** Decompresses with the built-in stream when available, then falls back to fflate. */
1608
+ async decompress(input) {
1609
+ if (this.options.useNative !== false) {
1610
+ const output = await decompressWithNativeDecompressionStream(input, "gzip");
1611
+ if (output) return output;
1612
+ }
1613
+ return this.decompressSync(input);
1614
+ }
1615
+ /** Decompresses batches with a built-in or fflate stream. */
1616
+ async *decompressBatches(inputBatches) {
1617
+ if (this.options.useNative !== false) {
1618
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, "gzip");
1619
+ if (output) {
1620
+ yield* output;
1621
+ return;
1622
+ }
1623
+ }
1624
+ yield* super.decompressBatches(inputBatches);
1625
+ }
1626
+ };
1627
+ }
1628
+ });
1629
+
1630
+ // ../compression/src/zstd-decompressor-fzstd.ts
1631
+ var import_fzstd, ZstdFzstdDecompressor;
1632
+ var init_zstd_decompressor_fzstd = __esm({
1633
+ "../compression/src/zstd-decompressor-fzstd.ts"() {
1634
+ "use strict";
1635
+ init_compression();
1636
+ import_fzstd = require("fzstd");
1637
+ ZstdFzstdDecompressor = class extends Decompressor {
1638
+ name = "zstd";
1639
+ extensions = ["zst"];
1640
+ contentEncodings = ["zstd"];
1641
+ isSupported = true;
1642
+ constructor(options = {}) {
1643
+ super(options);
1644
+ }
1645
+ /** Decompresses one Zstandard frame synchronously. */
1646
+ decompressSync(input) {
1647
+ return (0, import_fzstd.decompress)(new Uint8Array(input)).slice().buffer;
1648
+ }
1649
+ };
1650
+ }
1651
+ });
1652
+
1653
+ // ../compression/src/zstd-fallback.ts
1654
+ var zstd_fallback_exports = {};
1655
+ __export(zstd_fallback_exports, {
1656
+ decompressZstd: () => decompressZstd
1657
+ });
1658
+ function decompressZstd(input) {
1659
+ return (0, import_fzstd2.decompress)(input);
1660
+ }
1661
+ var import_fzstd2;
1662
+ var init_zstd_fallback = __esm({
1663
+ "../compression/src/zstd-fallback.ts"() {
1664
+ "use strict";
1665
+ import_fzstd2 = require("fzstd");
1666
+ }
1667
+ });
1668
+
1669
+ // ../compression/src/lib/zstd-compression.ts
1670
+ var zstd_compression_exports = {};
1671
+ __export(zstd_compression_exports, {
1672
+ ZstdCompression: () => ZstdCompression
1673
+ });
1674
+ var CHUNK_SIZE, zstdPromise, zstd, ZstdCompression;
1675
+ var init_zstd_compression = __esm({
1676
+ "../compression/src/lib/zstd-compression.ts"() {
1677
+ "use strict";
1678
+ init_compression();
1679
+ init_src();
1680
+ init_compression_stream();
1681
+ init_decompression_stream();
1682
+ CHUNK_SIZE = 1e6;
1683
+ ZstdCompression = class extends Compression {
1684
+ name = "zstd";
1685
+ extensions = [];
1686
+ contentEncodings = [];
1687
+ isSupported = true;
1688
+ options;
1689
+ /**
1690
+ * zstd-codec is an injectable dependency due to big size
1691
+ * @param options
1692
+ */
1693
+ constructor(options = {}) {
1694
+ super(options);
1695
+ this.options = options;
1696
+ registerJSModules(options == null ? void 0 : options.modules);
1697
+ }
1698
+ async preload(modules = {}) {
1699
+ registerJSModules(modules);
1700
+ const ZstdCodec = getJSModuleOrNull("zstd-codec");
1701
+ if (!zstdPromise && ZstdCodec) {
1702
+ zstdPromise = new Promise((resolve) => ZstdCodec.run((zstd2) => resolve(zstd2)));
1703
+ }
1704
+ if (zstdPromise) {
1705
+ zstd = await zstdPromise;
1706
+ }
1707
+ }
1708
+ compressSync(input) {
1709
+ getJSModule("zstd-codec", this.name);
1710
+ const simpleZstd = new zstd.Simple();
1711
+ const inputArray = new Uint8Array(input);
1712
+ return simpleZstd.compress(inputArray).buffer;
1713
+ }
1714
+ async compress(input) {
1715
+ var _a;
1716
+ if (this.options.useNative !== false && ((_a = this.options.zstd) == null ? void 0 : _a.useNative) !== false) {
1717
+ const nativeOutput = await compressWithNativeCompressionStream(input, "zstd");
1718
+ if (nativeOutput) return nativeOutput;
1719
+ }
1720
+ await this.preload();
1721
+ return this.compressSync(input);
1722
+ }
1723
+ decompressSync(input) {
1724
+ getJSModule("zstd-codec", this.name);
1725
+ const simpleZstd = new zstd.Simple();
1726
+ const inputArray = new Uint8Array(input);
1727
+ return simpleZstd.decompress(inputArray).buffer;
1728
+ }
1729
+ async decompress(input, size) {
1730
+ var _a;
1731
+ if (!getJSModuleOrNull("zstd-codec") && this.options.useNative !== false && ((_a = this.options.zstd) == null ? void 0 : _a.useNative) !== false) {
1732
+ const nativeOutput = await decompressWithNativeDecompressionStream(input, "zstd");
1733
+ if (nativeOutput) return nativeOutput;
1734
+ }
1735
+ await this.preload();
1736
+ const inputArray = new Uint8Array(input);
1737
+ if (!zstd) {
1738
+ const { decompressZstd: decompressZstd2 } = await Promise.resolve().then(() => (init_zstd_fallback(), zstd_fallback_exports));
1739
+ return ensureArrayBuffer(decompressZstd2(inputArray));
1740
+ }
1741
+ const simpleZstd = new zstd.Streaming();
1742
+ const chunks = [];
1743
+ for (let i = 0; i <= inputArray.length; i += CHUNK_SIZE) {
1744
+ const chunkView = inputArray.subarray(i, i + CHUNK_SIZE);
1745
+ const chunkArrayBuffer = ensureArrayBuffer(chunkView);
1746
+ chunks.push(new Uint8Array(chunkArrayBuffer));
1747
+ }
1748
+ const decompressResult = await simpleZstd.decompressChunks(chunks);
1749
+ return decompressResult.buffer;
1750
+ }
1751
+ };
1752
+ }
1753
+ });
1754
+
1755
+ // ../compression/src/zstd-decompressor.ts
1756
+ var zstd_decompressor_exports = {};
1757
+ __export(zstd_decompressor_exports, {
1758
+ ZstdDecompressor: () => ZstdDecompressor
1759
+ });
1760
+ var ZstdDecompressor;
1761
+ var init_zstd_decompressor = __esm({
1762
+ "../compression/src/zstd-decompressor.ts"() {
1763
+ "use strict";
1764
+ init_zstd_decompressor_fzstd();
1765
+ init_decompression_stream();
1766
+ init_src();
1767
+ ZstdDecompressor = class extends ZstdFzstdDecompressor {
1768
+ options;
1769
+ compatibility = null;
1770
+ constructor(options = {}) {
1771
+ super(options);
1772
+ this.options = options;
1773
+ registerJSModules(options.modules);
1774
+ }
1775
+ /** Preloads an injected zstd-codec implementation when supplied. */
1776
+ async preload(modules = {}) {
1777
+ registerJSModules(modules);
1778
+ if (getJSModuleOrNull("zstd-codec")) {
1779
+ const { ZstdCompression: ZstdCompression2 } = await Promise.resolve().then(() => (init_zstd_compression(), zstd_compression_exports));
1780
+ this.compatibility ||= new ZstdCompression2(this.options);
1781
+ await this.compatibility.preload(modules);
1782
+ }
1783
+ }
1784
+ /** Decompresses with the built-in stream when available, then falls back to fzstd. */
1785
+ async decompress(input) {
1786
+ if (this.options.useNative !== false) {
1787
+ const output = await decompressWithNativeDecompressionStream(input, "zstd");
1788
+ if (output) return output;
1789
+ }
1790
+ if (getJSModuleOrNull("zstd-codec")) {
1791
+ await this.preload(this.options.modules);
1792
+ }
1793
+ return this.decompressSync(input);
1794
+ }
1795
+ /** Decompresses with a preloaded zstd-codec implementation or compact fzstd. */
1796
+ decompressSync(input) {
1797
+ if (this.compatibility) {
1798
+ return this.compatibility.decompressSync(input);
1799
+ }
1800
+ if (getJSModuleOrNull("zstd-codec")) {
1801
+ throw new Error("zstd: call preload() before synchronous decompression with zstd-codec");
1802
+ }
1803
+ return super.decompressSync(input);
1804
+ }
1805
+ /** Decompresses batches with a built-in stream or compact fzstd fallback. */
1806
+ async *decompressBatches(inputBatches) {
1807
+ if (this.options.useNative !== false) {
1808
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, "zstd");
1809
+ if (output) {
1810
+ yield* output;
1811
+ return;
1812
+ }
1813
+ }
1814
+ if (getJSModuleOrNull("zstd-codec")) {
1815
+ yield this.decompress(await this.concatenate(inputBatches));
1816
+ return;
1817
+ }
1818
+ yield* super.decompressBatches(inputBatches);
1819
+ }
1820
+ };
1821
+ }
1822
+ });
1823
+
1824
+ // ../compression/src/default-codecs.ts
1825
+ var GZIP, ZSTD, GZipDecompressor2, ZstdDecompressor2;
1826
+ var init_default_codecs = __esm({
1827
+ "../compression/src/default-codecs.ts"() {
1828
+ "use strict";
1829
+ init_lazy_compression();
1830
+ init_src();
1831
+ GZIP = { name: "gzip", extensions: ["gz"], contentEncodings: ["gzip"] };
1832
+ ZSTD = { name: "zstd", extensions: ["zst"], contentEncodings: ["zstd"] };
1833
+ GZipDecompressor2 = class extends LazyDecompressor {
1834
+ constructor(options = {}) {
1835
+ super(
1836
+ GZIP,
1837
+ async () => (await Promise.resolve().then(() => (init_gzip_decompressor(), gzip_decompressor_exports))).GZipDecompressor,
1838
+ options,
1839
+ "gzip"
1840
+ );
1841
+ }
1842
+ };
1843
+ ZstdDecompressor2 = class extends LazyDecompressor {
1844
+ constructor(options = {}) {
1845
+ super(
1846
+ ZSTD,
1847
+ async () => (await Promise.resolve().then(() => (init_zstd_decompressor(), zstd_decompressor_exports))).ZstdDecompressor,
1848
+ options,
1849
+ "zstd",
1850
+ (preloadOptions) => {
1851
+ var _a;
1852
+ return !((_a = preloadOptions.modules) == null ? void 0 : _a["zstd-codec"]) && !getJSModuleOrNull("zstd-codec");
1853
+ }
1854
+ );
1855
+ }
1856
+ };
1857
+ }
1858
+ });
1859
+
1860
+ // ../compression/src/index.ts
1861
+ var init_src2 = __esm({
1862
+ "../compression/src/index.ts"() {
1863
+ "use strict";
1864
+ init_default_codecs();
1865
+ }
1866
+ });
1867
+
1868
+ // dist/lib/splat-utils.js
1869
+ function convertColorByteToSphericalHarmonicDc(colorByte) {
1870
+ return (colorByte / 255 - 0.5) / SH_C0;
1871
+ }
1872
+ function convertAlphaByteToLinearOpacity(alphaByte) {
1873
+ return Math.min(Math.max(alphaByte / 255, 0), 1);
1874
+ }
1875
+ function normalizeQuaternion(w, x, y, z2) {
1876
+ const length = Math.hypot(w, x, y, z2);
1877
+ if (!Number.isFinite(length) || length <= Number.EPSILON) {
1878
+ return [1, 0, 0, 0];
1879
+ }
1880
+ return [w / length, x / length, y / length, z2 / length];
1881
+ }
1882
+ function decodeQuaternionByte(byte) {
1883
+ return (byte - 128) / 128;
1884
+ }
1885
+ function decodeFloat16(value) {
1886
+ const sign = value & 32768 ? -1 : 1;
1887
+ const exponent = value >> 10 & 31;
1888
+ const fraction = value & 1023;
1889
+ if (exponent === 0) {
1890
+ return sign * Math.pow(2, -14) * (fraction / 1024);
1891
+ }
1892
+ if (exponent === 31) {
1893
+ return fraction ? Number.NaN : sign * Number.POSITIVE_INFINITY;
1894
+ }
1895
+ return sign * Math.pow(2, exponent - 15) * (1 + fraction / 1024);
1896
+ }
1897
+ var SH_C0;
1898
+ var init_splat_utils = __esm({
1899
+ "dist/lib/splat-utils.js"() {
1900
+ "use strict";
1901
+ SH_C0 = 0.28209479177387814;
1902
+ }
1903
+ });
1904
+
1905
+ // dist/lib/splats-arrow-table.js
1906
+ function makeGaussianSplatsArrowTable(splats) {
1907
+ const columns = {};
1908
+ const fields = [];
1909
+ const schemaFields = [];
1910
+ addColumn(columns, fields, schemaFields, "POSITION", makeFixedSizeListVector(splats.positions, 3), {
1911
+ type: "fixed-size-list",
1912
+ listSize: 3,
1913
+ children: [{ name: "value", type: "float32" }]
1914
+ });
1915
+ const colorCoefficients = getColorCoefficients(splats);
1916
+ addScalarColumn(columns, fields, schemaFields, "f_dc_0", colorCoefficients[0], {
1917
+ "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
1918
+ "loaders_gl.gaussian_splats.component": "0",
1919
+ "loaders_gl.gaussian_splats.encoding": "coefficient"
1920
+ });
1921
+ addScalarColumn(columns, fields, schemaFields, "f_dc_1", colorCoefficients[1], {
1922
+ "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
1923
+ "loaders_gl.gaussian_splats.component": "1",
1924
+ "loaders_gl.gaussian_splats.encoding": "coefficient"
1925
+ });
1926
+ addScalarColumn(columns, fields, schemaFields, "f_dc_2", colorCoefficients[2], {
1927
+ "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_dc",
1928
+ "loaders_gl.gaussian_splats.component": "2",
1929
+ "loaders_gl.gaussian_splats.encoding": "coefficient"
1930
+ });
1931
+ addScalarColumn(columns, fields, schemaFields, "opacity", splats.opacities, {
1932
+ "loaders_gl.gaussian_splats.semantic": "opacity",
1933
+ "loaders_gl.gaussian_splats.encoding": "linear"
1934
+ });
1935
+ addVectorComponents(columns, fields, schemaFields, "scale", splats.scales, 3, {
1936
+ "loaders_gl.gaussian_splats.semantic": "scale",
1937
+ "loaders_gl.gaussian_splats.encoding": "linear"
1938
+ });
1939
+ addVectorComponents(columns, fields, schemaFields, "rot", splats.rotations, 4, {
1940
+ "loaders_gl.gaussian_splats.semantic": "rotation",
1941
+ "loaders_gl.gaussian_splats.encoding": "quaternion"
1942
+ });
1943
+ if (splats.sphericalHarmonics && splats.sphericalHarmonicsComponentCount) {
1944
+ addSphericalHarmonicRestColumns(columns, fields, schemaFields, splats.sphericalHarmonics, splats.sphericalHarmonicsComponentCount);
1945
+ }
1946
+ const metadata = /* @__PURE__ */ new Map([
1947
+ ["loaders_gl.semantic_type", "gaussian-splats"],
1948
+ ["loaders_gl.gaussian_splats.version", "1"],
1949
+ ["loaders_gl.gaussian_splats.source_format", splats.format],
1950
+ ["topology", "point-list"],
1951
+ ["mode", "0"]
1952
+ ]);
1953
+ const arrowSchema = new arrow.Schema(fields, metadata);
1954
+ const schema = {
1955
+ fields: schemaFields,
1956
+ metadata: Object.fromEntries(metadata)
1957
+ };
1958
+ return {
1959
+ shape: "arrow-table",
1960
+ schema,
1961
+ data: new arrow.Table(arrowSchema, columns),
1962
+ topology: "point-list",
1963
+ loaderData: splats.loaderData
1964
+ };
1965
+ }
1966
+ function addVectorComponents(columns, fields, schemaFields, prefix, values, size, metadata) {
1967
+ for (let component = 0; component < size; component++) {
1968
+ const componentValues = new Float32Array(values.length / size);
1969
+ for (let rowIndex = 0; rowIndex < componentValues.length; rowIndex++) {
1970
+ componentValues[rowIndex] = values[rowIndex * size + component];
1971
+ }
1972
+ addScalarColumn(columns, fields, schemaFields, `${prefix}_${component}`, componentValues, {
1973
+ ...metadata,
1974
+ "loaders_gl.gaussian_splats.component": String(component)
1975
+ });
1976
+ }
1977
+ }
1978
+ function addSphericalHarmonicRestColumns(columns, fields, schemaFields, sphericalHarmonics, componentCount) {
1979
+ for (let component = 0; component < componentCount; component++) {
1980
+ const componentValues = new Float32Array(sphericalHarmonics.length / componentCount);
1981
+ for (let rowIndex = 0; rowIndex < componentValues.length; rowIndex++) {
1982
+ componentValues[rowIndex] = sphericalHarmonics[rowIndex * componentCount + component];
1983
+ }
1984
+ addScalarColumn(columns, fields, schemaFields, `f_rest_${component}`, componentValues, {
1985
+ "loaders_gl.gaussian_splats.semantic": "spherical_harmonic_rest",
1986
+ "loaders_gl.gaussian_splats.component": String(component),
1987
+ "loaders_gl.gaussian_splats.encoding": "coefficient"
1988
+ });
1989
+ }
1990
+ }
1991
+ function addScalarColumn(columns, fields, schemaFields, name, values, metadata) {
1992
+ addColumn(columns, fields, schemaFields, name, arrow.makeVector(values), "float32", metadata);
1993
+ }
1994
+ function addColumn(columns, fields, schemaFields, name, column, schemaType, metadata = {}) {
1995
+ columns[name] = column;
1996
+ fields.push(new arrow.Field(name, column.type, false, new Map(Object.entries(metadata))));
1997
+ schemaFields.push({ name, type: schemaType, nullable: false, metadata });
1998
+ }
1999
+ function makeFixedSizeListVector(value, size) {
2000
+ const values = arrow.makeVector(value);
2001
+ const child = values.data[0];
2002
+ const type = new arrow.FixedSizeList(size, new arrow.Field("value", child.type, false));
2003
+ const data = new arrow.Data(type, 0, value.length / size, 0, {}, [child]);
2004
+ return new arrow.Vector([data]);
2005
+ }
2006
+ function getColorCoefficients(splats) {
2007
+ const rowCount = splats.splatCount;
2008
+ const fdc0 = new Float32Array(rowCount);
2009
+ const fdc1 = new Float32Array(rowCount);
2010
+ const fdc2 = new Float32Array(rowCount);
2011
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
2012
+ if (splats.sphericalHarmonicDcs) {
2013
+ fdc0[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 0];
2014
+ fdc1[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 1];
2015
+ fdc2[rowIndex] = splats.sphericalHarmonicDcs[rowIndex * 3 + 2];
2016
+ } else {
2017
+ fdc0[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 0]);
2018
+ fdc1[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 1]);
2019
+ fdc2[rowIndex] = convertColorByteToSphericalHarmonicDc(splats.colors[rowIndex * 3 + 2]);
2020
+ }
2021
+ }
2022
+ return [fdc0, fdc1, fdc2];
2023
+ }
2024
+ var arrow;
2025
+ var init_splats_arrow_table = __esm({
2026
+ "dist/lib/splats-arrow-table.js"() {
2027
+ "use strict";
2028
+ arrow = __toESM(require("apache-arrow"), 1);
2029
+ init_splat_utils();
2030
+ }
2031
+ });
2032
+
2033
+ // dist/lib/parse-spz.js
2034
+ async function parseSPZ(data, options) {
2035
+ return makeGaussianSplatsArrowTable(await parseSPZToGaussianSplats(data, options));
2036
+ }
2037
+ async function parseSPZToGaussianSplats(data, options) {
2038
+ var _a, _b, _c;
2039
+ const version2 = detectSPZVersion(data);
2040
+ if (version2 === 0) {
2041
+ return await parseLegacySPZ(data, options);
2042
+ }
2043
+ if (version2 !== SPZ_VERSION) {
2044
+ throw new Error(`SPZLoader: version ${version2} is not supported.`);
2045
+ }
2046
+ const header = parseSPZHeader(data);
2047
+ const streamInfos = parseSPZStreamInfos(data, header, getSPZStreamByteLengths(header));
2048
+ const compressedStreams = streamInfos.map((streamInfo) => data.slice(streamInfo.compressedOffset, streamInfo.compressedOffset + streamInfo.compressedSize));
2049
+ const decompressor = new ZstdDecompressor2({ modules: options == null ? void 0 : options.modules });
2050
+ const streams = await Promise.all(compressedStreams.map((compressedStream, streamIndex) => decompressor.decompress(compressedStream, streamInfos[streamIndex].uncompressedSize)));
2051
+ validateSPZStreamLengths(streams, streamInfos);
2052
+ return applySPZCoordinateSystem(decodeSPZStreams(header, streams, data), ((_a = options == null ? void 0 : options.splats) == null ? void 0 : _a.sourceCoordinateSystem) ?? "RUB", ((_b = options == null ? void 0 : options.splats) == null ? void 0 : _b.targetCoordinateSystem) ?? ((_c = options == null ? void 0 : options.splats) == null ? void 0 : _c.sourceCoordinateSystem) ?? "RUB");
2053
+ }
2054
+ function detectSPZVersion(data) {
2055
+ if (data.byteLength < 8) {
2056
+ throw new Error("SPZLoader: file must contain at least an 8-byte header.");
2057
+ }
2058
+ const bytes = new Uint8Array(data);
2059
+ if (bytes[0] === 31 && bytes[1] === 139) {
2060
+ return 0;
2061
+ }
2062
+ if (data.byteLength < SPZ_HEADER_BYTE_LENGTH) {
2063
+ throw new Error("SPZLoader: file must contain a 32-byte header.");
2064
+ }
2065
+ return new DataView(data).getUint32(4, true);
2066
+ }
2067
+ async function parseLegacySPZ(data, options) {
2068
+ var _a, _b, _c;
2069
+ const decompressed = await new GZipDecompressor2({
2070
+ modules: options == null ? void 0 : options.modules,
2071
+ useNative: true
2072
+ }).decompress(data);
2073
+ if (decompressed.byteLength < 16) {
2074
+ throw new Error("SPZLoader: legacy payload must contain a 16-byte header.");
2075
+ }
2076
+ const dataView = new DataView(decompressed);
2077
+ const header = {
2078
+ magic: dataView.getUint32(0, true),
2079
+ version: dataView.getUint32(4, true),
2080
+ numPoints: dataView.getUint32(8, true),
2081
+ shDegree: dataView.getUint8(12),
2082
+ fractionalBits: dataView.getUint8(13),
2083
+ flags: dataView.getUint8(14)
2084
+ };
2085
+ if (header.magic !== SPZ_MAGIC) {
2086
+ throw new Error("SPZLoader: NGSP magic header not found.");
2087
+ }
2088
+ if (header.version !== 2 && header.version !== 3) {
2089
+ throw new Error(`SPZLoader: version ${header.version} is not supported.`);
2090
+ }
2091
+ if (dataView.getUint8(15) !== 0) {
2092
+ throw new Error("SPZLoader: legacy header reserved byte must be zero.");
2093
+ }
2094
+ if (header.shDegree > 3) {
2095
+ throw new Error(`SPZLoader: spherical harmonics degree ${header.shDegree} is not supported.`);
2096
+ }
2097
+ const count = header.numPoints;
2098
+ const shComponentCount = getSphericalHarmonicsComponentCount(header.shDegree);
2099
+ const positionByteLength = count * 9;
2100
+ const alphaByteLength = count;
2101
+ const colorByteLength = count * 3;
2102
+ const scaleByteLength = count * 3;
2103
+ const rotationByteLength = count * (header.version === 2 ? 3 : 4);
2104
+ const shByteLength = count * shComponentCount;
2105
+ const payloadByteLength = positionByteLength + alphaByteLength + colorByteLength + scaleByteLength + rotationByteLength + shByteLength;
2106
+ if (decompressed.byteLength - 16 !== payloadByteLength) {
2107
+ throw new Error(`SPZLoader: legacy payload has ${decompressed.byteLength - 16} bytes, expected ${payloadByteLength}.`);
2108
+ }
2109
+ let offset = 16;
2110
+ const positions = new Float32Array(count * 3);
2111
+ const opacities = new Float32Array(count);
2112
+ const colors = new Uint8Array(count * 3);
2113
+ const scales = new Float32Array(count * 3);
2114
+ const rotations = new Float32Array(count * 4);
2115
+ const sphericalHarmonicDcs = new Float32Array(count * 3);
2116
+ const sphericalHarmonics = shComponentCount ? new Float32Array(count * shComponentCount) : void 0;
2117
+ decodeSPZPositions(new Uint8Array(decompressed, offset, positionByteLength), positions, header.fractionalBits);
2118
+ offset += positionByteLength;
2119
+ decodeSPZOpacities(new Uint8Array(decompressed, offset, alphaByteLength), opacities);
2120
+ offset += alphaByteLength;
2121
+ decodeSPZColors(new Uint8Array(decompressed, offset, colorByteLength), colors, sphericalHarmonicDcs);
2122
+ offset += colorByteLength;
2123
+ decodeSPZScales(new Uint8Array(decompressed, offset, scaleByteLength), scales);
2124
+ offset += scaleByteLength;
2125
+ if (header.version === 2) {
2126
+ decodeLegacySPZRotations(new Uint8Array(decompressed, offset, rotationByteLength), rotations);
2127
+ } else {
2128
+ decodeSPZRotations(new Uint8Array(decompressed, offset, rotationByteLength), rotations);
2129
+ }
2130
+ offset += rotationByteLength;
2131
+ if (sphericalHarmonics) {
2132
+ decodeSPZSphericalHarmonics(new Uint8Array(decompressed, offset, shByteLength), sphericalHarmonics);
2133
+ }
2134
+ return applySPZCoordinateSystem({
2135
+ format: "spz",
2136
+ splatCount: count,
2137
+ positions,
2138
+ scales,
2139
+ rotations,
2140
+ colors,
2141
+ sphericalHarmonicDcs,
2142
+ opacities,
2143
+ sphericalHarmonics,
2144
+ sphericalHarmonicsComponentCount: shComponentCount || void 0,
2145
+ loaderData: { ...header, legacy: true }
2146
+ }, ((_a = options == null ? void 0 : options.splats) == null ? void 0 : _a.sourceCoordinateSystem) ?? "RUB", ((_b = options == null ? void 0 : options.splats) == null ? void 0 : _b.targetCoordinateSystem) ?? ((_c = options == null ? void 0 : options.splats) == null ? void 0 : _c.sourceCoordinateSystem) ?? "RUB");
2147
+ }
2148
+ function decodeLegacySPZRotations(rotationStream, rotations) {
2149
+ for (let splatIndex = 0; splatIndex < rotations.length / 4; splatIndex++) {
2150
+ const byteOffset = splatIndex * 3;
2151
+ const x = signedByte(rotationStream[byteOffset]) / 127;
2152
+ const y = signedByte(rotationStream[byteOffset + 1]) / 127;
2153
+ const z2 = signedByte(rotationStream[byteOffset + 2]) / 127;
2154
+ const w = Math.sqrt(Math.max(0, 1 - x * x - y * y - z2 * z2));
2155
+ const normalized = normalizeQuaternion(w, x, y, z2);
2156
+ rotations.set(normalized, splatIndex * 4);
2157
+ }
2158
+ }
2159
+ function signedByte(value) {
2160
+ return value > 127 ? value - 256 : value;
2161
+ }
2162
+ function applySPZCoordinateSystem(splats, source, target) {
2163
+ if (source === target || source === "UNSPECIFIED" || target === "UNSPECIFIED") {
2164
+ return splats;
2165
+ }
2166
+ if (source === "RUB" && target === "LUF") {
2167
+ for (let index = 0; index < splats.positions.length; index += 3) {
2168
+ splats.positions[index] = -splats.positions[index];
2169
+ splats.positions[index + 2] = -splats.positions[index + 2];
2170
+ }
2171
+ for (let index = 0; index < splats.rotations.length; index += 4) {
2172
+ splats.rotations[index + 1] = -splats.rotations[index + 1];
2173
+ splats.rotations[index + 3] = -splats.rotations[index + 3];
2174
+ }
2175
+ return splats;
2176
+ }
2177
+ if (source === "LUF" && target === "RUB") {
2178
+ return applySPZCoordinateSystem(splats, "RUB", "LUF");
2179
+ }
2180
+ throw new Error(`SPZLoader: coordinate conversion ${source} -> ${target} is not supported.`);
2181
+ }
2182
+ function parseSPZHeader(data) {
2183
+ if (data.byteLength < SPZ_HEADER_BYTE_LENGTH) {
2184
+ throw new Error(`SPZLoader: file must contain a ${SPZ_HEADER_BYTE_LENGTH}-byte header.`);
2185
+ }
2186
+ const dataView = new DataView(data);
2187
+ const header = {
2188
+ magic: dataView.getUint32(0, true),
2189
+ version: dataView.getUint32(4, true),
2190
+ numPoints: dataView.getUint32(8, true),
2191
+ shDegree: dataView.getUint8(12),
2192
+ fractionalBits: dataView.getUint8(13),
2193
+ flags: dataView.getUint8(14),
2194
+ numStreams: dataView.getUint8(15),
2195
+ tocByteOffset: dataView.getUint32(16, true)
2196
+ };
2197
+ if (header.magic !== SPZ_MAGIC) {
2198
+ throw new Error("SPZLoader: NGSP magic header not found.");
2199
+ }
2200
+ if (header.version !== SPZ_VERSION) {
2201
+ throw new Error(`SPZLoader: version ${header.version} is not supported.`);
2202
+ }
2203
+ if (header.shDegree > 4) {
2204
+ throw new Error(`SPZLoader: spherical harmonics degree ${header.shDegree} is not supported.`);
2205
+ }
2206
+ if (header.tocByteOffset < SPZ_HEADER_BYTE_LENGTH || header.tocByteOffset > data.byteLength) {
2207
+ throw new Error("SPZLoader: invalid table of contents byte offset.");
2208
+ }
2209
+ return header;
2210
+ }
2211
+ function parseSPZStreamInfos(data, header, expectedUncompressedSizes) {
2212
+ if (header.numStreams !== expectedUncompressedSizes.length) {
2213
+ throw new Error(`SPZLoader: expected ${expectedUncompressedSizes.length} streams, found ${header.numStreams}.`);
2214
+ }
2215
+ const tocByteLength = header.numStreams * 16;
2216
+ const tocEnd = header.tocByteOffset + tocByteLength;
2217
+ if (tocEnd > data.byteLength) {
2218
+ throw new Error("SPZLoader: table of contents exceeds file byte length.");
2219
+ }
2220
+ const dataView = new DataView(data);
2221
+ let compressedOffset = tocEnd;
2222
+ const streamInfos = [];
2223
+ for (let streamIndex = 0; streamIndex < header.numStreams; streamIndex++) {
2224
+ const tocOffset = header.tocByteOffset + streamIndex * 16;
2225
+ const compressedSize = readSafeUint64(dataView, tocOffset);
2226
+ const uncompressedSize = readSafeUint64(dataView, tocOffset + 8);
2227
+ const expectedUncompressedSize = expectedUncompressedSizes[streamIndex];
2228
+ if (uncompressedSize !== expectedUncompressedSize) {
2229
+ throw new Error(`SPZLoader: stream ${streamIndex} has ${uncompressedSize} uncompressed bytes, expected ${expectedUncompressedSize}.`);
2230
+ }
2231
+ if (compressedOffset + compressedSize > data.byteLength) {
2232
+ throw new Error(`SPZLoader: stream ${streamIndex} exceeds file byte length.`);
2233
+ }
2234
+ streamInfos.push({ compressedSize, uncompressedSize, compressedOffset });
2235
+ compressedOffset += compressedSize;
2236
+ }
2237
+ if (compressedOffset !== data.byteLength) {
2238
+ throw new Error("SPZLoader: compressed stream byte lengths do not match file byte length.");
2239
+ }
2240
+ return streamInfos;
2241
+ }
2242
+ function readSafeUint64(dataView, byteOffset) {
2243
+ const value = dataView.getBigUint64(byteOffset, true);
2244
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
2245
+ throw new Error("SPZLoader: stream byte length exceeds Number.MAX_SAFE_INTEGER.");
2246
+ }
2247
+ return Number(value);
2248
+ }
2249
+ function getSPZStreamByteLengths(header) {
2250
+ return [
2251
+ header.numPoints * 9,
2252
+ header.numPoints,
2253
+ header.numPoints * 3,
2254
+ header.numPoints * 3,
2255
+ header.numPoints * 4,
2256
+ header.numPoints * getSphericalHarmonicsComponentCount(header.shDegree)
2257
+ ].filter((byteLength) => byteLength > 0);
2258
+ }
2259
+ function validateSPZStreamLengths(streams, streamInfos) {
2260
+ for (let streamIndex = 0; streamIndex < streams.length; streamIndex++) {
2261
+ if (streams[streamIndex].byteLength !== streamInfos[streamIndex].uncompressedSize) {
2262
+ throw new Error(`SPZLoader: decompressed stream ${streamIndex} has unexpected byte length.`);
2263
+ }
2264
+ }
2265
+ }
2266
+ function decodeSPZStreams(header, streams, sourceData) {
2267
+ const splatCount = header.numPoints;
2268
+ const positions = new Float32Array(splatCount * 3);
2269
+ const scales = new Float32Array(splatCount * 3);
2270
+ const rotations = new Float32Array(splatCount * 4);
2271
+ const colors = new Uint8Array(splatCount * 3);
2272
+ const sphericalHarmonicDcs = new Float32Array(splatCount * 3);
2273
+ const opacities = new Float32Array(splatCount);
2274
+ const sphericalHarmonicsComponentCount = getSphericalHarmonicsComponentCount(header.shDegree);
2275
+ const sphericalHarmonics = sphericalHarmonicsComponentCount ? new Float32Array(splatCount * sphericalHarmonicsComponentCount) : void 0;
2276
+ const [positionStream, alphaStream, colorStream, scaleStream, rotationStream, sphericalHarmonicsStream] = streams.map((stream) => new Uint8Array(stream));
2277
+ decodeSPZPositions(positionStream, positions, header.fractionalBits);
2278
+ decodeSPZScales(scaleStream, scales);
2279
+ decodeSPZRotations(rotationStream, rotations);
2280
+ decodeSPZColors(colorStream, colors, sphericalHarmonicDcs);
2281
+ decodeSPZOpacities(alphaStream, opacities);
2282
+ if (sphericalHarmonics && sphericalHarmonicsStream) {
2283
+ decodeSPZSphericalHarmonics(sphericalHarmonicsStream, sphericalHarmonics);
2284
+ }
2285
+ return {
2286
+ format: "spz",
2287
+ splatCount,
2288
+ positions,
2289
+ scales,
2290
+ rotations,
2291
+ colors,
2292
+ sphericalHarmonicDcs,
2293
+ opacities,
2294
+ sphericalHarmonics,
2295
+ sphericalHarmonicsComponentCount,
2296
+ loaderData: {
2297
+ format: "spz",
2298
+ ...header,
2299
+ antialiased: Boolean(header.flags & 1),
2300
+ extensionByteLength: getSPZExtensionByteLength(header),
2301
+ extensionBytes: getSPZExtensionBytes(sourceData, header)
2302
+ }
2303
+ };
499
2304
  }
500
- function readCompressedCenterValue(data, byteOffset, component, compressionLevel) {
501
- const dataView = new DataView(data);
502
- return compressionLevel === 0 ? dataView.getFloat32(byteOffset + component * 4, true) : dataView.getUint16(byteOffset + component * 2, true);
2305
+ function decodeSPZPositions(positionStream, positions, fractionalBits) {
2306
+ const scale = 1 / 2 ** fractionalBits;
2307
+ for (let componentIndex = 0; componentIndex < positions.length; componentIndex++) {
2308
+ const byteOffset = componentIndex * 3;
2309
+ let fixed32 = positionStream[byteOffset] | positionStream[byteOffset + 1] << 8 | positionStream[byteOffset + 2] << 16;
2310
+ fixed32 |= fixed32 & 8388608 ? 4278190080 : 0;
2311
+ positions[componentIndex] = fixed32 * scale;
2312
+ }
503
2313
  }
504
- function getBucketCenter(data, section, localSplatIndex) {
505
- if (!section.bucketCount) {
506
- return [0, 0, 0];
2314
+ function decodeSPZScales(scaleStream, scales) {
2315
+ for (let componentIndex = 0; componentIndex < scales.length; componentIndex++) {
2316
+ scales[componentIndex] = Math.exp(scaleStream[componentIndex] / 16 - 10);
507
2317
  }
508
- const bucketIndex = getBucketIndex(data, section, localSplatIndex);
509
- const bucketBase = section.bucketsBase + bucketIndex * section.bucketStorageSizeBytes;
510
- const dataView = new DataView(data, bucketBase, 12);
511
- return [dataView.getFloat32(0, true), dataView.getFloat32(4, true), dataView.getFloat32(8, true)];
512
2318
  }
513
- function getBucketIndex(data, section, localSplatIndex) {
514
- const maxSplatIndexInFullBuckets = section.fullBucketCount * section.bucketSize;
515
- if (localSplatIndex < maxSplatIndexInFullBuckets) {
516
- return Math.floor(localSplatIndex / section.bucketSize);
2319
+ function decodeSPZRotations(rotationStream, rotations) {
2320
+ for (let splatIndex = 0; splatIndex < rotations.length / 4; splatIndex++) {
2321
+ const byteOffset = splatIndex * 4;
2322
+ const component = rotationStream[byteOffset] | rotationStream[byteOffset + 1] << 8 | rotationStream[byteOffset + 2] << 16 | rotationStream[byteOffset + 3] << 24;
2323
+ const xyzw = decodeSPZQuaternion(component >>> 0);
2324
+ const [w, x, y, z2] = normalizeQuaternion(xyzw[3], xyzw[0], xyzw[1], xyzw[2]);
2325
+ const rotationOffset = splatIndex * 4;
2326
+ rotations[rotationOffset + 0] = w;
2327
+ rotations[rotationOffset + 1] = x;
2328
+ rotations[rotationOffset + 2] = y;
2329
+ rotations[rotationOffset + 3] = z2;
517
2330
  }
518
- let bucketSplatIndex = maxSplatIndexInFullBuckets;
519
- let bucketIndex = section.fullBucketCount;
520
- for (let partiallyFilledBucketIndex = 0; partiallyFilledBucketIndex < section.partiallyFilledBucketCount; partiallyFilledBucketIndex++) {
521
- const bucketLength = new DataView(data, section.base + partiallyFilledBucketIndex * 4, 4).getUint32(0, true);
522
- if (localSplatIndex < bucketSplatIndex + bucketLength) {
523
- return bucketIndex;
2331
+ }
2332
+ function decodeSPZQuaternion(component) {
2333
+ const rotation = [0, 0, 0, 0];
2334
+ const largestComponent = component >>> 30;
2335
+ let remainingBits = component;
2336
+ let sumSquares = 0;
2337
+ for (let componentIndex = 3; componentIndex >= 0; componentIndex--) {
2338
+ if (componentIndex !== largestComponent) {
2339
+ const magnitude = remainingBits & SPZ_ROTATION_COMPONENT_MASK;
2340
+ const isNegative = remainingBits >>> 9 & 1;
2341
+ remainingBits >>>= 10;
2342
+ let value = SPZ_ROTATION_COMPONENT_SCALE * magnitude / SPZ_ROTATION_COMPONENT_MASK;
2343
+ if (isNegative) {
2344
+ value = -value;
2345
+ }
2346
+ rotation[componentIndex] = value;
2347
+ sumSquares += value * value;
524
2348
  }
525
- bucketSplatIndex += bucketLength;
526
- bucketIndex++;
527
2349
  }
528
- return Math.max(bucketIndex - 1, 0);
2350
+ rotation[largestComponent] = Math.sqrt(Math.max(0, 1 - sumSquares));
2351
+ return rotation;
529
2352
  }
530
- function decodeSphericalHarmonics(data, byteOffset, header, section, outputSplatIndex, output, outputComponentCount) {
531
- const componentCount = getSphericalHarmonicsComponentCount(section.sphericalHarmonicsDegree);
532
- const componentBase = outputSplatIndex * outputComponentCount;
533
- for (let component = 0; component < componentCount; component++) {
534
- output[componentBase + component] = readCompressedFloat(data, byteOffset, component, header.compressionLevel, true, header.minSphericalHarmonicsCoeff, header.maxSphericalHarmonicsCoeff);
2353
+ function decodeSPZColors(colorStream, colors, sphericalHarmonicDcs) {
2354
+ for (let componentIndex = 0; componentIndex < colors.length; componentIndex++) {
2355
+ sphericalHarmonicDcs[componentIndex] = (colorStream[componentIndex] / 255 - 0.5) / SPZ_COLOR_SCALE;
2356
+ colors[componentIndex] = normalizeColorByte(sphericalHarmonicDcs[componentIndex]);
535
2357
  }
536
2358
  }
537
- function readCompressedFloat(data, byteOffset, component, compressionLevel, sphericalHarmonic = false, sphericalHarmonicRangeMin = 0, sphericalHarmonicRangeMax = 0) {
538
- const dataView = new DataView(data);
539
- if (compressionLevel === 0) {
540
- return dataView.getFloat32(byteOffset + component * 4, true);
2359
+ function decodeSPZOpacities(alphaStream, opacities) {
2360
+ for (let splatIndex = 0; splatIndex < opacities.length; splatIndex++) {
2361
+ opacities[splatIndex] = alphaStream[splatIndex] / 255;
541
2362
  }
542
- if (compressionLevel === 1 || !sphericalHarmonic) {
543
- return decodeFloat16(dataView.getUint16(byteOffset + component * 2, true));
2363
+ }
2364
+ function decodeSPZSphericalHarmonics(sphericalHarmonicsStream, sphericalHarmonics) {
2365
+ for (let componentIndex = 0; componentIndex < sphericalHarmonics.length; componentIndex++) {
2366
+ sphericalHarmonics[componentIndex] = (sphericalHarmonicsStream[componentIndex] - 128) / 128;
544
2367
  }
545
- const value = dataView.getUint8(byteOffset + component);
546
- return value / 255 * (sphericalHarmonicRangeMax - sphericalHarmonicRangeMin) + sphericalHarmonicRangeMin;
547
2368
  }
548
- function getBytesPerSplat(compressionLevel, sphericalHarmonicsDegree) {
549
- const layout = COMPRESSION_LAYOUTS[compressionLevel];
550
- return layout.bytesPerCenter + layout.bytesPerScale + layout.bytesPerRotation + layout.bytesPerColor + layout.bytesPerSphericalHarmonicsComponent * getSphericalHarmonicsComponentCount(sphericalHarmonicsDegree);
2369
+ function normalizeColorByte(sphericalHarmonicDc) {
2370
+ return Math.min(Math.max(Math.round((sphericalHarmonicDc * SPZ_COLOR_SCALE + 0.5) * 255), 0), 255);
551
2371
  }
552
- function getSphericalHarmonicsComponentCount(sphericalHarmonicsDegree) {
553
- switch (sphericalHarmonicsDegree) {
2372
+ function getSphericalHarmonicsComponentCount(shDegree) {
2373
+ switch (shDegree) {
554
2374
  case 0:
555
2375
  return 0;
556
2376
  case 1:
@@ -559,324 +2379,346 @@ function getSphericalHarmonicsComponentCount(sphericalHarmonicsDegree) {
559
2379
  return 24;
560
2380
  case 3:
561
2381
  return 45;
2382
+ case 4:
2383
+ return 72;
562
2384
  default:
563
- throw new Error(`KSPLATLoader: unsupported spherical harmonics degree ${sphericalHarmonicsDegree}.`);
2385
+ throw new Error(`SPZLoader: spherical harmonics degree ${shDegree} is not supported.`);
564
2386
  }
565
2387
  }
566
- function getActiveSectionCount(header) {
567
- return header.sectionCount || header.maxSectionCount;
2388
+ function getSPZExtensionByteLength(header) {
2389
+ return header.flags & SPZ_EXTENSION_FLAG ? header.tocByteOffset - SPZ_HEADER_BYTE_LENGTH : 0;
568
2390
  }
569
- function getTotalSplatCount(header, sections) {
570
- const sectionSplatCount = sections.slice(0, getActiveSectionCount(header)).reduce((splatCount, section) => splatCount + section.splatCount, 0);
571
- return header.splatCount ? Math.min(header.splatCount, sectionSplatCount || header.splatCount) : sectionSplatCount;
2391
+ function getSPZExtensionBytes(data, header) {
2392
+ const extensionByteLength = getSPZExtensionByteLength(header);
2393
+ return extensionByteLength ? new Uint8Array(data.slice(SPZ_HEADER_BYTE_LENGTH, header.tocByteOffset)) : void 0;
572
2394
  }
573
- function validateSectionBounds(data, section) {
574
- const requiredByteLength = section.dataBase + section.bytesPerSplat * section.splatCount;
575
- if (requiredByteLength > data.byteLength) {
576
- throw new Error("KSPLATLoader: section data extends beyond the file length.");
2395
+ var SPZ_HEADER_BYTE_LENGTH, SPZ_MAGIC, SPZ_VERSION, SPZ_EXTENSION_FLAG, SPZ_COLOR_SCALE, SPZ_ROTATION_COMPONENT_SCALE, SPZ_ROTATION_COMPONENT_MASK;
2396
+ var init_parse_spz = __esm({
2397
+ "dist/lib/parse-spz.js"() {
2398
+ "use strict";
2399
+ init_src2();
2400
+ init_splats_arrow_table();
2401
+ init_splat_utils();
2402
+ SPZ_HEADER_BYTE_LENGTH = 32;
2403
+ SPZ_MAGIC = 1347635022;
2404
+ SPZ_VERSION = 4;
2405
+ SPZ_EXTENSION_FLAG = 2;
2406
+ SPZ_COLOR_SCALE = 0.15;
2407
+ SPZ_ROTATION_COMPONENT_SCALE = Math.SQRT1_2;
2408
+ SPZ_ROTATION_COMPONENT_MASK = (1 << 9) - 1;
2409
+ }
2410
+ });
2411
+
2412
+ // dist/lib/parse-splat.js
2413
+ function parseSPLAT(data) {
2414
+ return makeGaussianSplatsArrowTable(parseSPLATToGaussianSplats(data));
2415
+ }
2416
+ function parseSPLATToGaussianSplats(data) {
2417
+ if (data.byteLength % SPLAT_ROW_BYTE_LENGTH !== 0) {
2418
+ throw new Error(`SPLATLoader: byte length must be a multiple of ${SPLAT_ROW_BYTE_LENGTH}.`);
2419
+ }
2420
+ const splatCount = data.byteLength / SPLAT_ROW_BYTE_LENGTH;
2421
+ const dataView = new DataView(data);
2422
+ const positions = new Float32Array(splatCount * 3);
2423
+ const scales = new Float32Array(splatCount * 3);
2424
+ const rotations = new Float32Array(splatCount * 4);
2425
+ const colors = new Uint8Array(splatCount * 3);
2426
+ const opacities = new Float32Array(splatCount);
2427
+ for (let splatIndex = 0; splatIndex < splatCount; splatIndex++) {
2428
+ const byteOffset = splatIndex * SPLAT_ROW_BYTE_LENGTH;
2429
+ const positionOffset = splatIndex * 3;
2430
+ const rotationOffset = splatIndex * 4;
2431
+ positions[positionOffset + 0] = dataView.getFloat32(byteOffset + 0, true);
2432
+ positions[positionOffset + 1] = dataView.getFloat32(byteOffset + 4, true);
2433
+ positions[positionOffset + 2] = dataView.getFloat32(byteOffset + 8, true);
2434
+ scales[positionOffset + 0] = dataView.getFloat32(byteOffset + 12, true);
2435
+ scales[positionOffset + 1] = dataView.getFloat32(byteOffset + 16, true);
2436
+ scales[positionOffset + 2] = dataView.getFloat32(byteOffset + 20, true);
2437
+ colors[positionOffset + 0] = dataView.getUint8(byteOffset + 24);
2438
+ colors[positionOffset + 1] = dataView.getUint8(byteOffset + 25);
2439
+ colors[positionOffset + 2] = dataView.getUint8(byteOffset + 26);
2440
+ opacities[splatIndex] = convertAlphaByteToLinearOpacity(dataView.getUint8(byteOffset + 27));
2441
+ const [w, x, y, z2] = normalizeQuaternion(decodeQuaternionByte(dataView.getUint8(byteOffset + 28)), decodeQuaternionByte(dataView.getUint8(byteOffset + 29)), decodeQuaternionByte(dataView.getUint8(byteOffset + 30)), decodeQuaternionByte(dataView.getUint8(byteOffset + 31)));
2442
+ rotations[rotationOffset + 0] = w;
2443
+ rotations[rotationOffset + 1] = x;
2444
+ rotations[rotationOffset + 2] = y;
2445
+ rotations[rotationOffset + 3] = z2;
577
2446
  }
2447
+ return {
2448
+ format: "splat",
2449
+ splatCount,
2450
+ positions,
2451
+ scales,
2452
+ rotations,
2453
+ colors,
2454
+ opacities,
2455
+ loaderData: {
2456
+ format: "splat",
2457
+ splatCount,
2458
+ rowByteLength: SPLAT_ROW_BYTE_LENGTH
2459
+ }
2460
+ };
578
2461
  }
579
- var CURRENT_MAJOR_VERSION, CURRENT_MINOR_VERSION, HEADER_BYTE_LENGTH, SECTION_HEADER_BYTE_LENGTH, DEFAULT_SH_8BIT_COMPRESSION_RANGE, DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE, COMPRESSION_LAYOUTS;
580
- var init_parse_ksplat = __esm({
581
- "dist/lib/parse-ksplat.js"() {
2462
+ var SPLAT_ROW_BYTE_LENGTH;
2463
+ var init_parse_splat = __esm({
2464
+ "dist/lib/parse-splat.js"() {
582
2465
  "use strict";
583
2466
  init_splats_arrow_table();
584
2467
  init_splat_utils();
585
- CURRENT_MAJOR_VERSION = 0;
586
- CURRENT_MINOR_VERSION = 1;
587
- HEADER_BYTE_LENGTH = 4096;
588
- SECTION_HEADER_BYTE_LENGTH = 1024;
589
- DEFAULT_SH_8BIT_COMPRESSION_RANGE = 3;
590
- DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE = DEFAULT_SH_8BIT_COMPRESSION_RANGE / 2;
591
- COMPRESSION_LAYOUTS = {
592
- 0: {
593
- bytesPerCenter: 12,
594
- bytesPerScale: 12,
595
- bytesPerRotation: 16,
596
- bytesPerColor: 4,
597
- scaleOffsetBytes: 12,
598
- colorOffsetBytes: 40,
599
- sphericalHarmonicsOffsetBytes: 44,
600
- scaleRange: 1,
601
- bytesPerSphericalHarmonicsComponent: 4
602
- },
603
- 1: {
604
- bytesPerCenter: 6,
605
- bytesPerScale: 6,
606
- bytesPerRotation: 8,
607
- bytesPerColor: 4,
608
- scaleOffsetBytes: 6,
609
- colorOffsetBytes: 20,
610
- sphericalHarmonicsOffsetBytes: 24,
611
- scaleRange: 32767,
612
- bytesPerSphericalHarmonicsComponent: 2
613
- },
614
- 2: {
615
- bytesPerCenter: 6,
616
- bytesPerScale: 6,
617
- bytesPerRotation: 8,
618
- bytesPerColor: 4,
619
- scaleOffsetBytes: 6,
620
- colorOffsetBytes: 20,
621
- sphericalHarmonicsOffsetBytes: 24,
622
- scaleRange: 32767,
623
- bytesPerSphericalHarmonicsComponent: 1
624
- }
625
- };
2468
+ SPLAT_ROW_BYTE_LENGTH = 32;
626
2469
  }
627
2470
  });
628
2471
 
629
- // dist/ksplat-loader.js
630
- var ksplat_loader_exports = {};
631
- __export(ksplat_loader_exports, {
632
- KSPLATLoaderWithParser: () => KSPLATLoaderWithParser
2472
+ // dist/splat-loader.js
2473
+ var splat_loader_exports = {};
2474
+ __export(splat_loader_exports, {
2475
+ SPLATLoaderWithParser: () => SPLATLoaderWithParser
633
2476
  });
634
- var _KSPLATLoaderPreload, KSPLATLoaderMetadataWithoutPreload, KSPLATLoaderWithParser;
635
- var init_ksplat_loader = __esm({
636
- "dist/ksplat-loader.js"() {
2477
+ var _SPLATLoaderPreload, SPLATLoaderMetadataWithoutPreload, SPLATLoaderWithParser;
2478
+ var init_splat_loader = __esm({
2479
+ "dist/splat-loader.js"() {
637
2480
  "use strict";
638
- init_parse_ksplat();
639
- init_ksplat_loader_types();
640
- ({ preload: _KSPLATLoaderPreload, ...KSPLATLoaderMetadataWithoutPreload } = KSPLATLoader);
641
- KSPLATLoaderWithParser = {
642
- ...KSPLATLoaderMetadataWithoutPreload,
643
- parse: async (arrayBuffer) => parseKSPLAT(arrayBuffer),
644
- parseSync: (arrayBuffer) => parseKSPLAT(arrayBuffer)
2481
+ init_parse_splat();
2482
+ init_splat_loader_types();
2483
+ ({ preload: _SPLATLoaderPreload, ...SPLATLoaderMetadataWithoutPreload } = SPLATLoader);
2484
+ SPLATLoaderWithParser = {
2485
+ ...SPLATLoaderMetadataWithoutPreload,
2486
+ parse: async (arrayBuffer) => parseSPLAT(arrayBuffer),
2487
+ parseSync: (arrayBuffer) => parseSPLAT(arrayBuffer)
645
2488
  };
646
2489
  }
647
- });
648
-
649
- // dist/ksplat-loader-types.js
650
- async function preload2() {
651
- const { KSPLATLoaderWithParser: KSPLATLoaderWithParser2 } = await Promise.resolve().then(() => (init_ksplat_loader(), ksplat_loader_exports));
652
- return KSPLATLoaderWithParser2;
2490
+ });
2491
+
2492
+ // dist/splat-loader-types.js
2493
+ async function preload() {
2494
+ const { SPLATLoaderWithParser: SPLATLoaderWithParser2 } = await Promise.resolve().then(() => (init_splat_loader(), splat_loader_exports));
2495
+ return SPLATLoaderWithParser2;
653
2496
  }
654
- var VERSION2, KSPLATLoader;
655
- var init_ksplat_loader_types = __esm({
656
- "dist/ksplat-loader-types.js"() {
2497
+ var VERSION2, SPLATLoader;
2498
+ var init_splat_loader_types = __esm({
2499
+ "dist/splat-loader-types.js"() {
657
2500
  "use strict";
658
2501
  init_splats_format();
659
- VERSION2 = true ? "5.0.0-alpha.1" : "latest";
660
- KSPLATLoader = {
2502
+ VERSION2 = true ? "5.0.0-alpha.11" : "latest";
2503
+ SPLATLoader = {
661
2504
  dataType: null,
662
2505
  batchType: null,
663
- ...KSPLATFormat,
2506
+ ...SPLATFormat,
664
2507
  version: VERSION2,
665
2508
  options: {
666
2509
  splats: {
667
2510
  shape: "arrow-table"
668
2511
  }
669
2512
  },
670
- preload: preload2
2513
+ preload
671
2514
  };
672
2515
  }
673
2516
  });
674
2517
 
675
- // dist/lib/parse-spz.js
676
- async function parseSPZ(data, options) {
677
- return makeGaussianSplatsArrowTable(await parseSPZToGaussianSplats(data, options));
678
- }
679
- async function parseSPZToGaussianSplats(data, options) {
680
- const header = parseSPZHeader(data);
681
- const streamInfos = parseSPZStreamInfos(data, header, getSPZStreamByteLengths(header));
682
- const compressedStreams = streamInfos.map((streamInfo) => data.slice(streamInfo.compressedOffset, streamInfo.compressedOffset + streamInfo.compressedSize));
683
- const compression = new import_compression.ZstdCompression({ modules: options == null ? void 0 : options.modules });
684
- const streams = await Promise.all(compressedStreams.map((compressedStream, streamIndex) => compression.decompress(compressedStream, streamInfos[streamIndex].uncompressedSize)));
685
- validateSPZStreamLengths(streams, streamInfos);
686
- return decodeSPZStreams(header, streams, data);
687
- }
688
- function parseSPZHeader(data) {
689
- if (data.byteLength < SPZ_HEADER_BYTE_LENGTH) {
690
- throw new Error(`SPZLoader: file must contain a ${SPZ_HEADER_BYTE_LENGTH}-byte header.`);
691
- }
692
- const dataView = new DataView(data);
693
- const header = {
694
- magic: dataView.getUint32(0, true),
695
- version: dataView.getUint32(4, true),
696
- numPoints: dataView.getUint32(8, true),
697
- shDegree: dataView.getUint8(12),
698
- fractionalBits: dataView.getUint8(13),
699
- flags: dataView.getUint8(14),
700
- numStreams: dataView.getUint8(15),
701
- tocByteOffset: dataView.getUint32(16, true)
702
- };
703
- if (header.magic !== SPZ_MAGIC) {
704
- throw new Error("SPZLoader: NGSP magic header not found.");
705
- }
706
- if (header.version !== SPZ_VERSION) {
707
- throw new Error(`SPZLoader: version ${header.version} is not supported.`);
708
- }
709
- if (header.shDegree > 4) {
710
- throw new Error(`SPZLoader: spherical harmonics degree ${header.shDegree} is not supported.`);
711
- }
712
- if (header.tocByteOffset < SPZ_HEADER_BYTE_LENGTH || header.tocByteOffset > data.byteLength) {
713
- throw new Error("SPZLoader: invalid table of contents byte offset.");
714
- }
715
- return header;
716
- }
717
- function parseSPZStreamInfos(data, header, expectedUncompressedSizes) {
718
- if (header.numStreams !== expectedUncompressedSizes.length) {
719
- throw new Error(`SPZLoader: expected ${expectedUncompressedSizes.length} streams, found ${header.numStreams}.`);
720
- }
721
- const tocByteLength = header.numStreams * 16;
722
- const tocEnd = header.tocByteOffset + tocByteLength;
723
- if (tocEnd > data.byteLength) {
724
- throw new Error("SPZLoader: table of contents exceeds file byte length.");
725
- }
726
- const dataView = new DataView(data);
727
- let compressedOffset = tocEnd;
728
- const streamInfos = [];
729
- for (let streamIndex = 0; streamIndex < header.numStreams; streamIndex++) {
730
- const tocOffset = header.tocByteOffset + streamIndex * 16;
731
- const compressedSize = readSafeUint64(dataView, tocOffset);
732
- const uncompressedSize = readSafeUint64(dataView, tocOffset + 8);
733
- const expectedUncompressedSize = expectedUncompressedSizes[streamIndex];
734
- if (uncompressedSize !== expectedUncompressedSize) {
735
- throw new Error(`SPZLoader: stream ${streamIndex} has ${uncompressedSize} uncompressed bytes, expected ${expectedUncompressedSize}.`);
736
- }
737
- if (compressedOffset + compressedSize > data.byteLength) {
738
- throw new Error(`SPZLoader: stream ${streamIndex} exceeds file byte length.`);
739
- }
740
- streamInfos.push({ compressedSize, uncompressedSize, compressedOffset });
741
- compressedOffset += compressedSize;
742
- }
743
- if (compressedOffset !== data.byteLength) {
744
- throw new Error("SPZLoader: compressed stream byte lengths do not match file byte length.");
745
- }
746
- return streamInfos;
747
- }
748
- function readSafeUint64(dataView, byteOffset) {
749
- const value = dataView.getBigUint64(byteOffset, true);
750
- if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
751
- throw new Error("SPZLoader: stream byte length exceeds Number.MAX_SAFE_INTEGER.");
752
- }
753
- return Number(value);
754
- }
755
- function getSPZStreamByteLengths(header) {
756
- return [
757
- header.numPoints * 9,
758
- header.numPoints,
759
- header.numPoints * 3,
760
- header.numPoints * 3,
761
- header.numPoints * 4,
762
- header.numPoints * getSphericalHarmonicsComponentCount2(header.shDegree)
763
- ].filter((byteLength) => byteLength > 0);
2518
+ // dist/lib/parse-ksplat.js
2519
+ function parseKSPLAT(data) {
2520
+ return makeGaussianSplatsArrowTable(parseKSPLATToGaussianSplats(data));
764
2521
  }
765
- function validateSPZStreamLengths(streams, streamInfos) {
766
- for (let streamIndex = 0; streamIndex < streams.length; streamIndex++) {
767
- if (streams[streamIndex].byteLength !== streamInfos[streamIndex].uncompressedSize) {
768
- throw new Error(`SPZLoader: decompressed stream ${streamIndex} has unexpected byte length.`);
769
- }
2522
+ function parseKSPLATToGaussianSplats(data) {
2523
+ if (data.byteLength < HEADER_BYTE_LENGTH) {
2524
+ throw new Error(`KSPLATLoader: file must contain a ${HEADER_BYTE_LENGTH}-byte header.`);
770
2525
  }
771
- }
772
- function decodeSPZStreams(header, streams, sourceData) {
773
- const splatCount = header.numPoints;
2526
+ const header = parseKSPLATHeader(data);
2527
+ checkKSPLATVersion(header);
2528
+ const sections = parseKSPLATSections(data, header);
2529
+ const splatCount = getTotalSplatCount(header, sections);
2530
+ const sphericalHarmonicsComponentCount = Math.max(0, ...sections.slice(0, getActiveSectionCount(header)).map((section) => getSphericalHarmonicsComponentCount2(section.sphericalHarmonicsDegree)));
774
2531
  const positions = new Float32Array(splatCount * 3);
775
2532
  const scales = new Float32Array(splatCount * 3);
776
2533
  const rotations = new Float32Array(splatCount * 4);
777
2534
  const colors = new Uint8Array(splatCount * 3);
778
- const sphericalHarmonicDcs = new Float32Array(splatCount * 3);
779
2535
  const opacities = new Float32Array(splatCount);
780
- const sphericalHarmonicsComponentCount = getSphericalHarmonicsComponentCount2(header.shDegree);
781
2536
  const sphericalHarmonics = sphericalHarmonicsComponentCount ? new Float32Array(splatCount * sphericalHarmonicsComponentCount) : void 0;
782
- const [positionStream, alphaStream, colorStream, scaleStream, rotationStream, sphericalHarmonicsStream] = streams.map((stream) => new Uint8Array(stream));
783
- decodeSPZPositions(positionStream, positions, header.fractionalBits);
784
- decodeSPZScales(scaleStream, scales);
785
- decodeSPZRotations(rotationStream, rotations);
786
- decodeSPZColors(colorStream, colors, sphericalHarmonicDcs);
787
- decodeSPZOpacities(alphaStream, opacities);
788
- if (sphericalHarmonics && sphericalHarmonicsStream) {
789
- decodeSPZSphericalHarmonics(sphericalHarmonicsStream, sphericalHarmonics);
2537
+ let outputSplatIndex = 0;
2538
+ for (const section of sections.slice(0, getActiveSectionCount(header))) {
2539
+ validateSectionBounds(data, section);
2540
+ for (let localSplatIndex = 0; localSplatIndex < section.splatCount && outputSplatIndex < splatCount; localSplatIndex++) {
2541
+ decodeKSPLATSplat(data, header, section, localSplatIndex, outputSplatIndex, positions, scales, rotations, colors, opacities, sphericalHarmonics, sphericalHarmonicsComponentCount);
2542
+ outputSplatIndex++;
2543
+ }
790
2544
  }
791
2545
  return {
792
- format: "spz",
2546
+ format: "ksplat",
793
2547
  splatCount,
794
2548
  positions,
795
2549
  scales,
796
2550
  rotations,
797
2551
  colors,
798
- sphericalHarmonicDcs,
799
2552
  opacities,
800
2553
  sphericalHarmonics,
801
2554
  sphericalHarmonicsComponentCount,
802
2555
  loaderData: {
803
- format: "spz",
2556
+ format: "ksplat",
804
2557
  ...header,
805
- antialiased: Boolean(header.flags & 1),
806
- extensionByteLength: getSPZExtensionByteLength(header),
807
- extensionBytes: getSPZExtensionBytes(sourceData, header)
2558
+ sections: sections.slice(0, getActiveSectionCount(header)).map((section) => ({
2559
+ splatCount: section.splatCount,
2560
+ maxSplatCount: section.maxSplatCount,
2561
+ sphericalHarmonicsDegree: section.sphericalHarmonicsDegree
2562
+ }))
808
2563
  }
809
2564
  };
810
2565
  }
811
- function decodeSPZPositions(positionStream, positions, fractionalBits) {
812
- const scale = 1 / 2 ** fractionalBits;
813
- for (let componentIndex = 0; componentIndex < positions.length; componentIndex++) {
814
- const byteOffset = componentIndex * 3;
815
- let fixed32 = positionStream[byteOffset] | positionStream[byteOffset + 1] << 8 | positionStream[byteOffset + 2] << 16;
816
- fixed32 |= fixed32 & 8388608 ? 4278190080 : 0;
817
- positions[componentIndex] = fixed32 * scale;
2566
+ function decodeKSPLATSplat(data, header, section, localSplatIndex, outputSplatIndex, positions, scales, rotations, colors, opacities, sphericalHarmonics, sphericalHarmonicsComponentCount) {
2567
+ const layout = COMPRESSION_LAYOUTS[header.compressionLevel];
2568
+ const splatBase = section.dataBase + section.bytesPerSplat * localSplatIndex;
2569
+ const positionOffset = outputSplatIndex * 3;
2570
+ const rotationOffset = outputSplatIndex * 4;
2571
+ const bucketCenter = getBucketCenter(data, section, localSplatIndex);
2572
+ positions[positionOffset + 0] = decodeKSPLATCenterComponent(data, splatBase, 0, header, section, bucketCenter[0]);
2573
+ positions[positionOffset + 1] = decodeKSPLATCenterComponent(data, splatBase, 1, header, section, bucketCenter[1]);
2574
+ positions[positionOffset + 2] = decodeKSPLATCenterComponent(data, splatBase, 2, header, section, bucketCenter[2]);
2575
+ scales[positionOffset + 0] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 0, header.compressionLevel);
2576
+ scales[positionOffset + 1] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 1, header.compressionLevel);
2577
+ scales[positionOffset + 2] = readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 2, header.compressionLevel);
2578
+ const [w, x, y, z2] = normalizeQuaternion(readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 3, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 4, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 5, header.compressionLevel), readCompressedFloat(data, splatBase + layout.scaleOffsetBytes, 6, header.compressionLevel));
2579
+ rotations[rotationOffset + 0] = w;
2580
+ rotations[rotationOffset + 1] = x;
2581
+ rotations[rotationOffset + 2] = y;
2582
+ rotations[rotationOffset + 3] = z2;
2583
+ const colorBase = splatBase + layout.colorOffsetBytes;
2584
+ const colorView = new Uint8Array(data, colorBase, 4);
2585
+ colors[positionOffset + 0] = colorView[0];
2586
+ colors[positionOffset + 1] = colorView[1];
2587
+ colors[positionOffset + 2] = colorView[2];
2588
+ opacities[outputSplatIndex] = convertAlphaByteToLinearOpacity(colorView[3]);
2589
+ if (sphericalHarmonics && sphericalHarmonicsComponentCount) {
2590
+ decodeSphericalHarmonics(data, splatBase + layout.sphericalHarmonicsOffsetBytes, header, section, outputSplatIndex, sphericalHarmonics, sphericalHarmonicsComponentCount);
818
2591
  }
819
2592
  }
820
- function decodeSPZScales(scaleStream, scales) {
821
- for (let componentIndex = 0; componentIndex < scales.length; componentIndex++) {
822
- scales[componentIndex] = Math.exp(scaleStream[componentIndex] / 16 - 10);
2593
+ function parseKSPLATHeader(data) {
2594
+ const dataView = new DataView(data, 0, HEADER_BYTE_LENGTH);
2595
+ const compressionLevel = dataView.getUint16(20, true);
2596
+ if (compressionLevel !== 0 && compressionLevel !== 1 && compressionLevel !== 2) {
2597
+ throw new Error(`KSPLATLoader: unsupported compression level ${compressionLevel}.`);
2598
+ }
2599
+ return {
2600
+ versionMajor: dataView.getUint8(0),
2601
+ versionMinor: dataView.getUint8(1),
2602
+ maxSectionCount: dataView.getUint32(4, true),
2603
+ sectionCount: dataView.getUint32(8, true),
2604
+ maxSplatCount: dataView.getUint32(12, true),
2605
+ splatCount: dataView.getUint32(16, true),
2606
+ compressionLevel,
2607
+ minSphericalHarmonicsCoeff: dataView.getFloat32(36, true) || -DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE,
2608
+ maxSphericalHarmonicsCoeff: dataView.getFloat32(40, true) || DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE
2609
+ };
2610
+ }
2611
+ function checkKSPLATVersion(header) {
2612
+ if (header.versionMajor === CURRENT_MAJOR_VERSION ? header.versionMinor >= CURRENT_MINOR_VERSION : header.versionMajor > CURRENT_MAJOR_VERSION) {
2613
+ return;
2614
+ }
2615
+ throw new Error(`KSPLATLoader: version ${header.versionMajor}.${header.versionMinor} is not supported.`);
2616
+ }
2617
+ function parseKSPLATSections(data, header) {
2618
+ if (data.byteLength < HEADER_BYTE_LENGTH + header.maxSectionCount * SECTION_HEADER_BYTE_LENGTH) {
2619
+ throw new Error("KSPLATLoader: file does not contain all section headers.");
2620
+ }
2621
+ const sections = [];
2622
+ let sectionBase = HEADER_BYTE_LENGTH + header.maxSectionCount * SECTION_HEADER_BYTE_LENGTH;
2623
+ let splatCountOffset = 0;
2624
+ for (let sectionIndex = 0; sectionIndex < header.maxSectionCount; sectionIndex++) {
2625
+ const sectionHeaderBase = HEADER_BYTE_LENGTH + sectionIndex * SECTION_HEADER_BYTE_LENGTH;
2626
+ const dataView = new DataView(data, sectionHeaderBase, SECTION_HEADER_BYTE_LENGTH);
2627
+ const splatCount = dataView.getUint32(0, true);
2628
+ const maxSplatCount = dataView.getUint32(4, true);
2629
+ const bucketSize = dataView.getUint32(8, true);
2630
+ const bucketCount = dataView.getUint32(12, true);
2631
+ const bucketBlockSize = dataView.getFloat32(16, true);
2632
+ const bucketStorageSizeBytes = dataView.getUint16(20, true);
2633
+ const compressionScaleRange = dataView.getUint32(24, true) || COMPRESSION_LAYOUTS[header.compressionLevel].scaleRange;
2634
+ const fullBucketCount = dataView.getUint32(32, true);
2635
+ const partiallyFilledBucketCount = dataView.getUint32(36, true);
2636
+ const sphericalHarmonicsDegree = dataView.getUint16(40, true);
2637
+ const bytesPerSplat = getBytesPerSplat(header.compressionLevel, sphericalHarmonicsDegree);
2638
+ const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;
2639
+ const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;
2640
+ const storageSizeBytes = bytesPerSplat * maxSplatCount + bucketsStorageSizeBytes;
2641
+ sections.push({
2642
+ bytesPerSplat,
2643
+ splatCountOffset,
2644
+ splatCount: splatCount || maxSplatCount,
2645
+ maxSplatCount,
2646
+ bucketSize,
2647
+ bucketCount,
2648
+ bucketStorageSizeBytes,
2649
+ bucketsStorageSizeBytes,
2650
+ compressionScaleRange,
2651
+ compressionScaleFactor: bucketBlockSize / 2 / compressionScaleRange,
2652
+ base: sectionBase,
2653
+ bucketsBase: sectionBase + bucketsMetaDataSizeBytes,
2654
+ dataBase: sectionBase + bucketsStorageSizeBytes,
2655
+ fullBucketCount,
2656
+ partiallyFilledBucketCount,
2657
+ sphericalHarmonicsDegree
2658
+ });
2659
+ sectionBase += storageSizeBytes;
2660
+ splatCountOffset += maxSplatCount;
823
2661
  }
2662
+ return sections;
2663
+ }
2664
+ function decodeKSPLATCenterComponent(data, splatBase, component, header, section, bucketCenter) {
2665
+ const value = readCompressedCenterValue(data, splatBase, component, header.compressionLevel);
2666
+ return header.compressionLevel >= 1 ? (value - section.compressionScaleRange) * section.compressionScaleFactor + bucketCenter : value;
2667
+ }
2668
+ function readCompressedCenterValue(data, byteOffset, component, compressionLevel) {
2669
+ const dataView = new DataView(data);
2670
+ return compressionLevel === 0 ? dataView.getFloat32(byteOffset + component * 4, true) : dataView.getUint16(byteOffset + component * 2, true);
824
2671
  }
825
- function decodeSPZRotations(rotationStream, rotations) {
826
- for (let splatIndex = 0; splatIndex < rotations.length / 4; splatIndex++) {
827
- const byteOffset = splatIndex * 4;
828
- const component = rotationStream[byteOffset] | rotationStream[byteOffset + 1] << 8 | rotationStream[byteOffset + 2] << 16 | rotationStream[byteOffset + 3] << 24;
829
- const xyzw = decodeSPZQuaternion(component >>> 0);
830
- const [w, x, y, z] = normalizeQuaternion(xyzw[3], xyzw[0], xyzw[1], xyzw[2]);
831
- const rotationOffset = splatIndex * 4;
832
- rotations[rotationOffset + 0] = w;
833
- rotations[rotationOffset + 1] = x;
834
- rotations[rotationOffset + 2] = y;
835
- rotations[rotationOffset + 3] = z;
2672
+ function getBucketCenter(data, section, localSplatIndex) {
2673
+ if (!section.bucketCount) {
2674
+ return [0, 0, 0];
836
2675
  }
2676
+ const bucketIndex = getBucketIndex(data, section, localSplatIndex);
2677
+ const bucketBase = section.bucketsBase + bucketIndex * section.bucketStorageSizeBytes;
2678
+ const dataView = new DataView(data, bucketBase, 12);
2679
+ return [dataView.getFloat32(0, true), dataView.getFloat32(4, true), dataView.getFloat32(8, true)];
837
2680
  }
838
- function decodeSPZQuaternion(component) {
839
- const rotation = [0, 0, 0, 0];
840
- const largestComponent = component >>> 30;
841
- let remainingBits = component;
842
- let sumSquares = 0;
843
- for (let componentIndex = 3; componentIndex >= 0; componentIndex--) {
844
- if (componentIndex !== largestComponent) {
845
- const magnitude = remainingBits & SPZ_ROTATION_COMPONENT_MASK;
846
- const isNegative = remainingBits >>> 9 & 1;
847
- remainingBits >>>= 10;
848
- let value = SPZ_ROTATION_COMPONENT_SCALE * magnitude / SPZ_ROTATION_COMPONENT_MASK;
849
- if (isNegative) {
850
- value = -value;
851
- }
852
- rotation[componentIndex] = value;
853
- sumSquares += value * value;
2681
+ function getBucketIndex(data, section, localSplatIndex) {
2682
+ const maxSplatIndexInFullBuckets = section.fullBucketCount * section.bucketSize;
2683
+ if (localSplatIndex < maxSplatIndexInFullBuckets) {
2684
+ return Math.floor(localSplatIndex / section.bucketSize);
2685
+ }
2686
+ let bucketSplatIndex = maxSplatIndexInFullBuckets;
2687
+ let bucketIndex = section.fullBucketCount;
2688
+ for (let partiallyFilledBucketIndex = 0; partiallyFilledBucketIndex < section.partiallyFilledBucketCount; partiallyFilledBucketIndex++) {
2689
+ const bucketLength = new DataView(data, section.base + partiallyFilledBucketIndex * 4, 4).getUint32(0, true);
2690
+ if (localSplatIndex < bucketSplatIndex + bucketLength) {
2691
+ return bucketIndex;
854
2692
  }
2693
+ bucketSplatIndex += bucketLength;
2694
+ bucketIndex++;
855
2695
  }
856
- rotation[largestComponent] = Math.sqrt(Math.max(0, 1 - sumSquares));
857
- return rotation;
2696
+ return Math.max(bucketIndex - 1, 0);
858
2697
  }
859
- function decodeSPZColors(colorStream, colors, sphericalHarmonicDcs) {
860
- for (let componentIndex = 0; componentIndex < colors.length; componentIndex++) {
861
- sphericalHarmonicDcs[componentIndex] = (colorStream[componentIndex] / 255 - 0.5) / SPZ_COLOR_SCALE;
862
- colors[componentIndex] = normalizeColorByte(sphericalHarmonicDcs[componentIndex]);
2698
+ function decodeSphericalHarmonics(data, byteOffset, header, section, outputSplatIndex, output, outputComponentCount) {
2699
+ const componentCount = getSphericalHarmonicsComponentCount2(section.sphericalHarmonicsDegree);
2700
+ const componentBase = outputSplatIndex * outputComponentCount;
2701
+ for (let component = 0; component < componentCount; component++) {
2702
+ output[componentBase + component] = readCompressedFloat(data, byteOffset, component, header.compressionLevel, true, header.minSphericalHarmonicsCoeff, header.maxSphericalHarmonicsCoeff);
863
2703
  }
864
2704
  }
865
- function decodeSPZOpacities(alphaStream, opacities) {
866
- for (let splatIndex = 0; splatIndex < opacities.length; splatIndex++) {
867
- opacities[splatIndex] = alphaStream[splatIndex] / 255;
2705
+ function readCompressedFloat(data, byteOffset, component, compressionLevel, sphericalHarmonic = false, sphericalHarmonicRangeMin = 0, sphericalHarmonicRangeMax = 0) {
2706
+ const dataView = new DataView(data);
2707
+ if (compressionLevel === 0) {
2708
+ return dataView.getFloat32(byteOffset + component * 4, true);
868
2709
  }
869
- }
870
- function decodeSPZSphericalHarmonics(sphericalHarmonicsStream, sphericalHarmonics) {
871
- for (let componentIndex = 0; componentIndex < sphericalHarmonics.length; componentIndex++) {
872
- sphericalHarmonics[componentIndex] = (sphericalHarmonicsStream[componentIndex] - 128) / 128;
2710
+ if (compressionLevel === 1 || !sphericalHarmonic) {
2711
+ return decodeFloat16(dataView.getUint16(byteOffset + component * 2, true));
873
2712
  }
2713
+ const value = dataView.getUint8(byteOffset + component);
2714
+ return value / 255 * (sphericalHarmonicRangeMax - sphericalHarmonicRangeMin) + sphericalHarmonicRangeMin;
874
2715
  }
875
- function normalizeColorByte(sphericalHarmonicDc) {
876
- return Math.min(Math.max(Math.round((sphericalHarmonicDc * SPZ_COLOR_SCALE + 0.5) * 255), 0), 255);
2716
+ function getBytesPerSplat(compressionLevel, sphericalHarmonicsDegree) {
2717
+ const layout = COMPRESSION_LAYOUTS[compressionLevel];
2718
+ return layout.bytesPerCenter + layout.bytesPerScale + layout.bytesPerRotation + layout.bytesPerColor + layout.bytesPerSphericalHarmonicsComponent * getSphericalHarmonicsComponentCount2(sphericalHarmonicsDegree);
877
2719
  }
878
- function getSphericalHarmonicsComponentCount2(shDegree) {
879
- switch (shDegree) {
2720
+ function getSphericalHarmonicsComponentCount2(sphericalHarmonicsDegree) {
2721
+ switch (sphericalHarmonicsDegree) {
880
2722
  case 0:
881
2723
  return 0;
882
2724
  case 1:
@@ -885,33 +2727,116 @@ function getSphericalHarmonicsComponentCount2(shDegree) {
885
2727
  return 24;
886
2728
  case 3:
887
2729
  return 45;
888
- case 4:
889
- return 72;
890
2730
  default:
891
- throw new Error(`SPZLoader: spherical harmonics degree ${shDegree} is not supported.`);
2731
+ throw new Error(`KSPLATLoader: unsupported spherical harmonics degree ${sphericalHarmonicsDegree}.`);
892
2732
  }
893
2733
  }
894
- function getSPZExtensionByteLength(header) {
895
- return header.flags & SPZ_EXTENSION_FLAG ? header.tocByteOffset - SPZ_HEADER_BYTE_LENGTH : 0;
2734
+ function getActiveSectionCount(header) {
2735
+ return header.sectionCount || header.maxSectionCount;
896
2736
  }
897
- function getSPZExtensionBytes(data, header) {
898
- const extensionByteLength = getSPZExtensionByteLength(header);
899
- return extensionByteLength ? new Uint8Array(data.slice(SPZ_HEADER_BYTE_LENGTH, header.tocByteOffset)) : void 0;
2737
+ function getTotalSplatCount(header, sections) {
2738
+ const sectionSplatCount = sections.slice(0, getActiveSectionCount(header)).reduce((splatCount, section) => splatCount + section.splatCount, 0);
2739
+ return header.splatCount ? Math.min(header.splatCount, sectionSplatCount || header.splatCount) : sectionSplatCount;
900
2740
  }
901
- var import_compression, SPZ_HEADER_BYTE_LENGTH, SPZ_MAGIC, SPZ_VERSION, SPZ_EXTENSION_FLAG, SPZ_COLOR_SCALE, SPZ_ROTATION_COMPONENT_SCALE, SPZ_ROTATION_COMPONENT_MASK;
902
- var init_parse_spz = __esm({
903
- "dist/lib/parse-spz.js"() {
2741
+ function validateSectionBounds(data, section) {
2742
+ const requiredByteLength = section.dataBase + section.bytesPerSplat * section.splatCount;
2743
+ if (requiredByteLength > data.byteLength) {
2744
+ throw new Error("KSPLATLoader: section data extends beyond the file length.");
2745
+ }
2746
+ }
2747
+ var CURRENT_MAJOR_VERSION, CURRENT_MINOR_VERSION, HEADER_BYTE_LENGTH, SECTION_HEADER_BYTE_LENGTH, DEFAULT_SH_8BIT_COMPRESSION_RANGE, DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE, COMPRESSION_LAYOUTS;
2748
+ var init_parse_ksplat = __esm({
2749
+ "dist/lib/parse-ksplat.js"() {
904
2750
  "use strict";
905
- import_compression = require("@loaders.gl/compression");
906
2751
  init_splats_arrow_table();
907
2752
  init_splat_utils();
908
- SPZ_HEADER_BYTE_LENGTH = 32;
909
- SPZ_MAGIC = 1347635022;
910
- SPZ_VERSION = 4;
911
- SPZ_EXTENSION_FLAG = 2;
912
- SPZ_COLOR_SCALE = 0.15;
913
- SPZ_ROTATION_COMPONENT_SCALE = Math.SQRT1_2;
914
- SPZ_ROTATION_COMPONENT_MASK = (1 << 9) - 1;
2753
+ CURRENT_MAJOR_VERSION = 0;
2754
+ CURRENT_MINOR_VERSION = 1;
2755
+ HEADER_BYTE_LENGTH = 4096;
2756
+ SECTION_HEADER_BYTE_LENGTH = 1024;
2757
+ DEFAULT_SH_8BIT_COMPRESSION_RANGE = 3;
2758
+ DEFAULT_SH_8BIT_COMPRESSION_HALF_RANGE = DEFAULT_SH_8BIT_COMPRESSION_RANGE / 2;
2759
+ COMPRESSION_LAYOUTS = {
2760
+ 0: {
2761
+ bytesPerCenter: 12,
2762
+ bytesPerScale: 12,
2763
+ bytesPerRotation: 16,
2764
+ bytesPerColor: 4,
2765
+ scaleOffsetBytes: 12,
2766
+ colorOffsetBytes: 40,
2767
+ sphericalHarmonicsOffsetBytes: 44,
2768
+ scaleRange: 1,
2769
+ bytesPerSphericalHarmonicsComponent: 4
2770
+ },
2771
+ 1: {
2772
+ bytesPerCenter: 6,
2773
+ bytesPerScale: 6,
2774
+ bytesPerRotation: 8,
2775
+ bytesPerColor: 4,
2776
+ scaleOffsetBytes: 6,
2777
+ colorOffsetBytes: 20,
2778
+ sphericalHarmonicsOffsetBytes: 24,
2779
+ scaleRange: 32767,
2780
+ bytesPerSphericalHarmonicsComponent: 2
2781
+ },
2782
+ 2: {
2783
+ bytesPerCenter: 6,
2784
+ bytesPerScale: 6,
2785
+ bytesPerRotation: 8,
2786
+ bytesPerColor: 4,
2787
+ scaleOffsetBytes: 6,
2788
+ colorOffsetBytes: 20,
2789
+ sphericalHarmonicsOffsetBytes: 24,
2790
+ scaleRange: 32767,
2791
+ bytesPerSphericalHarmonicsComponent: 1
2792
+ }
2793
+ };
2794
+ }
2795
+ });
2796
+
2797
+ // dist/ksplat-loader.js
2798
+ var ksplat_loader_exports = {};
2799
+ __export(ksplat_loader_exports, {
2800
+ KSPLATLoaderWithParser: () => KSPLATLoaderWithParser
2801
+ });
2802
+ var _KSPLATLoaderPreload, KSPLATLoaderMetadataWithoutPreload, KSPLATLoaderWithParser;
2803
+ var init_ksplat_loader = __esm({
2804
+ "dist/ksplat-loader.js"() {
2805
+ "use strict";
2806
+ init_parse_ksplat();
2807
+ init_ksplat_loader_types();
2808
+ ({ preload: _KSPLATLoaderPreload, ...KSPLATLoaderMetadataWithoutPreload } = KSPLATLoader);
2809
+ KSPLATLoaderWithParser = {
2810
+ ...KSPLATLoaderMetadataWithoutPreload,
2811
+ parse: async (arrayBuffer) => parseKSPLAT(arrayBuffer),
2812
+ parseSync: (arrayBuffer) => parseKSPLAT(arrayBuffer)
2813
+ };
2814
+ }
2815
+ });
2816
+
2817
+ // dist/ksplat-loader-types.js
2818
+ async function preload2() {
2819
+ const { KSPLATLoaderWithParser: KSPLATLoaderWithParser2 } = await Promise.resolve().then(() => (init_ksplat_loader(), ksplat_loader_exports));
2820
+ return KSPLATLoaderWithParser2;
2821
+ }
2822
+ var VERSION3, KSPLATLoader;
2823
+ var init_ksplat_loader_types = __esm({
2824
+ "dist/ksplat-loader-types.js"() {
2825
+ "use strict";
2826
+ init_splats_format();
2827
+ VERSION3 = true ? "5.0.0-alpha.11" : "latest";
2828
+ KSPLATLoader = {
2829
+ dataType: null,
2830
+ batchType: null,
2831
+ ...KSPLATFormat,
2832
+ version: VERSION3,
2833
+ options: {
2834
+ splats: {
2835
+ shape: "arrow-table"
2836
+ }
2837
+ },
2838
+ preload: preload2
2839
+ };
915
2840
  }
916
2841
  });
917
2842
 
@@ -939,17 +2864,17 @@ async function preload3() {
939
2864
  const { SPZLoaderWithParser: SPZLoaderWithParser2 } = await Promise.resolve().then(() => (init_spz_loader(), spz_loader_exports));
940
2865
  return SPZLoaderWithParser2;
941
2866
  }
942
- var VERSION3, SPZLoader;
2867
+ var VERSION4, SPZLoader;
943
2868
  var init_spz_loader_types = __esm({
944
2869
  "dist/spz-loader-types.js"() {
945
2870
  "use strict";
946
2871
  init_splats_format();
947
- VERSION3 = true ? "5.0.0-alpha.1" : "latest";
2872
+ VERSION4 = true ? "5.0.0-alpha.11" : "latest";
948
2873
  SPZLoader = {
949
2874
  dataType: null,
950
2875
  batchType: null,
951
2876
  ...SPZFormat,
952
- version: VERSION3,
2877
+ version: VERSION4,
953
2878
  options: {
954
2879
  splats: {
955
2880
  shape: "arrow-table"
@@ -960,6 +2885,65 @@ var init_spz_loader_types = __esm({
960
2885
  }
961
2886
  });
962
2887
 
2888
+ // dist/rad-zod-schema.js
2889
+ var import_zod, nonNegativeSafeIntegerSchema, RADSplatEncodingSchema, RADChunkRangeSchema, RADMetadataJSONSchema, RADChunkPropertySchema, RADChunkMetadataJSONSchema;
2890
+ var init_rad_zod_schema = __esm({
2891
+ "dist/rad-zod-schema.js"() {
2892
+ "use strict";
2893
+ import_zod = require("zod");
2894
+ nonNegativeSafeIntegerSchema = import_zod.z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
2895
+ RADSplatEncodingSchema = import_zod.z.object({
2896
+ rgbMin: import_zod.z.number().finite().optional(),
2897
+ rgbMax: import_zod.z.number().finite().optional(),
2898
+ lnScaleMin: import_zod.z.number().finite().optional(),
2899
+ lnScaleMax: import_zod.z.number().finite().optional(),
2900
+ sh1Max: import_zod.z.number().finite().optional(),
2901
+ sh2Max: import_zod.z.number().finite().optional(),
2902
+ sh3Max: import_zod.z.number().finite().optional(),
2903
+ lodOpacity: import_zod.z.boolean().optional()
2904
+ }).passthrough();
2905
+ RADChunkRangeSchema = import_zod.z.object({
2906
+ offset: nonNegativeSafeIntegerSchema,
2907
+ bytes: nonNegativeSafeIntegerSchema,
2908
+ base: nonNegativeSafeIntegerSchema.optional(),
2909
+ count: nonNegativeSafeIntegerSchema.optional(),
2910
+ filename: import_zod.z.string().optional()
2911
+ }).passthrough();
2912
+ RADMetadataJSONSchema = import_zod.z.object({
2913
+ version: import_zod.z.literal(1),
2914
+ type: import_zod.z.literal("gsplat"),
2915
+ count: nonNegativeSafeIntegerSchema,
2916
+ maxSh: nonNegativeSafeIntegerSchema.optional(),
2917
+ lodTree: import_zod.z.boolean().optional(),
2918
+ chunkSize: nonNegativeSafeIntegerSchema.optional(),
2919
+ allChunkBytes: nonNegativeSafeIntegerSchema.optional(),
2920
+ chunks: import_zod.z.array(RADChunkRangeSchema),
2921
+ splatEncoding: RADSplatEncodingSchema.optional(),
2922
+ shCodeCount: nonNegativeSafeIntegerSchema.optional(),
2923
+ comment: import_zod.z.string().optional()
2924
+ }).passthrough();
2925
+ RADChunkPropertySchema = import_zod.z.object({
2926
+ offset: nonNegativeSafeIntegerSchema,
2927
+ bytes: nonNegativeSafeIntegerSchema,
2928
+ property: import_zod.z.string(),
2929
+ encoding: import_zod.z.string(),
2930
+ compression: import_zod.z.string().optional(),
2931
+ min: import_zod.z.number().finite().optional(),
2932
+ max: import_zod.z.number().finite().optional()
2933
+ }).passthrough();
2934
+ RADChunkMetadataJSONSchema = import_zod.z.object({
2935
+ version: import_zod.z.literal(1),
2936
+ base: nonNegativeSafeIntegerSchema,
2937
+ count: nonNegativeSafeIntegerSchema,
2938
+ payloadBytes: nonNegativeSafeIntegerSchema,
2939
+ maxSh: nonNegativeSafeIntegerSchema.optional(),
2940
+ lodTree: import_zod.z.boolean().optional(),
2941
+ splatEncoding: RADSplatEncodingSchema.optional(),
2942
+ properties: import_zod.z.array(RADChunkPropertySchema)
2943
+ }).passthrough();
2944
+ }
2945
+ });
2946
+
963
2947
  // dist/lib/parse-rad.js
964
2948
  function parseRADHeader(data) {
965
2949
  const metadata = tryParseRADHeader(data);
@@ -983,7 +2967,7 @@ function tryParseRADHeader(data) {
983
2967
  if (bytes.byteLength < headerJsonEnd) {
984
2968
  return null;
985
2969
  }
986
- const rawMetadata = parseJSONRecord(bytes.subarray(RAD_HEADER_BYTE_LENGTH, headerJsonEnd), "RADLoader: failed to parse RAD metadata JSON.");
2970
+ const rawMetadata = RADMetadataJSONSchema.parse(parseJSON(bytes.subarray(RAD_HEADER_BYTE_LENGTH, headerJsonEnd), "RADLoader: failed to parse RAD metadata JSON."));
987
2971
  return normalizeRADMetadata(rawMetadata, headerJsonByteLength);
988
2972
  }
989
2973
  function parseRADChunkHeader(data) {
@@ -1003,7 +2987,7 @@ function parseRADChunkHeader(data) {
1003
2987
  if (bytes.byteLength < payloadByteOffset) {
1004
2988
  throw new Error("RADLoader: RADC chunk must contain a complete metadata header.");
1005
2989
  }
1006
- const rawMetadata = parseJSONRecord(bytes.subarray(RAD_HEADER_BYTE_LENGTH, headerJsonEnd), "RADLoader: failed to parse RADC metadata JSON.");
2990
+ const rawMetadata = RADChunkMetadataJSONSchema.parse(parseJSON(bytes.subarray(RAD_HEADER_BYTE_LENGTH, headerJsonEnd), "RADLoader: failed to parse RADC metadata JSON."));
1007
2991
  const payloadBytes = readSafeUint642(dataView, payloadByteLengthOffset, "RADC payload byte length");
1008
2992
  return normalizeRADChunkMetadata(rawMetadata, headerJsonByteLength, payloadByteOffset, payloadBytes);
1009
2993
  }
@@ -1011,157 +2995,31 @@ function roundUpToEight(byteLength) {
1011
2995
  return byteLength + 7 & ~7;
1012
2996
  }
1013
2997
  function normalizeRADMetadata(rawMetadata, headerJsonByteLength) {
1014
- const version = requireSafeInteger(rawMetadata.version, "RAD version");
1015
- if (version !== 1) {
1016
- throw new Error(`RADLoader: version ${version} is not supported.`);
1017
- }
1018
- const type = requireString(rawMetadata.type, "RAD type");
1019
- if (type !== "gsplat") {
1020
- throw new Error(`RADLoader: RAD type ${type} is not supported.`);
1021
- }
1022
- const chunks = requireArray(rawMetadata.chunks, "RAD chunks").map((chunk, chunkIndex) => normalizeRADChunkRange(chunk, chunkIndex));
1023
- const metadata = {
1024
- version,
1025
- type,
1026
- count: requireSafeInteger(rawMetadata.count, "RAD count"),
1027
- maxSh: optionalSafeInteger(rawMetadata.maxSh, "RAD maxSh"),
1028
- lodTree: optionalBoolean(rawMetadata.lodTree, "RAD lodTree"),
1029
- chunkSize: optionalSafeInteger(rawMetadata.chunkSize, "RAD chunkSize"),
1030
- allChunkBytes: optionalSafeInteger(rawMetadata.allChunkBytes, "RAD allChunkBytes"),
1031
- chunks,
1032
- splatEncoding: optionalSplatEncoding(rawMetadata.splatEncoding, "RAD splatEncoding"),
1033
- shCodeCount: optionalSafeInteger(rawMetadata.shCodeCount, "RAD shCodeCount"),
1034
- comment: optionalString(rawMetadata.comment, "RAD comment"),
2998
+ return {
2999
+ ...rawMetadata,
1035
3000
  headerJsonByteLength,
1036
3001
  chunksByteOffset: RAD_HEADER_BYTE_LENGTH + roundUpToEight(headerJsonByteLength)
1037
3002
  };
1038
- return metadata;
1039
- }
1040
- function normalizeRADChunkRange(rawChunk, chunkIndex) {
1041
- const chunk = requireRecord(rawChunk, `RAD chunk ${chunkIndex}`);
1042
- return {
1043
- offset: requireSafeInteger(chunk.offset, `RAD chunk ${chunkIndex} offset`),
1044
- bytes: requireSafeInteger(chunk.bytes, `RAD chunk ${chunkIndex} bytes`),
1045
- base: optionalSafeInteger(chunk.base, `RAD chunk ${chunkIndex} base`),
1046
- count: optionalSafeInteger(chunk.count, `RAD chunk ${chunkIndex} count`),
1047
- filename: optionalString(chunk.filename, `RAD chunk ${chunkIndex} filename`)
1048
- };
1049
3003
  }
1050
3004
  function normalizeRADChunkMetadata(rawMetadata, headerJsonByteLength, payloadByteOffset, payloadBytes) {
1051
- const version = requireSafeInteger(rawMetadata.version, "RADC version");
1052
- if (version !== 1) {
1053
- throw new Error(`RADLoader: RADC version ${version} is not supported.`);
1054
- }
1055
- const metadataPayloadBytes = requireSafeInteger(rawMetadata.payloadBytes, "RADC payloadBytes");
1056
- if (metadataPayloadBytes !== payloadBytes) {
3005
+ if (rawMetadata.payloadBytes !== payloadBytes) {
1057
3006
  throw new Error("RADLoader: RADC metadata payload byte length does not match binary header.");
1058
3007
  }
1059
3008
  return {
1060
- version,
1061
- base: requireSafeInteger(rawMetadata.base, "RADC base"),
1062
- count: requireSafeInteger(rawMetadata.count, "RADC count"),
3009
+ ...rawMetadata,
1063
3010
  payloadBytes,
1064
- maxSh: optionalSafeInteger(rawMetadata.maxSh, "RADC maxSh"),
1065
- lodTree: optionalBoolean(rawMetadata.lodTree, "RADC lodTree"),
1066
- splatEncoding: optionalSplatEncoding(rawMetadata.splatEncoding, "RADC splatEncoding"),
1067
- properties: requireArray(rawMetadata.properties, "RADC properties").map((property, index) => normalizeRADChunkProperty(property, index)),
1068
3011
  headerJsonByteLength,
1069
3012
  payloadByteOffset,
1070
3013
  chunkByteLength: payloadByteOffset + payloadBytes
1071
3014
  };
1072
3015
  }
1073
- function normalizeRADChunkProperty(rawProperty, propertyIndex) {
1074
- const property = requireRecord(rawProperty, `RADC property ${propertyIndex}`);
1075
- return {
1076
- offset: requireSafeInteger(property.offset, `RADC property ${propertyIndex} offset`),
1077
- bytes: requireSafeInteger(property.bytes, `RADC property ${propertyIndex} bytes`),
1078
- property: requireString(property.property, `RADC property ${propertyIndex} name`),
1079
- encoding: requireString(property.encoding, `RADC property ${propertyIndex} encoding`),
1080
- compression: optionalString(property.compression, `RADC property ${propertyIndex} compression`),
1081
- min: optionalFiniteNumber(property.min, `RADC property ${propertyIndex} min`),
1082
- max: optionalFiniteNumber(property.max, `RADC property ${propertyIndex} max`)
1083
- };
1084
- }
1085
- function optionalSplatEncoding(value, fieldName) {
1086
- if (value === void 0) {
1087
- return void 0;
1088
- }
1089
- const encoding = requireRecord(value, fieldName);
1090
- return {
1091
- rgbMin: optionalFiniteNumber(encoding.rgbMin, `${fieldName}.rgbMin`),
1092
- rgbMax: optionalFiniteNumber(encoding.rgbMax, `${fieldName}.rgbMax`),
1093
- lnScaleMin: optionalFiniteNumber(encoding.lnScaleMin, `${fieldName}.lnScaleMin`),
1094
- lnScaleMax: optionalFiniteNumber(encoding.lnScaleMax, `${fieldName}.lnScaleMax`),
1095
- sh1Max: optionalFiniteNumber(encoding.sh1Max, `${fieldName}.sh1Max`),
1096
- sh2Max: optionalFiniteNumber(encoding.sh2Max, `${fieldName}.sh2Max`),
1097
- sh3Max: optionalFiniteNumber(encoding.sh3Max, `${fieldName}.sh3Max`),
1098
- lodOpacity: optionalBoolean(encoding.lodOpacity, `${fieldName}.lodOpacity`)
1099
- };
1100
- }
1101
- function parseJSONRecord(bytes, message) {
3016
+ function parseJSON(bytes, message) {
1102
3017
  try {
1103
- return requireRecord(JSON.parse(TEXT_DECODER.decode(bytes)), message);
1104
- } catch (error) {
1105
- if (error instanceof Error && error.message.startsWith("RADLoader:")) {
1106
- throw error;
1107
- }
3018
+ return JSON.parse(TEXT_DECODER.decode(bytes));
3019
+ } catch {
1108
3020
  throw new Error(message);
1109
3021
  }
1110
3022
  }
1111
- function requireRecord(value, fieldName) {
1112
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1113
- throw new Error(`RADLoader: ${fieldName} must be an object.`);
1114
- }
1115
- return value;
1116
- }
1117
- function requireArray(value, fieldName) {
1118
- if (!Array.isArray(value)) {
1119
- throw new Error(`RADLoader: ${fieldName} must be an array.`);
1120
- }
1121
- return value;
1122
- }
1123
- function requireString(value, fieldName) {
1124
- if (typeof value !== "string") {
1125
- throw new Error(`RADLoader: ${fieldName} must be a string.`);
1126
- }
1127
- return value;
1128
- }
1129
- function optionalString(value, fieldName) {
1130
- if (value === void 0) {
1131
- return void 0;
1132
- }
1133
- return requireString(value, fieldName);
1134
- }
1135
- function optionalBoolean(value, fieldName) {
1136
- if (value === void 0) {
1137
- return void 0;
1138
- }
1139
- if (typeof value !== "boolean") {
1140
- throw new Error(`RADLoader: ${fieldName} must be a boolean.`);
1141
- }
1142
- return value;
1143
- }
1144
- function requireSafeInteger(value, fieldName) {
1145
- if (!Number.isSafeInteger(value) || Number(value) < 0) {
1146
- throw new Error(`RADLoader: ${fieldName} must be a non-negative safe integer.`);
1147
- }
1148
- return Number(value);
1149
- }
1150
- function optionalSafeInteger(value, fieldName) {
1151
- if (value === void 0) {
1152
- return void 0;
1153
- }
1154
- return requireSafeInteger(value, fieldName);
1155
- }
1156
- function optionalFiniteNumber(value, fieldName) {
1157
- if (value === void 0) {
1158
- return void 0;
1159
- }
1160
- if (typeof value !== "number" || !Number.isFinite(value)) {
1161
- throw new Error(`RADLoader: ${fieldName} must be a finite number.`);
1162
- }
1163
- return value;
1164
- }
1165
3023
  function readSafeUint642(dataView, byteOffset, fieldName) {
1166
3024
  const value = dataView.getBigUint64(byteOffset, true);
1167
3025
  if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
@@ -1176,6 +3034,7 @@ var RAD_MAGIC, RAD_CHUNK_MAGIC, RAD_HEADER_BYTE_LENGTH, RAD_CHUNK_PAYLOAD_LENGTH
1176
3034
  var init_parse_rad = __esm({
1177
3035
  "dist/lib/parse-rad.js"() {
1178
3036
  "use strict";
3037
+ init_rad_zod_schema();
1179
3038
  RAD_MAGIC = 809779538;
1180
3039
  RAD_CHUNK_MAGIC = 1128546642;
1181
3040
  RAD_HEADER_BYTE_LENGTH = 8;
@@ -1184,6 +3043,75 @@ var init_parse_rad = __esm({
1184
3043
  }
1185
3044
  });
1186
3045
 
3046
+ // ../compression/src/deflate-decompressor-fflate.ts
3047
+ var DeflateFflateDecompressor;
3048
+ var init_deflate_decompressor_fflate = __esm({
3049
+ "../compression/src/deflate-decompressor-fflate.ts"() {
3050
+ "use strict";
3051
+ init_fflate();
3052
+ init_compression();
3053
+ init_fflate_stream();
3054
+ DeflateFflateDecompressor = class extends Decompressor {
3055
+ name = "deflate";
3056
+ extensions = [];
3057
+ contentEncodings = ["deflate"];
3058
+ isSupported = true;
3059
+ options;
3060
+ constructor(options = {}) {
3061
+ super(options);
3062
+ this.options = options;
3063
+ }
3064
+ /** Decompresses one zlib-wrapped DEFLATE payload synchronously. */
3065
+ decompressSync(input) {
3066
+ const bytes = new Uint8Array(input);
3067
+ const output = this.options.raw ? inflateSync(bytes) : unzlibSync(bytes);
3068
+ return output.slice().buffer;
3069
+ }
3070
+ /** Decompresses DEFLATE batches incrementally. */
3071
+ async *decompressBatches(inputBatches) {
3072
+ const processor = this.options.raw ? new Inflate() : new Unzlib();
3073
+ yield* transformFflateBatches(processor, inputBatches);
3074
+ }
3075
+ };
3076
+ }
3077
+ });
3078
+
3079
+ // ../compression/src/deflate-decompressor.ts
3080
+ var DeflateDecompressor2;
3081
+ var init_deflate_decompressor = __esm({
3082
+ "../compression/src/deflate-decompressor.ts"() {
3083
+ "use strict";
3084
+ init_deflate_decompressor_fflate();
3085
+ init_decompression_stream();
3086
+ DeflateDecompressor2 = class extends DeflateFflateDecompressor {
3087
+ constructor(options = {}) {
3088
+ super(options);
3089
+ }
3090
+ /** Decompresses with the built-in stream when available, then falls back to fflate. */
3091
+ async decompress(input) {
3092
+ if (this.options.useNative !== false) {
3093
+ const format = this.options.raw ? "deflate-raw" : "deflate";
3094
+ const output = await decompressWithNativeDecompressionStream(input, format);
3095
+ if (output) return output;
3096
+ }
3097
+ return this.decompressSync(input);
3098
+ }
3099
+ /** Decompresses batches with a built-in or fflate stream. */
3100
+ async *decompressBatches(inputBatches) {
3101
+ if (this.options.useNative !== false) {
3102
+ const format = this.options.raw ? "deflate-raw" : "deflate";
3103
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, format);
3104
+ if (output) {
3105
+ yield* output;
3106
+ return;
3107
+ }
3108
+ }
3109
+ yield* super.decompressBatches(inputBatches);
3110
+ }
3111
+ };
3112
+ }
3113
+ });
3114
+
1187
3115
  // dist/lib/parse-rad-chunk.js
1188
3116
  function parseRADChunk(data, options) {
1189
3117
  return makeGaussianSplatsArrowTable(parseRADChunkToGaussianSplats(data, options));
@@ -1281,9 +3209,9 @@ function decodeRADRotations(bytes, metadata, splatCount) {
1281
3209
  const rotationOffset = splatIndex * 4;
1282
3210
  const x = xyz[xyzOffset + 0];
1283
3211
  const y = xyz[xyzOffset + 1];
1284
- const z = xyz[xyzOffset + 2];
1285
- const w = Math.sqrt(Math.max(0, 1 - x * x - y * y - z * z));
1286
- const normalized = normalizeQuaternion(w, x, y, z);
3212
+ const z2 = xyz[xyzOffset + 2];
3213
+ const w = Math.sqrt(Math.max(0, 1 - x * x - y * y - z2 * z2));
3214
+ const normalized = normalizeQuaternion(w, x, y, z2);
1287
3215
  rotations.set(normalized, rotationOffset);
1288
3216
  }
1289
3217
  return rotations;
@@ -1392,7 +3320,7 @@ function getRADPropertyBytes(bytes, metadata, property) {
1392
3320
  return decompressRADProperty(propertyBytes, property.property);
1393
3321
  }
1394
3322
  function decompressRADProperty(bytes, propertyName) {
1395
- const arrayBuffer = copyToArrayBuffer(bytes);
3323
+ const arrayBuffer = copyToArrayBuffer3(bytes);
1396
3324
  try {
1397
3325
  return new Uint8Array(RAD_PROPERTY_DEFLATE.decompressSync(arrayBuffer));
1398
3326
  } catch {
@@ -1450,9 +3378,9 @@ function decodeLeBytesFloat16(bytes, dimensions, count) {
1450
3378
  }
1451
3379
  return values;
1452
3380
  }
1453
- function decodeR8(bytes, dimensions, count, min, max) {
3381
+ function decodeR8(bytes, dimensions, count, min, max2) {
1454
3382
  const values = new Float32Array(count * dimensions);
1455
- const range = max - min;
3383
+ const range = max2 - min;
1456
3384
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
1457
3385
  for (let dimension = 0; dimension < dimensions; dimension++) {
1458
3386
  values[rowIndex * dimensions + dimension] = bytes[dimension * count + rowIndex] / 255 * range + min;
@@ -1460,9 +3388,9 @@ function decodeR8(bytes, dimensions, count, min, max) {
1460
3388
  }
1461
3389
  return values;
1462
3390
  }
1463
- function decodeR8Delta(bytes, dimensions, count, min, max) {
3391
+ function decodeR8Delta(bytes, dimensions, count, min, max2) {
1464
3392
  const values = new Float32Array(count * dimensions);
1465
- const range = max - min;
3393
+ const range = max2 - min;
1466
3394
  const last = new Uint8Array(dimensions);
1467
3395
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
1468
3396
  for (let dimension = 0; dimension < dimensions; dimension++) {
@@ -1474,17 +3402,17 @@ function decodeR8Delta(bytes, dimensions, count, min, max) {
1474
3402
  }
1475
3403
  return values;
1476
3404
  }
1477
- function decodeS8(bytes, dimensions, count, max) {
3405
+ function decodeS8(bytes, dimensions, count, max2) {
1478
3406
  const values = new Float32Array(count * dimensions);
1479
3407
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
1480
3408
  for (let dimension = 0; dimension < dimensions; dimension++) {
1481
3409
  const byte = bytes[dimension * count + rowIndex];
1482
- values[rowIndex * dimensions + dimension] = (byte << 24 >> 24) / 127 * max;
3410
+ values[rowIndex * dimensions + dimension] = (byte << 24 >> 24) / 127 * max2;
1483
3411
  }
1484
3412
  }
1485
3413
  return values;
1486
3414
  }
1487
- function decodeS8Delta(bytes, dimensions, count, max) {
3415
+ function decodeS8Delta(bytes, dimensions, count, max2) {
1488
3416
  const values = new Float32Array(count * dimensions);
1489
3417
  const last = new Uint8Array(dimensions);
1490
3418
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
@@ -1492,16 +3420,16 @@ function decodeS8Delta(bytes, dimensions, count, max) {
1492
3420
  const byteOffset = dimension * count + rowIndex;
1493
3421
  const value = last[dimension] + bytes[byteOffset] & 255;
1494
3422
  last[dimension] = value;
1495
- values[rowIndex * dimensions + dimension] = (value << 24 >> 24) / 127 * max;
3423
+ values[rowIndex * dimensions + dimension] = (value << 24 >> 24) / 127 * max2;
1496
3424
  }
1497
3425
  }
1498
3426
  return values;
1499
3427
  }
1500
- function decodeScaleR8(bytes, dimensions, count, min, max) {
3428
+ function decodeScaleR8(bytes, dimensions, count, min, max2) {
1501
3429
  const values = new Float32Array(count * dimensions);
1502
3430
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
1503
3431
  for (let dimension = 0; dimension < dimensions; dimension++) {
1504
- values[rowIndex * dimensions + dimension] = decodeScale8(bytes[dimension * count + rowIndex], min, max);
3432
+ values[rowIndex * dimensions + dimension] = decodeScale8(bytes[dimension * count + rowIndex], min, max2);
1505
3433
  }
1506
3434
  }
1507
3435
  return values;
@@ -1517,8 +3445,8 @@ function decodeRADOct88R8Rotations(bytes, count) {
1517
3445
  const rotations = new Float32Array(count * 4);
1518
3446
  for (let splatIndex = 0; splatIndex < count; splatIndex++) {
1519
3447
  const byteOffset = splatIndex * 3;
1520
- const [x, y, z, w] = decodeQuatOct888(bytes[byteOffset], bytes[byteOffset + 1], bytes[byteOffset + 2]);
1521
- rotations.set(normalizeQuaternion(w, x, y, z), splatIndex * 4);
3448
+ const [x, y, z2, w] = decodeQuatOct888(bytes[byteOffset], bytes[byteOffset + 1], bytes[byteOffset + 2]);
3449
+ rotations.set(normalizeQuaternion(w, x, y, z2), splatIndex * 4);
1522
3450
  }
1523
3451
  return rotations;
1524
3452
  }
@@ -1539,24 +3467,24 @@ function makeIdentityRotations(count) {
1539
3467
  }
1540
3468
  return rotations;
1541
3469
  }
1542
- function decodeScale8(scale, min, max) {
3470
+ function decodeScale8(scale, min, max2) {
1543
3471
  if (scale === 0) {
1544
3472
  return 0;
1545
3473
  }
1546
- const logScaleStep = (max - min) / 254;
3474
+ const logScaleStep = (max2 - min) / 254;
1547
3475
  return Math.exp(min + (scale - 1) * logScaleStep);
1548
3476
  }
1549
3477
  function decodeQuatOct888(u, v, r) {
1550
3478
  let x = u / 255 * 2 - 1;
1551
3479
  let y = v / 255 * 2 - 1;
1552
- const z = 1 - Math.abs(x) - Math.abs(y);
1553
- const t = Math.max(-z, 0);
3480
+ const z2 = 1 - Math.abs(x) - Math.abs(y);
3481
+ const t = Math.max(-z2, 0);
1554
3482
  x = x >= 0 ? x - t : x + t;
1555
3483
  y = y >= 0 ? y - t : y + t;
1556
- const length = Math.hypot(x, y, z);
3484
+ const length = Math.hypot(x, y, z2);
1557
3485
  const axisX = length > Number.EPSILON ? x / length : 1;
1558
3486
  const axisY = length > Number.EPSILON ? y / length : 0;
1559
- const axisZ = length > Number.EPSILON ? z / length : 0;
3487
+ const axisZ = length > Number.EPSILON ? z2 / length : 0;
1560
3488
  const halfTheta = r / 255 * 0.5 * Math.PI;
1561
3489
  const sinHalfTheta = Math.sin(halfTheta);
1562
3490
  return [axisX * sinHalfTheta, axisY * sinHalfTheta, axisZ * sinHalfTheta, Math.cos(halfTheta)];
@@ -1634,7 +3562,7 @@ function getSplatEncodingMaximum(splatEncoding, propertyName) {
1634
3562
  function normalizeColorByte2(value) {
1635
3563
  return Math.round(Math.min(Math.max(value, 0), 1) * 255);
1636
3564
  }
1637
- function copyToArrayBuffer(bytes) {
3565
+ function copyToArrayBuffer3(bytes) {
1638
3566
  const copy = new Uint8Array(bytes.byteLength);
1639
3567
  copy.set(bytes);
1640
3568
  return copy.buffer;
@@ -1642,16 +3570,16 @@ function copyToArrayBuffer(bytes) {
1642
3570
  function getUint8Array2(data) {
1643
3571
  return data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
1644
3572
  }
1645
- var import_compression2, RAD_PROPERTY_DEFLATE, RAD_PROPERTY_RAW_DEFLATE;
3573
+ var RAD_PROPERTY_DEFLATE, RAD_PROPERTY_RAW_DEFLATE;
1646
3574
  var init_parse_rad_chunk = __esm({
1647
3575
  "dist/lib/parse-rad-chunk.js"() {
1648
3576
  "use strict";
1649
- import_compression2 = require("@loaders.gl/compression");
3577
+ init_deflate_decompressor();
1650
3578
  init_parse_rad();
1651
3579
  init_splats_arrow_table();
1652
3580
  init_splat_utils();
1653
- RAD_PROPERTY_DEFLATE = new import_compression2.DeflateCompression();
1654
- RAD_PROPERTY_RAW_DEFLATE = new import_compression2.DeflateCompression({ raw: true });
3581
+ RAD_PROPERTY_DEFLATE = new DeflateDecompressor2({ useNative: false });
3582
+ RAD_PROPERTY_RAW_DEFLATE = new DeflateDecompressor2({ raw: true, useNative: false });
1655
3583
  }
1656
3584
  });
1657
3585
 
@@ -1687,17 +3615,17 @@ async function preload4() {
1687
3615
  const { RADLoaderWithParser: RADLoaderWithParser2 } = await Promise.resolve().then(() => (init_rad_loader(), rad_loader_exports));
1688
3616
  return RADLoaderWithParser2;
1689
3617
  }
1690
- var VERSION4, RADLoader;
3618
+ var VERSION5, RADLoader;
1691
3619
  var init_rad_loader_types = __esm({
1692
3620
  "dist/rad-loader-types.js"() {
1693
3621
  "use strict";
1694
3622
  init_splats_format();
1695
- VERSION4 = true ? "5.0.0-alpha.1" : "latest";
3623
+ VERSION5 = true ? "5.0.0-alpha.11" : "latest";
1696
3624
  RADLoader = {
1697
3625
  dataType: null,
1698
3626
  batchType: null,
1699
3627
  ...RADFormat,
1700
- version: VERSION4,
3628
+ version: VERSION5,
1701
3629
  options: {},
1702
3630
  preload: preload4
1703
3631
  };
@@ -1705,8 +3633,8 @@ var init_rad_loader_types = __esm({
1705
3633
  });
1706
3634
 
1707
3635
  // dist/index.js
1708
- var dist_exports = {};
1709
- __export(dist_exports, {
3636
+ var index_exports = {};
3637
+ __export(index_exports, {
1710
3638
  KSPLATFormat: () => KSPLATFormat,
1711
3639
  KSPLATLoader: () => KSPLATLoader,
1712
3640
  RADFormat: () => RADFormat,
@@ -1717,30 +3645,33 @@ __export(dist_exports, {
1717
3645
  SPLATLoader: () => SPLATLoader,
1718
3646
  SPZFormat: () => SPZFormat,
1719
3647
  SPZLoader: () => SPZLoader,
3648
+ parseSPZ: () => parseSPZ,
3649
+ parseSPZToGaussianSplats: () => parseSPZToGaussianSplats,
1720
3650
  resolveRADChunkUrl: () => resolveRADChunkUrl
1721
3651
  });
1722
- module.exports = __toCommonJS(dist_exports);
3652
+ module.exports = __toCommonJS(index_exports);
1723
3653
  init_splats_format();
3654
+ init_parse_spz();
1724
3655
  init_splat_loader_types();
1725
3656
  init_ksplat_loader_types();
1726
3657
  init_spz_loader_types();
1727
3658
  init_rad_loader_types();
1728
3659
 
1729
3660
  // dist/rad-source-loader.js
1730
- var import_loader_utils = require("@loaders.gl/loader-utils");
3661
+ init_src();
1731
3662
  init_splats_format();
1732
3663
  init_parse_rad();
1733
3664
  init_parse_rad_chunk();
1734
3665
  init_splats_arrow_table();
1735
3666
  var DEFAULT_RAD_HEADER_BYTE_LENGTHS = [64 * 1024, 256 * 1024, 1024 * 1024];
1736
3667
  var DEFAULT_RAD_MAX_CONCURRENT_CHUNK_REQUESTS = 4;
1737
- var VERSION5 = true ? "5.0.0-alpha.1" : "latest";
3668
+ var VERSION6 = true ? "5.0.0-alpha.11" : "latest";
1738
3669
  var RADSourceLoader = {
1739
3670
  dataType: null,
1740
3671
  batchType: null,
1741
3672
  ...RADFormat,
1742
3673
  name: "RADSourceLoader",
1743
- version: VERSION5,
3674
+ version: VERSION6,
1744
3675
  type: "rad",
1745
3676
  fromUrl: true,
1746
3677
  fromBlob: true,
@@ -1761,7 +3692,7 @@ var RADSourceLoader = {
1761
3692
  testURL: (url) => /\.rad(?:$|[?#])/i.test(url),
1762
3693
  createDataSource: (data, options, coreApi) => new RADSource(data, options, coreApi)
1763
3694
  };
1764
- var RADSource = class extends import_loader_utils.DataSource {
3695
+ var RADSource = class extends DataSource {
1765
3696
  /** Shared metadata promise exposed for source-style integrations. */
1766
3697
  metadata;
1767
3698
  /** Lazily initialized RAD header promise. */