@sparkjsdev/spark 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/assets/worker-BbYVeANL.js.map +1 -0
- package/dist/assets/worker-CaMzlx2k.js.map +1 -0
- package/dist/spark.cjs.js +433 -175
- package/dist/spark.cjs.js.map +1 -1
- package/dist/spark.cjs.min.js +92 -53
- package/dist/spark.cjs.min.js.map +1 -1
- package/dist/spark.module.js +433 -175
- package/dist/spark.module.js.map +1 -1
- package/dist/spark.module.min.js +2503 -2310
- package/dist/spark.module.min.js.map +1 -1
- package/dist/types/SparkRenderer.d.ts +9 -0
- package/dist/types/SplatLoader.d.ts +29 -2
- package/dist/types/defines.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/pcsogs.d.ts +2 -2
- package/dist/types/ply.d.ts +3 -1
- package/dist/types/spz.d.ts +5 -3
- package/dist/types/utils.d.ts +8 -6
- package/package.json +3 -3
- package/dist/assets/worker-C1ojSBY1.js.map +0 -1
- package/dist/assets/worker-DXCsnY0K.js.map +0 -1
package/dist/spark.cjs.js
CHANGED
|
@@ -29,15 +29,34 @@ class FullscreenTriangleGeometry extends THREE.BufferGeometry {
|
|
|
29
29
|
}
|
|
30
30
|
const _geometry = new FullscreenTriangleGeometry();
|
|
31
31
|
class FullScreenQuad {
|
|
32
|
+
/**
|
|
33
|
+
* Constructs a new full screen quad.
|
|
34
|
+
*
|
|
35
|
+
* @param {?Material} material - The material to render te full screen quad with.
|
|
36
|
+
*/
|
|
32
37
|
constructor(material) {
|
|
33
38
|
this._mesh = new THREE.Mesh(_geometry, material);
|
|
34
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Frees the GPU-related resources allocated by this instance. Call this
|
|
42
|
+
* method whenever the instance is no longer used in your app.
|
|
43
|
+
*/
|
|
35
44
|
dispose() {
|
|
36
45
|
this._mesh.geometry.dispose();
|
|
37
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Renders the full screen quad.
|
|
49
|
+
*
|
|
50
|
+
* @param {WebGLRenderer} renderer - The renderer.
|
|
51
|
+
*/
|
|
38
52
|
render(renderer) {
|
|
39
53
|
renderer.render(this._mesh, _camera);
|
|
40
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* The quad's material.
|
|
57
|
+
*
|
|
58
|
+
* @type {?Material}
|
|
59
|
+
*/
|
|
41
60
|
get material() {
|
|
42
61
|
return this._mesh.material;
|
|
43
62
|
}
|
|
@@ -730,6 +749,7 @@ const SPLAT_TEX_WIDTH_MASK = SPLAT_TEX_WIDTH - 1;
|
|
|
730
749
|
const SPLAT_TEX_HEIGHT_MASK = SPLAT_TEX_HEIGHT - 1;
|
|
731
750
|
const SPLAT_TEX_DEPTH_MASK = SPLAT_TEX_DEPTH - 1;
|
|
732
751
|
const WASM_SPLAT_SORT = true;
|
|
752
|
+
const USE_COMPILED_PARSER_FUNCTION = true;
|
|
733
753
|
const defines = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
734
754
|
__proto__: null,
|
|
735
755
|
LN_SCALE_MAX,
|
|
@@ -749,6 +769,7 @@ const defines = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
749
769
|
SPLAT_TEX_WIDTH,
|
|
750
770
|
SPLAT_TEX_WIDTH_BITS,
|
|
751
771
|
SPLAT_TEX_WIDTH_MASK,
|
|
772
|
+
USE_COMPILED_PARSER_FUNCTION,
|
|
752
773
|
WASM_SPLAT_SORT
|
|
753
774
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
754
775
|
function isBoolType(type) {
|
|
@@ -2408,6 +2429,13 @@ class DynoSamplerCubeShadow extends DynoUniform {
|
|
|
2408
2429
|
}
|
|
2409
2430
|
const f32buffer = new Float32Array(1);
|
|
2410
2431
|
const u32buffer = new Uint32Array(f32buffer.buffer);
|
|
2432
|
+
const supportsFloat16Array = "Float16Array" in globalThis;
|
|
2433
|
+
const f16buffer = supportsFloat16Array ? new globalThis["Float16Array"](1) : null;
|
|
2434
|
+
const u16buffer = new Uint16Array(f16buffer == null ? void 0 : f16buffer.buffer);
|
|
2435
|
+
function normalize$1(vec) {
|
|
2436
|
+
const norm = Math.sqrt(vec.reduce((acc, v) => acc + v * v, 0));
|
|
2437
|
+
return vec.map((v) => v / norm);
|
|
2438
|
+
}
|
|
2411
2439
|
function floatBitsToUint$1(f) {
|
|
2412
2440
|
f32buffer[0] = f;
|
|
2413
2441
|
return u32buffer[0];
|
|
@@ -2416,7 +2444,13 @@ function uintBitsToFloat$1(u) {
|
|
|
2416
2444
|
u32buffer[0] = u;
|
|
2417
2445
|
return f32buffer[0];
|
|
2418
2446
|
}
|
|
2419
|
-
|
|
2447
|
+
const toHalf = supportsFloat16Array ? toHalfNative : toHalfJS;
|
|
2448
|
+
const fromHalf = supportsFloat16Array ? fromHalfNative : fromHalfJS;
|
|
2449
|
+
function toHalfNative(f) {
|
|
2450
|
+
f16buffer[0] = f;
|
|
2451
|
+
return u16buffer[0];
|
|
2452
|
+
}
|
|
2453
|
+
function toHalfJS(f) {
|
|
2420
2454
|
f32buffer[0] = f;
|
|
2421
2455
|
const bits2 = u32buffer[0];
|
|
2422
2456
|
const sign2 = bits2 >> 31 & 1;
|
|
@@ -2443,7 +2477,11 @@ function toHalf(f) {
|
|
|
2443
2477
|
const halfFrac = frac >> 13;
|
|
2444
2478
|
return halfSign | newExp << 10 | halfFrac;
|
|
2445
2479
|
}
|
|
2446
|
-
function
|
|
2480
|
+
function fromHalfNative(u) {
|
|
2481
|
+
u16buffer[0] = u;
|
|
2482
|
+
return f16buffer[0];
|
|
2483
|
+
}
|
|
2484
|
+
function fromHalfJS(h) {
|
|
2447
2485
|
const sign2 = h >> 15 & 1;
|
|
2448
2486
|
const exp3 = h >> 10 & 31;
|
|
2449
2487
|
const frac = h & 1023;
|
|
@@ -2604,7 +2642,7 @@ function setPackedSplat(packedSplats, index, x, y, z, scaleX, scaleY, scaleZ, qu
|
|
|
2604
2642
|
const uB = floatToUint8((b - rgbMin) / rgbRange);
|
|
2605
2643
|
const uA = floatToUint8(opacity);
|
|
2606
2644
|
const uQuat = encodeQuatOctXy88R8(
|
|
2607
|
-
|
|
2645
|
+
tempQuaternion.set(quatX, quatY, quatZ, quatW)
|
|
2608
2646
|
);
|
|
2609
2647
|
const uQuatX = uQuat & 255;
|
|
2610
2648
|
const uQuatY = uQuat >>> 8 & 255;
|
|
@@ -2678,9 +2716,10 @@ function setPackedSplatScales(packedSplats, index, scaleX, scaleY, scaleZ, encod
|
|
|
2678
2716
|
const i4 = index * 4;
|
|
2679
2717
|
packedSplats[i4 + 3] = uScaleX | uScaleY << 8 | uScaleZ << 16 | packedSplats[i4 + 3] & 4278190080;
|
|
2680
2718
|
}
|
|
2719
|
+
const tempQuaternion = new THREE__namespace.Quaternion();
|
|
2681
2720
|
function setPackedSplatQuat(packedSplats, index, quatX, quatY, quatZ, quatW) {
|
|
2682
2721
|
const uQuat = encodeQuatOctXy88R8(
|
|
2683
|
-
|
|
2722
|
+
tempQuaternion.set(quatX, quatY, quatZ, quatW)
|
|
2684
2723
|
);
|
|
2685
2724
|
const uQuatX = uQuat & 255;
|
|
2686
2725
|
const uQuatY = uQuat >>> 8 & 255;
|
|
@@ -2939,8 +2978,10 @@ function decodeQuatXyz888(encoded, out) {
|
|
|
2939
2978
|
out.w = Math.sqrt(Math.max(0, 1 - dotSelf));
|
|
2940
2979
|
return out;
|
|
2941
2980
|
}
|
|
2981
|
+
const tempNormalizedQuaternion = new THREE__namespace.Quaternion();
|
|
2982
|
+
const tempAxis = new THREE__namespace.Vector3();
|
|
2942
2983
|
function encodeQuatOctXy88R8(q) {
|
|
2943
|
-
const qnorm =
|
|
2984
|
+
const qnorm = tempNormalizedQuaternion.copy(q).normalize();
|
|
2944
2985
|
if (qnorm.w < 0) {
|
|
2945
2986
|
qnorm.set(-qnorm.x, -qnorm.y, -qnorm.z, -qnorm.w);
|
|
2946
2987
|
}
|
|
@@ -2948,7 +2989,7 @@ function encodeQuatOctXy88R8(q) {
|
|
|
2948
2989
|
const xyz_norm = Math.sqrt(
|
|
2949
2990
|
qnorm.x * qnorm.x + qnorm.y * qnorm.y + qnorm.z * qnorm.z
|
|
2950
2991
|
);
|
|
2951
|
-
const axis = xyz_norm < 1e-6 ?
|
|
2992
|
+
const axis = xyz_norm < 1e-6 ? tempAxis.set(1, 0, 0) : tempAxis.set(qnorm.x, qnorm.y, qnorm.z).divideScalar(xyz_norm);
|
|
2952
2993
|
const sum = Math.abs(axis.x) + Math.abs(axis.y) + Math.abs(axis.z);
|
|
2953
2994
|
let p_x = axis.x / sum;
|
|
2954
2995
|
let p_y = axis.y / sum;
|
|
@@ -2976,7 +3017,7 @@ function decodeQuatOctXy88R8(encoded, out) {
|
|
|
2976
3017
|
const t = Math.max(-f_z, 0);
|
|
2977
3018
|
f_x += f_x >= 0 ? -t : t;
|
|
2978
3019
|
f_y += f_y >= 0 ? -t : t;
|
|
2979
|
-
const axis =
|
|
3020
|
+
const axis = tempAxis.set(f_x, f_y, f_z).normalize();
|
|
2980
3021
|
const theta = angleInt / 255 * Math.PI;
|
|
2981
3022
|
const halfTheta = theta * 0.5;
|
|
2982
3023
|
const s = Math.sin(halfTheta);
|
|
@@ -3143,25 +3184,20 @@ class GunzipReader {
|
|
|
3143
3184
|
}) {
|
|
3144
3185
|
this.fileBytes = fileBytes;
|
|
3145
3186
|
this.chunkBytes = chunkBytes;
|
|
3146
|
-
this.offset = 0;
|
|
3147
3187
|
this.chunks = [];
|
|
3148
3188
|
this.totalBytes = 0;
|
|
3149
|
-
|
|
3189
|
+
const ds = new DecompressionStream("gzip");
|
|
3190
|
+
const decompressionStream = new Blob([fileBytes]).stream().pipeThrough(ds);
|
|
3191
|
+
this.reader = decompressionStream.getReader();
|
|
3192
|
+
}
|
|
3193
|
+
async read(numBytes) {
|
|
3194
|
+
while (this.totalBytes < numBytes) {
|
|
3195
|
+
const { value: chunk, done: readerDone } = await this.reader.read();
|
|
3196
|
+
if (readerDone) {
|
|
3197
|
+
break;
|
|
3198
|
+
}
|
|
3150
3199
|
this.chunks.push(chunk);
|
|
3151
3200
|
this.totalBytes += chunk.length;
|
|
3152
|
-
});
|
|
3153
|
-
}
|
|
3154
|
-
read(numBytes) {
|
|
3155
|
-
while (this.totalBytes < numBytes && this.offset < this.fileBytes.length) {
|
|
3156
|
-
const end = Math.min(
|
|
3157
|
-
this.offset + this.chunkBytes,
|
|
3158
|
-
this.fileBytes.length
|
|
3159
|
-
);
|
|
3160
|
-
this.gunzip.push(this.fileBytes.subarray(this.offset, end), false);
|
|
3161
|
-
this.offset = end;
|
|
3162
|
-
}
|
|
3163
|
-
if (this.totalBytes < numBytes && this.offset >= this.fileBytes.length) {
|
|
3164
|
-
this.gunzip.push(new Uint8Array(0), true);
|
|
3165
3201
|
}
|
|
3166
3202
|
if (this.totalBytes < numBytes) {
|
|
3167
3203
|
throw new Error(
|
|
@@ -3218,6 +3254,7 @@ const utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
3218
3254
|
mapFilterObject,
|
|
3219
3255
|
mapObject,
|
|
3220
3256
|
newArray,
|
|
3257
|
+
normalize: normalize$1,
|
|
3221
3258
|
omitUndefined,
|
|
3222
3259
|
pixelsToPngUrl,
|
|
3223
3260
|
setPackedSplat,
|
|
@@ -7210,6 +7247,7 @@ const _SplatMesh = class _SplatMesh extends SplatGenerator {
|
|
|
7210
7247
|
}
|
|
7211
7248
|
}
|
|
7212
7249
|
}
|
|
7250
|
+
this.add(createRendererDetectionMesh());
|
|
7213
7251
|
}
|
|
7214
7252
|
async asyncInitialize(options) {
|
|
7215
7253
|
const {
|
|
@@ -7767,6 +7805,39 @@ function evaluateSH3(gsplat, sh3, viewDir) {
|
|
|
7767
7805
|
`)
|
|
7768
7806
|
}).outputs.rgb;
|
|
7769
7807
|
}
|
|
7808
|
+
const EMPTY_GEOMETRY$1 = new THREE__namespace.BufferGeometry();
|
|
7809
|
+
const EMPTY_MATERIAL = new THREE__namespace.ShaderMaterial();
|
|
7810
|
+
function createRendererDetectionMesh() {
|
|
7811
|
+
const mesh = new THREE__namespace.Mesh(EMPTY_GEOMETRY$1, EMPTY_MATERIAL);
|
|
7812
|
+
mesh.frustumCulled = false;
|
|
7813
|
+
mesh.onBeforeRender = function(renderer, scene) {
|
|
7814
|
+
if (!scene.isScene) {
|
|
7815
|
+
this.removeFromParent();
|
|
7816
|
+
return;
|
|
7817
|
+
}
|
|
7818
|
+
let hasSparkRenderer = false;
|
|
7819
|
+
scene.traverse((c) => {
|
|
7820
|
+
if (c instanceof SparkRenderer) {
|
|
7821
|
+
hasSparkRenderer = true;
|
|
7822
|
+
}
|
|
7823
|
+
});
|
|
7824
|
+
if (!hasSparkRenderer) {
|
|
7825
|
+
scene.add(new SparkRenderer({ renderer }));
|
|
7826
|
+
}
|
|
7827
|
+
this.removeFromParent();
|
|
7828
|
+
};
|
|
7829
|
+
return mesh;
|
|
7830
|
+
}
|
|
7831
|
+
const PLY_PROPERTY_TYPES = [
|
|
7832
|
+
"char",
|
|
7833
|
+
"uchar",
|
|
7834
|
+
"short",
|
|
7835
|
+
"ushort",
|
|
7836
|
+
"int",
|
|
7837
|
+
"uint",
|
|
7838
|
+
"float",
|
|
7839
|
+
"double"
|
|
7840
|
+
];
|
|
7770
7841
|
const _PlyReader = class _PlyReader {
|
|
7771
7842
|
// Create a PlyReader from a Uint8Array/ArrayBuffer, no parsing done yet
|
|
7772
7843
|
constructor({ fileBytes }) {
|
|
@@ -7880,46 +7951,12 @@ const _PlyReader = class _PlyReader {
|
|
|
7880
7951
|
for (const elementName in this.elements) {
|
|
7881
7952
|
const element = this.elements[elementName];
|
|
7882
7953
|
const { count, properties } = element;
|
|
7883
|
-
const item =
|
|
7884
|
-
const
|
|
7885
|
-
for (const [propertyName, property] of Object.entries(properties)) {
|
|
7886
|
-
if (!property.isList) {
|
|
7887
|
-
item[propertyName] = 0;
|
|
7888
|
-
parsers.push(() => {
|
|
7889
|
-
item[propertyName] = PARSE_FIELD[property.type](
|
|
7890
|
-
data,
|
|
7891
|
-
offset,
|
|
7892
|
-
this.littleEndian
|
|
7893
|
-
);
|
|
7894
|
-
offset += FIELD_BYTES[property.type];
|
|
7895
|
-
});
|
|
7896
|
-
} else {
|
|
7897
|
-
item[propertyName] = [];
|
|
7898
|
-
parsers.push(() => {
|
|
7899
|
-
const list = item[propertyName];
|
|
7900
|
-
list.length = PARSE_FIELD[property.countType](
|
|
7901
|
-
data,
|
|
7902
|
-
offset,
|
|
7903
|
-
this.littleEndian
|
|
7904
|
-
);
|
|
7905
|
-
offset += FIELD_BYTES[property.countType];
|
|
7906
|
-
for (let i = 0; i < list.length; i++) {
|
|
7907
|
-
list[i] = PARSE_FIELD[property.type](
|
|
7908
|
-
data,
|
|
7909
|
-
offset,
|
|
7910
|
-
this.littleEndian
|
|
7911
|
-
);
|
|
7912
|
-
offset += FIELD_BYTES[property.type];
|
|
7913
|
-
}
|
|
7914
|
-
});
|
|
7915
|
-
}
|
|
7916
|
-
}
|
|
7954
|
+
const item = createEmptyItem(properties);
|
|
7955
|
+
const parseFn = createParseFn(properties, this.littleEndian);
|
|
7917
7956
|
const callback = elementCallback(element) ?? (() => {
|
|
7918
7957
|
});
|
|
7919
7958
|
for (let index = 0; index < count; index++) {
|
|
7920
|
-
|
|
7921
|
-
parser();
|
|
7922
|
-
}
|
|
7959
|
+
offset = parseFn(data, offset, item);
|
|
7923
7960
|
callback(index, item);
|
|
7924
7961
|
}
|
|
7925
7962
|
}
|
|
@@ -7941,14 +7978,12 @@ const _PlyReader = class _PlyReader {
|
|
|
7941
7978
|
let sh3 = void 0;
|
|
7942
7979
|
function prepareSh() {
|
|
7943
7980
|
const num_f_rest = NUM_SH_TO_NUM_F_REST[numSh];
|
|
7944
|
-
sh1Props = new Array(3).fill(null).flatMap(
|
|
7945
|
-
(_, k) => [0, 1, 2].map((_2, d) => `f_rest_${k + d * num_f_rest / 3}`)
|
|
7946
|
-
);
|
|
7981
|
+
sh1Props = new Array(3).fill(null).flatMap((_, k) => [0, 1, 2].map((_2, d) => k + d * num_f_rest / 3));
|
|
7947
7982
|
sh2Props = new Array(5).fill(null).flatMap(
|
|
7948
|
-
(_, k) => [0, 1, 2].map((_2, d) =>
|
|
7983
|
+
(_, k) => [0, 1, 2].map((_2, d) => 3 + k + d * num_f_rest / 3)
|
|
7949
7984
|
);
|
|
7950
7985
|
sh3Props = new Array(7).fill(null).flatMap(
|
|
7951
|
-
(_, k) => [0, 1, 2].map((_2, d) =>
|
|
7986
|
+
(_, k) => [0, 1, 2].map((_2, d) => 8 + k + d * num_f_rest / 3)
|
|
7952
7987
|
);
|
|
7953
7988
|
sh1 = numSh >= 1 ? new Float32Array(3 * 3) : void 0;
|
|
7954
7989
|
sh2 = numSh >= 2 ? new Float32Array(5 * 3) : void 0;
|
|
@@ -7958,17 +7993,18 @@ const _PlyReader = class _PlyReader {
|
|
|
7958
7993
|
if (!sh1) {
|
|
7959
7994
|
throw new Error("Missing sh1");
|
|
7960
7995
|
}
|
|
7961
|
-
|
|
7962
|
-
|
|
7996
|
+
const sh = item.f_rest;
|
|
7997
|
+
for (let i = 0; i < sh1Props.length; i++) {
|
|
7998
|
+
sh1[i] = sh[sh1Props[i]] * 8 / 255 - 4;
|
|
7963
7999
|
}
|
|
7964
8000
|
if (sh2) {
|
|
7965
|
-
for (
|
|
7966
|
-
sh2[i] =
|
|
8001
|
+
for (let i = 0; i < sh2Props.length; i++) {
|
|
8002
|
+
sh2[i] = sh[sh2Props[i]] * 8 / 255 - 4;
|
|
7967
8003
|
}
|
|
7968
8004
|
}
|
|
7969
8005
|
if (sh3) {
|
|
7970
|
-
for (
|
|
7971
|
-
sh3[i] =
|
|
8006
|
+
for (let i = 0; i < sh3Props.length; i++) {
|
|
8007
|
+
sh3[i] = sh[sh3Props[i]] * 8 / 255 - 4;
|
|
7972
8008
|
}
|
|
7973
8009
|
}
|
|
7974
8010
|
shCallback == null ? void 0 : shCallback(index, sh1, sh2, sh3);
|
|
@@ -8192,19 +8228,20 @@ const _PlyReader = class _PlyReader {
|
|
|
8192
8228
|
b
|
|
8193
8229
|
);
|
|
8194
8230
|
if (shCallback && sh1) {
|
|
8231
|
+
const sh = item.f_rest;
|
|
8195
8232
|
if (sh1) {
|
|
8196
|
-
for (
|
|
8197
|
-
sh1[i] =
|
|
8233
|
+
for (let i = 0; i < sh1Props.length; i++) {
|
|
8234
|
+
sh1[i] = sh[sh1Props[i]];
|
|
8198
8235
|
}
|
|
8199
8236
|
}
|
|
8200
8237
|
if (sh2) {
|
|
8201
|
-
for (
|
|
8202
|
-
sh2[i] =
|
|
8238
|
+
for (let i = 0; i < sh2Props.length; i++) {
|
|
8239
|
+
sh2[i] = sh[sh2Props[i]];
|
|
8203
8240
|
}
|
|
8204
8241
|
}
|
|
8205
8242
|
if (sh3) {
|
|
8206
|
-
for (
|
|
8207
|
-
sh3[i] =
|
|
8243
|
+
for (let i = 0; i < sh3Props.length; i++) {
|
|
8244
|
+
sh3[i] = sh[sh3Props[i]];
|
|
8208
8245
|
}
|
|
8209
8246
|
}
|
|
8210
8247
|
shCallback(index, sh1, sh2, sh3);
|
|
@@ -8384,6 +8421,154 @@ const NUM_SH_TO_NUM_F_REST = {
|
|
|
8384
8421
|
2: 24,
|
|
8385
8422
|
3: 45
|
|
8386
8423
|
};
|
|
8424
|
+
const F_REST_REGEX = /^f_rest_([0-9]{1,2})$/;
|
|
8425
|
+
function createEmptyItem(properties) {
|
|
8426
|
+
const item = {};
|
|
8427
|
+
for (const [propertyName, property] of Object.entries(properties)) {
|
|
8428
|
+
if (F_REST_REGEX.test(propertyName)) {
|
|
8429
|
+
item.f_rest = new Array(getNumSh(properties));
|
|
8430
|
+
} else {
|
|
8431
|
+
item[propertyName] = property.isList ? [] : 0;
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
return item;
|
|
8435
|
+
}
|
|
8436
|
+
function createParseFn(properties, littleEndian) {
|
|
8437
|
+
if (safeToCompile(properties)) {
|
|
8438
|
+
return createCompiledParserFn(properties, littleEndian);
|
|
8439
|
+
}
|
|
8440
|
+
return createDynamicParserFn(properties, littleEndian);
|
|
8441
|
+
}
|
|
8442
|
+
const UNSAFE_EVAL_ALLOWED = (() => {
|
|
8443
|
+
try {
|
|
8444
|
+
new Function("return 42;");
|
|
8445
|
+
} catch (e) {
|
|
8446
|
+
return false;
|
|
8447
|
+
}
|
|
8448
|
+
return true;
|
|
8449
|
+
})();
|
|
8450
|
+
const PROPERTY_NAME_REGEX = /^[a-zA-Z0-9_]+$/;
|
|
8451
|
+
function safeToCompile(properties) {
|
|
8452
|
+
if (!UNSAFE_EVAL_ALLOWED) {
|
|
8453
|
+
return false;
|
|
8454
|
+
}
|
|
8455
|
+
for (const [propertyName, property] of Object.entries(properties)) {
|
|
8456
|
+
if (!PROPERTY_NAME_REGEX.test(propertyName)) {
|
|
8457
|
+
return false;
|
|
8458
|
+
}
|
|
8459
|
+
if (property.isList && !PLY_PROPERTY_TYPES.includes(property.countType)) {
|
|
8460
|
+
return false;
|
|
8461
|
+
}
|
|
8462
|
+
if (!PLY_PROPERTY_TYPES.includes(property.type)) {
|
|
8463
|
+
return false;
|
|
8464
|
+
}
|
|
8465
|
+
}
|
|
8466
|
+
return true;
|
|
8467
|
+
}
|
|
8468
|
+
function createCompiledParserFn(properties, littleEndian) {
|
|
8469
|
+
const parserSrc = ["let list;"];
|
|
8470
|
+
for (const [propertyName, property] of Object.entries(properties)) {
|
|
8471
|
+
const fRestMatch = propertyName.match(F_REST_REGEX);
|
|
8472
|
+
if (fRestMatch) {
|
|
8473
|
+
const fRestIndex = +fRestMatch[1];
|
|
8474
|
+
parserSrc.push(
|
|
8475
|
+
/*js*/
|
|
8476
|
+
`
|
|
8477
|
+
item.f_rest[${fRestIndex}] = PARSE_FIELD['${property.type}'](data, offset, ${littleEndian});
|
|
8478
|
+
offset += ${FIELD_BYTES[property.type]};
|
|
8479
|
+
`
|
|
8480
|
+
);
|
|
8481
|
+
} else if (!property.isList) {
|
|
8482
|
+
parserSrc.push(
|
|
8483
|
+
/*js*/
|
|
8484
|
+
`
|
|
8485
|
+
item['${propertyName}'] = PARSE_FIELD['${property.type}'](data, offset, ${littleEndian});
|
|
8486
|
+
offset += ${FIELD_BYTES[property.type]};
|
|
8487
|
+
`
|
|
8488
|
+
);
|
|
8489
|
+
} else {
|
|
8490
|
+
parserSrc.push(
|
|
8491
|
+
/*js*/
|
|
8492
|
+
`
|
|
8493
|
+
list = item['${propertyName}'];
|
|
8494
|
+
list.length = PARSE_FIELD['${property.countType}'](data, offset, ${littleEndian});
|
|
8495
|
+
offset += ${FIELD_BYTES[property.countType]};
|
|
8496
|
+
for (let i = 0; i < list.length; i++) {
|
|
8497
|
+
list[i] = PARSE_FIELD['${property.type}'](data, offset, ${littleEndian});
|
|
8498
|
+
offset += ${FIELD_BYTES[property.type]};
|
|
8499
|
+
}
|
|
8500
|
+
`
|
|
8501
|
+
);
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
parserSrc.push("return offset;");
|
|
8505
|
+
const fn = new Function(
|
|
8506
|
+
"data",
|
|
8507
|
+
"offset",
|
|
8508
|
+
"item",
|
|
8509
|
+
"PARSE_FIELD",
|
|
8510
|
+
parserSrc.join("\n")
|
|
8511
|
+
);
|
|
8512
|
+
return (data, offset, item) => fn(data, offset, item, PARSE_FIELD);
|
|
8513
|
+
}
|
|
8514
|
+
function createDynamicParserFn(properties, littleEndian) {
|
|
8515
|
+
const parsers = [];
|
|
8516
|
+
for (const [propertyName, property] of Object.entries(properties)) {
|
|
8517
|
+
const fRestMatch = propertyName.match(F_REST_REGEX);
|
|
8518
|
+
if (fRestMatch) {
|
|
8519
|
+
const fRestIndex = +fRestMatch[1];
|
|
8520
|
+
parsers.push(
|
|
8521
|
+
(data, offset, item) => {
|
|
8522
|
+
item.f_rest[fRestIndex] = PARSE_FIELD[property.type](
|
|
8523
|
+
data,
|
|
8524
|
+
offset,
|
|
8525
|
+
littleEndian
|
|
8526
|
+
);
|
|
8527
|
+
return offset + FIELD_BYTES[property.type];
|
|
8528
|
+
}
|
|
8529
|
+
);
|
|
8530
|
+
} else if (!property.isList) {
|
|
8531
|
+
parsers.push(
|
|
8532
|
+
(data, offset, item) => {
|
|
8533
|
+
item[propertyName] = PARSE_FIELD[property.type](
|
|
8534
|
+
data,
|
|
8535
|
+
offset,
|
|
8536
|
+
littleEndian
|
|
8537
|
+
);
|
|
8538
|
+
return offset + FIELD_BYTES[property.type];
|
|
8539
|
+
}
|
|
8540
|
+
);
|
|
8541
|
+
} else {
|
|
8542
|
+
parsers.push(
|
|
8543
|
+
(data, offset, item) => {
|
|
8544
|
+
const list = item[propertyName];
|
|
8545
|
+
list.length = PARSE_FIELD[property.countType](
|
|
8546
|
+
data,
|
|
8547
|
+
offset,
|
|
8548
|
+
littleEndian
|
|
8549
|
+
);
|
|
8550
|
+
let currentOffset = offset + FIELD_BYTES[property.countType];
|
|
8551
|
+
for (let i = 0; i < list.length; i++) {
|
|
8552
|
+
list[i] = PARSE_FIELD[property.type](
|
|
8553
|
+
data,
|
|
8554
|
+
currentOffset,
|
|
8555
|
+
littleEndian
|
|
8556
|
+
);
|
|
8557
|
+
currentOffset += FIELD_BYTES[property.type];
|
|
8558
|
+
}
|
|
8559
|
+
return currentOffset;
|
|
8560
|
+
}
|
|
8561
|
+
);
|
|
8562
|
+
}
|
|
8563
|
+
}
|
|
8564
|
+
return (data, offset, item) => {
|
|
8565
|
+
let currentOffset = offset;
|
|
8566
|
+
for (let parserIndex = 0; parserIndex < parsers.length; parserIndex++) {
|
|
8567
|
+
currentOffset = parsers[parserIndex](data, currentOffset, item);
|
|
8568
|
+
}
|
|
8569
|
+
return currentOffset;
|
|
8570
|
+
};
|
|
8571
|
+
}
|
|
8387
8572
|
function getNumSh(properties) {
|
|
8388
8573
|
let num_f_rest = 0;
|
|
8389
8574
|
while (properties[`f_rest_${num_f_rest}`]) {
|
|
@@ -8395,7 +8580,7 @@ function getNumSh(properties) {
|
|
|
8395
8580
|
}
|
|
8396
8581
|
return numSh;
|
|
8397
8582
|
}
|
|
8398
|
-
const jsContent = '(function() {\n "use strict";\n let wasm;\n const cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }) : { decode: () => {\n throw Error("TextDecoder not available");\n } };\n if (typeof TextDecoder !== "undefined") {\n cachedTextDecoder.decode();\n }\n let cachedUint8ArrayMemory0 = null;\n function getUint8ArrayMemory0() {\n if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8ArrayMemory0;\n }\n function getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n }\n function sort_splats(num_splats, readback, ordering) {\n const ret = wasm.sort_splats(num_splats, readback, ordering);\n return ret >>> 0;\n }\n function sort32_splats(num_splats, readback, ordering) {\n const ret = wasm.sort32_splats(num_splats, readback, ordering);\n return ret >>> 0;\n }\n async function __wbg_load(module, imports) {\n if (typeof Response === "function" && module instanceof Response) {\n if (typeof WebAssembly.instantiateStreaming === "function") {\n try {\n return await WebAssembly.instantiateStreaming(module, imports);\n } catch (e) {\n if (module.headers.get("Content-Type") != "application/wasm") {\n console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n", e);\n } else {\n throw e;\n }\n }\n }\n const bytes = await module.arrayBuffer();\n return await WebAssembly.instantiate(bytes, imports);\n } else {\n const instance = await WebAssembly.instantiate(module, imports);\n if (instance instanceof WebAssembly.Instance) {\n return { instance, module };\n } else {\n return instance;\n }\n }\n }\n function __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) {\n const ret = arg0.buffer;\n return ret;\n };\n imports.wbg.__wbg_length_3b4f022188ae8db6 = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_length_6ca527665d89694d = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_length_8cfd2c6409af88ad = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_new_9fee97a409b32b68 = function(arg0) {\n const ret = new Uint16Array(arg0);\n return ret;\n };\n imports.wbg.__wbg_new_e3b321dcfef89fc7 = function(arg0) {\n const ret = new Uint32Array(arg0);\n return ret;\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_e6b7e69acd4c7354 = function(arg0, arg1, arg2) {\n const ret = new Float32Array(arg0, arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_f1dead44d1fc7212 = function(arg0, arg1, arg2) {\n const ret = new Uint32Array(arg0, arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_newwithlength_5a5efe313cfd59f1 = function(arg0) {\n const ret = new Float32Array(arg0 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_set_10bad9bee0e9c58b = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_set_d23661d19148b229 = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_set_f4f1f0daa30696fc = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_subarray_3aaeec89bb2544f0 = function(arg0, arg1, arg2) {\n const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_subarray_769e1e0f81bb259b = function(arg0, arg1, arg2) {\n const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbindgen_init_externref_table = function() {\n const table = wasm.__wbindgen_export_0;\n const offset = table.grow(4);\n table.set(0, void 0);\n table.set(offset + 0, void 0);\n table.set(offset + 1, null);\n table.set(offset + 2, true);\n table.set(offset + 3, false);\n };\n imports.wbg.__wbindgen_memory = function() {\n const ret = wasm.memory;\n return ret;\n };\n imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n return imports;\n }\n function __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n __wbg_init.__wbindgen_wasm_module = module;\n cachedUint8ArrayMemory0 = null;\n wasm.__wbindgen_start();\n return wasm;\n }\n async function __wbg_init(module_or_path) {\n if (wasm !== void 0) return wasm;\n if (typeof module_or_path !== "undefined") {\n if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n ({ module_or_path } = module_or_path);\n } else {\n console.warn("using deprecated parameters for the initialization function; pass a single object instead");\n }\n }\n if (typeof module_or_path === "undefined") {\n module_or_path = new URL("data:application/wasm;base64,AGFzbQEAAAABzAEeYAJ/fwF/YAJ/fwBgA39/fwF/YAF/AX9gA39/fwBgAX8AYAV/f39/fwBgA29/fwFvYAV/f39/fwF/YAFvAW9gA29vfwBgAW8Bf2AAAX9gBH9/f38AYAAAYAR/f39/AX9gA39vbwF/YAF/AW9gAAFvYAF9AX1gBn9/f39/fwBgDX19fX19fX19f29/fX0Bb2AGf39/f39/AX9gBX9/fH9/AGAEf3x/fwBgBX9/fX9/AGAEf31/fwBgBX9/fn9/AGAEf35/fwBgAn19AX0C8gQRA3diZx1fX3diZ19idWZmZXJfNjA5Y2MzZWVlNTFlZDE1OAAJA3diZxpfX3diZ19uZXdfOWZlZTk3YTQwOWIzMmI2OAAJA3diZxpfX3diZ19zZXRfZjRmMWYwZGFhMzA2OTZmYwAKA3diZx1fX3diZ19sZW5ndGhfOGNmZDJjNjQwOWFmODhhZAALA3diZzFfX3diZ19uZXd3aXRoYnl0ZW9mZnNldGFuZGxlbmd0aF9mMWRlYWQ0NGQxZmM3MjEyAAcDd2JnGl9fd2JnX25ld19lM2IzMjFkY2ZlZjg5ZmM3AAkDd2JnGl9fd2JnX3NldF9kMjM2NjFkMTkxNDhiMjI5AAoDd2JnHV9fd2JnX2xlbmd0aF82Y2E1Mjc2NjVkODk2OTRkAAsDd2JnMV9fd2JnX25ld3dpdGhieXRlb2Zmc2V0YW5kbGVuZ3RoX2U2YjdlNjlhY2Q0YzczNTQABwN3YmcaX193Ymdfc2V0XzEwYmFkOWJlZTBlOWM1OGIACgN3YmcdX193YmdfbGVuZ3RoXzNiNGYwMjIxODhhZThkYjYACwN3YmcfX193Ymdfc3ViYXJyYXlfNzY5ZTFlMGY4MWJiMjU5YgAHA3diZx9fX3diZ19zdWJhcnJheV8zYWFlZWM4OWJiMjU0NGYwAAcDd2JnJF9fd2JnX25ld3dpdGhsZW5ndGhfNWE1ZWZlMzEzY2ZkNTlmMQARA3diZxBfX3diaW5kZ2VuX3Rocm93AAEDd2JnEV9fd2JpbmRnZW5fbWVtb3J5ABIDd2JnH19fd2JpbmRnZW5faW5pdF9leHRlcm5yZWZfdGFibGUADgNhYAMAAQIIBQQCEwEMAAEBAgAAAQwBBAYFBQQAAQYFFAENBAAGBQQEAQQOAgECAQAIBAAVARYGCBcZGwUNAhAQBR0FAQMPAAIDAwMADAAAAQEBAAAABAECAAEAAQAAAQEDAwQJAnABLi5vAIABBQMBABEGCQF/AUGAgMAACwdiBgZtZW1vcnkCAAtzb3J0X3NwbGF0cwBNDXNvcnQzMl9zcGxhdHMATg5yYXljYXN0X3NwbGF0cwBCE19fd2JpbmRnZW5fZXhwb3J0XzABARBfX3diaW5kZ2VuX3N0YXJ0ABAJMwEAQQELLVhZV1xBZ0YuRUZETEtFRUhHST5RN086IWlfXmE7YGpKMiQrbk88IGtsVVpiYwrF3wFghCQCCX8BfiMAQRBrIggkAAJ/AkACQAJAAkACQAJAIABB9QFPBEBBACAAQc3/e08NBxogAEELaiIBQXhxIQVB7JbAACgCACIJRQ0EQR8hB0EAIAVrIQQgAEH0//8HTQRAIAVBBiABQQh2ZyIAa3ZBAXEgAEEBdGtBPmohBwsgB0ECdEHQk8AAaigCACIBRQRAQQAhAAwCC0EAIQAgBUEZIAdBAXZrQQAgB0EfRxt0IQMDQAJAIAEoAgRBeHEiBiAFSQ0AIAYgBWsiBiAETw0AIAEhAiAGIgQNAEEAIQQgASEADAQLIAEoAhQiBiAAIAYgASADQR12QQRxakEQaigCACIBRxsgACAGGyEAIANBAXQhAyABDQALDAELQeiWwAAoAgAiAkEQIABBC2pB+ANxIABBC0kbIgVBA3YiAHYiAUEDcQRAAkAgAUF/c0EBcSAAaiIGQQN0IgBB4JTAAGoiAyAAQeiUwABqKAIAIgEoAggiBEcEQCAEIAM2AgwgAyAENgIIDAELQeiWwAAgAkF+IAZ3cTYCAAsgASAAQQNyNgIEIAAgAWoiACAAKAIEQQFyNgIEIAFBCGoMBwsgBUHwlsAAKAIATQ0DAkACQCABRQRAQeyWwAAoAgAiAEUNBiAAaEECdEHQk8AAaigCACICKAIEQXhxIAVrIQQgAiEBA0ACQCACKAIQIgANACACKAIUIgANACABKAIYIQcCQAJAIAEgASgCDCIARgRAIAFBFEEQIAEoAhQiABtqKAIAIgINAUEAIQAMAgsgASgCCCICIAA2AgwgACACNgIIDAELIAFBFGogAUEQaiAAGyEDA0AgAyEGIAIiAEEUaiAAQRBqIAAoAhQiAhshAyAAQRRBECACG2ooAgAiAg0ACyAGQQA2AgALIAdFDQQgASABKAIcQQJ0QdCTwABqIgIoAgBHBEAgB0EQQRQgBygCECABRhtqIAA2AgAgAEUNBQwECyACIAA2AgAgAA0DQeyWwABB7JbAACgCAEF+IAEoAhx3cTYCAAwECyAAKAIEQXhxIAVrIgIgBCACIARJIgIbIQQgACABIAIbIQEgACECDAALAAsCQEECIAB0IgNBACADa3IgASAAdHFoIgZBA3QiAUHglMAAaiIDIAFB6JTAAGooAgAiACgCCCIERwRAIAQgAzYCDCADIAQ2AggMAQtB6JbAACACQX4gBndxNgIACyAAIAVBA3I2AgQgACAFaiIGIAEgBWsiA0EBcjYCBCAAIAFqIAM2AgBB8JbAACgCACIEBEAgBEF4cUHglMAAaiEBQfiWwAAoAgAhAgJ/QeiWwAAoAgAiBUEBIARBA3Z0IgRxRQRAQeiWwAAgBCAFcjYCACABDAELIAEoAggLIQQgASACNgIIIAQgAjYCDCACIAE2AgwgAiAENgIIC0H4lsAAIAY2AgBB8JbAACADNgIAIABBCGoMCAsgACAHNgIYIAEoAhAiAgRAIAAgAjYCECACIAA2AhgLIAEoAhQiAkUNACAAIAI2AhQgAiAANgIYCwJAAkAgBEEQTwRAIAEgBUEDcjYCBCABIAVqIgMgBEEBcjYCBCADIARqIAQ2AgBB8JbAACgCACIGRQ0BIAZBeHFB4JTAAGohAEH4lsAAKAIAIQICf0HolsAAKAIAIgVBASAGQQN2dCIGcUUEQEHolsAAIAUgBnI2AgAgAAwBCyAAKAIICyEGIAAgAjYCCCAGIAI2AgwgAiAANgIMIAIgBjYCCAwBCyABIAQgBWoiAEEDcjYCBCAAIAFqIgAgACgCBEEBcjYCBAwBC0H4lsAAIAM2AgBB8JbAACAENgIACyABQQhqDAYLIAAgAnJFBEBBACECQQIgB3QiAEEAIABrciAJcSIARQ0DIABoQQJ0QdCTwABqKAIAIQALIABFDQELA0AgACACIAAoAgRBeHEiAyAFayIGIARJIgcbIQkgACgCECIBRQRAIAAoAhQhAQsgAiAJIAMgBUkiABshAiAEIAYgBCAHGyAAGyEEIAEiAA0ACwsgAkUNACAFQfCWwAAoAgAiAE0gBCAAIAVrT3ENACACKAIYIQcCQAJAIAIgAigCDCIARgRAIAJBFEEQIAIoAhQiABtqKAIAIgENAUEAIQAMAgsgAigCCCIBIAA2AgwgACABNgIIDAELIAJBFGogAkEQaiAAGyEDA0AgAyEGIAEiAEEUaiAAQRBqIAAoAhQiARshAyAAQRRBECABG2ooAgAiAQ0ACyAGQQA2AgALIAdFDQIgAiACKAIcQQJ0QdCTwABqIgEoAgBHBEAgB0EQQRQgBygCECACRhtqIAA2AgAgAEUNAwwCCyABIAA2AgAgAA0BQeyWwABB7JbAACgCAEF+IAIoAhx3cTYCAAwCCwJAAkACQAJAAkAgBUHwlsAAKAIAIgFLBEAgBUH0lsAAKAIAIgBPBEAgBUGvgARqQYCAfHEiAkEQdkAAIQAgCEEEaiIBQQA2AgggAUEAIAJBgIB8cSAAQX9GIgIbNgIEIAFBACAAQRB0IAIbNgIAQQAgCCgCBCIBRQ0JGiAIKAIMIQZBgJfAACAIKAIIIgRBgJfAACgCAGoiADYCAEGEl8AAQYSXwAAoAgAiAiAAIAAgAkkbNgIAAkACQEH8lsAAKAIAIgIEQEHQlMAAIQADQCABIAAoAgAiAyAAKAIEIgdqRg0CIAAoAggiAA0ACwwCC0GMl8AAKAIAIgBBACAAIAFNG0UEQEGMl8AAIAE2AgALQZCXwABB/x82AgBB3JTAACAGNgIAQdSUwAAgBDYCAEHQlMAAIAE2AgBB7JTAAEHglMAANgIAQfSUwABB6JTAADYCAEHolMAAQeCUwAA2AgBB/JTAAEHwlMAANgIAQfCUwABB6JTAADYCAEGElcAAQfiUwAA2AgBB+JTAAEHwlMAANgIAQYyVwABBgJXAADYCAEGAlcAAQfiUwAA2AgBBlJXAAEGIlcAANgIAQYiVwABBgJXAADYCAEGclcAAQZCVwAA2AgBBkJXAAEGIlcAANgIAQaSVwABBmJXAADYCAEGYlcAAQZCVwAA2AgBBrJXAAEGglcAANgIAQaCVwABBmJXAADYCAEGolcAAQaCVwAA2AgBBtJXAAEGolcAANgIAQbCVwABBqJXAADYCAEG8lcAAQbCVwAA2AgBBuJXAAEGwlcAANgIAQcSVwABBuJXAADYCAEHAlcAAQbiVwAA2AgBBzJXAAEHAlcAANgIAQciVwABBwJXAADYCAEHUlcAAQciVwAA2AgBB0JXAAEHIlcAANgIAQdyVwABB0JXAADYCAEHYlcAAQdCVwAA2AgBB5JXAAEHYlcAANgIAQeCVwABB2JXAADYCAEHslcAAQeCVwAA2AgBB9JXAAEHolcAANgIAQeiVwABB4JXAADYCAEH8lcAAQfCVwAA2AgBB8JXAAEHolcAANgIAQYSWwABB+JXAADYCAEH4lcAAQfCVwAA2AgBBjJbAAEGAlsAANgIAQYCWwABB+JXAADYCAEGUlsAAQYiWwAA2AgBBiJbAAEGAlsAANgIAQZyWwABBkJbAADYCAEGQlsAAQYiWwAA2AgBBpJbAAEGYlsAANgIAQZiWwABBkJbAADYCAEGslsAAQaCWwAA2AgBBoJbAAEGYlsAANgIAQbSWwABBqJbAADYCAEGolsAAQaCWwAA2AgBBvJbAAEGwlsAANgIAQbCWwABBqJbAADYCAEHElsAAQbiWwAA2AgBBuJbAAEGwlsAANgIAQcyWwABBwJbAADYCAEHAlsAAQbiWwAA2AgBB1JbAAEHIlsAANgIAQciWwABBwJbAADYCAEHclsAAQdCWwAA2AgBB0JbAAEHIlsAANgIAQeSWwABB2JbAADYCAEHYlsAAQdCWwAA2AgBB/JbAACABQQ9qQXhxIgBBCGsiAjYCAEHglsAAQdiWwAA2AgBB9JbAACAEQShrIgMgASAAa2pBCGoiADYCACACIABBAXI2AgQgASADakEoNgIEQYiXwABBgICAATYCAAwICyACIANJIAEgAk1yDQAgACgCDCIDQQFxDQAgA0EBdiAGRg0DC0GMl8AAQYyXwAAoAgAiACABIAAgAUkbNgIAIAEgBGohA0HQlMAAIQACQAJAA0AgAyAAKAIAIgdHBEAgACgCCCIADQEMAgsLIAAoAgwiA0EBcQ0AIANBAXYgBkYNAQtB0JTAACEAA0ACQCACIAAoAgAiA08EQCACIAMgACgCBGoiB0kNAQsgACgCCCEADAELC0H8lsAAIAFBD2pBeHEiAEEIayIDNgIAQfSWwAAgBEEoayIJIAEgAGtqQQhqIgA2AgAgAyAAQQFyNgIEIAEgCWpBKDYCBEGIl8AAQYCAgAE2AgAgAiAHQSBrQXhxQQhrIgAgACACQRBqSRsiA0EbNgIEQdCUwAApAgAhCiADQRBqQdiUwAApAgA3AgAgAyAKNwIIQdyUwAAgBjYCAEHUlMAAIAQ2AgBB0JTAACABNgIAQdiUwAAgA0EIajYCACADQRxqIQADQCAAQQc2AgAgAEEEaiIAIAdJDQALIAIgA0YNByADIAMoAgRBfnE2AgQgAiADIAJrIgBBAXI2AgQgAyAANgIAIABBgAJPBEAgAiAAECIMCAsgAEH4AXFB4JTAAGohAQJ/QeiWwAAoAgAiA0EBIABBA3Z0IgBxRQRAQeiWwAAgACADcjYCACABDAELIAEoAggLIQAgASACNgIIIAAgAjYCDCACIAE2AgwgAiAANgIIDAcLIAAgATYCACAAIAAoAgQgBGo2AgQgAUEPakF4cUEIayICIAVBA3I2AgQgB0EPakF4cUEIayIEIAIgBWoiAGshBSAEQfyWwAAoAgBGDQMgBEH4lsAAKAIARg0EIAQoAgQiAUEDcUEBRgRAIAQgAUF4cSIBEB4gASAFaiEFIAEgBGoiBCgCBCEBCyAEIAFBfnE2AgQgACAFQQFyNgIEIAAgBWogBTYCACAFQYACTwRAIAAgBRAiDAYLIAVB+AFxQeCUwABqIQECf0HolsAAKAIAIgNBASAFQQN2dCIEcUUEQEHolsAAIAMgBHI2AgAgAQwBCyABKAIICyEDIAEgADYCCCADIAA2AgwgACABNgIMIAAgAzYCCAwFC0H0lsAAIAAgBWsiATYCAEH8lsAAQfyWwAAoAgAiACAFaiICNgIAIAIgAUEBcjYCBCAAIAVBA3I2AgQgAEEIagwIC0H4lsAAKAIAIQACQCABIAVrIgJBD00EQEH4lsAAQQA2AgBB8JbAAEEANgIAIAAgAUEDcjYCBCAAIAFqIgEgASgCBEEBcjYCBAwBC0HwlsAAIAI2AgBB+JbAACAAIAVqIgM2AgAgAyACQQFyNgIEIAAgAWogAjYCACAAIAVBA3I2AgQLIABBCGoMBwsgACAEIAdqNgIEQfyWwABB/JbAACgCACIAQQ9qQXhxIgFBCGsiAjYCAEH0lsAAQfSWwAAoAgAgBGoiAyAAIAFrakEIaiIBNgIAIAIgAUEBcjYCBCAAIANqQSg2AgRBiJfAAEGAgIABNgIADAMLQfyWwAAgADYCAEH0lsAAQfSWwAAoAgAgBWoiATYCACAAIAFBAXI2AgQMAQtB+JbAACAANgIAQfCWwABB8JbAACgCACAFaiIBNgIAIAAgAUEBcjYCBCAAIAFqIAE2AgALIAJBCGoMAwtBAEH0lsAAKAIAIgAgBU0NAhpB9JbAACAAIAVrIgE2AgBB/JbAAEH8lsAAKAIAIgAgBWoiAjYCACACIAFBAXI2AgQgACAFQQNyNgIEIABBCGoMAgsgACAHNgIYIAIoAhAiAQRAIAAgATYCECABIAA2AhgLIAIoAhQiAUUNACAAIAE2AhQgASAANgIYCwJAIARBEE8EQCACIAVBA3I2AgQgAiAFaiIAIARBAXI2AgQgACAEaiAENgIAIARBgAJPBEAgACAEECIMAgsgBEH4AXFB4JTAAGohAQJ/QeiWwAAoAgAiA0EBIARBA3Z0IgRxRQRAQeiWwAAgAyAEcjYCACABDAELIAEoAggLIQMgASAANgIIIAMgADYCDCAAIAE2AgwgACADNgIIDAELIAIgBCAFaiIAQQNyNgIEIAAgAmoiACAAKAIEQQFyNgIECyACQQhqCyAIQRBqJAALxgYBCH8CQAJAIAEgAEEDakF8cSICIABrIghJDQAgASAIayIGQQRJDQAgBkEDcSEHQQAhAQJAIAAgAkYiCQ0AAkAgACACayIEQXxLBEBBACECDAELQQAhAgNAIAEgACACaiIDLAAAQb9/SmogA0EBaiwAAEG/f0pqIANBAmosAABBv39KaiADQQNqLAAAQb9/SmohASACQQRqIgINAAsLIAkNACAAIAJqIQMDQCABIAMsAABBv39KaiEBIANBAWohAyAEQQFqIgQNAAsLIAAgCGohAgJAIAdFDQAgAiAGQXxxaiIALAAAQb9/SiEFIAdBAUYNACAFIAAsAAFBv39KaiEFIAdBAkYNACAFIAAsAAJBv39KaiEFCyAGQQJ2IQYgASAFaiEEA0AgAiEAIAZFDQJBwAEgBiAGQcABTxsiBUEDcSEHIAVBAnQhCEEAIQMgBkEETwRAIAAgCEHwB3FqIQkgACEBA0AgASgCACICQX9zQQd2IAJBBnZyQYGChAhxIANqIAEoAgQiAkF/c0EHdiACQQZ2ckGBgoQIcWogASgCCCICQX9zQQd2IAJBBnZyQYGChAhxaiABKAIMIgJBf3NBB3YgAkEGdnJBgYKECHFqIQMgAUEQaiIBIAlHDQALCyAGIAVrIQYgACAIaiECIANBCHZB/4H8B3EgA0H/gfwHcWpBgYAEbEEQdiAEaiEEIAdFDQALAn8gACAFQfwBcUECdGoiACgCACIBQX9zQQd2IAFBBnZyQYGChAhxIgEgB0EBRg0AGiABIAAoAgQiAUF/c0EHdiABQQZ2ckGBgoQIcWoiASAHQQJGDQAaIAAoAggiAEF/c0EHdiAAQQZ2ckGBgoQIcSABagsiAUEIdkH/gRxxIAFB/4H8B3FqQYGABGxBEHYgBGoPCyABRQRAQQAPCyABQQNxIQICQCABQQRJBEAMAQsgAUF8cSEFA0AgBCAAIANqIgEsAABBv39KaiABQQFqLAAAQb9/SmogAUECaiwAAEG/f0pqIAFBA2osAABBv39KaiEEIAUgA0EEaiIDRw0ACwsgAkUNACAAIANqIQEDQCAEIAEsAABBv39KaiEEIAFBAWohASACQQFrIgINAAsLIAQL3QUBBX8gACgCCCIDIAFJBEAgASADIgJrIgQgACgCACACa0sEQCAAIAIgBEEEQQQQJiAAKAIIIQILIAAoAgQiBiACQQJ0aiEFIARBAk8EQCAFIANBf3MgAWpBAnQQKhogASACakECdCADQQJ0ayAGakEEayEFIAIgBGpBAWshAgsgBUEANgIAIAAgAkEBajYCCAsgACgCFCIDIAFJBEAgASADIgJrIgQgACgCDCACa0sEQCAAQQxqIAIgBEEEQQQQJiAAKAIUIQILIAAoAhAiBiACQQJ0aiEFIARBAk8EQCAFIANBf3MgAWpBAnQQKhogASACakECdCADQQJ0ayAGakEEayEFIAIgBGpBAWshAgsgBUEANgIAIAAgAkEBajYCFAsgACgCOCIDIAFJBEAgASADIgJrIgQgACgCMCACa0sEQCAAQTBqIAIgBEEEQQQQJiAAKAI4IQILIAAoAjQiBiACQQJ0aiEFIARBAk8EQCAFIANBf3MgAWpBAnQQKhogASACakECdCADQQJ0ayAGakEEayEFIAIgBGpBAWshAgsgBUEANgIAIAAgAkEBajYCOAsgACgCICIDQf//A00EQCADIQFBgIAEIANrIgIgACgCGCADa0sEQCAAQRhqIAMgAkEEQQQQJiAAKAIgIQELIAAoAhwiBSABQQJ0IgRqIQIgA0H//wNHBEAgAkH8/w8gA0ECdCICaxAqGiAEIAJrIAVqQfz/D2ohAiABIANrQf//A2ohAQsgAkEANgIAIAAgAUEBajYCIAsgACgCLCIDQf//A00EQCADIQFBgIAEIANrIgIgACgCJCADa0sEQCAAQSRqIAMgAkEEQQQQJiAAKAIsIQELIAAoAigiBSABQQJ0IgRqIQIgA0H//wNHBEAgAkH8/w8gA0ECdCICaxAqGiAEIAJrIAVqQfz/D2ohAiABIANrQf//A2ohAQsgAkEANgIAIAAgAUEBajYCLAsLqQUBB38CQCAAKAIIQQFxRSIEIAAoAgAiCUVxRQRAAkAgBA0AIAEgAmohBwJAIAAoAgwiBkUEQCABIQQMAQsgASEEA0AgBCIDIAdGDQICfyADQQFqIAMsAAAiCEEATg0AGiADQQJqIAhBYEkNABogA0EDaiAIQXBJDQAaIANBBGoLIgQgA2sgBWohBSAGQQFrIgYNAAsLIAQgB0YNACAELAAAGiAFIAICfwJAIAVFDQAgAiAFSwRAIAEgBWosAABBv39KDQFBAAwCCyACIAVGDQBBAAwBCyABCyIDGyECIAMgASADGyEBCyAJRQ0BIAAoAgQhBwJAIAJBEE8EQCABIAIQEiEDDAELIAJFBEBBACEDDAELIAJBA3EhBgJAIAJBBEkEQEEAIQNBACEFDAELIAJBDHEhCEEAIQNBACEFA0AgAyABIAVqIgQsAABBv39KaiAEQQFqLAAAQb9/SmogBEECaiwAAEG/f0pqIARBA2osAABBv39KaiEDIAggBUEEaiIFRw0ACwsgBkUNACABIAVqIQQDQCADIAQsAABBv39KaiEDIARBAWohBCAGQQFrIgYNAAsLAkAgAyAHSQRAIAcgA2shBEEAIQMCQAJAAkAgAC0AIEEBaw4CAAECCyAEIQNBACEEDAELIARBAXYhAyAEQQFqQQF2IQQLIANBAWohAyAAKAIQIQYgACgCGCEFIAAoAhQhAANAIANBAWsiA0UNAiAAIAYgBSgCEBEAAEUNAAtBAQ8LDAILIAAgASACIAUoAgwRAgAEQEEBDwtBACEDA0AgAyAERgRAQQAPCyADQQFqIQMgACAGIAUoAhARAABFDQALIANBAWsgBEkPCyAAKAIUIAEgAiAAKAIYKAIMEQIADwsgACgCFCABIAIgACgCGCgCDBECAAu/BQEIf0ErQYCAxAAgACgCHCIIQQFxIgYbIQwgBCAGaiEGAkAgCEEEcUUEQEEAIQEMAQsCQCACQRBPBEAgASACEBIhBQwBCyACRQRADAELIAJBA3EhCQJAIAJBBEkEQAwBCyACQQxxIQoDQCAFIAEgB2oiCywAAEG/f0pqIAtBAWosAABBv39KaiALQQJqLAAAQb9/SmogC0EDaiwAAEG/f0pqIQUgCiAHQQRqIgdHDQALCyAJRQ0AIAEgB2ohBwNAIAUgBywAAEG/f0pqIQUgB0EBaiEHIAlBAWsiCQ0ACwsgBSAGaiEGCyAAKAIARQRAIAAoAhQiBiAAKAIYIgAgDCABIAIQPwRAQQEPCyAGIAMgBCAAKAIMEQIADwsCQAJAAkAgBiAAKAIEIgdPBEAgACgCFCIGIAAoAhgiACAMIAEgAhA/RQ0BQQEPCyAIQQhxRQ0BIAAoAhAhCCAAQTA2AhAgAC0AICEKQQEhBSAAQQE6ACAgACgCFCIJIAAoAhgiCyAMIAEgAhA/DQIgByAGa0EBaiEFAkADQCAFQQFrIgVFDQEgCUEwIAsoAhARAABFDQALQQEPCyAJIAMgBCALKAIMEQIABEBBAQ8LIAAgCjoAICAAIAg2AhBBAA8LIAYgAyAEIAAoAgwRAgAhBQwBCyAHIAZrIQYCQAJAAkAgAC0AICIFQQFrDgMAAQACCyAGIQVBACEGDAELIAZBAXYhBSAGQQFqQQF2IQYLIAVBAWohBSAAKAIQIQogACgCGCEIIAAoAhQhAAJAA0AgBUEBayIFRQ0BIAAgCiAIKAIQEQAARQ0AC0EBDwtBASEFIAAgCCAMIAEgAhA/DQAgACADIAQgCCgCDBECAA0AQQAhBQNAIAUgBkYEQEEADwsgBUEBaiEFIAAgCiAIKAIQEQAARQ0ACyAFQQFrIAZJDwsgBQv+BQEFfyAAQQhrIgEgAEEEaygCACIDQXhxIgBqIQICQAJAIANBAXENACADQQJxRQ0BIAEoAgAiAyAAaiEAIAEgA2siAUH4lsAAKAIARgRAIAIoAgRBA3FBA0cNAUHwlsAAIAA2AgAgAiACKAIEQX5xNgIEIAEgAEEBcjYCBCACIAA2AgAPCyABIAMQHgsCQAJAAkACQAJAIAIoAgQiA0ECcUUEQCACQfyWwAAoAgBGDQIgAkH4lsAAKAIARg0DIAIgA0F4cSICEB4gASAAIAJqIgBBAXI2AgQgACABaiAANgIAIAFB+JbAACgCAEcNAUHwlsAAIAA2AgAPCyACIANBfnE2AgQgASAAQQFyNgIEIAAgAWogADYCAAsgAEGAAkkNAiABIAAQIkEAIQFBkJfAAEGQl8AAKAIAQQFrIgA2AgAgAA0EQdiUwAAoAgAiAARAA0AgAUEBaiEBIAAoAggiAA0ACwtBkJfAAEH/HyABIAFB/x9NGzYCAA8LQfyWwAAgATYCAEH0lsAAQfSWwAAoAgAgAGoiADYCACABIABBAXI2AgRB+JbAACgCACABRgRAQfCWwABBADYCAEH4lsAAQQA2AgALIABBiJfAACgCACIDTQ0DQfyWwAAoAgAiAkUNA0EAIQBB9JbAACgCACIEQSlJDQJB0JTAACEBA0AgAiABKAIAIgVPBEAgAiAFIAEoAgRqSQ0ECyABKAIIIQEMAAsAC0H4lsAAIAE2AgBB8JbAAEHwlsAAKAIAIABqIgA2AgAgASAAQQFyNgIEIAAgAWogADYCAA8LIABB+AFxQeCUwABqIQICf0HolsAAKAIAIgNBASAAQQN2dCIAcUUEQEHolsAAIAAgA3I2AgAgAgwBCyACKAIICyEAIAIgATYCCCAAIAE2AgwgASACNgIMIAEgADYCCA8LQdiUwAAoAgAiAQRAA0AgAEEBaiEAIAEoAggiAQ0ACwtBkJfAAEH/HyAAIABB/x9NGzYCACADIARPDQBBiJfAAEF/NgIACwvpBAEFfwJ/AkAgAkECTwRAIAEoAgQiBEH//wFxRQRAIARBEHQMAwsgBEH/B3EhBSAEQYCAAnEhAyAEQYD4AXEiBkGA+AFGBEAgA0EQdCEDIANBgICA/AdyIAVFDQMaIAMgBUENdHJBgICA/gdyDAMLIANBEHQhAyAGRQ0BIAZBDXRBgICA/ABxIAVBDXRyQYCAgMADaiADcgwCC0EBQQFB9IHAABA1AAsgBSAFZ0EQayIFQf//A3FBCGp0Qf///wNxIANBgICA2ANyIAVBF3RrcgshBQJ/IARBgIB8cSAEQRB2IgNB//8BcUUNABogA0H/B3EhBCADQYCAAnEhBiADQYD4AXEiB0GA+AFGBEAgBkEQdCEGIAZBgICA/AdyIARFDQEaIAYgA0ENdHJBgICA/gdyDAELIAZBEHQhAyAHQQ10QYCAgPwAcSAEQQ10ckGAgIDAA2ogA3IgBw0AGiAEIARnQRBrIgRB//8DcUEIanRB////A3EgA0GAgIDYA3IgBEEXdGtyCyEEIAACfwJAIAJBAkcEQCABKAIIIgJB//8BcUUEQCACQRB0DAMLIAJB/wdxIQEgAkGAgAJxIQMgAkGA+AFxIgJBgPgBRgRAIANBEHQhAiACQYCAgPwHciABRQ0DGiACIAFBDXRyQYCAgP4HcgwDCyADQRB0IQMgAkUNASACQQ10QYCAgPwAcSABQQ10ckGAgIDAA2ogA3IMAgtBAkECQYSCwAAQNQALIAEgAWdBEGsiAUH//wNxQQhqdEH///8DcSADQYCAgNgDciABQRd0a3ILNgIIIAAgBDYCBCAAIAU2AgAL6wQBCn8jAEEwayIDJAAgA0EDOgAsIANBIDYCHCADQQA2AiggAyABNgIkIAMgADYCICADQQA2AhQgA0EANgIMAn8CQAJAAkAgAigCECIKRQRAIAIoAgwiAEUNASACKAIIIgEgAEEDdGohBCAAQQFrQf////8BcUEBaiEHIAIoAgAhAANAIABBBGooAgAiBQRAIAMoAiAgACgCACAFIAMoAiQoAgwRAgANBAsgASgCACADQQxqIAEoAgQRAAANAyAAQQhqIQAgAUEIaiIBIARHDQALDAELIAIoAhQiAEUNACAAQQV0IQsgAEEBa0H///8/cUEBaiEHIAIoAgghBSACKAIAIQADQCAAQQRqKAIAIgEEQCADKAIgIAAoAgAgASADKAIkKAIMEQIADQMLIAMgCCAKaiIBQRBqKAIANgIcIAMgAUEcai0AADoALCADIAFBGGooAgA2AiggAUEMaigCACEEQQAhCUEAIQYCQAJAAkAgAUEIaigCAEEBaw4CAAIBCyAEQQN0IAVqIgwoAgANASAMKAIEIQQLQQEhBgsgAyAENgIQIAMgBjYCDCABQQRqKAIAIQQCQAJAAkAgASgCAEEBaw4CAAIBCyAEQQN0IAVqIgYoAgANASAGKAIEIQQLQQEhCQsgAyAENgIYIAMgCTYCFCAFIAFBFGooAgBBA3RqIgEoAgAgA0EMaiABKAIEEQAADQIgAEEIaiEAIAsgCEEgaiIIRw0ACwsgByACKAIETw0BIAMoAiAgAigCACAHQQN0aiIAKAIAIAAoAgQgAygCJCgCDBECAEUNAQtBAQwBC0EACyADQTBqJAALsgQCAn0EfyMAQRBrIQQgALwiBUEfdiEGAkACfSAAAn8CQAJAAkACQCAFQf////8HcSIDQdDYupUETwRAIANBgICA/AdLBEAgAA8LIAVBAEgiBUUgA0GX5MWVBEtxDQIgBUUNASAEQwAAgIAgAJU4AgggBCoCCBogA0G047+WBE0NAQwHCyADQZjkxfUDTQRAIANBgICAyANNDQNBACEDIAAMBgsgA0GSq5T8A00NAwsgAEM7qrg/lCAGQQJ0QYiSwABqKgIAkiIBQwAAAM9gIQRB/////wcCfyABi0MAAABPXQRAIAGoDAELQYCAgIB4C0GAgICAeCAEGyABQ////05eG0EAIAEgAVsbDAMLIABDAAAAf5QPCyAEIABDAAAAf5I4AgwgBCoCDBogAEMAAIA/kg8LIAZFIAZrCyIDsiIBQwByMb+UkiIAIAFDjr6/NZQiApMLIQEgACABIAEgASABlCIAIABDFVI1u5RDj6oqPpKUkyIAlEMAAABAIACTlSACk5JDAACAP5IhASADRQ0AAkACQAJAIANB/wBMBEAgA0GCf04NAyABQwAAgAyUIQEgA0Gbfk0NASADQeYAaiEDDAMLIAFDAAAAf5QhASADQf4BSw0BIANB/wBrIQMMAgsgAUMAAIAMlCEBQbZ9IAMgA0G2fU0bQcwBaiEDDAELIAFDAAAAf5QhAUH9AiADIANB/QJPG0H+AWshAwsgASADQRd0QYCAgPwDar6UIQELIAEL+QMBAn8gACABaiECAkACQCAAKAIEIgNBAXENACADQQJxRQ0BIAAoAgAiAyABaiEBIAAgA2siAEH4lsAAKAIARgRAIAIoAgRBA3FBA0cNAUHwlsAAIAE2AgAgAiACKAIEQX5xNgIEIAAgAUEBcjYCBCACIAE2AgAMAgsgACADEB4LAkACQAJAIAIoAgQiA0ECcUUEQCACQfyWwAAoAgBGDQIgAkH4lsAAKAIARg0DIAIgA0F4cSICEB4gACABIAJqIgFBAXI2AgQgACABaiABNgIAIABB+JbAACgCAEcNAUHwlsAAIAE2AgAPCyACIANBfnE2AgQgACABQQFyNgIEIAAgAWogATYCAAsgAUGAAk8EQCAAIAEQIg8LIAFB+AFxQeCUwABqIQICf0HolsAAKAIAIgNBASABQQN2dCIBcUUEQEHolsAAIAEgA3I2AgAgAgwBCyACKAIICyEBIAIgADYCCCABIAA2AgwgACACNgIMIAAgATYCCA8LQfyWwAAgADYCAEH0lsAAQfSWwAAoAgAgAWoiATYCACAAIAFBAXI2AgQgAEH4lsAAKAIARw0BQfCWwABBADYCAEH4lsAAQQA2AgAPC0H4lsAAIAA2AgBB8JbAAEHwlsAAKAIAIAFqIgE2AgAgACABQQFyNgIEIAAgAWogATYCAAsLggMBCX8jAEEgayIEJAAQIyIAKAIQIQUgACgCDCEIIABCADcCDCAAKAIEIQYgACgCCCEDIABCBDcCBCAAKAIAIQIgAEEANgIAAkAgAyAIRgRAAkAgAiADRgRA0G9BgAEgAiACQYABTRsiB/wPASIBQX9GDQMCQCAFRQRAIAEhBQwBCyACIAVqIAFHDQQLIAIgB2oiByACSSAHQf////8DS3INAyAHQQJ0IgFB/P///wdLDQMgBCACBH8gBCAGNgIUIAQgAkECdDYCHEEEBUEACzYCGCAEQQhqQQQgASAEQRRqEDAgBCgCCEEBRg0DIAQoAgwhBiACIQEgByECDAELIAIgAyIBTQ0CCyAGIAFBAnRqIANBAWo2AgAgAUEBaiEDCyADIAhNDQAgBiAIQQJ0aigCACEBIAAgBTYCECAAIAE2AgwgACADNgIIIAAoAgQhAyAAIAY2AgQgACgCACEBIAAgAjYCACABBEAgAyABQQJ0EGULIARBIGokACAFIAhqDwsAC+cCAQV/AkBBzf97QRAgACAAQRBNGyIAayABTQ0AIABBECABQQtqQXhxIAFBC0kbIgRqQQxqEBEiAkUNACACQQhrIQECQCAAQQFrIgMgAnFFBEAgASEADAELIAJBBGsiBSgCACIGQXhxIAIgA2pBACAAa3FBCGsiAiAAQQAgAiABa0EQTRtqIgAgAWsiAmshAyAGQQNxBEAgACADIAAoAgRBAXFyQQJyNgIEIAAgA2oiAyADKAIEQQFyNgIEIAUgAiAFKAIAQQFxckECcjYCACABIAJqIgMgAygCBEEBcjYCBCABIAIQGgwBCyABKAIAIQEgACADNgIEIAAgASACajYCAAsCQCAAKAIEIgFBA3FFDQAgAUF4cSICIARBEGpNDQAgACAEIAFBAXFyQQJyNgIEIAAgBGoiASACIARrIgRBA3I2AgQgACACaiICIAIoAgRBAXI2AgQgASAEEBoLIABBCGohAwsgAwv7AgEHfyMAQRBrIgQkAAJAAkACQAJAAkAgASgCBCICRQ0AIAEoAgAhByACQQNxIQUCQCACQQRJBEBBACECDAELIAdBHGohAyACQXxxIQhBACECA0AgAygCACADQQhrKAIAIANBEGsoAgAgA0EYaygCACACampqaiECIANBIGohAyAIIAZBBGoiBkcNAAsLIAUEQCAGQQN0IAdqQQRqIQMDQCADKAIAIAJqIQIgA0EIaiEDIAVBAWsiBQ0ACwsgASgCDARAIAJBAEgNASAHKAIERSACQRBJcQ0BIAJBAXQhAgtBACEFIAJBAEgNAyACDQELQQEhA0EAIQIMAQtBsZPAAC0AABpBASEFIAJBARBdIgNFDQELIARBADYCCCAEIAM2AgQgBCACNgIAIARBwIvAACABEBhFDQFBqIzAAEHWACAEQQ9qQZiMwABBkI3AABAzAAsgBSACEFIACyAAIAQpAgA3AgAgAEEIaiAEQQhqKAIANgIAIARBEGokAAvxAgEEfyAAKAIMIQICQAJAIAFBgAJPBEAgACgCGCEDAkACQCAAIAJGBEAgAEEUQRAgACgCFCICG2ooAgAiAQ0BQQAhAgwCCyAAKAIIIgEgAjYCDCACIAE2AggMAQsgAEEUaiAAQRBqIAIbIQQDQCAEIQUgASICQRRqIAJBEGogAigCFCIBGyEEIAJBFEEQIAEbaigCACIBDQALIAVBADYCAAsgA0UNAiAAIAAoAhxBAnRB0JPAAGoiASgCAEcEQCADQRBBFCADKAIQIABGG2ogAjYCACACRQ0DDAILIAEgAjYCACACDQFB7JbAAEHslsAAKAIAQX4gACgCHHdxNgIADAILIAAoAggiACACRwRAIAAgAjYCDCACIAA2AggPC0HolsAAQeiWwAAoAgBBfiABQQN2d3E2AgAPCyACIAM2AhggACgCECIBBEAgAiABNgIQIAEgAjYCGAsgACgCFCIARQ0AIAIgADYCFCAAIAI2AhgLC7YCAQd/AkAgAkEQSQRAIAAhAwwBCyAAQQAgAGtBA3EiBGohBSAEBEAgACEDIAEhBgNAIAMgBi0AADoAACAGQQFqIQYgA0EBaiIDIAVJDQALCyAFIAIgBGsiCEF8cSIHaiEDAkAgASAEaiIEQQNxBEAgB0EATA0BIARBA3QiAkEYcSEJIARBfHEiBkEEaiEBQQAgAmtBGHEhAiAGKAIAIQYDQCAFIAYgCXYgASgCACIGIAJ0cjYCACABQQRqIQEgBUEEaiIFIANJDQALDAELIAdBAEwNACAEIQEDQCAFIAEoAgA2AgAgAUEEaiEBIAVBBGoiBSADSQ0ACwsgCEEDcSECIAQgB2ohAQsgAgRAIAIgA2ohAgNAIAMgAS0AADoAACABQQFqIQEgA0EBaiIDIAJJDQALCyAAC78CAQN/IwBBEGsiAiQAAkAgAUGAAU8EQCACQQA2AgwCfyABQYAQTwRAIAFBgIAETwRAIAJBDGpBA3IhBCACIAFBEnZB8AFyOgAMIAIgAUEGdkE/cUGAAXI6AA4gAiABQQx2QT9xQYABcjoADUEEDAILIAJBDGpBAnIhBCACIAFBDHZB4AFyOgAMIAIgAUEGdkE/cUGAAXI6AA1BAwwBCyACQQxqQQFyIQQgAiABQQZ2QcABcjoADEECCyEDIAQgAUE/cUGAAXI6AAAgAyAAKAIAIAAoAggiAWtLBEAgACABIAMQKSAAKAIIIQELIAAoAgQgAWogAkEMaiADEB8aIAAgASADajYCCAwBCyAAKAIIIgMgACgCAEYEQCAAECgLIAAgA0EBajYCCCAAKAIEIANqIAE6AAALIAJBEGokAEEAC70CAQJ/IwBBEGsiAiQAAkAgAUGAAU8EQCACQQA2AgwCfyABQYAQTwRAIAFBgIAETwRAIAIgAUE/cUGAAXI6AA8gAiABQRJ2QfABcjoADCACIAFBBnZBP3FBgAFyOgAOIAIgAUEMdkE/cUGAAXI6AA1BBAwCCyACIAFBP3FBgAFyOgAOIAIgAUEMdkHgAXI6AAwgAiABQQZ2QT9xQYABcjoADUEDDAELIAIgAUE/cUGAAXI6AA0gAiABQQZ2QcABcjoADEECCyEBIAEgACgCACAAKAIIIgNrSwRAIAAgAyABECUgACgCCCEDCyAAKAIEIANqIAJBDGogARAfGiAAIAEgA2o2AggMAQsgACgCCCIDIAAoAgBGBEAgABAoCyAAIANBAWo2AgggACgCBCADaiABOgAACyACQRBqJABBAAvEAgEEfyAAQgA3AhAgAAJ/QQAgAUGAAkkNABpBHyABQf///wdLDQAaIAFBBiABQQh2ZyIDa3ZBAXEgA0EBdGtBPmoLIgI2AhwgAkECdEHQk8AAaiEEQQEgAnQiA0HslsAAKAIAcUUEQCAEIAA2AgAgACAENgIYIAAgADYCDCAAIAA2AghB7JbAAEHslsAAKAIAIANyNgIADwsCQAJAIAEgBCgCACIDKAIEQXhxRgRAIAMhAgwBCyABQRkgAkEBdmtBACACQR9HG3QhBQNAIAMgBUEddkEEcWpBEGoiBCgCACICRQ0CIAVBAXQhBSACIQMgAigCBEF4cSABRw0ACwsgAigCCCIBIAA2AgwgAiAANgIIIABBADYCGCAAIAI2AgwgACABNgIIDwsgBCAANgIAIAAgAzYCGCAAIAA2AgwgACAANgIIC/MCAQR/IwBBMGsiACQAAkACQEGQksAAKAIARQRAQaiSwAAoAgAhAUGoksAAQQA2AgAgAUUNASAAQRhqIAERBQAgAEEQaiICIABBJGopAgA3AwAgACAAKQIcNwMIIAAoAhghAUGQksAAKAIAIgMNAgJAIANFDQBBlJLAACgCACICRQ0AQZiSwAAoAgAgAkECdBBlC0GUksAAIAE2AgBBkJLAAEEBNgIAQZiSwAAgACkDCDcCAEGgksAAIABBEGopAwA3AgALIABBMGokAEGUksAADwsgAEEANgIoIABBATYCHCAAQaCHwAA2AhggAEIENwIgIABBGGpBiIjAABBDAAsgAEEoaiACKQMANwIAIAAgACkDCDcCICAAIAE2AhwgAEEBNgIYAkAgAEEYaiIBKAIARQ0AIAEoAgQiAkUNACABKAIIIAJBAnQQZQsgAEEANgIoIABBATYCHCAAQaiIwAA2AhggAEIENwIgIAFBsIjAABBDAAuoAgIDfwF+IwBBQGoiAiQAIAEoAgBBgICAgHhGBEAgASgCDCEDIAJBJGoiBEEANgIAIAJCgICAgBA3AhwgAkEwaiADKAIAIgNBCGopAgA3AwAgAkE4aiADQRBqKQIANwMAIAIgAykCADcDKCACQRxqQcCIwAAgAkEoahAYGiACQRhqIAQoAgAiAzYCACACIAIpAhwiBTcDECABQQhqIAM2AgAgASAFNwIACyABKQIAIQUgAUKAgICAEDcCACACQQhqIgMgAUEIaiIBKAIANgIAIAFBADYCAEGxk8AALQAAGiACIAU3AwBBDEEEEF0iAUUEQEEEQQwQbQALIAEgAikDADcCACABQQhqIAMoAgA2AgAgAEHgisAANgIEIAAgATYCACACQUBrJAAL0gECBH8BfiMAQSBrIgMkACABIAEgAmoiAksEQEEAQQAQUgALQQggACgCACIEQQF0IgEgAiABIAJLGyICIAJBCEkb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QQRqrUKAgICA4ACENwMoIAEgAa1CgICAgOAAhDcDICABIAFBIGo2AhAgAUEIakHIj8AAEEMAC2kCAX8BfiMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBAjYCDCADQfyNwAA2AgggA0ICNwIUIANCgICAgOAAIgQgA62ENwMoIAMgBCADQQRqrYQ3AyAgAyADQSBqNgIQIANBCGogAhBDAAtpAgF/AX4jAEEwayIDJAAgAyAANgIAIAMgATYCBCADQQI2AgwgA0H4kcAANgIIIANCAjcCFCADQoCAgIDgACIEIANBBGqthDcDKCADIAQgA62ENwMgIAMgA0EgajYCECADQQhqIAIQQwALZgAjAEEwayIAJABBsJPAAC0AAARAIABBAjYCDCAAQbCKwAA2AgggAEIBNwIUIAAgATYCLCAAIABBLGqtQoCAgIDgAIQ3AyAgACAAQSBqNgIQIABBCGpB0IrAABBDAAsgAEEwaiQAC5QBAgN/AW8jAEEgayIDJAAgAyAAKAIAEHAiBDYCACADIAI2AgQgAiAERwRAIANBADYCCCADIANBBGogA0EIahBAAAsQWyIEEFMiBSUBEAUhBhAbIgIgBiYBIAVBhAFPBEAgBRAtCyACIAAoAgAgAUECdhBkIAJBhAFPBEAgAhAtCyAEQYQBTwRAIAQQLQsgA0EgaiQAC08BAX8jAEEwayIAJAAgAEEBNgIMIABBwI3AADYCCCAAQgE3AhQgACAAQS9qrUKAgICAoAWENwMgIAAgAEEgajYCECAAQQhqQcSBwAAQQwALQQEBfyACIAAoAgAgACgCCCIDa0sEQCAAIAMgAhAlIAAoAgghAwsgACgCBCADaiABIAIQHxogACACIANqNgIIQQALTQECf0Gxk8AALQAAGiABKAIEIQIgASgCACEDQQhBBBBdIgFFBEBBBEEIEG0ACyABIAI2AgQgASADNgIAIABB8IrAADYCBCAAIAE2AgALQQEBfyACIAAoAgAgACgCCCIDa0sEQCAAIAMgAhApIAAoAgghAwsgACgCBCADaiABIAIQHxogACACIANqNgIIQQALQQEBfyMAQSBrIgIkACACQQA2AhAgAkEBNgIEIAJCBDcCCCACQS42AhwgAiAANgIYIAIgAkEYajYCACACIAEQQwALswIBA38gACgCACECIAEoAhwiAEEQcUUE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ZCByZWN1cnNpdmVseSBvciBhZnRlciBiZWluZyBkcm9wcGVkTGF6eSBpbnN0YW5jZSBoYXMgcHJldmlvdXNseSBiZWVuIHBvaXNvbmVkdgMQACoAAAAvVXNlcnMvZG1hcmNvcy8uY2FyZ28vcmVnaXN0cnkvc3JjL2luZGV4LmNyYXRlcy5pby02ZjE3ZDIyYmJhMTUwMDFmL29uY2VfY2VsbC0xLjIxLjMvc3JjL2xpYi5ycwCoAxAAXwAAAAgDAAAZAAAAcmVlbnRyYW50IGluaXQAABgEEAAOAAAAqAMQAF8AAAB6AgAADQAAABYAAAAMAAAABAAAABcAAAAYAAAAGQAAAC9ydXN0L2RlcHMvZGxtYWxsb2MtMC4yLjYvc3JjL2RsbWFsbG9jLnJzYXNzZXJ0aW9uIGZhaWxlZDogcHNpemUgPj0gc2l6ZSArIG1pbl9vdmVyaGVhZABYBBAAKQAAAKgEAAAJAAAAYXNzZXJ0aW9uIGZhaWxlZDogcHNpemUgPD0gc2l6ZSArIG1heF9vdmVyaGVhZAAAWAQQACkAAACuBAAADQAAAEFjY2Vzc0Vycm9ybWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAAAAAsFEAAVAAAAIAUQAA0AAABzdGQvc3JjL2FsbG9jLnJzQAUQABAAAABjAQAACQAAABYAAAAMAAAABAAAABoAAAAAAAAACAAAAAQAAAAbAAAAAAAAAAgAAAAEAAAAHAAAAB0AAAAeAAAAHwAAACAAAAAQAAAABAAAACEAAAAiAAAAIwAAACQAAABFcnJvcgAAACUAAAAMAAAABAAAACYAAAAnAAAAKAAAAGNhcGFjaXR5IG92ZXJmbG93AAAA2AUQABEAAABhbGxvYy9zcmMvcmF3X3ZlYy5yc/QFEAAUAAAAGAAAAAUAQaCMwAAL8AUBAAAAKQAAAGEgZm9ybWF0dGluZyB0cmFpdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB3aGVuIHRoZSB1bmRlcmx5aW5nIHN0cmVhbSBkaWQgbm90YWxsb2Mvc3JjL2ZtdC5ycwAAfgYQABAAAAB+AgAADgAAAEJvcnJvd011dEVycm9yYWxyZWFkeSBib3Jyb3dlZDogrgYQABIAAABpbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIAAAyAYQACAAAADoBhAAEgAAAD09IT1tYXRjaGVzYXNzZXJ0aW9uIGBsZWZ0ICByaWdodGAgZmFpbGVkCiAgbGVmdDogCiByaWdodDogABcHEAAQAAAAJwcQABcAAAA+BxAACQAAACByaWdodGAgZmFpbGVkOiAKICBsZWZ0OiAAAAAXBxAAEAAAAGAHEAAQAAAAcAcQAAkAAAA+BxAACQAAADogAAABAAAAAAAAAJwHEAACAAAAfSB9Y29yZS9zcmMvZm10L251bS5ycwAAswcQABMAAABmAAAAFwAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlyYW5nZSBzdGFydCBpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggAACiCBAAEgAAALQIEAAiAAAAcmFuZ2UgZW5kIGluZGV4IOgIEAAQAAAAtAgQACIAAAAAAAA/AAAAvwBBqJLAAAsBFABwCXByb2R1Y2VycwIIbGFuZ3VhZ2UBBFJ1c3QADHByb2Nlc3NlZC1ieQMFcnVzdGMdMS44My4wICg5MGIzNWE2MjMgMjAyNC0xMS0yNikGd2FscnVzBjAuMjMuMwx3YXNtLWJpbmRnZW4HMC4yLjEwMABJD3RhcmdldF9mZWF0dXJlcwQrD211dGFibGUtZ2xvYmFscysIc2lnbi1leHQrD3JlZmVyZW5jZS10eXBlcysKbXVsdGl2YWx1ZQ==", self.location.href);\n }\n const imports = __wbg_get_imports();\n if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) {\n module_or_path = fetch(module_or_path);\n }\n const { instance, module } = await __wbg_load(await module_or_path, imports);\n return __wbg_finalize_init(instance, module);\n }\n var ch2 = {};\n var wk = function(c, id, msg, transfer, cb) {\n var w = new Worker(ch2[id] || (ch2[id] = URL.createObjectURL(new Blob([\n c + \';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})\'\n ], { type: "text/javascript" }))));\n w.onmessage = function(e) {\n var d = e.data, ed = d.$e$;\n if (ed) {\n var err2 = new Error(ed[0]);\n err2["code"] = ed[1];\n err2.stack = ed[2];\n cb(err2, null);\n } else\n cb(null, d);\n };\n w.postMessage(msg, transfer);\n return w;\n };\n var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;\n var fleb = new u8([\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 1,\n 1,\n 1,\n 1,\n 2,\n 2,\n 2,\n 2,\n 3,\n 3,\n 3,\n 3,\n 4,\n 4,\n 4,\n 4,\n 5,\n 5,\n 5,\n 5,\n 0,\n /* unused */\n 0,\n 0,\n /* impossible */\n 0\n ]);\n var fdeb = new u8([\n 0,\n 0,\n 0,\n 0,\n 1,\n 1,\n 2,\n 2,\n 3,\n 3,\n 4,\n 4,\n 5,\n 5,\n 6,\n 6,\n 7,\n 7,\n 8,\n 8,\n 9,\n 9,\n 10,\n 10,\n 11,\n 11,\n 12,\n 12,\n 13,\n 13,\n /* unused */\n 0,\n 0\n ]);\n var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n var freb = function(eb, start) {\n var b = new u16(31);\n for (var i2 = 0; i2 < 31; ++i2) {\n b[i2] = start += 1 << eb[i2 - 1];\n }\n var r = new i32(b[30]);\n for (var i2 = 1; i2 < 30; ++i2) {\n for (var j = b[i2]; j < b[i2 + 1]; ++j) {\n r[j] = j - b[i2] << 5 | i2;\n }\n }\n return { b, r };\n };\n var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;\n fl[28] = 258, revfl[258] = 28;\n var _b = freb(fdeb, 0), fd = _b.b;\n var rev = new u16(32768);\n for (var i = 0; i < 32768; ++i) {\n var x = (i & 43690) >> 1 | (i & 21845) << 1;\n x = (x & 52428) >> 2 | (x & 13107) << 2;\n x = (x & 61680) >> 4 | (x & 3855) << 4;\n rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;\n }\n var hMap = function(cd, mb, r) {\n var s = cd.length;\n var i2 = 0;\n var l = new u16(mb);\n for (; i2 < s; ++i2) {\n if (cd[i2])\n ++l[cd[i2] - 1];\n }\n var le = new u16(mb);\n for (i2 = 1; i2 < mb; ++i2) {\n le[i2] = le[i2 - 1] + l[i2 - 1] << 1;\n }\n var co;\n if (r) {\n co = new u16(1 << mb);\n var rvb = 15 - mb;\n for (i2 = 0; i2 < s; ++i2) {\n if (cd[i2]) {\n var sv = i2 << 4 | cd[i2];\n var r_1 = mb - cd[i2];\n var v = le[cd[i2] - 1]++ << r_1;\n for (var m = v | (1 << r_1) - 1; v <= m; ++v) {\n co[rev[v] >> rvb] = sv;\n }\n }\n }\n } else {\n co = new u16(s);\n for (i2 = 0; i2 < s; ++i2) {\n if (cd[i2]) {\n co[i2] = rev[le[cd[i2] - 1]++] >> 15 - cd[i2];\n }\n }\n }\n return co;\n };\n var flt = new u8(288);\n for (var i = 0; i < 144; ++i)\n flt[i] = 8;\n for (var i = 144; i < 256; ++i)\n flt[i] = 9;\n for (var i = 256; i < 280; ++i)\n flt[i] = 7;\n for (var i = 280; i < 288; ++i)\n flt[i] = 8;\n var fdt = new u8(32);\n for (var i = 0; i < 32; ++i)\n fdt[i] = 5;\n var flrm = /* @__PURE__ */ hMap(flt, 9, 1);\n var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);\n var max = function(a) {\n var m = a[0];\n for (var i2 = 1; i2 < a.length; ++i2) {\n if (a[i2] > m)\n m = a[i2];\n }\n return m;\n };\n var bits = function(d, p, m) {\n var o = p / 8 | 0;\n return (d[o] | d[o + 1] << 8) >> (p & 7) & m;\n };\n var bits16 = function(d, p) {\n var o = p / 8 | 0;\n return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);\n };\n var shft = function(p) {\n return (p + 7) / 8 | 0;\n };\n var slc = function(v, s, e) {\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n return new u8(v.subarray(s, e));\n };\n var ec = [\n "unexpected EOF",\n "invalid block type",\n "invalid length/literal",\n "invalid distance",\n "stream finished",\n "no stream handler",\n ,\n "no callback",\n "invalid UTF-8 data",\n "extra field too long",\n "date not in range 1980-2099",\n "filename too long",\n "stream finishing",\n "invalid zip data"\n // determined by unknown compression method\n ];\n var err = function(ind, msg, nt) {\n var e = new Error(msg || ec[ind]);\n e.code = ind;\n if (Error.captureStackTrace)\n Error.captureStackTrace(e, err);\n if (!nt)\n throw e;\n return e;\n };\n var inflt = function(dat, st, buf, dict) {\n var sl = dat.length, dl = dict ? dict.length : 0;\n if (!sl || st.f && !st.l)\n return buf || new u8(0);\n var noBuf = !buf;\n var resize = noBuf || st.i != 2;\n var noSt = st.i;\n if (noBuf)\n buf = new u8(sl * 3);\n var cbuf = function(l2) {\n var bl = buf.length;\n if (l2 > bl) {\n var nbuf = new u8(Math.max(bl * 2, l2));\n nbuf.set(buf);\n buf = nbuf;\n }\n };\n var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;\n var tbts = sl * 8;\n do {\n if (!lm) {\n final = bits(dat, pos, 1);\n var type = bits(dat, pos + 1, 3);\n pos += 3;\n if (!type) {\n var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;\n if (t > sl) {\n if (noSt)\n err(0);\n break;\n }\n if (resize)\n cbuf(bt + l);\n buf.set(dat.subarray(s, t), bt);\n st.b = bt += l, st.p = pos = t * 8, st.f = final;\n continue;\n } else if (type == 1)\n lm = flrm, dm = fdrm, lbt = 9, dbt = 5;\n else if (type == 2) {\n var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;\n var tl = hLit + bits(dat, pos + 5, 31) + 1;\n pos += 14;\n var ldt = new u8(tl);\n var clt = new u8(19);\n for (var i2 = 0; i2 < hcLen; ++i2) {\n clt[clim[i2]] = bits(dat, pos + i2 * 3, 7);\n }\n pos += hcLen * 3;\n var clb = max(clt), clbmsk = (1 << clb) - 1;\n var clm = hMap(clt, clb, 1);\n for (var i2 = 0; i2 < tl; ) {\n var r = clm[bits(dat, pos, clbmsk)];\n pos += r & 15;\n var s = r >> 4;\n if (s < 16) {\n ldt[i2++] = s;\n } else {\n var c = 0, n = 0;\n if (s == 16)\n n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i2 - 1];\n else if (s == 17)\n n = 3 + bits(dat, pos, 7), pos += 3;\n else if (s == 18)\n n = 11 + bits(dat, pos, 127), pos += 7;\n while (n--)\n ldt[i2++] = c;\n }\n }\n var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);\n lbt = max(lt);\n dbt = max(dt);\n lm = hMap(lt, lbt, 1);\n dm = hMap(dt, dbt, 1);\n } else\n err(1);\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n }\n if (resize)\n cbuf(bt + 131072);\n var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;\n var lpos = pos;\n for (; ; lpos = pos) {\n var c = lm[bits16(dat, pos) & lms], sym = c >> 4;\n pos += c & 15;\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n if (!c)\n err(2);\n if (sym < 256)\n buf[bt++] = sym;\n else if (sym == 256) {\n lpos = pos, lm = null;\n break;\n } else {\n var add = sym - 254;\n if (sym > 264) {\n var i2 = sym - 257, b = fleb[i2];\n add = bits(dat, pos, (1 << b) - 1) + fl[i2];\n pos += b;\n }\n var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;\n if (!d)\n err(3);\n pos += d & 15;\n var dt = fd[dsym];\n if (dsym > 3) {\n var b = fdeb[dsym];\n dt += bits16(dat, pos) & (1 << b) - 1, pos += b;\n }\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n if (resize)\n cbuf(bt + 131072);\n var end = bt + add;\n if (bt < dt) {\n var shift = dl - dt, dend = Math.min(dt, end);\n if (shift + bt < 0)\n err(3);\n for (; bt < dend; ++bt)\n buf[bt] = dict[shift + bt];\n }\n for (; bt < end; ++bt)\n buf[bt] = buf[bt - dt];\n }\n }\n st.l = lm, st.p = lpos, st.b = bt, st.f = final;\n if (lm)\n final = 1, st.m = lbt, st.d = dm, st.n = dbt;\n } while (!final);\n return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);\n };\n var et = /* @__PURE__ */ new u8(0);\n var mrg = function(a, b) {\n var o = {};\n for (var k in a)\n o[k] = a[k];\n for (var k in b)\n o[k] = b[k];\n return o;\n };\n var wcln = function(fn, fnStr, td2) {\n var dt = fn();\n var st = fn.toString();\n var ks = st.slice(st.indexOf("[") + 1, st.lastIndexOf("]")).replace(/\\s+/g, "").split(",");\n for (var i2 = 0; i2 < dt.length; ++i2) {\n var v = dt[i2], k = ks[i2];\n if (typeof v == "function") {\n fnStr += ";" + k + "=";\n var st_1 = v.toString();\n if (v.prototype) {\n if (st_1.indexOf("[native code]") != -1) {\n var spInd = st_1.indexOf(" ", 8) + 1;\n fnStr += st_1.slice(spInd, st_1.indexOf("(", spInd));\n } else {\n fnStr += st_1;\n for (var t in v.prototype)\n fnStr += ";" + k + ".prototype." + t + "=" + v.prototype[t].toString();\n }\n } else\n fnStr += st_1;\n } else\n td2[k] = v;\n }\n return fnStr;\n };\n var ch = [];\n var cbfs = function(v) {\n var tl = [];\n for (var k in v) {\n if (v[k].buffer) {\n tl.push((v[k] = new v[k].constructor(v[k])).buffer);\n }\n }\n return tl;\n };\n var wrkr = function(fns, init, id, cb) {\n if (!ch[id]) {\n var fnStr = "", td_1 = {}, m = fns.length - 1;\n for (var i2 = 0; i2 < m; ++i2)\n fnStr = wcln(fns[i2], fnStr, td_1);\n ch[id] = { c: wcln(fns[m], fnStr, td_1), e: td_1 };\n }\n var td2 = mrg({}, ch[id].e);\n return wk(ch[id].c + ";onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=" + init.toString() + "}", id, td2, cbfs(td2), cb);\n };\n var bInflt = function() {\n return [u8, u16, i32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gopt];\n };\n var pbf = function(msg) {\n return postMessage(msg, [msg.buffer]);\n };\n var gopt = function(o) {\n return o && {\n out: o.size && new u8(o.size),\n dictionary: o.dictionary\n };\n };\n var cbify = function(dat, opts, fns, init, id, cb) {\n var w = wrkr(fns, init, id, function(err2, dat2) {\n w.terminate();\n cb(err2, dat2);\n });\n w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []);\n return function() {\n w.terminate();\n };\n };\n var b2 = function(d, b) {\n return d[b] | d[b + 1] << 8;\n };\n var b4 = function(d, b) {\n return (d[b] | d[b + 1] << 8 | d[b + 2] << 16 | d[b + 3] << 24) >>> 0;\n };\n var b8 = function(d, b) {\n return b4(d, b) + b4(d, b + 4) * 4294967296;\n };\n var gzs = function(d) {\n if (d[0] != 31 || d[1] != 139 || d[2] != 8)\n err(6, "invalid gzip data");\n var flg = d[3];\n var st = 10;\n if (flg & 4)\n st += (d[10] | d[11] << 8) + 2;\n for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++])\n ;\n return st + (flg & 2);\n };\n var Inflate = /* @__PURE__ */ function() {\n function Inflate2(opts, cb) {\n if (typeof opts == "function")\n cb = opts, opts = {};\n this.ondata = cb;\n var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768);\n this.s = { i: 0, b: dict ? dict.length : 0 };\n this.o = new u8(32768);\n this.p = new u8(0);\n if (dict)\n this.o.set(dict);\n }\n Inflate2.prototype.e = function(c) {\n if (!this.ondata)\n err(5);\n if (this.d)\n err(4);\n if (!this.p.length)\n this.p = c;\n else if (c.length) {\n var n = new u8(this.p.length + c.length);\n n.set(this.p), n.set(c, this.p.length), this.p = n;\n }\n };\n Inflate2.prototype.c = function(final) {\n this.s.i = +(this.d = final || false);\n var bts = this.s.b;\n var dt = inflt(this.p, this.s, this.o);\n this.ondata(slc(dt, bts, this.s.b), this.d);\n this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;\n this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;\n };\n Inflate2.prototype.push = function(chunk, final) {\n this.e(chunk), this.c(final);\n };\n return Inflate2;\n }();\n function inflate(data, opts, cb) {\n if (!cb)\n cb = opts, opts = {};\n if (typeof cb != "function")\n err(7);\n return cbify(data, opts, [\n bInflt\n ], function(ev) {\n return pbf(inflateSync(ev.data[0], gopt(ev.data[1])));\n }, 1, cb);\n }\n function inflateSync(data, opts) {\n return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary);\n }\n var Gunzip = /* @__PURE__ */ function() {\n function Gunzip2(opts, cb) {\n this.v = 1;\n this.r = 0;\n Inflate.call(this, opts, cb);\n }\n Gunzip2.prototype.push = function(chunk, final) {\n Inflate.prototype.e.call(this, chunk);\n this.r += chunk.length;\n if (this.v) {\n var p = this.p.subarray(this.v - 1);\n var s = p.length > 3 ? gzs(p) : 4;\n if (s > p.length) {\n if (!final)\n return;\n } else if (this.v > 1 && this.onmember) {\n this.onmember(this.r - p.length);\n }\n this.p = p.subarray(s), this.v = 0;\n }\n Inflate.prototype.c.call(this, final);\n if (this.s.f && !this.s.l && !final) {\n this.v = shft(this.s.p) + 9;\n this.s = { i: 0 };\n this.o = new u8(0);\n this.push(new u8(0), final);\n }\n };\n return Gunzip2;\n }();\n var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();\n try {\n td.decode(et, { stream: true });\n } catch (e) {\n }\n var dutf8 = function(d) {\n for (var r = "", i2 = 0; ; ) {\n var c = d[i2++];\n var eb = (c > 127) + (c > 223) + (c > 239);\n if (i2 + eb > d.length)\n return { s: r, r: slc(d, i2 - 1) };\n if (!eb)\n r += String.fromCharCode(c);\n else if (eb == 3) {\n c = ((c & 15) << 18 | (d[i2++] & 63) << 12 | (d[i2++] & 63) << 6 | d[i2++] & 63) - 65536, r += String.fromCharCode(55296 | c >> 10, 56320 | c & 1023);\n } else if (eb & 1)\n r += String.fromCharCode((c & 31) << 6 | d[i2++] & 63);\n else\n r += String.fromCharCode((c & 15) << 12 | (d[i2++] & 63) << 6 | d[i2++] & 63);\n }\n };\n function strFromU8(dat, latin1) {\n if (latin1) {\n var r = "";\n for (var i2 = 0; i2 < dat.length; i2 += 16384)\n r += String.fromCharCode.apply(null, dat.subarray(i2, i2 + 16384));\n return r;\n } else if (td) {\n return td.decode(dat);\n } else {\n var _a2 = dutf8(dat), s = _a2.s, r = _a2.r;\n if (r.length)\n err(8);\n return s;\n }\n }\n var slzh = function(d, b) {\n return b + 30 + b2(d, b + 26) + b2(d, b + 28);\n };\n var zh = function(d, b, z) {\n var fnl = b2(d, b + 28), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl, bs = b4(d, b + 20);\n var _a2 = z && bs == 4294967295 ? z64e(d, es) : [bs, b4(d, b + 24), b4(d, b + 42)], sc = _a2[0], su = _a2[1], off = _a2[2];\n return [b2(d, b + 10), sc, su, fn, es + b2(d, b + 30) + b2(d, b + 32), off];\n };\n var z64e = function(d, b) {\n for (; b2(d, b) != 1; b += 4 + b2(d, b + 2))\n ;\n return [b8(d, b + 12), b8(d, b + 4), b8(d, b + 20)];\n };\n var mt = typeof queueMicrotask == "function" ? queueMicrotask : typeof setTimeout == "function" ? setTimeout : function(fn) {\n fn();\n };\n function unzip(data, opts, cb) {\n if (!cb)\n cb = opts, opts = {};\n if (typeof cb != "function")\n err(7);\n var term = [];\n var tAll = function() {\n for (var i3 = 0; i3 < term.length; ++i3)\n term[i3]();\n };\n var files = {};\n var cbd = function(a, b) {\n mt(function() {\n cb(a, b);\n });\n };\n mt(function() {\n cbd = cb;\n });\n var e = data.length - 22;\n for (; b4(data, e) != 101010256; --e) {\n if (!e || data.length - e > 65558) {\n cbd(err(13, 0, 1), null);\n return tAll;\n }\n }\n var lft = b2(data, e + 8);\n if (lft) {\n var c = lft;\n var o = b4(data, e + 16);\n var z = o == 4294967295 || c == 65535;\n if (z) {\n var ze = b4(data, e - 12);\n z = b4(data, ze) == 101075792;\n if (z) {\n c = lft = b4(data, ze + 32);\n o = b4(data, ze + 48);\n }\n }\n var fltr = opts && opts.filter;\n var _loop_3 = function(i3) {\n var _a2 = zh(data, o, z), c_1 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);\n o = no;\n var cbl = function(e2, d) {\n if (e2) {\n tAll();\n cbd(e2, null);\n } else {\n if (d)\n files[fn] = d;\n if (!--lft)\n cbd(null, files);\n }\n };\n if (!fltr || fltr({\n name: fn,\n size: sc,\n originalSize: su,\n compression: c_1\n })) {\n if (!c_1)\n cbl(null, slc(data, b, b + sc));\n else if (c_1 == 8) {\n var infl = data.subarray(b, b + sc);\n if (su < 524288 || sc > 0.8 * su) {\n try {\n cbl(null, inflateSync(infl, { out: new u8(su) }));\n } catch (e2) {\n cbl(e2, null);\n }\n } else\n term.push(inflate(infl, { size: su }, cbl));\n } else\n cbl(err(14, "unknown compression type " + c_1, 1), null);\n } else\n cbl(null, null);\n };\n for (var i2 = 0; i2 < c; ++i2) {\n _loop_3(i2);\n }\n } else\n cbd(null, {});\n return tAll;\n }\n function unzipSync(data, opts) {\n var files = {};\n var e = data.length - 22;\n for (; b4(data, e) != 101010256; --e) {\n if (!e || data.length - e > 65558)\n err(13);\n }\n var c = b2(data, e + 8);\n if (!c)\n return {};\n var o = b4(data, e + 16);\n var z = o == 4294967295 || c == 65535;\n if (z) {\n var ze = b4(data, e - 12);\n z = b4(data, ze) == 101075792;\n if (z) {\n c = b4(data, ze + 32);\n o = b4(data, ze + 48);\n }\n }\n var fltr = opts && opts.filter;\n for (var i2 = 0; i2 < c; ++i2) {\n var _a2 = zh(data, o, z), c_2 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);\n o = no;\n if (!fltr || fltr({\n name: fn,\n size: sc,\n originalSize: su,\n compression: c_2\n })) {\n if (!c_2)\n files[fn] = slc(data, b, b + sc);\n else if (c_2 == 8)\n files[fn] = inflateSync(data.subarray(b, b + sc), { out: new u8(su) });\n else\n err(14, "unknown compression type " + c_2);\n }\n }\n return files;\n }\n /**\n * @license\n * Copyright 2010-2024 Three.js Authors\n * SPDX-License-Identifier: MIT\n */\n const REVISION = "172";\n const NoColorSpace = "";\n const SRGBColorSpace = "srgb";\n const LinearSRGBColorSpace = "srgb-linear";\n const LinearTransfer = "linear";\n const SRGBTransfer = "srgb";\n function clamp(value, min, max2) {\n return Math.max(min, Math.min(max2, value));\n }\n function euclideanModulo(n, m) {\n return (n % m + m) % m;\n }\n function lerp(x2, y, t) {\n return (1 - t) * x2 + t * y;\n }\n class Matrix3 {\n constructor(n11, n12, n13, n21, n22, n23, n31, n32, n33) {\n Matrix3.prototype.isMatrix3 = true;\n this.elements = [\n 1,\n 0,\n 0,\n 0,\n 1,\n 0,\n 0,\n 0,\n 1\n ];\n if (n11 !== void 0) {\n this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);\n }\n }\n set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {\n const te = this.elements;\n te[0] = n11;\n te[1] = n21;\n te[2] = n31;\n te[3] = n12;\n te[4] = n22;\n te[5] = n32;\n te[6] = n13;\n te[7] = n23;\n te[8] = n33;\n return this;\n }\n identity() {\n this.set(\n 1,\n 0,\n 0,\n 0,\n 1,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n copy(m) {\n const te = this.elements;\n const me = m.elements;\n te[0] = me[0];\n te[1] = me[1];\n te[2] = me[2];\n te[3] = me[3];\n te[4] = me[4];\n te[5] = me[5];\n te[6] = me[6];\n te[7] = me[7];\n te[8] = me[8];\n return this;\n }\n extractBasis(xAxis, yAxis, zAxis) {\n xAxis.setFromMatrix3Column(this, 0);\n yAxis.setFromMatrix3Column(this, 1);\n zAxis.setFromMatrix3Column(this, 2);\n return this;\n }\n setFromMatrix4(m) {\n const me = m.elements;\n this.set(\n me[0],\n me[4],\n me[8],\n me[1],\n me[5],\n me[9],\n me[2],\n me[6],\n me[10]\n );\n return this;\n }\n multiply(m) {\n return this.multiplyMatrices(this, m);\n }\n premultiply(m) {\n return this.multiplyMatrices(m, this);\n }\n multiplyMatrices(a, b) {\n const ae = a.elements;\n const be = b.elements;\n const te = this.elements;\n const a11 = ae[0], a12 = ae[3], a13 = ae[6];\n const a21 = ae[1], a22 = ae[4], a23 = ae[7];\n const a31 = ae[2], a32 = ae[5], a33 = ae[8];\n const b11 = be[0], b12 = be[3], b13 = be[6];\n const b21 = be[1], b22 = be[4], b23 = be[7];\n const b31 = be[2], b32 = be[5], b33 = be[8];\n te[0] = a11 * b11 + a12 * b21 + a13 * b31;\n te[3] = a11 * b12 + a12 * b22 + a13 * b32;\n te[6] = a11 * b13 + a12 * b23 + a13 * b33;\n te[1] = a21 * b11 + a22 * b21 + a23 * b31;\n te[4] = a21 * b12 + a22 * b22 + a23 * b32;\n te[7] = a21 * b13 + a22 * b23 + a23 * b33;\n te[2] = a31 * b11 + a32 * b21 + a33 * b31;\n te[5] = a31 * b12 + a32 * b22 + a33 * b32;\n te[8] = a31 * b13 + a32 * b23 + a33 * b33;\n return this;\n }\n multiplyScalar(s) {\n const te = this.elements;\n te[0] *= s;\n te[3] *= s;\n te[6] *= s;\n te[1] *= s;\n te[4] *= s;\n te[7] *= s;\n te[2] *= s;\n te[5] *= s;\n te[8] *= s;\n return this;\n }\n determinant() {\n const te = this.elements;\n const a = te[0], b = te[1], c = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i2 = te[8];\n return a * e * i2 - a * f * h - b * d * i2 + b * f * g + c * d * h - c * e * g;\n }\n invert() {\n const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13;\n if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);\n const detInv = 1 / det;\n te[0] = t11 * detInv;\n te[1] = (n31 * n23 - n33 * n21) * detInv;\n te[2] = (n32 * n21 - n31 * n22) * detInv;\n te[3] = t12 * detInv;\n te[4] = (n33 * n11 - n31 * n13) * detInv;\n te[5] = (n31 * n12 - n32 * n11) * detInv;\n te[6] = t13 * detInv;\n te[7] = (n21 * n13 - n23 * n11) * detInv;\n te[8] = (n22 * n11 - n21 * n12) * detInv;\n return this;\n }\n transpose() {\n let tmp;\n const m = this.elements;\n tmp = m[1];\n m[1] = m[3];\n m[3] = tmp;\n tmp = m[2];\n m[2] = m[6];\n m[6] = tmp;\n tmp = m[5];\n m[5] = m[7];\n m[7] = tmp;\n return this;\n }\n getNormalMatrix(matrix4) {\n return this.setFromMatrix4(matrix4).invert().transpose();\n }\n transposeIntoArray(r) {\n const m = this.elements;\n r[0] = m[0];\n r[1] = m[3];\n r[2] = m[6];\n r[3] = m[1];\n r[4] = m[4];\n r[5] = m[7];\n r[6] = m[2];\n r[7] = m[5];\n r[8] = m[8];\n return this;\n }\n setUvTransform(tx, ty, sx, sy, rotation, cx, cy) {\n const c = Math.cos(rotation);\n const s = Math.sin(rotation);\n this.set(\n sx * c,\n sx * s,\n -sx * (c * cx + s * cy) + cx + tx,\n -sy * s,\n sy * c,\n -sy * (-s * cx + c * cy) + cy + ty,\n 0,\n 0,\n 1\n );\n return this;\n }\n //\n scale(sx, sy) {\n this.premultiply(_m3.makeScale(sx, sy));\n return this;\n }\n rotate(theta) {\n this.premultiply(_m3.makeRotation(-theta));\n return this;\n }\n translate(tx, ty) {\n this.premultiply(_m3.makeTranslation(tx, ty));\n return this;\n }\n // for 2D Transforms\n makeTranslation(x2, y) {\n if (x2.isVector2) {\n this.set(\n 1,\n 0,\n x2.x,\n 0,\n 1,\n x2.y,\n 0,\n 0,\n 1\n );\n } else {\n this.set(\n 1,\n 0,\n x2,\n 0,\n 1,\n y,\n 0,\n 0,\n 1\n );\n }\n return this;\n }\n makeRotation(theta) {\n const c = Math.cos(theta);\n const s = Math.sin(theta);\n this.set(\n c,\n -s,\n 0,\n s,\n c,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n makeScale(x2, y) {\n this.set(\n x2,\n 0,\n 0,\n 0,\n y,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n //\n equals(matrix) {\n const te = this.elements;\n const me = matrix.elements;\n for (let i2 = 0; i2 < 9; i2++) {\n if (te[i2] !== me[i2]) return false;\n }\n return true;\n }\n fromArray(array, offset = 0) {\n for (let i2 = 0; i2 < 9; i2++) {\n this.elements[i2] = array[i2 + offset];\n }\n return this;\n }\n toArray(array = [], offset = 0) {\n const te = this.elements;\n array[offset] = te[0];\n array[offset + 1] = te[1];\n array[offset + 2] = te[2];\n array[offset + 3] = te[3];\n array[offset + 4] = te[4];\n array[offset + 5] = te[5];\n array[offset + 6] = te[6];\n array[offset + 7] = te[7];\n array[offset + 8] = te[8];\n return array;\n }\n clone() {\n return new this.constructor().fromArray(this.elements);\n }\n }\n const _m3 = /* @__PURE__ */ new Matrix3();\n const LINEAR_REC709_TO_XYZ = /* @__PURE__ */ new Matrix3().set(\n 0.4123908,\n 0.3575843,\n 0.1804808,\n 0.212639,\n 0.7151687,\n 0.0721923,\n 0.0193308,\n 0.1191948,\n 0.9505322\n );\n const XYZ_TO_LINEAR_REC709 = /* @__PURE__ */ new Matrix3().set(\n 3.2409699,\n -1.5373832,\n -0.4986108,\n -0.9692436,\n 1.8759675,\n 0.0415551,\n 0.0556301,\n -0.203977,\n 1.0569715\n );\n function createColorManagement() {\n const ColorManagement2 = {\n enabled: true,\n workingColorSpace: LinearSRGBColorSpace,\n /**\n * Implementations of supported color spaces.\n *\n * Required:\n * - primaries: chromaticity coordinates [ rx ry gx gy bx by ]\n * - whitePoint: reference white [ x y ]\n * - transfer: transfer function (pre-defined)\n * - toXYZ: Matrix3 RGB to XYZ transform\n * - fromXYZ: Matrix3 XYZ to RGB transform\n * - luminanceCoefficients: RGB luminance coefficients\n *\n * Optional:\n * - outputColorSpaceConfig: { drawingBufferColorSpace: ColorSpace }\n * - workingColorSpaceConfig: { unpackColorSpace: ColorSpace }\n *\n * Reference:\n * - https://www.russellcottrell.com/photo/matrixCalculator.htm\n */\n spaces: {},\n convert: function(color, sourceColorSpace, targetColorSpace) {\n if (this.enabled === false || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) {\n return color;\n }\n if (this.spaces[sourceColorSpace].transfer === SRGBTransfer) {\n color.r = SRGBToLinear(color.r);\n color.g = SRGBToLinear(color.g);\n color.b = SRGBToLinear(color.b);\n }\n if (this.spaces[sourceColorSpace].primaries !== this.spaces[targetColorSpace].primaries) {\n color.applyMatrix3(this.spaces[sourceColorSpace].toXYZ);\n color.applyMatrix3(this.spaces[targetColorSpace].fromXYZ);\n }\n if (this.spaces[targetColorSpace].transfer === SRGBTransfer) {\n color.r = LinearToSRGB(color.r);\n color.g = LinearToSRGB(color.g);\n color.b = LinearToSRGB(color.b);\n }\n return color;\n },\n fromWorkingColorSpace: function(color, targetColorSpace) {\n return this.convert(color, this.workingColorSpace, targetColorSpace);\n },\n toWorkingColorSpace: function(color, sourceColorSpace) {\n return this.convert(color, sourceColorSpace, this.workingColorSpace);\n },\n getPrimaries: function(colorSpace) {\n return this.spaces[colorSpace].primaries;\n },\n getTransfer: function(colorSpace) {\n if (colorSpace === NoColorSpace) return LinearTransfer;\n return this.spaces[colorSpace].transfer;\n },\n getLuminanceCoefficients: function(target, colorSpace = this.workingColorSpace) {\n return target.fromArray(this.spaces[colorSpace].luminanceCoefficients);\n },\n define: function(colorSpaces) {\n Object.assign(this.spaces, colorSpaces);\n },\n // Internal APIs\n _getMatrix: function(targetMatrix, sourceColorSpace, targetColorSpace) {\n return targetMatrix.copy(this.spaces[sourceColorSpace].toXYZ).multiply(this.spaces[targetColorSpace].fromXYZ);\n },\n _getDrawingBufferColorSpace: function(colorSpace) {\n return this.spaces[colorSpace].outputColorSpaceConfig.drawingBufferColorSpace;\n },\n _getUnpackColorSpace: function(colorSpace = this.workingColorSpace) {\n return this.spaces[colorSpace].workingColorSpaceConfig.unpackColorSpace;\n }\n };\n const REC709_PRIMARIES = [0.64, 0.33, 0.3, 0.6, 0.15, 0.06];\n const REC709_LUMINANCE_COEFFICIENTS = [0.2126, 0.7152, 0.0722];\n const D65 = [0.3127, 0.329];\n ColorManagement2.define({\n [LinearSRGBColorSpace]: {\n primaries: REC709_PRIMARIES,\n whitePoint: D65,\n transfer: LinearTransfer,\n toXYZ: LINEAR_REC709_TO_XYZ,\n fromXYZ: XYZ_TO_LINEAR_REC709,\n luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,\n workingColorSpaceConfig: { unpackColorSpace: SRGBColorSpace },\n outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }\n },\n [SRGBColorSpace]: {\n primaries: REC709_PRIMARIES,\n whitePoint: D65,\n transfer: SRGBTransfer,\n toXYZ: LINEAR_REC709_TO_XYZ,\n fromXYZ: XYZ_TO_LINEAR_REC709,\n luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,\n outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }\n }\n });\n return ColorManagement2;\n }\n const ColorManagement = /* @__PURE__ */ createColorManagement();\n function SRGBToLinear(c) {\n return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);\n }\n function LinearToSRGB(c) {\n return c < 31308e-7 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055;\n }\n class Quaternion {\n constructor(x2 = 0, y = 0, z = 0, w = 1) {\n this.isQuaternion = true;\n this._x = x2;\n this._y = y;\n this._z = z;\n this._w = w;\n }\n static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {\n let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3];\n const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3];\n if (t === 0) {\n dst[dstOffset + 0] = x0;\n dst[dstOffset + 1] = y0;\n dst[dstOffset + 2] = z0;\n dst[dstOffset + 3] = w0;\n return;\n }\n if (t === 1) {\n dst[dstOffset + 0] = x1;\n dst[dstOffset + 1] = y1;\n dst[dstOffset + 2] = z1;\n dst[dstOffset + 3] = w1;\n return;\n }\n if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {\n let s = 1 - t;\n const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos;\n if (sqrSin > Number.EPSILON) {\n const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir);\n s = Math.sin(s * len) / sin;\n t = Math.sin(t * len) / sin;\n }\n const tDir = t * dir;\n x0 = x0 * s + x1 * tDir;\n y0 = y0 * s + y1 * tDir;\n z0 = z0 * s + z1 * tDir;\n w0 = w0 * s + w1 * tDir;\n if (s === 1 - t) {\n const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);\n x0 *= f;\n y0 *= f;\n z0 *= f;\n w0 *= f;\n }\n }\n dst[dstOffset] = x0;\n dst[dstOffset + 1] = y0;\n dst[dstOffset + 2] = z0;\n dst[dstOffset + 3] = w0;\n }\n static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) {\n const x0 = src0[srcOffset0];\n const y0 = src0[srcOffset0 + 1];\n const z0 = src0[srcOffset0 + 2];\n const w0 = src0[srcOffset0 + 3];\n const x1 = src1[srcOffset1];\n const y1 = src1[srcOffset1 + 1];\n const z1 = src1[srcOffset1 + 2];\n const w1 = src1[srcOffset1 + 3];\n dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;\n dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;\n dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;\n dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;\n return dst;\n }\n get x() {\n return this._x;\n }\n set x(value) {\n this._x = value;\n this._onChangeCallback();\n }\n get y() {\n return this._y;\n }\n set y(value) {\n this._y = value;\n this._onChangeCallback();\n }\n get z() {\n return this._z;\n }\n set z(value) {\n this._z = value;\n this._onChangeCallback();\n }\n get w() {\n return this._w;\n }\n set w(value) {\n this._w = value;\n this._onChangeCallback();\n }\n set(x2, y, z, w) {\n this._x = x2;\n this._y = y;\n this._z = z;\n this._w = w;\n this._onChangeCallback();\n return this;\n }\n clone() {\n return new this.constructor(this._x, this._y, this._z, this._w);\n }\n copy(quaternion) {\n this._x = quaternion.x;\n this._y = quaternion.y;\n this._z = quaternion.z;\n this._w = quaternion.w;\n this._onChangeCallback();\n return this;\n }\n setFromEuler(euler, update = true) {\n const x2 = euler._x, y = euler._y, z = euler._z, order = euler._order;\n const cos = Math.cos;\n const sin = Math.sin;\n const c1 = cos(x2 / 2);\n const c2 = cos(y / 2);\n const c3 = cos(z / 2);\n const s1 = sin(x2 / 2);\n const s2 = sin(y / 2);\n const s3 = sin(z / 2);\n switch (order) {\n case "XYZ":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "YXZ":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case "ZXY":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "ZYX":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case "YZX":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "XZY":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n default:\n console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: " + order);\n }\n if (update === true) this._onChangeCallback();\n return this;\n }\n setFromAxisAngle(axis, angle) {\n const halfAngle = angle / 2, s = Math.sin(halfAngle);\n this._x = axis.x * s;\n this._y = axis.y * s;\n this._z = axis.z * s;\n this._w = Math.cos(halfAngle);\n this._onChangeCallback();\n return this;\n }\n setFromRotationMatrix(m) {\n const te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33;\n if (trace > 0) {\n const s = 0.5 / Math.sqrt(trace + 1);\n this._w = 0.25 / s;\n this._x = (m32 - m23) * s;\n this._y = (m13 - m31) * s;\n this._z = (m21 - m12) * s;\n } else if (m11 > m22 && m11 > m33) {\n const s = 2 * Math.sqrt(1 + m11 - m22 - m33);\n this._w = (m32 - m23) / s;\n this._x = 0.25 * s;\n this._y = (m12 + m21) / s;\n this._z = (m13 + m31) / s;\n } else if (m22 > m33) {\n const s = 2 * Math.sqrt(1 + m22 - m11 - m33);\n this._w = (m13 - m31) / s;\n this._x = (m12 + m21) / s;\n this._y = 0.25 * s;\n this._z = (m23 + m32) / s;\n } else {\n const s = 2 * Math.sqrt(1 + m33 - m11 - m22);\n this._w = (m21 - m12) / s;\n this._x = (m13 + m31) / s;\n this._y = (m23 + m32) / s;\n this._z = 0.25 * s;\n }\n this._onChangeCallback();\n return this;\n }\n setFromUnitVectors(vFrom, vTo) {\n let r = vFrom.dot(vTo) + 1;\n if (r < Number.EPSILON) {\n r = 0;\n if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {\n this._x = -vFrom.y;\n this._y = vFrom.x;\n this._z = 0;\n this._w = r;\n } else {\n this._x = 0;\n this._y = -vFrom.z;\n this._z = vFrom.y;\n this._w = r;\n }\n } else {\n this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\n this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\n this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\n this._w = r;\n }\n return this.normalize();\n }\n angleTo(q) {\n return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1)));\n }\n rotateTowards(q, step) {\n const angle = this.angleTo(q);\n if (angle === 0) return this;\n const t = Math.min(1, step / angle);\n this.slerp(q, t);\n return this;\n }\n identity() {\n return this.set(0, 0, 0, 1);\n }\n invert() {\n return this.conjugate();\n }\n conjugate() {\n this._x *= -1;\n this._y *= -1;\n this._z *= -1;\n this._onChangeCallback();\n return this;\n }\n dot(v) {\n return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\n }\n lengthSq() {\n return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\n }\n length() {\n return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);\n }\n normalize() {\n let l = this.length();\n if (l === 0) {\n this._x = 0;\n this._y = 0;\n this._z = 0;\n this._w = 1;\n } else {\n l = 1 / l;\n this._x = this._x * l;\n this._y = this._y * l;\n this._z = this._z * l;\n this._w = this._w * l;\n }\n this._onChangeCallback();\n return this;\n }\n multiply(q) {\n return this.multiplyQuaternions(this, q);\n }\n premultiply(q) {\n return this.multiplyQuaternions(q, this);\n }\n multiplyQuaternions(a, b) {\n const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\n const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\n this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\n this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\n this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\n this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\n this._onChangeCallback();\n return this;\n }\n slerp(qb, t) {\n if (t === 0) return this;\n if (t === 1) return this.copy(qb);\n const x2 = this._x, y = this._y, z = this._z, w = this._w;\n let cosHalfTheta = w * qb._w + x2 * qb._x + y * qb._y + z * qb._z;\n if (cosHalfTheta < 0) {\n this._w = -qb._w;\n this._x = -qb._x;\n this._y = -qb._y;\n this._z = -qb._z;\n cosHalfTheta = -cosHalfTheta;\n } else {\n this.copy(qb);\n }\n if (cosHalfTheta >= 1) {\n this._w = w;\n this._x = x2;\n this._y = y;\n this._z = z;\n return this;\n }\n const sqrSinHalfTheta = 1 - cosHalfTheta * cosHalfTheta;\n if (sqrSinHalfTheta <= Number.EPSILON) {\n const s = 1 - t;\n this._w = s * w + t * this._w;\n this._x = s * x2 + t * this._x;\n this._y = s * y + t * this._y;\n this._z = s * z + t * this._z;\n this.normalize();\n return this;\n }\n const sinHalfTheta = Math.sqrt(sqrSinHalfTheta);\n const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);\n const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta;\n this._w = w * ratioA + this._w * ratioB;\n this._x = x2 * ratioA + this._x * ratioB;\n this._y = y * ratioA + this._y * ratioB;\n this._z = z * ratioA + this._z * ratioB;\n this._onChangeCallback();\n return this;\n }\n slerpQuaternions(qa, qb, t) {\n return this.copy(qa).slerp(qb, t);\n }\n random() {\n const theta1 = 2 * Math.PI * Math.random();\n const theta2 = 2 * Math.PI * Math.random();\n const x0 = Math.random();\n const r1 = Math.sqrt(1 - x0);\n const r2 = Math.sqrt(x0);\n return this.set(\n r1 * Math.sin(theta1),\n r1 * Math.cos(theta1),\n r2 * Math.sin(theta2),\n r2 * Math.cos(theta2)\n );\n }\n equals(quaternion) {\n return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w;\n }\n fromArray(array, offset = 0) {\n this._x = array[offset];\n this._y = array[offset + 1];\n this._z = array[offset + 2];\n this._w = array[offset + 3];\n this._onChangeCallback();\n return this;\n }\n toArray(array = [], offset = 0) {\n array[offset] = this._x;\n array[offset + 1] = this._y;\n array[offset + 2] = this._z;\n array[offset + 3] = this._w;\n return array;\n }\n fromBufferAttribute(attribute, index) {\n this._x = attribute.getX(index);\n this._y = attribute.getY(index);\n this._z = attribute.getZ(index);\n this._w = attribute.getW(index);\n this._onChangeCallback();\n return this;\n }\n toJSON() {\n return this.toArray();\n }\n _onChange(callback) {\n this._onChangeCallback = callback;\n return this;\n }\n _onChangeCallback() {\n }\n *[Symbol.iterator]() {\n yield this._x;\n yield this._y;\n yield this._z;\n yield this._w;\n }\n }\n class Vector3 {\n constructor(x2 = 0, y = 0, z = 0) {\n Vector3.prototype.isVector3 = true;\n this.x = x2;\n this.y = y;\n this.z = z;\n }\n set(x2, y, z) {\n if (z === void 0) z = this.z;\n this.x = x2;\n this.y = y;\n this.z = z;\n return this;\n }\n setScalar(scalar) {\n this.x = scalar;\n this.y = scalar;\n this.z = scalar;\n return this;\n }\n setX(x2) {\n this.x = x2;\n return this;\n }\n setY(y) {\n this.y = y;\n return this;\n }\n setZ(z) {\n this.z = z;\n return this;\n }\n setComponent(index, value) {\n switch (index) {\n case 0:\n this.x = value;\n break;\n case 1:\n this.y = value;\n break;\n case 2:\n this.z = value;\n break;\n default:\n throw new Error("index is out of range: " + index);\n }\n return this;\n }\n getComponent(index) {\n switch (index) {\n case 0:\n return this.x;\n case 1:\n return this.y;\n case 2:\n return this.z;\n default:\n throw new Error("index is out of range: " + index);\n }\n }\n clone() {\n return new this.constructor(this.x, this.y, this.z);\n }\n copy(v) {\n this.x = v.x;\n this.y = v.y;\n this.z = v.z;\n return this;\n }\n add(v) {\n this.x += v.x;\n this.y += v.y;\n this.z += v.z;\n return this;\n }\n addScalar(s) {\n this.x += s;\n this.y += s;\n this.z += s;\n return this;\n }\n addVectors(a, b) {\n this.x = a.x + b.x;\n this.y = a.y + b.y;\n this.z = a.z + b.z;\n return this;\n }\n addScaledVector(v, s) {\n this.x += v.x * s;\n this.y += v.y * s;\n this.z += v.z * s;\n return this;\n }\n sub(v) {\n this.x -= v.x;\n this.y -= v.y;\n this.z -= v.z;\n return this;\n }\n subScalar(s) {\n this.x -= s;\n this.y -= s;\n this.z -= s;\n return this;\n }\n subVectors(a, b) {\n this.x = a.x - b.x;\n this.y = a.y - b.y;\n this.z = a.z - b.z;\n return this;\n }\n multiply(v) {\n this.x *= v.x;\n this.y *= v.y;\n this.z *= v.z;\n return this;\n }\n multiplyScalar(scalar) {\n this.x *= scalar;\n this.y *= scalar;\n this.z *= scalar;\n return this;\n }\n multiplyVectors(a, b) {\n this.x = a.x * b.x;\n this.y = a.y * b.y;\n this.z = a.z * b.z;\n return this;\n }\n applyEuler(euler) {\n return this.applyQuaternion(_quaternion$4.setFromEuler(euler));\n }\n applyAxisAngle(axis, angle) {\n return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle));\n }\n applyMatrix3(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n this.x = e[0] * x2 + e[3] * y + e[6] * z;\n this.y = e[1] * x2 + e[4] * y + e[7] * z;\n this.z = e[2] * x2 + e[5] * y + e[8] * z;\n return this;\n }\n applyNormalMatrix(m) {\n return this.applyMatrix3(m).normalize();\n }\n applyMatrix4(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n const w = 1 / (e[3] * x2 + e[7] * y + e[11] * z + e[15]);\n this.x = (e[0] * x2 + e[4] * y + e[8] * z + e[12]) * w;\n this.y = (e[1] * x2 + e[5] * y + e[9] * z + e[13]) * w;\n this.z = (e[2] * x2 + e[6] * y + e[10] * z + e[14]) * w;\n return this;\n }\n applyQuaternion(q) {\n const vx = this.x, vy = this.y, vz = this.z;\n const qx = q.x, qy = q.y, qz = q.z, qw = q.w;\n const tx = 2 * (qy * vz - qz * vy);\n const ty = 2 * (qz * vx - qx * vz);\n const tz = 2 * (qx * vy - qy * vx);\n this.x = vx + qw * tx + qy * tz - qz * ty;\n this.y = vy + qw * ty + qz * tx - qx * tz;\n this.z = vz + qw * tz + qx * ty - qy * tx;\n return this;\n }\n project(camera) {\n return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);\n }\n unproject(camera) {\n return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld);\n }\n transformDirection(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n this.x = e[0] * x2 + e[4] * y + e[8] * z;\n this.y = e[1] * x2 + e[5] * y + e[9] * z;\n this.z = e[2] * x2 + e[6] * y + e[10] * z;\n return this.normalize();\n }\n divide(v) {\n this.x /= v.x;\n this.y /= v.y;\n this.z /= v.z;\n return this;\n }\n divideScalar(scalar) {\n return this.multiplyScalar(1 / scalar);\n }\n min(v) {\n this.x = Math.min(this.x, v.x);\n this.y = Math.min(this.y, v.y);\n this.z = Math.min(this.z, v.z);\n return this;\n }\n max(v) {\n this.x = Math.max(this.x, v.x);\n this.y = Math.max(this.y, v.y);\n this.z = Math.max(this.z, v.z);\n return this;\n }\n clamp(min, max2) {\n this.x = clamp(this.x, min.x, max2.x);\n this.y = clamp(this.y, min.y, max2.y);\n this.z = clamp(this.z, min.z, max2.z);\n return this;\n }\n clampScalar(minVal, maxVal) {\n this.x = clamp(this.x, minVal, maxVal);\n this.y = clamp(this.y, minVal, maxVal);\n this.z = clamp(this.z, minVal, maxVal);\n return this;\n }\n clampLength(min, max2) {\n const length = this.length();\n return this.divideScalar(length || 1).multiplyScalar(clamp(length, min, max2));\n }\n floor() {\n this.x = Math.floor(this.x);\n this.y = Math.floor(this.y);\n this.z = Math.floor(this.z);\n return this;\n }\n ceil() {\n this.x = Math.ceil(this.x);\n this.y = Math.ceil(this.y);\n this.z = Math.ceil(this.z);\n return this;\n }\n round() {\n this.x = Math.round(this.x);\n this.y = Math.round(this.y);\n this.z = Math.round(this.z);\n return this;\n }\n roundToZero() {\n this.x = Math.trunc(this.x);\n this.y = Math.trunc(this.y);\n this.z = Math.trunc(this.z);\n return this;\n }\n negate() {\n this.x = -this.x;\n this.y = -this.y;\n this.z = -this.z;\n return this;\n }\n dot(v) {\n return this.x * v.x + this.y * v.y + this.z * v.z;\n }\n // TODO lengthSquared?\n lengthSq() {\n return this.x * this.x + this.y * this.y + this.z * this.z;\n }\n length() {\n return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n }\n manhattanLength() {\n return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);\n }\n normalize() {\n return this.divideScalar(this.length() || 1);\n }\n setLength(length) {\n return this.normalize().multiplyScalar(length);\n }\n lerp(v, alpha) {\n this.x += (v.x - this.x) * alpha;\n this.y += (v.y - this.y) * alpha;\n this.z += (v.z - this.z) * alpha;\n return this;\n }\n lerpVectors(v1, v2, alpha) {\n this.x = v1.x + (v2.x - v1.x) * alpha;\n this.y = v1.y + (v2.y - v1.y) * alpha;\n this.z = v1.z + (v2.z - v1.z) * alpha;\n return this;\n }\n cross(v) {\n return this.crossVectors(this, v);\n }\n crossVectors(a, b) {\n const ax = a.x, ay = a.y, az = a.z;\n const bx = b.x, by = b.y, bz = b.z;\n this.x = ay * bz - az * by;\n this.y = az * bx - ax * bz;\n this.z = ax * by - ay * bx;\n return this;\n }\n projectOnVector(v) {\n const denominator = v.lengthSq();\n if (denominator === 0) return this.set(0, 0, 0);\n const scalar = v.dot(this) / denominator;\n return this.copy(v).multiplyScalar(scalar);\n }\n projectOnPlane(planeNormal) {\n _vector$c.copy(this).projectOnVector(planeNormal);\n return this.sub(_vector$c);\n }\n reflect(normal) {\n return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)));\n }\n angleTo(v) {\n const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());\n if (denominator === 0) return Math.PI / 2;\n const theta = this.dot(v) / denominator;\n return Math.acos(clamp(theta, -1, 1));\n }\n distanceTo(v) {\n return Math.sqrt(this.distanceToSquared(v));\n }\n distanceToSquared(v) {\n const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\n return dx * dx + dy * dy + dz * dz;\n }\n manhattanDistanceTo(v) {\n return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);\n }\n setFromSpherical(s) {\n return this.setFromSphericalCoords(s.radius, s.phi, s.theta);\n }\n setFromSphericalCoords(radius, phi, theta) {\n const sinPhiRadius = Math.sin(phi) * radius;\n this.x = sinPhiRadius * Math.sin(theta);\n this.y = Math.cos(phi) * radius;\n this.z = sinPhiRadius * Math.cos(theta);\n return this;\n }\n setFromCylindrical(c) {\n return this.setFromCylindricalCoords(c.radius, c.theta, c.y);\n }\n setFromCylindricalCoords(radius, theta, y) {\n this.x = radius * Math.sin(theta);\n this.y = y;\n this.z = radius * Math.cos(theta);\n return this;\n }\n setFromMatrixPosition(m) {\n const e = m.elements;\n this.x = e[12];\n this.y = e[13];\n this.z = e[14];\n return this;\n }\n setFromMatrixScale(m) {\n const sx = this.setFromMatrixColumn(m, 0).length();\n const sy = this.setFromMatrixColumn(m, 1).length();\n const sz = this.setFromMatrixColumn(m, 2).length();\n this.x = sx;\n this.y = sy;\n this.z = sz;\n return this;\n }\n setFromMatrixColumn(m, index) {\n return this.fromArray(m.elements, index * 4);\n }\n setFromMatrix3Column(m, index) {\n return this.fromArray(m.elements, index * 3);\n }\n setFromEuler(e) {\n this.x = e._x;\n this.y = e._y;\n this.z = e._z;\n return this;\n }\n setFromColor(c) {\n this.x = c.r;\n this.y = c.g;\n this.z = c.b;\n return this;\n }\n equals(v) {\n return v.x === this.x && v.y === this.y && v.z === this.z;\n }\n fromArray(array, offset = 0) {\n this.x = array[offset];\n this.y = array[offset + 1];\n this.z = array[offset + 2];\n return this;\n }\n toArray(array = [], offset = 0) {\n array[offset] = this.x;\n array[offset + 1] = this.y;\n array[offset + 2] = this.z;\n return array;\n }\n fromBufferAttribute(attribute, index) {\n this.x = attribute.getX(index);\n this.y = attribute.getY(index);\n this.z = attribute.getZ(index);\n return this;\n }\n random() {\n this.x = Math.random();\n this.y = Math.random();\n this.z = Math.random();\n return this;\n }\n randomDirection() {\n const theta = Math.random() * Math.PI * 2;\n const u = Math.random() * 2 - 1;\n const c = Math.sqrt(1 - u * u);\n this.x = c * Math.cos(theta);\n this.y = u;\n this.z = c * Math.sin(theta);\n return this;\n }\n *[Symbol.iterator]() {\n yield this.x;\n yield this.y;\n yield this.z;\n }\n }\n const _vector$c = /* @__PURE__ */ new Vector3();\n const _quaternion$4 = /* @__PURE__ */ new Quaternion();\n class Box3 {\n constructor(min = new Vector3(Infinity, Infinity, Infinity), max2 = new Vector3(-Infinity, -Infinity, -Infinity)) {\n this.isBox3 = true;\n this.min = min;\n this.max = max2;\n }\n set(min, max2) {\n this.min.copy(min);\n this.max.copy(max2);\n return this;\n }\n setFromArray(array) {\n this.makeEmpty();\n for (let i2 = 0, il = array.length; i2 < il; i2 += 3) {\n this.expandByPoint(_vector$b.fromArray(array, i2));\n }\n return this;\n }\n setFromBufferAttribute(attribute) {\n this.makeEmpty();\n for (let i2 = 0, il = attribute.count; i2 < il; i2++) {\n this.expandByPoint(_vector$b.fromBufferAttribute(attribute, i2));\n }\n return this;\n }\n setFromPoints(points) {\n this.makeEmpty();\n for (let i2 = 0, il = points.length; i2 < il; i2++) {\n this.expandByPoint(points[i2]);\n }\n return this;\n }\n setFromCenterAndSize(center, size) {\n const halfSize = _vector$b.copy(size).multiplyScalar(0.5);\n this.min.copy(center).sub(halfSize);\n this.max.copy(center).add(halfSize);\n return this;\n }\n setFromObject(object, precise = false) {\n this.makeEmpty();\n return this.expandByObject(object, precise);\n }\n clone() {\n return new this.constructor().copy(this);\n }\n copy(box) {\n this.min.copy(box.min);\n this.max.copy(box.max);\n return this;\n }\n makeEmpty() {\n this.min.x = this.min.y = this.min.z = Infinity;\n this.max.x = this.max.y = this.max.z = -Infinity;\n return this;\n }\n isEmpty() {\n return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z;\n }\n getCenter(target) {\n return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);\n }\n getSize(target) {\n return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min);\n }\n expandByPoint(point) {\n this.min.min(point);\n this.max.max(point);\n return this;\n }\n expandByVector(vector) {\n this.min.sub(vector);\n this.max.add(vector);\n return this;\n }\n expandByScalar(scalar) {\n this.min.addScalar(-scalar);\n this.max.addScalar(scalar);\n return this;\n }\n expandByObject(object, precise = false) {\n object.updateWorldMatrix(false, false);\n const geometry = object.geometry;\n if (geometry !== void 0) {\n const positionAttribute = geometry.getAttribute("position");\n if (precise === true && positionAttribute !== void 0 && object.isInstancedMesh !== true) {\n for (let i2 = 0, l = positionAttribute.count; i2 < l; i2++) {\n if (object.isMesh === true) {\n object.getVertexPosition(i2, _vector$b);\n } else {\n _vector$b.fromBufferAttribute(positionAttribute, i2);\n }\n _vector$b.applyMatrix4(object.matrixWorld);\n this.expandByPoint(_vector$b);\n }\n } else {\n if (object.boundingBox !== void 0) {\n if (object.boundingBox === null) {\n object.computeBoundingBox();\n }\n _box$4.copy(object.boundingBox);\n } else {\n if (geometry.boundingBox === null) {\n geometry.computeBoundingBox();\n }\n _box$4.copy(geometry.boundingBox);\n }\n _box$4.applyMatrix4(object.matrixWorld);\n this.union(_box$4);\n }\n }\n const children = object.children;\n for (let i2 = 0, l = children.length; i2 < l; i2++) {\n this.expandByObject(children[i2], precise);\n }\n return this;\n }\n containsPoint(point) {\n return point.x >= this.min.x && point.x <= this.max.x && point.y >= this.min.y && point.y <= this.max.y && point.z >= this.min.z && point.z <= this.max.z;\n }\n containsBox(box) {\n return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z;\n }\n getParameter(point, target) {\n return target.set(\n (point.x - this.min.x) / (this.max.x - this.min.x),\n (point.y - this.min.y) / (this.max.y - this.min.y),\n (point.z - this.min.z) / (this.max.z - this.min.z)\n );\n }\n intersectsBox(box) {\n return box.max.x >= this.min.x && box.min.x <= this.max.x && box.max.y >= this.min.y && box.min.y <= this.max.y && box.max.z >= this.min.z && box.min.z <= this.max.z;\n }\n intersectsSphere(sphere) {\n this.clampPoint(sphere.center, _vector$b);\n return _vector$b.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;\n }\n intersectsPlane(plane) {\n let min, max2;\n if (plane.normal.x > 0) {\n min = plane.normal.x * this.min.x;\n max2 = plane.normal.x * this.max.x;\n } else {\n min = plane.normal.x * this.max.x;\n max2 = plane.normal.x * this.min.x;\n }\n if (plane.normal.y > 0) {\n min += plane.normal.y * this.min.y;\n max2 += plane.normal.y * this.max.y;\n } else {\n min += plane.normal.y * this.max.y;\n max2 += plane.normal.y * this.min.y;\n }\n if (plane.normal.z > 0) {\n min += plane.normal.z * this.min.z;\n max2 += plane.normal.z * this.max.z;\n } else {\n min += plane.normal.z * this.max.z;\n max2 += plane.normal.z * this.min.z;\n }\n return min <= -plane.constant && max2 >= -plane.constant;\n }\n intersectsTriangle(triangle) {\n if (this.isEmpty()) {\n return false;\n }\n this.getCenter(_center);\n _extents.subVectors(this.max, _center);\n _v0$2.subVectors(triangle.a, _center);\n _v1$7.subVectors(triangle.b, _center);\n _v2$4.subVectors(triangle.c, _center);\n _f0.subVectors(_v1$7, _v0$2);\n _f1.subVectors(_v2$4, _v1$7);\n _f2.subVectors(_v0$2, _v2$4);\n let axes = [\n 0,\n -_f0.z,\n _f0.y,\n 0,\n -_f1.z,\n _f1.y,\n 0,\n -_f2.z,\n _f2.y,\n _f0.z,\n 0,\n -_f0.x,\n _f1.z,\n 0,\n -_f1.x,\n _f2.z,\n 0,\n -_f2.x,\n -_f0.y,\n _f0.x,\n 0,\n -_f1.y,\n _f1.x,\n 0,\n -_f2.y,\n _f2.x,\n 0\n ];\n if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {\n return false;\n }\n axes = [1, 0, 0, 0, 1, 0, 0, 0, 1];\n if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {\n return false;\n }\n _triangleNormal.crossVectors(_f0, _f1);\n axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z];\n return satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents);\n }\n clampPoint(point, target) {\n return target.copy(point).clamp(this.min, this.max);\n }\n distanceToPoint(point) {\n return this.clampPoint(point, _vector$b).distanceTo(point);\n }\n getBoundingSphere(target) {\n if (this.isEmpty()) {\n target.makeEmpty();\n } else {\n this.getCenter(target.center);\n target.radius = this.getSize(_vector$b).length() * 0.5;\n }\n return target;\n }\n intersect(box) {\n this.min.max(box.min);\n this.max.min(box.max);\n if (this.isEmpty()) this.makeEmpty();\n return this;\n }\n union(box) {\n this.min.min(box.min);\n this.max.max(box.max);\n return this;\n }\n applyMatrix4(matrix) {\n if (this.isEmpty()) return this;\n _points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix);\n _points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix);\n _points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix);\n _points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix);\n _points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix);\n _points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix);\n _points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix);\n _points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix);\n this.setFromPoints(_points);\n return this;\n }\n translate(offset) {\n this.min.add(offset);\n this.max.add(offset);\n return this;\n }\n equals(box) {\n return box.min.equals(this.min) && box.max.equals(this.max);\n }\n }\n const _points = [\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3()\n ];\n const _vector$b = /* @__PURE__ */ new Vector3();\n const _box$4 = /* @__PURE__ */ new Box3();\n const _v0$2 = /* @__PURE__ */ new Vector3();\n const _v1$7 = /* @__PURE__ */ new Vector3();\n const _v2$4 = /* @__PURE__ */ new Vector3();\n const _f0 = /* @__PURE__ */ new Vector3();\n const _f1 = /* @__PURE__ */ new Vector3();\n const _f2 = /* @__PURE__ */ new Vector3();\n const _center = /* @__PURE__ */ new Vector3();\n const _extents = /* @__PURE__ */ new Vector3();\n const _triangleNormal = /* @__PURE__ */ new Vector3();\n const _testAxis = /* @__PURE__ */ new Vector3();\n function satForAxes(axes, v0, v1, v2, extents) {\n for (let i2 = 0, j = axes.length - 3; i2 <= j; i2 += 3) {\n _testAxis.fromArray(axes, i2);\n const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z);\n const p0 = v0.dot(_testAxis);\n const p1 = v1.dot(_testAxis);\n const p2 = v2.dot(_testAxis);\n if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {\n return false;\n }\n }\n return true;\n }\n const _colorKeywords = {\n "aliceblue": 15792383,\n "antiquewhite": 16444375,\n "aqua": 65535,\n "aquamarine": 8388564,\n "azure": 15794175,\n "beige": 16119260,\n "bisque": 16770244,\n "black": 0,\n "blanchedalmond": 16772045,\n "blue": 255,\n "blueviolet": 9055202,\n "brown": 10824234,\n "burlywood": 14596231,\n "cadetblue": 6266528,\n "chartreuse": 8388352,\n "chocolate": 13789470,\n "coral": 16744272,\n "cornflowerblue": 6591981,\n "cornsilk": 16775388,\n "crimson": 14423100,\n "cyan": 65535,\n "darkblue": 139,\n "darkcyan": 35723,\n "darkgoldenrod": 12092939,\n "darkgray": 11119017,\n "darkgreen": 25600,\n "darkgrey": 11119017,\n "darkkhaki": 12433259,\n "darkmagenta": 9109643,\n "darkolivegreen": 5597999,\n "darkorange": 16747520,\n "darkorchid": 10040012,\n "darkred": 9109504,\n "darksalmon": 15308410,\n "darkseagreen": 9419919,\n "darkslateblue": 4734347,\n "darkslategray": 3100495,\n "darkslategrey": 3100495,\n "darkturquoise": 52945,\n "darkviolet": 9699539,\n "deeppink": 16716947,\n "deepskyblue": 49151,\n "dimgray": 6908265,\n "dimgrey": 6908265,\n "dodgerblue": 2003199,\n "firebrick": 11674146,\n "floralwhite": 16775920,\n "forestgreen": 2263842,\n "fuchsia": 16711935,\n "gainsboro": 14474460,\n "ghostwhite": 16316671,\n "gold": 16766720,\n "goldenrod": 14329120,\n "gray": 8421504,\n "green": 32768,\n "greenyellow": 11403055,\n "grey": 8421504,\n "honeydew": 15794160,\n "hotpink": 16738740,\n "indianred": 13458524,\n "indigo": 4915330,\n "ivory": 16777200,\n "khaki": 15787660,\n "lavender": 15132410,\n "lavenderblush": 16773365,\n "lawngreen": 8190976,\n "lemonchiffon": 16775885,\n "lightblue": 11393254,\n "lightcoral": 15761536,\n "lightcyan": 14745599,\n "lightgoldenrodyellow": 16448210,\n "lightgray": 13882323,\n "lightgreen": 9498256,\n "lightgrey": 13882323,\n "lightpink": 16758465,\n "lightsalmon": 16752762,\n "lightseagreen": 2142890,\n "lightskyblue": 8900346,\n "lightslategray": 7833753,\n "lightslategrey": 7833753,\n "lightsteelblue": 11584734,\n "lightyellow": 16777184,\n "lime": 65280,\n "limegreen": 3329330,\n "linen": 16445670,\n "magenta": 16711935,\n "maroon": 8388608,\n "mediumaquamarine": 6737322,\n "mediumblue": 205,\n "mediumorchid": 12211667,\n "mediumpurple": 9662683,\n "mediumseagreen": 3978097,\n "mediumslateblue": 8087790,\n "mediumspringgreen": 64154,\n "mediumturquoise": 4772300,\n "mediumvioletred": 13047173,\n "midnightblue": 1644912,\n "mintcream": 16121850,\n "mistyrose": 16770273,\n "moccasin": 16770229,\n "navajowhite": 16768685,\n "navy": 128,\n "oldlace": 16643558,\n "olive": 8421376,\n "olivedrab": 7048739,\n "orange": 16753920,\n "orangered": 16729344,\n "orchid": 14315734,\n "palegoldenrod": 15657130,\n "palegreen": 10025880,\n "paleturquoise": 11529966,\n "palevioletred": 14381203,\n "papayawhip": 16773077,\n "peachpuff": 16767673,\n "peru": 13468991,\n "pink": 16761035,\n "plum": 14524637,\n "powderblue": 11591910,\n "purple": 8388736,\n "rebeccapurple": 6697881,\n "red": 16711680,\n "rosybrown": 12357519,\n "royalblue": 4286945,\n "saddlebrown": 9127187,\n "salmon": 16416882,\n "sandybrown": 16032864,\n "seagreen": 3050327,\n "seashell": 16774638,\n "sienna": 10506797,\n "silver": 12632256,\n "skyblue": 8900331,\n "slateblue": 6970061,\n "slategray": 7372944,\n "slategrey": 7372944,\n "snow": 16775930,\n "springgreen": 65407,\n "steelblue": 4620980,\n "tan": 13808780,\n "teal": 32896,\n "thistle": 14204888,\n "tomato": 16737095,\n "turquoise": 4251856,\n "violet": 15631086,\n "wheat": 16113331,\n "white": 16777215,\n "whitesmoke": 16119285,\n "yellow": 16776960,\n "yellowgreen": 10145074\n };\n const _hslA = { h: 0, s: 0, l: 0 };\n const _hslB = { h: 0, s: 0, l: 0 };\n function hue2rgb(p, q, t) {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * 6 * (2 / 3 - t);\n return p;\n }\n class Color {\n constructor(r, g, b) {\n this.isColor = true;\n this.r = 1;\n this.g = 1;\n this.b = 1;\n return this.set(r, g, b);\n }\n set(r, g, b) {\n if (g === void 0 && b === void 0) {\n const value = r;\n if (value && value.isColor) {\n this.copy(value);\n } else if (typeof value === "number") {\n this.setHex(value);\n } else if (typeof value === "string") {\n this.setStyle(value);\n }\n } else {\n this.setRGB(r, g, b);\n }\n return this;\n }\n setScalar(scalar) {\n this.r = scalar;\n this.g = scalar;\n this.b = scalar;\n return this;\n }\n setHex(hex, colorSpace = SRGBColorSpace) {\n hex = Math.floor(hex);\n this.r = (hex >> 16 & 255) / 255;\n this.g = (hex >> 8 & 255) / 255;\n this.b = (hex & 255) / 255;\n ColorManagement.toWorkingColorSpace(this, colorSpace);\n return this;\n }\n setRGB(r, g, b, colorSpace = ColorManagement.workingColorSpace) {\n this.r = r;\n this.g = g;\n this.b = b;\n ColorManagement.toWorkingColorSpace(this, colorSpace);\n return this;\n }\n setHSL(h, s, l, colorSpace = ColorManagement.workingColorSpace) {\n h = euclideanModulo(h, 1);\n s = clamp(s, 0, 1);\n l = clamp(l, 0, 1);\n if (s === 0) {\n this.r = this.g = this.b = l;\n } else {\n const p = l <= 0.5 ? l * (1 + s) : l + s - l * s;\n const q = 2 * l - p;\n this.r = hue2rgb(q, p, h + 1 / 3);\n this.g = hue2rgb(q, p, h);\n this.b = hue2rgb(q, p, h - 1 / 3);\n }\n ColorManagement.toWorkingColorSpace(this, colorSpace);\n return this;\n }\n setStyle(style, colorSpace = SRGBColorSpace) {\n function handleAlpha(string) {\n if (string === void 0) return;\n if (parseFloat(string) < 1) {\n console.warn("THREE.Color: Alpha component of " + style + " will be ignored.");\n }\n }\n let m;\n if (m = /^(\\w+)\\(([^\\)]*)\\)/.exec(style)) {\n let color;\n const name = m[1];\n const components = m[2];\n switch (name) {\n case "rgb":\n case "rgba":\n if (color = /^\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setRGB(\n Math.min(255, parseInt(color[1], 10)) / 255,\n Math.min(255, parseInt(color[2], 10)) / 255,\n Math.min(255, parseInt(color[3], 10)) / 255,\n colorSpace\n );\n }\n if (color = /^\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setRGB(\n Math.min(100, parseInt(color[1], 10)) / 100,\n Math.min(100, parseInt(color[2], 10)) / 100,\n Math.min(100, parseInt(color[3], 10)) / 100,\n colorSpace\n );\n }\n break;\n case "hsl":\n case "hsla":\n if (color = /^\\s*(\\d*\\.?\\d+)\\s*,\\s*(\\d*\\.?\\d+)\\%\\s*,\\s*(\\d*\\.?\\d+)\\%\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setHSL(\n parseFloat(color[1]) / 360,\n parseFloat(color[2]) / 100,\n parseFloat(color[3]) / 100,\n colorSpace\n );\n }\n break;\n default:\n console.warn("THREE.Color: Unknown color model " + style);\n }\n } else if (m = /^\\#([A-Fa-f\\d]+)$/.exec(style)) {\n const hex = m[1];\n const size = hex.length;\n if (size === 3) {\n return this.setRGB(\n parseInt(hex.charAt(0), 16) / 15,\n parseInt(hex.charAt(1), 16) / 15,\n parseInt(hex.charAt(2), 16) / 15,\n colorSpace\n );\n } else if (size === 6) {\n return this.setHex(parseInt(hex, 16), colorSpace);\n } else {\n console.warn("THREE.Color: Invalid hex color " + style);\n }\n } else if (style && style.length > 0) {\n return this.setColorName(style, colorSpace);\n }\n return this;\n }\n setColorName(style, colorSpace = SRGBColorSpace) {\n const hex = _colorKeywords[style.toLowerCase()];\n if (hex !== void 0) {\n this.setHex(hex, colorSpace);\n } else {\n console.warn("THREE.Color: Unknown color " + style);\n }\n return this;\n }\n clone() {\n return new this.constructor(this.r, this.g, this.b);\n }\n copy(color) {\n this.r = color.r;\n this.g = color.g;\n this.b = color.b;\n return this;\n }\n copySRGBToLinear(color) {\n this.r = SRGBToLinear(color.r);\n this.g = SRGBToLinear(color.g);\n this.b = SRGBToLinear(color.b);\n return this;\n }\n copyLinearToSRGB(color) {\n this.r = LinearToSRGB(color.r);\n this.g = LinearToSRGB(color.g);\n this.b = LinearToSRGB(color.b);\n return this;\n }\n convertSRGBToLinear() {\n this.copySRGBToLinear(this);\n return this;\n }\n convertLinearToSRGB() {\n this.copyLinearToSRGB(this);\n return this;\n }\n getHex(colorSpace = SRGBColorSpace) {\n ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);\n return Math.round(clamp(_color.r * 255, 0, 255)) * 65536 + Math.round(clamp(_color.g * 255, 0, 255)) * 256 + Math.round(clamp(_color.b * 255, 0, 255));\n }\n getHexString(colorSpace = SRGBColorSpace) {\n return ("000000" + this.getHex(colorSpace).toString(16)).slice(-6);\n }\n getHSL(target, colorSpace = ColorManagement.workingColorSpace) {\n ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);\n const r = _color.r, g = _color.g, b = _color.b;\n const max2 = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let hue, saturation;\n const lightness = (min + max2) / 2;\n if (min === max2) {\n hue = 0;\n saturation = 0;\n } else {\n const delta = max2 - min;\n saturation = lightness <= 0.5 ? delta / (max2 + min) : delta / (2 - max2 - min);\n switch (max2) {\n case r:\n hue = (g - b) / delta + (g < b ? 6 : 0);\n break;\n case g:\n hue = (b - r) / delta + 2;\n break;\n case b:\n hue = (r - g) / delta + 4;\n break;\n }\n hue /= 6;\n }\n target.h = hue;\n target.s = saturation;\n target.l = lightness;\n return target;\n }\n getRGB(target, colorSpace = ColorManagement.workingColorSpace) {\n ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);\n target.r = _color.r;\n target.g = _color.g;\n target.b = _color.b;\n return target;\n }\n getStyle(colorSpace = SRGBColorSpace) {\n ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);\n const r = _color.r, g = _color.g, b = _color.b;\n if (colorSpace !== SRGBColorSpace) {\n return `color(${colorSpace} ${r.toFixed(3)} ${g.toFixed(3)} ${b.toFixed(3)})`;\n }\n return `rgb(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)})`;\n }\n offsetHSL(h, s, l) {\n this.getHSL(_hslA);\n return this.setHSL(_hslA.h + h, _hslA.s + s, _hslA.l + l);\n }\n add(color) {\n this.r += color.r;\n this.g += color.g;\n this.b += color.b;\n return this;\n }\n addColors(color1, color2) {\n this.r = color1.r + color2.r;\n this.g = color1.g + color2.g;\n this.b = color1.b + color2.b;\n return this;\n }\n addScalar(s) {\n this.r += s;\n this.g += s;\n this.b += s;\n return this;\n }\n sub(color) {\n this.r = Math.max(0, this.r - color.r);\n this.g = Math.max(0, this.g - color.g);\n this.b = Math.max(0, this.b - color.b);\n return this;\n }\n multiply(color) {\n this.r *= color.r;\n this.g *= color.g;\n this.b *= color.b;\n return this;\n }\n multiplyScalar(s) {\n this.r *= s;\n this.g *= s;\n this.b *= s;\n return this;\n }\n lerp(color, alpha) {\n this.r += (color.r - this.r) * alpha;\n this.g += (color.g - this.g) * alpha;\n this.b += (color.b - this.b) * alpha;\n return this;\n }\n lerpColors(color1, color2, alpha) {\n this.r = color1.r + (color2.r - color1.r) * alpha;\n this.g = color1.g + (color2.g - color1.g) * alpha;\n this.b = color1.b + (color2.b - color1.b) * alpha;\n return this;\n }\n lerpHSL(color, alpha) {\n this.getHSL(_hslA);\n color.getHSL(_hslB);\n const h = lerp(_hslA.h, _hslB.h, alpha);\n const s = lerp(_hslA.s, _hslB.s, alpha);\n const l = lerp(_hslA.l, _hslB.l, alpha);\n this.setHSL(h, s, l);\n return this;\n }\n setFromVector3(v) {\n this.r = v.x;\n this.g = v.y;\n this.b = v.z;\n return this;\n }\n applyMatrix3(m) {\n const r = this.r, g = this.g, b = this.b;\n const e = m.elements;\n this.r = e[0] * r + e[3] * g + e[6] * b;\n this.g = e[1] * r + e[4] * g + e[7] * b;\n this.b = e[2] * r + e[5] * g + e[8] * b;\n return this;\n }\n equals(c) {\n return c.r === this.r && c.g === this.g && c.b === this.b;\n }\n fromArray(array, offset = 0) {\n this.r = array[offset];\n this.g = array[offset + 1];\n this.b = array[offset + 2];\n return this;\n }\n toArray(array = [], offset = 0) {\n array[offset] = this.r;\n array[offset + 1] = this.g;\n array[offset + 2] = this.b;\n return array;\n }\n fromBufferAttribute(attribute, index) {\n this.r = attribute.getX(index);\n this.g = attribute.getY(index);\n this.b = attribute.getZ(index);\n return this;\n }\n toJSON() {\n return this.getHex();\n }\n *[Symbol.iterator]() {\n yield this.r;\n yield this.g;\n yield this.b;\n }\n }\n const _color = /* @__PURE__ */ new Color();\n Color.NAMES = _colorKeywords;\n if (typeof __THREE_DEVTOOLS__ !== "undefined") {\n __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { detail: {\n revision: REVISION\n } }));\n }\n if (typeof window !== "undefined") {\n if (window.__THREE__) {\n console.warn("WARNING: Multiple instances of Three.js being imported.");\n } else {\n window.__THREE__ = REVISION;\n }\n }\n const LN_SCALE_MIN = -12;\n const LN_SCALE_MAX = 9;\n const LN_SCALE_ZERO = -30;\n const SCALE_ZERO = Math.exp(LN_SCALE_ZERO);\n const SPLAT_TEX_WIDTH_BITS = 11;\n const SPLAT_TEX_HEIGHT_BITS = 11;\n const SPLAT_TEX_WIDTH = 1 << SPLAT_TEX_WIDTH_BITS;\n const SPLAT_TEX_HEIGHT = 1 << SPLAT_TEX_HEIGHT_BITS;\n const SPLAT_TEX_MIN_HEIGHT = 1;\n function unindentLines(s) {\n var _a2;\n let seenNonEmpty = false;\n const lines = s.split("\\n").map((line) => {\n const trimmedLine = line.trimEnd();\n if (seenNonEmpty) {\n return trimmedLine;\n }\n if (trimmedLine.length > 0) {\n seenNonEmpty = true;\n return trimmedLine;\n }\n return null;\n }).filter((line) => line != null);\n while (lines.length > 0 && lines[lines.length - 1].length === 0) {\n lines.pop();\n }\n if (lines.length === 0) {\n return [];\n }\n const indent = (_a2 = lines[0].match(/^\\s*/)) == null ? void 0 : _a2[0];\n if (!indent) {\n return lines;\n }\n const regex = new RegExp(`^${indent}`);\n return lines.map((line) => line.replace(regex, ""));\n }\n function unindent(s) {\n return unindentLines(s).join("\\n");\n }\n const f32buffer = new Float32Array(1);\n const u32buffer = new Uint32Array(f32buffer.buffer);\n function toHalf(f) {\n f32buffer[0] = f;\n const bits2 = u32buffer[0];\n const sign = bits2 >> 31 & 1;\n const exp = bits2 >> 23 & 255;\n const frac = bits2 & 8388607;\n const halfSign = sign << 15;\n if (exp === 255) {\n if (frac !== 0) {\n return halfSign | 32767;\n }\n return halfSign | 31744;\n }\n const newExp = exp - 127 + 15;\n if (newExp >= 31) {\n return halfSign | 31744;\n }\n if (newExp <= 0) {\n if (newExp < -10) {\n return halfSign;\n }\n const subFrac = (frac | 8388608) >> 1 - newExp + 13;\n return halfSign | subFrac;\n }\n const halfFrac = frac >> 13;\n return halfSign | newExp << 10 | halfFrac;\n }\n function fromHalf(h) {\n const sign = h >> 15 & 1;\n const exp = h >> 10 & 31;\n const frac = h & 1023;\n let f32bits;\n if (exp === 0) {\n if (frac === 0) {\n f32bits = sign << 31;\n } else {\n let mant = frac;\n let e = -14;\n while ((mant & 1024) === 0) {\n mant <<= 1;\n e--;\n }\n mant &= 1023;\n const newExp = e + 127;\n const newFrac = mant << 13;\n f32bits = sign << 31 | newExp << 23 | newFrac;\n }\n } else if (exp === 31) {\n if (frac === 0) {\n f32bits = sign << 31 | 2139095040;\n } else {\n f32bits = sign << 31 | 2143289344;\n }\n } else {\n const newExp = exp - 15 + 127;\n const newFrac = frac << 13;\n f32bits = sign << 31 | newExp << 23 | newFrac;\n }\n u32buffer[0] = f32bits;\n return f32buffer[0];\n }\n function floatToUint8(v) {\n return Math.max(0, Math.min(255, Math.round(v * 255)));\n }\n function getArrayBuffers(ctx) {\n const buffers = [];\n const seen = /* @__PURE__ */ new Set();\n function traverse(obj) {\n if (obj && typeof obj === "object" && !seen.has(obj)) {\n seen.add(obj);\n if (obj instanceof ArrayBuffer) {\n buffers.push(obj);\n } else if (ArrayBuffer.isView(obj)) {\n buffers.push(obj.buffer);\n } else if (Array.isArray(obj)) {\n obj.forEach(traverse);\n } else {\n Object.values(obj).forEach(traverse);\n }\n }\n }\n traverse(ctx);\n return buffers;\n }\n function setPackedSplat(packedSplats, index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const uA = floatToUint8(opacity);\n const uQuat = encodeQuatOctXy88R8(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n const uQuatX = uQuat & 255;\n const uQuatY = uQuat >>> 8 & 255;\n const uQuatZ = uQuat >>> 16 & 255;\n const lnScaleMin = (encoding == null ? void 0 : encoding.lnScaleMin) ?? LN_SCALE_MIN;\n const lnScaleMax = (encoding == null ? void 0 : encoding.lnScaleMax) ?? LN_SCALE_MAX;\n const lnScaleScale = 254 / (lnScaleMax - lnScaleMin);\n const uScaleX = scaleX < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleX) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleY = scaleY < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleY) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleZ = scaleZ < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleZ) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uCenterX = toHalf(x2);\n const uCenterY = toHalf(y);\n const uCenterZ = toHalf(z);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | uA << 24;\n packedSplats[i4 + 1] = uCenterX | uCenterY << 16;\n packedSplats[i4 + 2] = uCenterZ | uQuatX << 16 | uQuatY << 24;\n packedSplats[i4 + 3] = uScaleX | uScaleY << 8 | uScaleZ << 16 | uQuatZ << 24;\n }\n function setPackedSplatCenter(packedSplats, index, x2, y, z) {\n const uCenterX = toHalf(x2);\n const uCenterY = toHalf(y);\n const uCenterZ = toHalf(z);\n const i4 = index * 4;\n packedSplats[i4 + 1] = uCenterX | uCenterY << 16;\n packedSplats[i4 + 2] = uCenterZ | packedSplats[i4 + 2] & 4294901760;\n }\n function setPackedSplatScales(packedSplats, index, scaleX, scaleY, scaleZ, encoding) {\n const lnScaleMin = (encoding == null ? void 0 : encoding.lnScaleMin) ?? LN_SCALE_MIN;\n const lnScaleMax = (encoding == null ? void 0 : encoding.lnScaleMax) ?? LN_SCALE_MAX;\n const lnScaleScale = 254 / (lnScaleMax - lnScaleMin);\n const uScaleX = scaleX < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleX) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleY = scaleY < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleY) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleZ = scaleZ < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleZ) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const i4 = index * 4;\n packedSplats[i4 + 3] = uScaleX | uScaleY << 8 | uScaleZ << 16 | packedSplats[i4 + 3] & 4278190080;\n }\n function setPackedSplatQuat(packedSplats, index, quatX, quatY, quatZ, quatW) {\n const uQuat = encodeQuatOctXy88R8(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n const uQuatX = uQuat & 255;\n const uQuatY = uQuat >>> 8 & 255;\n const uQuatZ = uQuat >>> 16 & 255;\n const i4 = index * 4;\n packedSplats[i4 + 2] = packedSplats[i4 + 2] & 65535 | uQuatX << 16 | uQuatY << 24;\n packedSplats[i4 + 3] = packedSplats[i4 + 3] & 16777215 | uQuatZ << 24;\n }\n function setPackedSplatRgba(packedSplats, index, r, g, b, a, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const uA = floatToUint8(a);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | uA << 24;\n }\n function setPackedSplatRgb(packedSplats, index, r, g, b, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | packedSplats[i4] & 4278190080;\n }\n function setPackedSplatOpacity(packedSplats, index, opacity) {\n const uA = floatToUint8(opacity);\n const i4 = index * 4;\n packedSplats[i4] = packedSplats[i4] & 16777215 | uA << 24;\n }\n new Vector3();\n new Vector3();\n new Color();\n function getTextureSize(numSplats) {\n const width = SPLAT_TEX_WIDTH;\n const height = Math.max(\n SPLAT_TEX_MIN_HEIGHT,\n Math.min(SPLAT_TEX_HEIGHT, Math.ceil(numSplats / width))\n );\n const depth = Math.ceil(numSplats / (width * height));\n const maxSplats = width * height * depth;\n return { width, height, depth, maxSplats };\n }\n function computeMaxSplats(numSplats) {\n const width = SPLAT_TEX_WIDTH;\n const height = Math.max(\n SPLAT_TEX_MIN_HEIGHT,\n Math.min(SPLAT_TEX_HEIGHT, Math.ceil(numSplats / width))\n );\n const depth = Math.ceil(numSplats / (width * height));\n return width * height * depth;\n }\n unindent(`\n precision highp float;\n\n in vec3 position;\n\n void main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n }\n`);\n function encodeQuatOctXy88R8(q) {\n const qnorm = q.clone().normalize();\n if (qnorm.w < 0) {\n qnorm.set(-qnorm.x, -qnorm.y, -qnorm.z, -qnorm.w);\n }\n const theta = 2 * Math.acos(qnorm.w);\n const xyz_norm = Math.sqrt(\n qnorm.x * qnorm.x + qnorm.y * qnorm.y + qnorm.z * qnorm.z\n );\n const axis = xyz_norm < 1e-6 ? new Vector3(1, 0, 0) : new Vector3(qnorm.x, qnorm.y, qnorm.z).divideScalar(xyz_norm);\n const sum = Math.abs(axis.x) + Math.abs(axis.y) + Math.abs(axis.z);\n let p_x = axis.x / sum;\n let p_y = axis.y / sum;\n if (axis.z < 0) {\n const tmp = p_x;\n p_x = (1 - Math.abs(p_y)) * (p_x >= 0 ? 1 : -1);\n p_y = (1 - Math.abs(tmp)) * (p_y >= 0 ? 1 : -1);\n }\n const u_f = p_x * 0.5 + 0.5;\n const v_f = p_y * 0.5 + 0.5;\n const quantU = Math.round(u_f * 255);\n const quantV = Math.round(v_f * 255);\n const angleInt = Math.round(theta * (255 / Math.PI));\n return angleInt << 16 | quantV << 8 | quantU;\n }\n function packSint8Bytes(b0, b1, b22, b3) {\n const clampedB0 = Math.max(-127, Math.min(127, b0 * 127));\n const clampedB1 = Math.max(-127, Math.min(127, b1 * 127));\n const clampedB2 = Math.max(-127, Math.min(127, b22 * 127));\n const clampedB3 = Math.max(-127, Math.min(127, b3 * 127));\n return clampedB0 & 255 | (clampedB1 & 255) << 8 | (clampedB2 & 255) << 16 | (clampedB3 & 255) << 24;\n }\n function encodeSh1Rgb(sh1Array, index, sh1Rgb, encoding) {\n const sh1Min = (encoding == null ? void 0 : encoding.sh1Min) ?? -1;\n const sh1Max = (encoding == null ? void 0 : encoding.sh1Max) ?? 1;\n const sh1Mid = 0.5 * (sh1Min + sh1Max);\n const sh1Scale = 126 / (sh1Max - sh1Min);\n const base = index * 2;\n for (let i2 = 0; i2 < 9; ++i2) {\n const s = (sh1Rgb[i2] - sh1Mid) * sh1Scale;\n const value = Math.round(Math.max(-63, Math.min(63, s))) & 127;\n const bitStart = i2 * 7;\n const bitEnd = bitStart + 7;\n const wordStart = Math.floor(bitStart / 32);\n const bitOffset = bitStart - wordStart * 32;\n const firstWord = value << bitOffset & 4294967295;\n sh1Array[base + wordStart] |= firstWord;\n if (bitEnd > wordStart * 32 + 32) {\n const secondWord = value >>> 32 - bitOffset & 4294967295;\n sh1Array[base + wordStart + 1] |= secondWord;\n }\n }\n }\n function encodeSh2Rgb(sh2Array, index, sh2Rgb, encoding) {\n const sh2Min = (encoding == null ? void 0 : encoding.sh2Min) ?? -1;\n const sh2Max = (encoding == null ? void 0 : encoding.sh2Max) ?? 1;\n const sh2Mid = 0.5 * (sh2Min + sh2Max);\n const sh2Scale = 2 / (sh2Max - sh2Min);\n sh2Array[index * 4 + 0] = packSint8Bytes(\n (sh2Rgb[0] - sh2Mid) * sh2Scale,\n (sh2Rgb[1] - sh2Mid) * sh2Scale,\n (sh2Rgb[2] - sh2Mid) * sh2Scale,\n (sh2Rgb[3] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 1] = packSint8Bytes(\n (sh2Rgb[4] - sh2Mid) * sh2Scale,\n (sh2Rgb[5] - sh2Mid) * sh2Scale,\n (sh2Rgb[6] - sh2Mid) * sh2Scale,\n (sh2Rgb[7] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 2] = packSint8Bytes(\n (sh2Rgb[8] - sh2Mid) * sh2Scale,\n (sh2Rgb[9] - sh2Mid) * sh2Scale,\n (sh2Rgb[10] - sh2Mid) * sh2Scale,\n (sh2Rgb[11] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 3] = packSint8Bytes(\n (sh2Rgb[12] - sh2Mid) * sh2Scale,\n (sh2Rgb[13] - sh2Mid) * sh2Scale,\n (sh2Rgb[14] - sh2Mid) * sh2Scale,\n 0\n );\n }\n function encodeSh3Rgb(sh3Array, index, sh3Rgb, encoding) {\n const sh3Min = (encoding == null ? void 0 : encoding.sh3Min) ?? -1;\n const sh3Max = (encoding == null ? void 0 : encoding.sh3Max) ?? 1;\n const sh3Mid = 0.5 * (sh3Min + sh3Max);\n const sh3Scale = 62 / (sh3Max - sh3Min);\n const base = index * 4;\n for (let i2 = 0; i2 < 21; ++i2) {\n const s = (sh3Rgb[i2] - sh3Mid) * sh3Scale;\n const value = Math.round(Math.max(-31, Math.min(31, s))) & 63;\n const bitStart = i2 * 6;\n const bitEnd = bitStart + 6;\n const wordStart = Math.floor(bitStart / 32);\n const bitOffset = bitStart - wordStart * 32;\n const firstWord = value << bitOffset & 4294967295;\n sh3Array[base + wordStart] |= firstWord;\n if (bitEnd > wordStart * 32 + 32) {\n const secondWord = value >>> 32 - bitOffset & 4294967295;\n sh3Array[base + wordStart + 1] |= secondWord;\n }\n }\n }\n function decompressPartialGzip(fileBytes, numBytes) {\n const chunks = [];\n let totalBytes = 0;\n let result = null;\n const gunzip = new Gunzip((data, final) => {\n chunks.push(data);\n totalBytes += data.length;\n if (final || totalBytes >= numBytes) {\n const allBytes = new Uint8Array(totalBytes);\n let offset2 = 0;\n for (const chunk of chunks) {\n allBytes.set(chunk, offset2);\n offset2 += chunk.length;\n }\n result = allBytes.slice(0, numBytes);\n }\n });\n const CHUNK_SIZE = 1024;\n let offset = 0;\n while (result == null && offset < fileBytes.length) {\n const chunk = fileBytes.slice(offset, offset + CHUNK_SIZE);\n gunzip.push(chunk, false);\n offset += CHUNK_SIZE;\n }\n if (result == null) {\n gunzip.push(new Uint8Array(), true);\n if (result == null) {\n throw new Error("Failed to decompress partial gzip");\n }\n }\n return result;\n }\n class GunzipReader {\n constructor({\n fileBytes,\n chunkBytes = 64 * 1024\n }) {\n this.fileBytes = fileBytes;\n this.chunkBytes = chunkBytes;\n this.offset = 0;\n this.chunks = [];\n this.totalBytes = 0;\n this.gunzip = new Gunzip((chunk, _final) => {\n this.chunks.push(chunk);\n this.totalBytes += chunk.length;\n });\n }\n read(numBytes) {\n while (this.totalBytes < numBytes && this.offset < this.fileBytes.length) {\n const end = Math.min(\n this.offset + this.chunkBytes,\n this.fileBytes.length\n );\n this.gunzip.push(this.fileBytes.subarray(this.offset, end), false);\n this.offset = end;\n }\n if (this.totalBytes < numBytes && this.offset >= this.fileBytes.length) {\n this.gunzip.push(new Uint8Array(0), true);\n }\n if (this.totalBytes < numBytes) {\n throw new Error(\n `Unexpected EOF: needed ${numBytes}, got ${this.totalBytes}`\n );\n }\n const allBytes = new Uint8Array(this.totalBytes);\n let outOffset = 0;\n for (const chunk of this.chunks) {\n allBytes.set(chunk, outOffset);\n outOffset += chunk.length;\n }\n const result = allBytes.subarray(0, numBytes);\n this.chunks = [allBytes.subarray(numBytes)];\n this.totalBytes -= numBytes;\n return result;\n }\n }\n function decodeAntiSplat(fileBytes, initNumSplats, splatCallback) {\n const numSplats = Math.floor(fileBytes.length / 32);\n if (numSplats * 32 !== fileBytes.length) {\n throw new Error("Invalid .splat file size");\n }\n initNumSplats(numSplats);\n const f32 = new Float32Array(fileBytes.buffer);\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i322 = i2 * 32;\n const i8 = i2 * 8;\n const x2 = f32[i8 + 0];\n const y = f32[i8 + 1];\n const z = f32[i8 + 2];\n const scaleX = f32[i8 + 3];\n const scaleY = f32[i8 + 4];\n const scaleZ = f32[i8 + 5];\n const r = fileBytes[i322 + 24] / 255;\n const g = fileBytes[i322 + 25] / 255;\n const b = fileBytes[i322 + 26] / 255;\n const opacity = fileBytes[i322 + 27] / 255;\n const quatW = (fileBytes[i322 + 28] - 128) / 128;\n const quatX = (fileBytes[i322 + 29] - 128) / 128;\n const quatY = (fileBytes[i322 + 30] - 128) / 128;\n const quatZ = (fileBytes[i322 + 31] - 128) / 128;\n splatCallback(\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n }\n }\n function unpackAntiSplat(fileBytes, splatEncoding) {\n let numSplats = 0;\n let maxSplats = 0;\n let packedArray = new Uint32Array(0);\n decodeAntiSplat(\n fileBytes,\n (cbNumSplats) => {\n numSplats = cbNumSplats;\n maxSplats = computeMaxSplats(numSplats);\n packedArray = new Uint32Array(maxSplats * 4);\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n setPackedSplat(\n packedArray,\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n }\n );\n return { packedArray, numSplats };\n }\n const KSPLAT_COMPRESSION = {\n 0: {\n bytesPerCenter: 12,\n bytesPerScale: 12,\n bytesPerRotation: 16,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 4,\n scaleOffsetBytes: 12,\n rotationOffsetBytes: 24,\n colorOffsetBytes: 40,\n sphericalHarmonicsOffsetBytes: 44,\n scaleRange: 1\n },\n 1: {\n bytesPerCenter: 6,\n bytesPerScale: 6,\n bytesPerRotation: 8,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 2,\n scaleOffsetBytes: 6,\n rotationOffsetBytes: 12,\n colorOffsetBytes: 20,\n sphericalHarmonicsOffsetBytes: 24,\n scaleRange: 32767\n },\n 2: {\n bytesPerCenter: 6,\n bytesPerScale: 6,\n bytesPerRotation: 8,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 1,\n scaleOffsetBytes: 6,\n rotationOffsetBytes: 12,\n colorOffsetBytes: 20,\n sphericalHarmonicsOffsetBytes: 24,\n scaleRange: 32767\n }\n };\n const KSPLAT_SH_DEGREE_TO_COMPONENTS = {\n 0: 0,\n 1: 9,\n 2: 24,\n 3: 45\n };\n function decodeKsplat(fileBytes, initNumSplats, splatCallback, shCallback) {\n var _a2;\n const HEADER_BYTES = 4096;\n const SECTION_BYTES = 1024;\n let headerOffset = 0;\n const header = new DataView(fileBytes.buffer, headerOffset, HEADER_BYTES);\n headerOffset += HEADER_BYTES;\n const versionMajor = header.getUint8(0);\n const versionMinor = header.getUint8(1);\n if (versionMajor !== 0 || versionMinor < 1) {\n throw new Error(\n `Unsupported .ksplat version: ${versionMajor}.${versionMinor}`\n );\n }\n const maxSectionCount = header.getUint32(4, true);\n header.getUint32(16, true);\n const compressionLevel = header.getUint16(20, true);\n if (compressionLevel < 0 || compressionLevel > 2) {\n throw new Error(`Invalid .ksplat compression level: ${compressionLevel}`);\n }\n const minSphericalHarmonicsCoeff = header.getFloat32(36, true) || -1.5;\n const maxSphericalHarmonicsCoeff = header.getFloat32(40, true) || 1.5;\n let sectionBase = HEADER_BYTES + maxSectionCount * SECTION_BYTES;\n for (let section = 0; section < maxSectionCount; ++section) {\n let getSh = function(splatOffset, component) {\n if (compressionLevel === 0) {\n return data.getFloat32(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 4,\n true\n );\n }\n if (compressionLevel === 1) {\n return fromHalf(\n data.getUint16(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 2,\n true\n )\n );\n }\n const t = data.getUint8(splatOffset + sphericalHarmonicsOffsetBytes + component) / 255;\n return minSphericalHarmonicsCoeff + t * (maxSphericalHarmonicsCoeff - minSphericalHarmonicsCoeff);\n };\n const section2 = new DataView(fileBytes.buffer, headerOffset, SECTION_BYTES);\n headerOffset += SECTION_BYTES;\n const sectionSplatCount = section2.getUint32(0, true);\n const sectionMaxSplatCount = section2.getUint32(4, true);\n const bucketSize = section2.getUint32(8, true);\n const bucketCount = section2.getUint32(12, true);\n const bucketBlockSize = section2.getFloat32(16, true);\n const bucketStorageSizeBytes = section2.getUint16(20, true);\n const compressionScaleRange = (section2.getUint32(24, true) || ((_a2 = KSPLAT_COMPRESSION[compressionLevel]) == null ? void 0 : _a2.scaleRange)) ?? 1;\n const fullBucketCount = section2.getUint32(32, true);\n const fullBucketSplats = fullBucketCount * bucketSize;\n const partiallyFilledBucketCount = section2.getUint32(36, true);\n const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;\n const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;\n const sphericalHarmonicsDegree = section2.getUint16(40, true);\n const shComponents = KSPLAT_SH_DEGREE_TO_COMPONENTS[sphericalHarmonicsDegree];\n const {\n bytesPerCenter,\n bytesPerScale,\n bytesPerRotation,\n bytesPerColor,\n bytesPerSphericalHarmonicsComponent,\n scaleOffsetBytes,\n rotationOffsetBytes,\n colorOffsetBytes,\n sphericalHarmonicsOffsetBytes\n } = KSPLAT_COMPRESSION[compressionLevel];\n const bytesPerSplat = bytesPerCenter + bytesPerScale + bytesPerRotation + bytesPerColor + shComponents * bytesPerSphericalHarmonicsComponent;\n const splatDataStorageSizeBytes = bytesPerSplat * sectionMaxSplatCount;\n const storageSizeBytes = splatDataStorageSizeBytes + bucketsStorageSizeBytes;\n const sh1Index = [0, 3, 6, 1, 4, 7, 2, 5, 8];\n const sh2Index = [\n 9,\n 14,\n 19,\n 10,\n 15,\n 20,\n 11,\n 16,\n 21,\n 12,\n 17,\n 22,\n 13,\n 18,\n 23\n ];\n const sh3Index = [\n 24,\n 31,\n 38,\n 25,\n 32,\n 39,\n 26,\n 33,\n 40,\n 27,\n 34,\n 41,\n 28,\n 35,\n 42,\n 29,\n 36,\n 43,\n 30,\n 37,\n 44\n ];\n const sh1 = sphericalHarmonicsDegree >= 1 ? new Float32Array(3 * 3) : void 0;\n const sh2 = sphericalHarmonicsDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = sphericalHarmonicsDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const compressionScaleFactor = bucketBlockSize / 2 / compressionScaleRange;\n const bucketsBase = sectionBase + bucketsMetaDataSizeBytes;\n const dataBase = sectionBase + bucketsStorageSizeBytes;\n const data = new DataView(\n fileBytes.buffer,\n dataBase,\n splatDataStorageSizeBytes\n );\n const bucketArray = new Float32Array(\n fileBytes.buffer,\n bucketsBase,\n bucketCount * 3\n );\n const partiallyFilledBucketLengths = new Uint32Array(\n fileBytes.buffer,\n sectionBase,\n partiallyFilledBucketCount\n );\n let partialBucketIndex = fullBucketCount;\n let partialBucketBase = fullBucketSplats;\n for (let i2 = 0; i2 < sectionSplatCount; ++i2) {\n const splatOffset = i2 * bytesPerSplat;\n let bucketIndex;\n if (i2 < fullBucketSplats) {\n bucketIndex = Math.floor(i2 / bucketSize);\n } else {\n const bucketLength = partiallyFilledBucketLengths[partialBucketIndex - fullBucketCount];\n if (i2 >= partialBucketBase + bucketLength) {\n partialBucketIndex += 1;\n partialBucketBase += bucketLength;\n }\n bucketIndex = partialBucketIndex;\n }\n const x2 = compressionLevel === 0 ? data.getFloat32(splatOffset + 0, true) : (data.getUint16(splatOffset + 0, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 0];\n const y = compressionLevel === 0 ? data.getFloat32(splatOffset + 4, true) : (data.getUint16(splatOffset + 2, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 1];\n const z = compressionLevel === 0 ? data.getFloat32(splatOffset + 8, true) : (data.getUint16(splatOffset + 4, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 2];\n const scaleX = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 0, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 0, true));\n const scaleY = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 4, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 2, true));\n const scaleZ = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 8, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 4, true));\n const quatW = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 0, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 0, true)\n );\n const quatX = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 4, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 2, true)\n );\n const quatY = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 8, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 4, true)\n );\n const quatZ = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 12, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 6, true)\n );\n const r = data.getUint8(splatOffset + colorOffsetBytes + 0) / 255;\n const g = data.getUint8(splatOffset + colorOffsetBytes + 1) / 255;\n const b = data.getUint8(splatOffset + colorOffsetBytes + 2) / 255;\n const opacity = data.getUint8(splatOffset + colorOffsetBytes + 3) / 255;\n splatCallback(\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n if (sphericalHarmonicsDegree >= 1 && sh1) {\n for (const [i22, key] of sh1Index.entries()) {\n sh1[i22] = getSh(splatOffset, key);\n }\n if (sh2) {\n for (const [i22, key] of sh2Index.entries()) {\n sh2[i22] = getSh(splatOffset, key);\n }\n }\n if (sh3) {\n for (const [i22, key] of sh3Index.entries()) {\n sh3[i22] = getSh(splatOffset, key);\n }\n }\n shCallback == null ? void 0 : shCallback(i2, sh1, sh2, sh3);\n }\n }\n sectionBase += storageSizeBytes;\n }\n }\n function unpackKsplat(fileBytes, splatEncoding) {\n var _a2;\n const HEADER_BYTES = 4096;\n const SECTION_BYTES = 1024;\n let headerOffset = 0;\n const header = new DataView(fileBytes.buffer, headerOffset, HEADER_BYTES);\n headerOffset += HEADER_BYTES;\n const versionMajor = header.getUint8(0);\n const versionMinor = header.getUint8(1);\n if (versionMajor !== 0 || versionMinor < 1) {\n throw new Error(\n `Unsupported .ksplat version: ${versionMajor}.${versionMinor}`\n );\n }\n const maxSectionCount = header.getUint32(4, true);\n const splatCount = header.getUint32(16, true);\n const compressionLevel = header.getUint16(20, true);\n if (compressionLevel < 0 || compressionLevel > 2) {\n throw new Error(`Invalid .ksplat compression level: ${compressionLevel}`);\n }\n const minSphericalHarmonicsCoeff = header.getFloat32(36, true) || -1.5;\n const maxSphericalHarmonicsCoeff = header.getFloat32(40, true) || 1.5;\n const numSplats = splatCount;\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n let sectionBase = HEADER_BYTES + maxSectionCount * SECTION_BYTES;\n for (let section = 0; section < maxSectionCount; ++section) {\n let getSh = function(splatOffset, component) {\n if (compressionLevel === 0) {\n return data.getFloat32(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 4,\n true\n );\n }\n if (compressionLevel === 1) {\n return fromHalf(\n data.getUint16(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 2,\n true\n )\n );\n }\n const t = data.getUint8(splatOffset + sphericalHarmonicsOffsetBytes + component) / 255;\n return minSphericalHarmonicsCoeff + t * (maxSphericalHarmonicsCoeff - minSphericalHarmonicsCoeff);\n };\n const section2 = new DataView(fileBytes.buffer, headerOffset, SECTION_BYTES);\n headerOffset += SECTION_BYTES;\n const sectionSplatCount = section2.getUint32(0, true);\n const sectionMaxSplatCount = section2.getUint32(4, true);\n const bucketSize = section2.getUint32(8, true);\n const bucketCount = section2.getUint32(12, true);\n const bucketBlockSize = section2.getFloat32(16, true);\n const bucketStorageSizeBytes = section2.getUint16(20, true);\n const compressionScaleRange = (section2.getUint32(24, true) || ((_a2 = KSPLAT_COMPRESSION[compressionLevel]) == null ? void 0 : _a2.scaleRange)) ?? 1;\n const fullBucketCount = section2.getUint32(32, true);\n const fullBucketSplats = fullBucketCount * bucketSize;\n const partiallyFilledBucketCount = section2.getUint32(36, true);\n const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;\n const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;\n const sphericalHarmonicsDegree = section2.getUint16(40, true);\n const shComponents = KSPLAT_SH_DEGREE_TO_COMPONENTS[sphericalHarmonicsDegree];\n const {\n bytesPerCenter,\n bytesPerScale,\n bytesPerRotation,\n bytesPerColor,\n bytesPerSphericalHarmonicsComponent,\n scaleOffsetBytes,\n rotationOffsetBytes,\n colorOffsetBytes,\n sphericalHarmonicsOffsetBytes\n } = KSPLAT_COMPRESSION[compressionLevel];\n const bytesPerSplat = bytesPerCenter + bytesPerScale + bytesPerRotation + bytesPerColor + shComponents * bytesPerSphericalHarmonicsComponent;\n const splatDataStorageSizeBytes = bytesPerSplat * sectionMaxSplatCount;\n const storageSizeBytes = splatDataStorageSizeBytes + bucketsStorageSizeBytes;\n const sh1Index = [0, 3, 6, 1, 4, 7, 2, 5, 8];\n const sh2Index = [\n 9,\n 14,\n 19,\n 10,\n 15,\n 20,\n 11,\n 16,\n 21,\n 12,\n 17,\n 22,\n 13,\n 18,\n 23\n ];\n const sh3Index = [\n 24,\n 31,\n 38,\n 25,\n 32,\n 39,\n 26,\n 33,\n 40,\n 27,\n 34,\n 41,\n 28,\n 35,\n 42,\n 29,\n 36,\n 43,\n 30,\n 37,\n 44\n ];\n const sh1 = sphericalHarmonicsDegree >= 1 ? new Float32Array(3 * 3) : void 0;\n const sh2 = sphericalHarmonicsDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = sphericalHarmonicsDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const compressionScaleFactor = bucketBlockSize / 2 / compressionScaleRange;\n const bucketsBase = sectionBase + bucketsMetaDataSizeBytes;\n const dataBase = sectionBase + bucketsStorageSizeBytes;\n const data = new DataView(\n fileBytes.buffer,\n dataBase,\n splatDataStorageSizeBytes\n );\n const bucketArray = new Float32Array(\n fileBytes.buffer,\n bucketsBase,\n bucketCount * 3\n );\n const partiallyFilledBucketLengths = new Uint32Array(\n fileBytes.buffer,\n sectionBase,\n partiallyFilledBucketCount\n );\n let partialBucketIndex = fullBucketCount;\n let partialBucketBase = fullBucketSplats;\n for (let i2 = 0; i2 < sectionSplatCount; ++i2) {\n const splatOffset = i2 * bytesPerSplat;\n let bucketIndex;\n if (i2 < fullBucketSplats) {\n bucketIndex = Math.floor(i2 / bucketSize);\n } else {\n const bucketLength = partiallyFilledBucketLengths[partialBucketIndex - fullBucketCount];\n if (i2 >= partialBucketBase + bucketLength) {\n partialBucketIndex += 1;\n partialBucketBase += bucketLength;\n }\n bucketIndex = partialBucketIndex;\n }\n const x2 = compressionLevel === 0 ? data.getFloat32(splatOffset + 0, true) : (data.getUint16(splatOffset + 0, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 0];\n const y = compressionLevel === 0 ? data.getFloat32(splatOffset + 4, true) : (data.getUint16(splatOffset + 2, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 1];\n const z = compressionLevel === 0 ? data.getFloat32(splatOffset + 8, true) : (data.getUint16(splatOffset + 4, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 2];\n const scaleX = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 0, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 0, true));\n const scaleY = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 4, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 2, true));\n const scaleZ = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 8, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 4, true));\n const quatW = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 0, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 0, true)\n );\n const quatX = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 4, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 2, true)\n );\n const quatY = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 8, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 4, true)\n );\n const quatZ = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 12, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 6, true)\n );\n const r = data.getUint8(splatOffset + colorOffsetBytes + 0) / 255;\n const g = data.getUint8(splatOffset + colorOffsetBytes + 1) / 255;\n const b = data.getUint8(splatOffset + colorOffsetBytes + 2) / 255;\n const opacity = data.getUint8(splatOffset + colorOffsetBytes + 3) / 255;\n setPackedSplat(\n packedArray,\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n if (sphericalHarmonicsDegree >= 1) {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n for (const [i22, key] of sh1Index.entries()) {\n sh1[i22] = getSh(splatOffset, key);\n }\n encodeSh1Rgb(extra.sh1, i2, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n for (const [i22, key] of sh2Index.entries()) {\n sh2[i22] = getSh(splatOffset, key);\n }\n encodeSh2Rgb(extra.sh2, i2, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n for (const [i22, key] of sh3Index.entries()) {\n sh3[i22] = getSh(splatOffset, key);\n }\n encodeSh3Rgb(extra.sh3, i2, sh3, splatEncoding);\n }\n }\n }\n sectionBase += storageSizeBytes;\n }\n return { packedArray, numSplats, extra };\n }\n const _PlyReader = class _PlyReader {\n // Create a PlyReader from a Uint8Array/ArrayBuffer, no parsing done yet\n constructor({ fileBytes }) {\n this.header = "";\n this.littleEndian = true;\n this.elements = {};\n this.comments = [];\n this.data = null;\n this.numSplats = 0;\n this.fileBytes = fileBytes instanceof ArrayBuffer ? new Uint8Array(fileBytes) : fileBytes;\n }\n // Identify and parse the PLY text header (assumed to be <64KB in size).\n // this.elements will contain all the elements in the file, typically\n // "vertex" contains the Gsplat data.\n async parseHeader() {\n const bufferStream = new ReadableStream({\n start: (controller) => {\n controller.enqueue(this.fileBytes.slice(0, 65536));\n controller.close();\n }\n });\n const decoder = bufferStream.pipeThrough(new TextDecoderStream()).getReader();\n this.header = "";\n const headerTerminator = "end_header\\n";\n while (true) {\n const { value, done } = await decoder.read();\n if (done) {\n throw new Error("Failed to read header");\n }\n this.header += value;\n const endHeader = this.header.indexOf(headerTerminator);\n if (endHeader >= 0) {\n this.header = this.header.slice(0, endHeader + headerTerminator.length);\n break;\n }\n }\n const headerLen = new TextEncoder().encode(this.header).length;\n this.data = new DataView(this.fileBytes.buffer, headerLen);\n this.elements = {};\n let curElement = null;\n this.comments = [];\n this.header.trim().split("\\n").forEach((line, lineIndex) => {\n const trimmedLine = line.trim();\n if (lineIndex === 0) {\n if (trimmedLine !== "ply") {\n throw new Error("Invalid PLY header");\n }\n return;\n }\n if (trimmedLine.length === 0) {\n return;\n }\n const fields = trimmedLine.split(" ");\n switch (fields[0]) {\n case "format":\n if (fields[1] === "binary_little_endian") {\n this.littleEndian = true;\n } else if (fields[1] === "binary_big_endian") {\n this.littleEndian = false;\n } else {\n throw new Error(`Unsupported PLY format: ${fields[1]}`);\n }\n if (fields[2] !== "1.0") {\n throw new Error(`Unsupported PLY version: ${fields[2]}`);\n }\n break;\n case "end_header":\n break;\n case "comment":\n this.comments.push(trimmedLine.slice("comment ".length));\n break;\n case "element": {\n const name = fields[1];\n curElement = {\n name,\n count: Number.parseInt(fields[2]),\n properties: {}\n };\n this.elements[name] = curElement;\n break;\n }\n case "property":\n if (curElement == null) {\n throw new Error("Property must be inside an element");\n }\n if (fields[1] === "list") {\n curElement.properties[fields[4]] = {\n isList: true,\n type: fields[3],\n countType: fields[2]\n };\n } else {\n curElement.properties[fields[2]] = {\n isList: false,\n type: fields[1]\n };\n }\n break;\n }\n });\n if (this.elements.vertex) {\n this.numSplats = this.elements.vertex.count;\n }\n }\n parseData(elementCallback) {\n let offset = 0;\n const data = this.data;\n if (data == null) {\n throw new Error("No data to parse");\n }\n for (const elementName in this.elements) {\n const element = this.elements[elementName];\n const { count, properties } = element;\n const item = {};\n const parsers = [];\n for (const [propertyName, property] of Object.entries(properties)) {\n if (!property.isList) {\n item[propertyName] = 0;\n parsers.push(() => {\n item[propertyName] = PARSE_FIELD[property.type](\n data,\n offset,\n this.littleEndian\n );\n offset += FIELD_BYTES[property.type];\n });\n } else {\n item[propertyName] = [];\n parsers.push(() => {\n const list = item[propertyName];\n list.length = PARSE_FIELD[property.countType](\n data,\n offset,\n this.littleEndian\n );\n offset += FIELD_BYTES[property.countType];\n for (let i2 = 0; i2 < list.length; i2++) {\n list[i2] = PARSE_FIELD[property.type](\n data,\n offset,\n this.littleEndian\n );\n offset += FIELD_BYTES[property.type];\n }\n });\n }\n }\n const callback = elementCallback(element) ?? (() => {\n });\n for (let index = 0; index < count; index++) {\n for (const parser of parsers) {\n parser();\n }\n callback(index, item);\n }\n }\n }\n // Parse all the Gsplat data in the PLY file in go, invoking the given\n // callbacks for each Gsplat.\n parseSplats(splatCallback, shCallback) {\n if (this.elements.vertex == null) {\n throw new Error("No vertex element found");\n }\n let isSuperSplat = false;\n const ssChunks = [];\n let numSh = 0;\n let sh1Props = [];\n let sh2Props = [];\n let sh3Props = [];\n let sh1 = void 0;\n let sh2 = void 0;\n let sh3 = void 0;\n function prepareSh() {\n const num_f_rest = NUM_SH_TO_NUM_F_REST[numSh];\n sh1Props = new Array(3).fill(null).flatMap(\n (_, k) => [0, 1, 2].map((_2, d) => `f_rest_${k + d * num_f_rest / 3}`)\n );\n sh2Props = new Array(5).fill(null).flatMap(\n (_, k) => [0, 1, 2].map((_2, d) => `f_rest_${3 + k + d * num_f_rest / 3}`)\n );\n sh3Props = new Array(7).fill(null).flatMap(\n (_, k) => [0, 1, 2].map((_2, d) => `f_rest_${8 + k + d * num_f_rest / 3}`)\n );\n sh1 = numSh >= 1 ? new Float32Array(3 * 3) : void 0;\n sh2 = numSh >= 2 ? new Float32Array(5 * 3) : void 0;\n sh3 = numSh >= 3 ? new Float32Array(7 * 3) : void 0;\n }\n function ssShCallback(index, item) {\n if (!sh1) {\n throw new Error("Missing sh1");\n }\n for (const [i2, key] of sh1Props.entries()) {\n sh1[i2] = item[key] * 8 / 255 - 4;\n }\n if (sh2) {\n for (const [i2, key] of sh2Props.entries()) {\n sh2[i2] = item[key] * 8 / 255 - 4;\n }\n }\n if (sh3) {\n for (const [i2, key] of sh3Props.entries()) {\n sh3[i2] = item[key] * 8 / 255 - 4;\n }\n }\n shCallback == null ? void 0 : shCallback(index, sh1, sh2, sh3);\n }\n function initSuperSplat(element) {\n const {\n min_x,\n min_y,\n min_z,\n max_x,\n max_y,\n max_z,\n min_scale_x,\n min_scale_y,\n min_scale_z,\n max_scale_x,\n max_scale_y,\n max_scale_z\n } = element.properties;\n if (!min_x || !min_y || !min_z || !max_x || !max_y || !max_z || !min_scale_x || !min_scale_y || !min_scale_z || !max_scale_x || !max_scale_y || !max_scale_z) {\n throw new Error("Missing PLY chunk properties");\n }\n isSuperSplat = true;\n return (index, item) => {\n const {\n min_x: min_x2,\n min_y: min_y2,\n min_z: min_z2,\n max_x: max_x2,\n max_y: max_y2,\n max_z: max_z2,\n min_scale_x: min_scale_x2,\n min_scale_y: min_scale_y2,\n min_scale_z: min_scale_z2,\n max_scale_x: max_scale_x2,\n max_scale_y: max_scale_y2,\n max_scale_z: max_scale_z2,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n } = item;\n ssChunks.push({\n min_x: min_x2,\n min_y: min_y2,\n min_z: min_z2,\n max_x: max_x2,\n max_y: max_y2,\n max_z: max_z2,\n min_scale_x: min_scale_x2,\n min_scale_y: min_scale_y2,\n min_scale_z: min_scale_z2,\n max_scale_x: max_scale_x2,\n max_scale_y: max_scale_y2,\n max_scale_z: max_scale_z2,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n });\n };\n }\n function decodeSuperSplat(element) {\n if (shCallback && element.name === "sh") {\n numSh = getNumSh(element.properties);\n prepareSh();\n return ssShCallback;\n }\n if (element.name !== "vertex") {\n return null;\n }\n const { packed_position, packed_rotation, packed_scale, packed_color } = element.properties;\n if (!packed_position || !packed_rotation || !packed_scale || !packed_color) {\n throw new Error(\n "Missing PLY properties: packed_position, packed_rotation, packed_scale, packed_color"\n );\n }\n const SQRT2 = Math.sqrt(2);\n return (index, item) => {\n const chunk = ssChunks[index >>> 8];\n if (chunk == null) {\n throw new Error("Missing PLY chunk");\n }\n const {\n min_x,\n min_y,\n min_z,\n max_x,\n max_y,\n max_z,\n min_scale_x,\n min_scale_y,\n min_scale_z,\n max_scale_x,\n max_scale_y,\n max_scale_z,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n } = chunk;\n const { packed_position: packed_position2, packed_rotation: packed_rotation2, packed_scale: packed_scale2, packed_color: packed_color2 } = item;\n const x2 = (packed_position2 >>> 21 & 2047) / 2047 * (max_x - min_x) + min_x;\n const y = (packed_position2 >>> 11 & 1023) / 1023 * (max_y - min_y) + min_y;\n const z = (packed_position2 & 2047) / 2047 * (max_z - min_z) + min_z;\n const r0 = ((packed_rotation2 >>> 20 & 1023) / 1023 - 0.5) * SQRT2;\n const r1 = ((packed_rotation2 >>> 10 & 1023) / 1023 - 0.5) * SQRT2;\n const r2 = ((packed_rotation2 & 1023) / 1023 - 0.5) * SQRT2;\n const rr = Math.sqrt(Math.max(0, 1 - r0 * r0 - r1 * r1 - r2 * r2));\n const rOrder = packed_rotation2 >>> 30;\n const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1;\n const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2;\n const quatZ = rOrder <= 2 ? r2 : rr;\n const quatW = rOrder === 0 ? rr : r0;\n const scaleX = Math.exp(\n (packed_scale2 >>> 21 & 2047) / 2047 * (max_scale_x - min_scale_x) + min_scale_x\n );\n const scaleY = Math.exp(\n (packed_scale2 >>> 11 & 1023) / 1023 * (max_scale_y - min_scale_y) + min_scale_y\n );\n const scaleZ = Math.exp(\n (packed_scale2 & 2047) / 2047 * (max_scale_z - min_scale_z) + min_scale_z\n );\n const r = (packed_color2 >>> 24 & 255) / 255 * ((max_r ?? 1) - (min_r ?? 0)) + (min_r ?? 0);\n const g = (packed_color2 >>> 16 & 255) / 255 * ((max_g ?? 1) - (min_g ?? 0)) + (min_g ?? 0);\n const b = (packed_color2 >>> 8 & 255) / 255 * ((max_b ?? 1) - (min_b ?? 0)) + (min_b ?? 0);\n const opacity = (packed_color2 & 255) / 255;\n splatCallback(\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n };\n }\n const elementCallback = (element) => {\n if (element.name === "chunk") {\n return initSuperSplat(element);\n }\n if (isSuperSplat) {\n return decodeSuperSplat(element);\n }\n if (element.name !== "vertex") {\n return null;\n }\n const {\n x: x2,\n y,\n z,\n scale_0,\n scale_1,\n scale_2,\n rot_0,\n rot_1,\n rot_2,\n rot_3,\n opacity,\n f_dc_0,\n f_dc_1,\n f_dc_2,\n red,\n green,\n blue,\n alpha\n } = element.properties;\n if (!x2 || !y || !z) {\n throw new Error("Missing PLY properties: x, y, z");\n }\n const hasScales = scale_0 && scale_1 && scale_2;\n const hasRots = rot_0 && rot_1 && rot_2 && rot_3;\n const alphaDiv = alpha != null ? FIELD_SCALE[alpha.type] : 1;\n const redDiv = red != null ? FIELD_SCALE[red.type] : 1;\n const greenDiv = green != null ? FIELD_SCALE[green.type] : 1;\n const blueDiv = blue != null ? FIELD_SCALE[blue.type] : 1;\n numSh = getNumSh(element.properties);\n prepareSh();\n return (index, item) => {\n const scaleX = hasScales ? Math.exp(item.scale_0) : _PlyReader.defaultPointScale;\n const scaleY = hasScales ? Math.exp(item.scale_1) : _PlyReader.defaultPointScale;\n const scaleZ = hasScales ? Math.exp(item.scale_2) : _PlyReader.defaultPointScale;\n const quatX = hasRots ? item.rot_1 : 0;\n const quatY = hasRots ? item.rot_2 : 0;\n const quatZ = hasRots ? item.rot_3 : 0;\n const quatW = hasRots ? item.rot_0 : 1;\n const op = opacity != null ? 1 / (1 + Math.exp(-item.opacity)) : alpha != null ? item.alpha / alphaDiv : 1;\n const r = f_dc_0 != null ? item.f_dc_0 * SH_C0$1 + 0.5 : red != null ? item.red / redDiv : 1;\n const g = f_dc_1 != null ? item.f_dc_1 * SH_C0$1 + 0.5 : green != null ? item.green / greenDiv : 1;\n const b = f_dc_2 != null ? item.f_dc_2 * SH_C0$1 + 0.5 : blue != null ? item.blue / blueDiv : 1;\n splatCallback(\n index,\n item.x,\n item.y,\n item.z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n op,\n r,\n g,\n b\n );\n if (shCallback && sh1) {\n if (sh1) {\n for (const [i2, key] of sh1Props.entries()) {\n sh1[i2] = item[key];\n }\n }\n if (sh2) {\n for (const [i2, key] of sh2Props.entries()) {\n sh2[i2] = item[key];\n }\n }\n if (sh3) {\n for (const [i2, key] of sh3Props.entries()) {\n sh3[i2] = item[key];\n }\n }\n shCallback(index, sh1, sh2, sh3);\n }\n };\n };\n this.parseData(elementCallback);\n }\n // Inject RGBA values into original PLY file, which can be used to modify\n // the color/opacity of the Gsplats and write out the modified PLY file.\n injectRgba(rgba) {\n let offset = 0;\n const data = this.data;\n if (data == null) {\n throw new Error("No parsed data");\n }\n if (rgba.length !== this.numSplats * 4) {\n throw new Error("Invalid RGBA array length");\n }\n for (const elementName in this.elements) {\n const element = this.elements[elementName];\n const { count, properties } = element;\n const parsers = [];\n let rgbaOffset = 0;\n const isVertex = elementName === "vertex";\n if (isVertex) {\n for (const name of ["opacity", "f_dc_0", "f_dc_1", "f_dc_2"]) {\n if (!properties[name] || properties[name].type !== "float") {\n throw new Error(`Can\'t injectRgba due to property: ${name}`);\n }\n }\n }\n for (const [propertyName, property] of Object.entries(properties)) {\n if (!property.isList) {\n if (isVertex) {\n if (propertyName === "f_dc_0" || propertyName === "f_dc_1" || propertyName === "f_dc_2") {\n const component = Number.parseInt(\n propertyName.slice("f_dc_".length)\n );\n parsers.push(() => {\n const value = (rgba[rgbaOffset + component] / 255 - 0.5) / SH_C0$1;\n SET_FIELD[property.type](\n data,\n offset,\n this.littleEndian,\n value\n );\n });\n } else if (propertyName === "opacity") {\n parsers.push(() => {\n const value = Math.max(\n -100,\n Math.min(\n 100,\n -Math.log(1 / (rgba[rgbaOffset + 3] / 255) - 1)\n )\n );\n SET_FIELD[property.type](\n data,\n offset,\n this.littleEndian,\n value\n );\n });\n }\n }\n parsers.push(() => {\n offset += FIELD_BYTES[property.type];\n });\n } else {\n parsers.push(() => {\n const length = PARSE_FIELD[property.countType](\n data,\n offset,\n this.littleEndian\n );\n offset += FIELD_BYTES[property.countType];\n offset += length * FIELD_BYTES[property.type];\n });\n }\n }\n for (let index = 0; index < count; index++) {\n for (const parser of parsers) {\n parser();\n }\n if (isVertex) {\n rgbaOffset += 4;\n }\n }\n }\n }\n };\n _PlyReader.defaultPointScale = 1e-3;\n let PlyReader = _PlyReader;\n const SH_C0$1 = 0.28209479177387814;\n const PARSE_FIELD = {\n char: (data, offset, littleEndian) => {\n return data.getInt8(offset);\n },\n uchar: (data, offset, littleEndian) => {\n return data.getUint8(offset);\n },\n short: (data, offset, littleEndian) => {\n return data.getInt16(offset, littleEndian);\n },\n ushort: (data, offset, littleEndian) => {\n return data.getUint16(offset, littleEndian);\n },\n int: (data, offset, littleEndian) => {\n return data.getInt32(offset, littleEndian);\n },\n uint: (data, offset, littleEndian) => {\n return data.getUint32(offset, littleEndian);\n },\n float: (data, offset, littleEndian) => {\n return data.getFloat32(offset, littleEndian);\n },\n double: (data, offset, littleEndian) => {\n return data.getFloat64(offset, littleEndian);\n }\n };\n const SET_FIELD = {\n char: (data, offset, littleEndian, value) => {\n data.setInt8(offset, value);\n },\n uchar: (data, offset, littleEndian, value) => {\n data.setUint8(offset, value);\n },\n short: (data, offset, littleEndian, value) => {\n data.setInt16(offset, value, littleEndian);\n },\n ushort: (data, offset, littleEndian, value) => {\n data.setUint16(offset, value, littleEndian);\n },\n int: (data, offset, littleEndian, value) => {\n data.setInt32(offset, value, littleEndian);\n },\n uint: (data, offset, littleEndian, value) => {\n data.setUint32(offset, value, littleEndian);\n },\n float: (data, offset, littleEndian, value) => {\n data.setFloat32(offset, value, littleEndian);\n },\n double: (data, offset, littleEndian, value) => {\n data.setFloat64(offset, value, littleEndian);\n }\n };\n const FIELD_BYTES = {\n char: 1,\n uchar: 1,\n short: 2,\n ushort: 2,\n int: 4,\n uint: 4,\n float: 4,\n double: 8\n };\n const FIELD_SCALE = {\n char: 127,\n uchar: 255,\n short: 32767,\n ushort: 65535,\n int: 2147483647,\n uint: 4294967295,\n float: 1,\n double: 1\n };\n const NUM_F_REST_TO_NUM_SH = {\n 0: 0,\n 9: 1,\n 24: 2,\n 45: 3\n };\n const NUM_SH_TO_NUM_F_REST = {\n 0: 0,\n 1: 9,\n 2: 24,\n 3: 45\n };\n function getNumSh(properties) {\n let num_f_rest = 0;\n while (properties[`f_rest_${num_f_rest}`]) {\n num_f_rest += 1;\n }\n const numSh = NUM_F_REST_TO_NUM_SH[num_f_rest];\n if (numSh == null) {\n throw new Error(`Unsupported number of SH coefficients: ${num_f_rest}`);\n }\n return numSh;\n }\n var SplatFileType = /* @__PURE__ */ ((SplatFileType2) => {\n SplatFileType2["PLY"] = "ply";\n SplatFileType2["SPZ"] = "spz";\n SplatFileType2["SPLAT"] = "splat";\n SplatFileType2["KSPLAT"] = "ksplat";\n SplatFileType2["PCSOGS"] = "pcsogs";\n SplatFileType2["PCSOGSZIP"] = "pcsogszip";\n return SplatFileType2;\n })(SplatFileType || {});\n function getSplatFileType(fileBytes) {\n const view = new DataView(fileBytes.buffer);\n if ((view.getUint32(0, true) & 16777215) === 7957616) {\n return "ply";\n }\n if ((view.getUint32(0, true) & 16777215) === 559903) {\n const header = decompressPartialGzip(fileBytes, 4);\n const gView = new DataView(header.buffer);\n if (gView.getUint32(0, true) === 1347635022) {\n return "spz";\n }\n return void 0;\n }\n if (view.getUint32(0, true) === 67324752) {\n if (tryPcSogsZip(fileBytes)) {\n return "pcsogszip";\n }\n return void 0;\n }\n return void 0;\n }\n function getFileExtension(pathOrUrl) {\n const noTrailing = pathOrUrl.split(/[?#]/, 1)[0];\n const lastSlash = Math.max(\n noTrailing.lastIndexOf("/"),\n noTrailing.lastIndexOf("\\\\")\n );\n const filename = noTrailing.slice(lastSlash + 1);\n const lastDot = filename.lastIndexOf(".");\n if (lastDot <= 0 || lastDot === filename.length - 1) {\n return "";\n }\n return filename.slice(lastDot + 1).toLowerCase();\n }\n function getSplatFileTypeFromPath(pathOrUrl) {\n const extension = getFileExtension(pathOrUrl);\n if (extension === "ply") {\n return "ply";\n }\n if (extension === "spz") {\n return "spz";\n }\n if (extension === "splat") {\n return "splat";\n }\n if (extension === "ksplat") {\n return "ksplat";\n }\n return void 0;\n }\n function tryPcSogs(input) {\n try {\n let text;\n if (typeof input === "string") {\n text = input;\n } else {\n const fileBytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input;\n if (fileBytes.length > 65536) {\n return void 0;\n }\n text = new TextDecoder().decode(fileBytes);\n }\n const json = JSON.parse(text);\n if (!json || typeof json !== "object" || Array.isArray(json)) {\n return void 0;\n }\n for (const key of ["means", "scales", "quats", "sh0"]) {\n if (!json[key] || typeof json[key] !== "object" || Array.isArray(json[key])) {\n return void 0;\n }\n if (!json[key].shape || !json[key].files) {\n return void 0;\n }\n if (key !== "quats" && (!json[key].mins || !json[key].maxs)) {\n return void 0;\n }\n }\n return json;\n } catch {\n return void 0;\n }\n }\n function tryPcSogsZip(input) {\n try {\n const fileBytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input;\n let metaFilename = null;\n const unzipped = unzipSync(fileBytes, {\n filter: ({ name }) => {\n const filename = name.split(/[\\\\/]/).pop();\n if (filename === "meta.json") {\n metaFilename = name;\n return true;\n }\n return false;\n }\n });\n if (!metaFilename) {\n return void 0;\n }\n const json = tryPcSogs(unzipped[metaFilename]);\n if (!json) {\n return void 0;\n }\n return { name: metaFilename, json };\n } catch {\n return void 0;\n }\n }\n class SplatData {\n constructor({ maxSplats = 1 } = {}) {\n this.numSplats = 0;\n this.maxSplats = getTextureSize(maxSplats).maxSplats;\n this.centers = new Float32Array(this.maxSplats * 3);\n this.scales = new Float32Array(this.maxSplats * 3);\n this.quaternions = new Float32Array(this.maxSplats * 4);\n this.opacities = new Float32Array(this.maxSplats);\n this.colors = new Float32Array(this.maxSplats * 3);\n }\n pushSplat() {\n const index = this.numSplats;\n this.ensureIndex(index);\n this.numSplats += 1;\n return index;\n }\n unpushSplat(index) {\n if (index === this.numSplats - 1) {\n this.numSplats -= 1;\n } else {\n throw new Error("Cannot unpush splat from non-last position");\n }\n }\n ensureCapacity(numSplats) {\n if (numSplats > this.maxSplats) {\n const targetSplats = Math.max(numSplats, this.maxSplats * 2);\n const newCenters = new Float32Array(targetSplats * 3);\n const newScales = new Float32Array(targetSplats * 3);\n const newQuaternions = new Float32Array(targetSplats * 4);\n const newOpacities = new Float32Array(targetSplats);\n const newColors = new Float32Array(targetSplats * 3);\n newCenters.set(this.centers);\n newScales.set(this.scales);\n newQuaternions.set(this.quaternions);\n newOpacities.set(this.opacities);\n newColors.set(this.colors);\n this.centers = newCenters;\n this.scales = newScales;\n this.quaternions = newQuaternions;\n this.opacities = newOpacities;\n this.colors = newColors;\n if (this.sh1) {\n const newSh1 = new Float32Array(targetSplats * 9);\n newSh1.set(this.sh1);\n this.sh1 = newSh1;\n }\n if (this.sh2) {\n const newSh2 = new Float32Array(targetSplats * 15);\n newSh2.set(this.sh2);\n this.sh2 = newSh2;\n }\n if (this.sh3) {\n const newSh3 = new Float32Array(targetSplats * 21);\n newSh3.set(this.sh3);\n this.sh3 = newSh3;\n }\n this.maxSplats = targetSplats;\n }\n }\n ensureIndex(index) {\n this.ensureCapacity(index + 1);\n }\n setCenter(index, x2, y, z) {\n this.centers[index * 3] = x2;\n this.centers[index * 3 + 1] = y;\n this.centers[index * 3 + 2] = z;\n }\n setScale(index, scaleX, scaleY, scaleZ) {\n this.scales[index * 3] = scaleX;\n this.scales[index * 3 + 1] = scaleY;\n this.scales[index * 3 + 2] = scaleZ;\n }\n setQuaternion(index, x2, y, z, w) {\n this.quaternions[index * 4] = x2;\n this.quaternions[index * 4 + 1] = y;\n this.quaternions[index * 4 + 2] = z;\n this.quaternions[index * 4 + 3] = w;\n }\n setOpacity(index, opacity) {\n this.opacities[index] = opacity;\n }\n setColor(index, r, g, b) {\n this.colors[index * 3] = r;\n this.colors[index * 3 + 1] = g;\n this.colors[index * 3 + 2] = b;\n }\n setSh1(index, sh1) {\n if (!this.sh1) {\n this.sh1 = new Float32Array(this.maxSplats * 9);\n }\n for (let j = 0; j < 9; ++j) {\n this.sh1[index * 9 + j] = sh1[j];\n }\n }\n setSh2(index, sh2) {\n if (!this.sh2) {\n this.sh2 = new Float32Array(this.maxSplats * 15);\n }\n for (let j = 0; j < 15; ++j) {\n this.sh2[index * 15 + j] = sh2[j];\n }\n }\n setSh3(index, sh3) {\n if (!this.sh3) {\n this.sh3 = new Float32Array(this.maxSplats * 21);\n }\n for (let j = 0; j < 21; ++j) {\n this.sh3[index * 21 + j] = sh3[j];\n }\n }\n }\n async function unpackPcSogs(json, extraFiles, splatEncoding) {\n if (json.quats.encoding !== "quaternion_packed") {\n throw new Error("Unsupported quaternion encoding");\n }\n const numSplats = json.means.shape[0];\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n const meansPromise = Promise.all([\n decodeImageRgba(extraFiles[json.means.files[0]]),\n decodeImageRgba(extraFiles[json.means.files[1]])\n ]).then((means) => {\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const fx = (means[0][i4 + 0] + (means[1][i4 + 0] << 8)) / 65535;\n const fy = (means[0][i4 + 1] + (means[1][i4 + 1] << 8)) / 65535;\n const fz = (means[0][i4 + 2] + (means[1][i4 + 2] << 8)) / 65535;\n let x2 = json.means.mins[0] + (json.means.maxs[0] - json.means.mins[0]) * fx;\n let y = json.means.mins[1] + (json.means.maxs[1] - json.means.mins[1]) * fy;\n let z = json.means.mins[2] + (json.means.maxs[2] - json.means.mins[2]) * fz;\n x2 = Math.sign(x2) * (Math.exp(Math.abs(x2)) - 1);\n y = Math.sign(y) * (Math.exp(Math.abs(y)) - 1);\n z = Math.sign(z) * (Math.exp(Math.abs(z)) - 1);\n setPackedSplatCenter(packedArray, i2, x2, y, z);\n }\n });\n const scalesPromise = decodeImageRgba(extraFiles[json.scales.files[0]]).then(\n (scales) => {\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const fx = scales[i4 + 0] / 255;\n const fy = scales[i4 + 1] / 255;\n const fz = scales[i4 + 2] / 255;\n const x2 = json.scales.mins[0] + (json.scales.maxs[0] - json.scales.mins[0]) * fx;\n const y = json.scales.mins[1] + (json.scales.maxs[1] - json.scales.mins[1]) * fy;\n const z = json.scales.mins[2] + (json.scales.maxs[2] - json.scales.mins[2]) * fz;\n setPackedSplatScales(\n packedArray,\n i2,\n Math.exp(x2),\n Math.exp(y),\n Math.exp(z),\n splatEncoding\n );\n }\n }\n );\n const quatsPromise = decodeImageRgba(extraFiles[json.quats.files[0]]).then(\n (quats) => {\n const SQRT2 = Math.sqrt(2);\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const r0 = (quats[i4 + 0] / 255 - 0.5) * SQRT2;\n const r1 = (quats[i4 + 1] / 255 - 0.5) * SQRT2;\n const r2 = (quats[i4 + 2] / 255 - 0.5) * SQRT2;\n const rr = Math.sqrt(Math.max(0, 1 - r0 * r0 - r1 * r1 - r2 * r2));\n const rOrder = quats[i4 + 3] - 252;\n const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1;\n const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2;\n const quatZ = rOrder <= 2 ? r2 : rr;\n const quatW = rOrder === 0 ? rr : r0;\n setPackedSplatQuat(packedArray, i2, quatX, quatY, quatZ, quatW);\n }\n }\n );\n const sh0Promise = decodeImageRgba(extraFiles[json.sh0.files[0]]).then(\n (sh0) => {\n const SH_C02 = 0.28209479177387814;\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const f0 = sh0[i4 + 0] / 255;\n const f1 = sh0[i4 + 1] / 255;\n const f2 = sh0[i4 + 2] / 255;\n const f3 = sh0[i4 + 3] / 255;\n const dc0 = json.sh0.mins[0] + (json.sh0.maxs[0] - json.sh0.mins[0]) * f0;\n const dc1 = json.sh0.mins[1] + (json.sh0.maxs[1] - json.sh0.mins[1]) * f1;\n const dc2 = json.sh0.mins[2] + (json.sh0.maxs[2] - json.sh0.mins[2]) * f2;\n const opa = json.sh0.mins[3] + (json.sh0.maxs[3] - json.sh0.mins[3]) * f3;\n const r = SH_C02 * dc0 + 0.5;\n const g = SH_C02 * dc1 + 0.5;\n const b = SH_C02 * dc2 + 0.5;\n const a = 1 / (1 + Math.exp(-opa));\n setPackedSplatRgba(packedArray, i2, r, g, b, a, splatEncoding);\n }\n }\n );\n const promises = [meansPromise, scalesPromise, quatsPromise, sh0Promise];\n if (json.shN) {\n const useSH3 = json.shN.shape[1] >= 48 - 3;\n const useSH2 = json.shN.shape[1] >= 27 - 3;\n const useSH1 = json.shN.shape[1] >= 12 - 3;\n if (useSH1) extra.sh1 = new Uint32Array(numSplats * 2);\n if (useSH2) extra.sh2 = new Uint32Array(numSplats * 4);\n if (useSH3) extra.sh3 = new Uint32Array(numSplats * 4);\n const sh1 = new Float32Array(9);\n const sh2 = new Float32Array(15);\n const sh3 = new Float32Array(21);\n const shN = json.shN;\n const shNPromise = Promise.all([\n decodeImage(extraFiles[json.shN.files[0]]),\n decodeImage(extraFiles[json.shN.files[1]])\n ]).then(([centroids, labels]) => {\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const label = labels.rgba[i4 + 0] + (labels.rgba[i4 + 1] << 8);\n const col = (label & 63) * 15;\n const row = label >>> 6;\n const offset = row * centroids.width + col;\n for (let d = 0; d < 3; ++d) {\n if (useSH1) {\n for (let k = 0; k < 3; ++k) {\n sh1[k * 3 + d] = shN.mins + (shN.maxs - shN.mins) * centroids.rgba[(offset + k) * 4 + d] / 255;\n }\n }\n if (useSH2) {\n for (let k = 0; k < 5; ++k) {\n sh2[k * 3 + d] = shN.mins + (shN.maxs - shN.mins) * centroids.rgba[(offset + 3 + k) * 4 + d] / 255;\n }\n }\n if (useSH3) {\n for (let k = 0; k < 7; ++k) {\n sh3[k * 3 + d] = shN.mins + (shN.maxs - shN.mins) * centroids.rgba[(offset + 8 + k) * 4 + d] / 255;\n }\n }\n }\n if (useSH1)\n encodeSh1Rgb(extra.sh1, i2, sh1, splatEncoding);\n if (useSH2)\n encodeSh2Rgb(extra.sh2, i2, sh2, splatEncoding);\n if (useSH3)\n encodeSh3Rgb(extra.sh3, i2, sh3, splatEncoding);\n }\n });\n promises.push(shNPromise);\n }\n await Promise.all(promises);\n return { packedArray, numSplats, extra };\n }\n let offscreenGlContext = null;\n async function decodeImage(fileBytes) {\n if (!offscreenGlContext) {\n const canvas = new OffscreenCanvas(1, 1);\n offscreenGlContext = canvas.getContext("webgl2");\n if (!offscreenGlContext) {\n throw new Error("Failed to create WebGL2 context");\n }\n }\n const imageBlob = new Blob([fileBytes]);\n const bitmap = await createImageBitmap(imageBlob, {\n premultiplyAlpha: "none"\n });\n const gl = offscreenGlContext;\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n const data = new Uint8Array(bitmap.width * bitmap.height * 4);\n gl.readPixels(\n 0,\n 0,\n bitmap.width,\n bitmap.height,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n data\n );\n gl.deleteTexture(texture);\n gl.deleteFramebuffer(framebuffer);\n return { rgba: data, width: bitmap.width, height: bitmap.height };\n }\n async function decodeImageRgba(fileBytes) {\n const { rgba } = await decodeImage(fileBytes);\n return rgba;\n }\n async function unpackPcSogsZip(fileBytes, splatEncoding) {\n var _a2;\n const nameJson = tryPcSogsZip(fileBytes);\n if (!nameJson) {\n throw new Error("Invalid PC SOGS zip file");\n }\n const { name, json } = nameJson;\n const lastSlash = name.lastIndexOf("/");\n const lastBackslash = name.lastIndexOf("\\\\");\n const prefix = name.slice(0, Math.max(lastSlash, lastBackslash) + 1);\n const fileMap = /* @__PURE__ */ new Map();\n const refFiles = [\n ...json.means.files,\n ...json.scales.files,\n ...json.quats.files,\n ...json.sh0.files,\n ...((_a2 = json.shN) == null ? void 0 : _a2.files) ?? []\n ];\n for (const file of refFiles) {\n fileMap.set(prefix + file, file);\n }\n const unzipped = await new Promise(\n (resolve, reject) => {\n unzip(\n fileBytes,\n {\n filter: ({ name: name2 }) => {\n return fileMap.has(name2);\n }\n },\n (err2, files) => {\n if (err2) {\n reject(err2);\n } else {\n resolve(files);\n }\n }\n );\n }\n );\n const extraFiles = {};\n for (const [full, name2] of fileMap.entries()) {\n extraFiles[name2] = unzipped[full];\n }\n return await unpackPcSogs(json, extraFiles, splatEncoding);\n }\n class SpzReader {\n constructor({ fileBytes }) {\n this.fileBytes = fileBytes instanceof ArrayBuffer ? new Uint8Array(fileBytes) : fileBytes;\n this.reader = new GunzipReader({ fileBytes: this.fileBytes });\n const header = new DataView(this.reader.read(16).buffer);\n if (header.getUint32(0, true) !== 1347635022) {\n throw new Error("Invalid SPZ file");\n }\n this.version = header.getUint32(4, true);\n if (this.version < 1 || this.version > 2) {\n throw new Error(`Unsupported SPZ version: ${this.version}`);\n }\n this.numSplats = header.getUint32(8, true);\n this.shDegree = header.getUint8(12);\n this.fractionalBits = header.getUint8(13);\n this.flags = header.getUint8(14);\n this.flagAntiAlias = (this.flags & 1) !== 0;\n this.reserved = header.getUint8(15);\n this.parsed = false;\n }\n parseSplats(centerCallback, alphaCallback, rgbCallback, scalesCallback, quatCallback, shCallback) {\n if (this.parsed) {\n throw new Error("SPZ file already parsed");\n }\n this.parsed = true;\n if (this.version === 1) {\n const centerBytes = this.reader.read(this.numSplats * 3 * 2);\n const centerUint16 = new Uint16Array(centerBytes.buffer);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const x2 = fromHalf(centerUint16[i3]);\n const y = fromHalf(centerUint16[i3 + 1]);\n const z = fromHalf(centerUint16[i3 + 2]);\n centerCallback == null ? void 0 : centerCallback(i2, x2, y, z);\n }\n } else if (this.version === 2) {\n const fixed = 1 << this.fractionalBits;\n const centerBytes = this.reader.read(this.numSplats * 3 * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i9 = i2 * 9;\n const x2 = ((centerBytes[i9 + 2] << 24 | centerBytes[i9 + 1] << 16 | centerBytes[i9] << 8) >> 8) / fixed;\n const y = ((centerBytes[i9 + 5] << 24 | centerBytes[i9 + 4] << 16 | centerBytes[i9 + 3] << 8) >> 8) / fixed;\n const z = ((centerBytes[i9 + 8] << 24 | centerBytes[i9 + 7] << 16 | centerBytes[i9 + 6] << 8) >> 8) / fixed;\n centerCallback == null ? void 0 : centerCallback(i2, x2, y, z);\n }\n } else {\n throw new Error("Unreachable");\n }\n {\n const bytes = this.reader.read(this.numSplats);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n alphaCallback == null ? void 0 : alphaCallback(i2, bytes[i2] / 255);\n }\n }\n {\n const rgbBytes = this.reader.read(this.numSplats * 3);\n const scale = SH_C0 / 0.15;\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const r = (rgbBytes[i3] / 255 - 0.5) * scale + 0.5;\n const g = (rgbBytes[i3 + 1] / 255 - 0.5) * scale + 0.5;\n const b = (rgbBytes[i3 + 2] / 255 - 0.5) * scale + 0.5;\n rgbCallback == null ? void 0 : rgbCallback(i2, r, g, b);\n }\n }\n {\n const scalesBytes = this.reader.read(this.numSplats * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const scaleX = Math.exp(scalesBytes[i3] / 16 - 10);\n const scaleY = Math.exp(scalesBytes[i3 + 1] / 16 - 10);\n const scaleZ = Math.exp(scalesBytes[i3 + 2] / 16 - 10);\n scalesCallback == null ? void 0 : scalesCallback(i2, scaleX, scaleY, scaleZ);\n }\n }\n {\n const quatBytes = this.reader.read(this.numSplats * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const quatX = quatBytes[i3] / 127.5 - 1;\n const quatY = quatBytes[i3 + 1] / 127.5 - 1;\n const quatZ = quatBytes[i3 + 2] / 127.5 - 1;\n const quatW = Math.sqrt(\n Math.max(0, 1 - quatX * quatX - quatY * quatY - quatZ * quatZ)\n );\n quatCallback == null ? void 0 : quatCallback(i2, quatX, quatY, quatZ, quatW);\n }\n }\n if (shCallback && this.shDegree >= 1) {\n const sh1 = new Float32Array(3 * 3);\n const sh2 = this.shDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = this.shDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const shBytes = this.reader.read(\n this.numSplats * SH_DEGREE_TO_VECS[this.shDegree] * 3\n );\n let offset = 0;\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n for (let j = 0; j < 9; ++j) {\n sh1[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 9;\n if (sh2) {\n for (let j = 0; j < 15; ++j) {\n sh2[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 15;\n }\n if (sh3) {\n for (let j = 0; j < 21; ++j) {\n sh3[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 21;\n }\n shCallback == null ? void 0 : shCallback(i2, sh1, sh2, sh3);\n }\n }\n }\n }\n const SH_DEGREE_TO_VECS = { 1: 3, 2: 8, 3: 15 };\n const SH_C0 = 0.28209479177387814;\n const SPZ_MAGIC = 1347635022;\n const SPZ_VERSION = 2;\n const FLAG_ANTIALIASED = 1;\n class SpzWriter {\n constructor({\n numSplats,\n shDegree,\n fractionalBits = 12,\n flagAntiAlias = true\n }) {\n this.clippedCount = 0;\n const splatSize = 9 + 1 + 3 + 3 + 3 + (shDegree >= 1 ? 9 : 0) + (shDegree >= 2 ? 15 : 0) + (shDegree >= 3 ? 21 : 0);\n const bufferSize = 16 + numSplats * splatSize;\n this.buffer = new ArrayBuffer(bufferSize);\n this.view = new DataView(this.buffer);\n this.view.setUint32(0, SPZ_MAGIC, true);\n this.view.setUint32(4, SPZ_VERSION, true);\n this.view.setUint32(8, numSplats, true);\n this.view.setUint8(12, shDegree);\n this.view.setUint8(13, fractionalBits);\n this.view.setUint8(14, flagAntiAlias ? FLAG_ANTIALIASED : 0);\n this.view.setUint8(15, 0);\n this.numSplats = numSplats;\n this.shDegree = shDegree;\n this.fractionalBits = fractionalBits;\n this.fraction = 1 << fractionalBits;\n this.flagAntiAlias = flagAntiAlias;\n }\n setCenter(index, x2, y, z) {\n const xRounded = Math.round(x2 * this.fraction);\n const xInt = Math.max(-8388607, Math.min(8388607, xRounded));\n const yRounded = Math.round(y * this.fraction);\n const yInt = Math.max(-8388607, Math.min(8388607, yRounded));\n const zRounded = Math.round(z * this.fraction);\n const zInt = Math.max(-8388607, Math.min(8388607, zRounded));\n const clipped = xRounded !== xInt || yRounded !== yInt || zRounded !== zInt;\n if (clipped) {\n this.clippedCount += 1;\n }\n const i9 = index * 9;\n const base = 16 + i9;\n this.view.setUint8(base, xInt & 255);\n this.view.setUint8(base + 1, xInt >> 8 & 255);\n this.view.setUint8(base + 2, xInt >> 16 & 255);\n this.view.setUint8(base + 3, yInt & 255);\n this.view.setUint8(base + 4, yInt >> 8 & 255);\n this.view.setUint8(base + 5, yInt >> 16 & 255);\n this.view.setUint8(base + 6, zInt & 255);\n this.view.setUint8(base + 7, zInt >> 8 & 255);\n this.view.setUint8(base + 8, zInt >> 16 & 255);\n }\n setAlpha(index, alpha) {\n const base = 16 + this.numSplats * 9 + index;\n this.view.setUint8(\n base,\n Math.max(0, Math.min(255, Math.round(alpha * 255)))\n );\n }\n static scaleRgb(r) {\n const v = ((r - 0.5) / (SH_C0 / 0.15) + 0.5) * 255;\n return Math.max(0, Math.min(255, Math.round(v)));\n }\n setRgb(index, r, g, b) {\n const base = 16 + this.numSplats * 10 + index * 3;\n this.view.setUint8(base, SpzWriter.scaleRgb(r));\n this.view.setUint8(base + 1, SpzWriter.scaleRgb(g));\n this.view.setUint8(base + 2, SpzWriter.scaleRgb(b));\n }\n setScale(index, scaleX, scaleY, scaleZ) {\n const base = 16 + this.numSplats * 13 + index * 3;\n this.view.setUint8(\n base,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleX) + 10) * 16)))\n );\n this.view.setUint8(\n base + 1,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleY) + 10) * 16)))\n );\n this.view.setUint8(\n base + 2,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleZ) + 10) * 16)))\n );\n }\n setQuat(index, quatX, quatY, quatZ, quatW) {\n const base = 16 + this.numSplats * 16 + index * 3;\n const quatNeg = quatW < 0;\n this.view.setUint8(\n base,\n Math.max(\n 0,\n Math.min(255, Math.round(((quatNeg ? -quatX : quatX) + 1) * 127.5))\n )\n );\n this.view.setUint8(\n base + 1,\n Math.max(\n 0,\n Math.min(255, Math.round(((quatNeg ? -quatY : quatY) + 1) * 127.5))\n )\n );\n this.view.setUint8(\n base + 2,\n Math.max(\n 0,\n Math.min(255, Math.round(((quatNeg ? -quatZ : quatZ) + 1) * 127.5))\n )\n );\n }\n static quantizeSh(sh, bits2) {\n const value = Math.round(sh * 128) + 128;\n const bucketSize = 1 << 8 - bits2;\n const quantized = Math.floor((value + bucketSize / 2) / bucketSize) * bucketSize;\n return Math.max(0, Math.min(255, quantized));\n }\n setSh(index, sh1, sh2, sh3) {\n const shVecs = SH_DEGREE_TO_VECS[this.shDegree] || 0;\n const base1 = 16 + this.numSplats * 19 + index * shVecs * 3;\n for (let j = 0; j < 9; ++j) {\n this.view.setUint8(base1 + j, SpzWriter.quantizeSh(sh1[j], 5));\n }\n if (sh2) {\n const base2 = base1 + 9;\n for (let j = 0; j < 15; ++j) {\n this.view.setUint8(base2 + j, SpzWriter.quantizeSh(sh2[j], 4));\n }\n if (sh3) {\n const base3 = base2 + 15;\n for (let j = 0; j < 21; ++j) {\n this.view.setUint8(base3 + j, SpzWriter.quantizeSh(sh3[j], 4));\n }\n }\n }\n }\n async finalize() {\n const input = new Uint8Array(this.buffer);\n const stream = new ReadableStream({\n async start(controller) {\n controller.enqueue(input);\n controller.close();\n }\n });\n const compressed = stream.pipeThrough(new CompressionStream("gzip"));\n const response = new Response(compressed);\n const buffer = await response.arrayBuffer();\n console.log(\n "Compressed",\n input.length,\n "bytes to",\n buffer.byteLength,\n "bytes"\n );\n return new Uint8Array(buffer);\n }\n }\n async function transcodeSpz(input) {\n var _a2, _b2, _c;\n const splats = new SplatData();\n const {\n inputs,\n clipXyz,\n maxSh,\n fractionalBits = 12,\n opacityThreshold\n } = input;\n for (const input2 of inputs) {\n let transformPos = function(pos) {\n pos.multiplyScalar(scale);\n pos.applyQuaternion(quaternion);\n pos.add(translate);\n return pos;\n }, transformScales = function(scales) {\n scales.multiplyScalar(scale);\n return scales;\n }, transformQuaternion = function(quat) {\n quat.premultiply(quaternion);\n return quat;\n }, withinClip = function(p) {\n return !clip || clip.containsPoint(p);\n }, withinOpacity = function(opacity) {\n return opacityThreshold !== void 0 ? opacity >= opacityThreshold : true;\n };\n const scale = ((_a2 = input2.transform) == null ? void 0 : _a2.scale) ?? 1;\n const quaternion = new Quaternion().fromArray(\n ((_b2 = input2.transform) == null ? void 0 : _b2.quaternion) ?? [0, 0, 0, 1]\n );\n const translate = new Vector3().fromArray(\n ((_c = input2.transform) == null ? void 0 : _c.translate) ?? [0, 0, 0]\n );\n const clip = clipXyz ? new Box3(\n new Vector3().fromArray(clipXyz.min),\n new Vector3().fromArray(clipXyz.max)\n ) : void 0;\n let fileType = input2.fileType;\n if (!fileType) {\n fileType = getSplatFileType(input2.fileBytes);\n if (!fileType && input2.pathOrUrl) {\n fileType = getSplatFileTypeFromPath(input2.pathOrUrl);\n }\n }\n switch (fileType) {\n case SplatFileType.PLY: {\n const ply = new PlyReader({ fileBytes: input2.fileBytes });\n await ply.parseHeader();\n let lastIndex = null;\n ply.parseSplats(\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n lastIndex = splats.pushSplat();\n splats.setCenter(lastIndex, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(lastIndex, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n lastIndex,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(lastIndex, opacity);\n splats.setColor(lastIndex, r, g, b);\n } else {\n lastIndex = null;\n }\n },\n (index, sh1, sh2, sh3) => {\n if (sh1 && lastIndex !== null) {\n splats.setSh1(lastIndex, sh1);\n }\n if (sh2 && lastIndex !== null) {\n splats.setSh2(lastIndex, sh2);\n }\n if (sh3 && lastIndex !== null) {\n splats.setSh3(lastIndex, sh3);\n }\n }\n );\n break;\n }\n case SplatFileType.SPZ: {\n const spz2 = new SpzReader({ fileBytes: input2.fileBytes });\n const mapping = new Int32Array(spz2.numSplats);\n mapping.fill(-1);\n const centers = new Float32Array(spz2.numSplats * 3);\n const center = new Vector3();\n spz2.parseSplats(\n (index, x2, y, z) => {\n const center2 = transformPos(new Vector3(x2, y, z));\n centers[index * 3] = center2.x;\n centers[index * 3 + 1] = center2.y;\n centers[index * 3 + 2] = center2.z;\n },\n (index, alpha) => {\n center.fromArray(centers, index * 3);\n if (withinClip(center) && withinOpacity(alpha)) {\n mapping[index] = splats.pushSplat();\n splats.setCenter(mapping[index], center.x, center.y, center.z);\n splats.setOpacity(mapping[index], alpha);\n }\n },\n (index, r, g, b) => {\n if (mapping[index] >= 0) {\n splats.setColor(mapping[index], r, g, b);\n }\n },\n (index, scaleX, scaleY, scaleZ) => {\n if (mapping[index] >= 0) {\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(mapping[index], scales.x, scales.y, scales.z);\n }\n },\n (index, quatX, quatY, quatZ, quatW) => {\n if (mapping[index] >= 0) {\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n mapping[index],\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n }\n },\n (index, sh1, sh2, sh3) => {\n if (mapping[index] >= 0) {\n splats.setSh1(mapping[index], sh1);\n if (sh2) {\n splats.setSh2(mapping[index], sh2);\n }\n if (sh3) {\n splats.setSh3(mapping[index], sh3);\n }\n }\n }\n );\n break;\n }\n case SplatFileType.SPLAT:\n decodeAntiSplat(\n input2.fileBytes,\n (numSplats) => {\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n const index2 = splats.pushSplat();\n splats.setCenter(index2, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(index2, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n index2,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(index2, opacity);\n splats.setColor(index2, r, g, b);\n }\n }\n );\n break;\n case SplatFileType.KSPLAT: {\n let lastIndex = null;\n decodeKsplat(\n input2.fileBytes,\n (numSplats) => {\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n lastIndex = splats.pushSplat();\n splats.setCenter(lastIndex, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(lastIndex, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n lastIndex,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(lastIndex, opacity);\n splats.setColor(lastIndex, r, g, b);\n } else {\n lastIndex = null;\n }\n },\n (index, sh1, sh2, sh3) => {\n if (lastIndex !== null) {\n splats.setSh1(lastIndex, sh1);\n if (sh2) {\n splats.setSh2(lastIndex, sh2);\n }\n if (sh3) {\n splats.setSh3(lastIndex, sh3);\n }\n }\n }\n );\n break;\n }\n default:\n throw new Error(`transcodeSpz not implemented for ${fileType}`);\n }\n }\n const shDegree = Math.min(\n maxSh ?? 3,\n splats.sh3 ? 3 : splats.sh2 ? 2 : splats.sh1 ? 1 : 0\n );\n const spz = new SpzWriter({\n numSplats: splats.numSplats,\n shDegree,\n fractionalBits,\n flagAntiAlias: true\n });\n for (let i2 = 0; i2 < splats.numSplats; ++i2) {\n const i3 = i2 * 3;\n const i4 = i2 * 4;\n spz.setCenter(\n i2,\n splats.centers[i3],\n splats.centers[i3 + 1],\n splats.centers[i3 + 2]\n );\n spz.setScale(\n i2,\n splats.scales[i3],\n splats.scales[i3 + 1],\n splats.scales[i3 + 2]\n );\n spz.setQuat(\n i2,\n splats.quaternions[i4],\n splats.quaternions[i4 + 1],\n splats.quaternions[i4 + 2],\n splats.quaternions[i4 + 3]\n );\n spz.setAlpha(i2, splats.opacities[i2]);\n spz.setRgb(\n i2,\n splats.colors[i3],\n splats.colors[i3 + 1],\n splats.colors[i3 + 2]\n );\n if (splats.sh1 && shDegree >= 1) {\n spz.setSh(\n i2,\n splats.sh1.slice(i2 * 9, (i2 + 1) * 9),\n shDegree >= 2 && splats.sh2 ? splats.sh2.slice(i2 * 15, (i2 + 1) * 15) : void 0,\n shDegree >= 3 && splats.sh3 ? splats.sh3.slice(i2 * 21, (i2 + 1) * 21) : void 0\n );\n }\n }\n const spzBytes = await spz.finalize();\n return { fileBytes: spzBytes, clippedCount: spz.clippedCount };\n }\n async function onMessage(event) {\n const { name, args, id } = event.data;\n let result = void 0;\n let error = void 0;\n try {\n switch (name) {\n case "unpackPly": {\n const { packedArray, fileBytes, splatEncoding } = args;\n const decoded = await unpackPly({\n packedArray,\n fileBytes,\n splatEncoding\n });\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodeSpz": {\n const { fileBytes, splatEncoding } = args;\n const decoded = unpackSpz(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodeAntiSplat": {\n const { fileBytes, splatEncoding } = args;\n const decoded = unpackAntiSplat(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray\n };\n break;\n }\n case "decodeKsplat": {\n const { fileBytes, splatEncoding } = args;\n const decoded = unpackKsplat(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodePcSogs": {\n const { fileBytes, extraFiles, splatEncoding } = args;\n const json = JSON.parse(\n new TextDecoder().decode(fileBytes)\n );\n const decoded = await unpackPcSogs(json, extraFiles, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodePcSogsZip": {\n const { fileBytes, splatEncoding } = args;\n const decoded = await unpackPcSogsZip(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "sortSplats": {\n const { totalSplats, readback, ordering } = args;\n result = {\n id,\n readback,\n ...sortSplats({ totalSplats, readback, ordering })\n };\n break;\n }\n case "sortDoubleSplats": {\n const { numSplats, readback, ordering } = args;\n {\n result = {\n id,\n readback,\n ordering,\n activeSplats: sort_splats(numSplats, readback, ordering)\n };\n }\n break;\n }\n case "sort32Splats": {\n const { numSplats, readback, ordering } = args;\n {\n result = {\n id,\n readback,\n ordering,\n activeSplats: sort32_splats(numSplats, readback, ordering)\n };\n }\n break;\n }\n case "transcodeSpz": {\n const input = args;\n const spzBytes = await transcodeSpz(input);\n result = {\n id,\n fileBytes: spzBytes,\n input\n };\n break;\n }\n default: {\n throw new Error(`Unknown name: ${name}`);\n }\n }\n } catch (e) {\n error = e;\n console.error(error);\n }\n self.postMessage(\n { id, result, error },\n { transfer: getArrayBuffers(result) }\n );\n }\n async function unpackPly({\n packedArray,\n fileBytes,\n splatEncoding\n }) {\n const ply = new PlyReader({ fileBytes });\n await ply.parseHeader();\n const numSplats = ply.numSplats;\n const extra = {};\n ply.parseSplats(\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n setPackedSplat(\n packedArray,\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n },\n (index, sh1, sh2, sh3) => {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n encodeSh1Rgb(extra.sh1, index, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n encodeSh2Rgb(extra.sh2, index, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n encodeSh3Rgb(extra.sh3, index, sh3, splatEncoding);\n }\n }\n );\n return { packedArray, numSplats, extra };\n }\n function unpackSpz(fileBytes, splatEncoding) {\n const spz = new SpzReader({ fileBytes });\n const numSplats = spz.numSplats;\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n spz.parseSplats(\n (index, x2, y, z) => {\n setPackedSplatCenter(packedArray, index, x2, y, z);\n },\n (index, alpha) => {\n setPackedSplatOpacity(packedArray, index, alpha);\n },\n (index, r, g, b) => {\n setPackedSplatRgb(packedArray, index, r, g, b, splatEncoding);\n },\n (index, scaleX, scaleY, scaleZ) => {\n setPackedSplatScales(\n packedArray,\n index,\n scaleX,\n scaleY,\n scaleZ,\n splatEncoding\n );\n },\n (index, quatX, quatY, quatZ, quatW) => {\n setPackedSplatQuat(packedArray, index, quatX, quatY, quatZ, quatW);\n },\n (index, sh1, sh2, sh3) => {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n encodeSh1Rgb(extra.sh1, index, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n encodeSh2Rgb(extra.sh2, index, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n encodeSh3Rgb(extra.sh3, index, sh3, splatEncoding);\n }\n }\n );\n return { packedArray, numSplats, extra };\n }\n const DEPTH_INFINITY_F16 = 31744;\n const DEPTH_SIZE_16 = DEPTH_INFINITY_F16 + 1;\n let depthArray16 = null;\n function sortSplats({\n totalSplats,\n readback,\n ordering\n }) {\n if (!depthArray16) {\n depthArray16 = new Uint32Array(DEPTH_SIZE_16);\n }\n depthArray16.fill(0);\n const readbackUint32 = readback.map((layer) => new Uint32Array(layer.buffer));\n const layerSize = readbackUint32[0].length;\n const numLayers = Math.ceil(totalSplats / layerSize);\n let layerBase = 0;\n for (let layer = 0; layer < numLayers; ++layer) {\n const readbackLayer = readbackUint32[layer];\n const layerSplats = Math.min(readbackLayer.length, totalSplats - layerBase);\n for (let i2 = 0; i2 < layerSplats; ++i2) {\n const pri = readbackLayer[i2] & 32767;\n if (pri < DEPTH_INFINITY_F16) {\n depthArray16[pri] += 1;\n }\n }\n layerBase += layerSplats;\n }\n let activeSplats = 0;\n for (let j = 0; j < DEPTH_SIZE_16; ++j) {\n const nextIndex = activeSplats + depthArray16[j];\n depthArray16[j] = activeSplats;\n activeSplats = nextIndex;\n }\n layerBase = 0;\n for (let layer = 0; layer < numLayers; ++layer) {\n const readbackLayer = readbackUint32[layer];\n const layerSplats = Math.min(readbackLayer.length, totalSplats - layerBase);\n for (let i2 = 0; i2 < layerSplats; ++i2) {\n const pri = readbackLayer[i2] & 32767;\n if (pri < DEPTH_INFINITY_F16) {\n ordering[depthArray16[pri]] = layerBase + i2;\n depthArray16[pri] += 1;\n }\n }\n layerBase += layerSplats;\n }\n if (depthArray16[DEPTH_SIZE_16 - 1] !== activeSplats) {\n throw new Error(\n `Expected ${activeSplats} active splats but got ${depthArray16[DEPTH_SIZE_16 - 1]}`\n );\n }\n return { activeSplats, ordering };\n }\n const messageBuffer = [];\n function bufferMessage(event) {\n messageBuffer.push(event);\n }\n async function initialize() {\n self.addEventListener("message", bufferMessage);\n await __wbg_init();\n self.removeEventListener("message", bufferMessage);\n self.addEventListener("message", onMessage);\n for (const event of messageBuffer) {\n onMessage(event);\n }\n messageBuffer.length = 0;\n }\n initialize().catch(console.error);\n})();\n//# sourceMappingURL=worker-C1ojSBY1.js.map\n';
|
|
8583
|
+
const jsContent = '(function() {\n "use strict";\n let wasm;\n const cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }) : { decode: () => {\n throw Error("TextDecoder not available");\n } };\n if (typeof TextDecoder !== "undefined") {\n cachedTextDecoder.decode();\n }\n let cachedUint8ArrayMemory0 = null;\n function getUint8ArrayMemory0() {\n if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8ArrayMemory0;\n }\n function getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n }\n function sort_splats(num_splats, readback, ordering) {\n const ret = wasm.sort_splats(num_splats, readback, ordering);\n return ret >>> 0;\n }\n function sort32_splats(num_splats, readback, ordering) {\n const ret = wasm.sort32_splats(num_splats, readback, ordering);\n return ret >>> 0;\n }\n async function __wbg_load(module, imports) {\n if (typeof Response === "function" && module instanceof Response) {\n if (typeof WebAssembly.instantiateStreaming === "function") {\n try {\n return await WebAssembly.instantiateStreaming(module, imports);\n } catch (e) {\n if (module.headers.get("Content-Type") != "application/wasm") {\n console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n", e);\n } else {\n throw e;\n }\n }\n }\n const bytes = await module.arrayBuffer();\n return await WebAssembly.instantiate(bytes, imports);\n } else {\n const instance = await WebAssembly.instantiate(module, imports);\n if (instance instanceof WebAssembly.Instance) {\n return { instance, module };\n } else {\n return instance;\n }\n }\n }\n function __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) {\n const ret = arg0.buffer;\n return ret;\n };\n imports.wbg.__wbg_length_3b4f022188ae8db6 = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_length_6ca527665d89694d = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_length_8cfd2c6409af88ad = function(arg0) {\n const ret = arg0.length;\n return ret;\n };\n imports.wbg.__wbg_new_9fee97a409b32b68 = function(arg0) {\n const ret = new Uint16Array(arg0);\n return ret;\n };\n imports.wbg.__wbg_new_e3b321dcfef89fc7 = function(arg0) {\n const ret = new Uint32Array(arg0);\n return ret;\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_e6b7e69acd4c7354 = function(arg0, arg1, arg2) {\n const ret = new Float32Array(arg0, arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_newwithbyteoffsetandlength_f1dead44d1fc7212 = function(arg0, arg1, arg2) {\n const ret = new Uint32Array(arg0, arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_newwithlength_5a5efe313cfd59f1 = function(arg0) {\n const ret = new Float32Array(arg0 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_set_10bad9bee0e9c58b = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_set_d23661d19148b229 = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_set_f4f1f0daa30696fc = function(arg0, arg1, arg2) {\n arg0.set(arg1, arg2 >>> 0);\n };\n imports.wbg.__wbg_subarray_3aaeec89bb2544f0 = function(arg0, arg1, arg2) {\n const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbg_subarray_769e1e0f81bb259b = function(arg0, arg1, arg2) {\n const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);\n return ret;\n };\n imports.wbg.__wbindgen_init_externref_table = function() {\n const table = wasm.__wbindgen_export_0;\n const offset = table.grow(4);\n table.set(0, void 0);\n table.set(offset + 0, void 0);\n table.set(offset + 1, null);\n table.set(offset + 2, true);\n table.set(offset + 3, false);\n };\n imports.wbg.__wbindgen_memory = function() {\n const ret = wasm.memory;\n return ret;\n };\n imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n return imports;\n }\n function __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n __wbg_init.__wbindgen_wasm_module = module;\n cachedUint8ArrayMemory0 = null;\n wasm.__wbindgen_start();\n return wasm;\n }\n async function __wbg_init(module_or_path) {\n if (wasm !== void 0) return wasm;\n if (typeof module_or_path !== "undefined") {\n if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n ({ module_or_path } = module_or_path);\n } else {\n console.warn("using deprecated parameters for the initialization function; pass a single object instead");\n }\n }\n if (typeof module_or_path === "undefined") {\n module_or_path = new URL("data:application/wasm;base64,AGFzbQEAAAABzAEeYAJ/fwF/YAJ/fwBgA39/fwF/YAF/AX9gA39/fwBgAX8AYAV/f39/fwBgA29/fwFvYAV/f39/fwF/YAFvAW9gA29vfwBgAW8Bf2AAAX9gBH9/f38AYAAAYAR/f39/AX9gA39vbwF/YAF/AW9gAAFvYAF9AX1gBn9/f39/fwBgDX19fX19fX19f29/fX0Bb2AGf39/f39/AX9gBX9/fH9/AGAEf3x/fwBgBX9/fX9/AGAEf31/fwBgBX9/fn9/AGAEf35/fwBgAn19AX0C8gQRA3diZx1fX3diZ19idWZmZXJfNjA5Y2MzZWVlNTFlZDE1OAAJA3diZxpfX3diZ19uZXdfOWZlZTk3YTQwOWIzMmI2OAAJA3diZxpfX3diZ19zZXRfZjRmMWYwZGFhMzA2OTZmYwAKA3diZx1fX3diZ19sZW5ndGhfOGNmZDJjNjQwOWFmODhhZAALA3diZzFfX3diZ19uZXd3aXRoYnl0ZW9mZnNldGFuZGxlbmd0aF9mMWRlYWQ0NGQxZmM3MjEyAAcDd2JnGl9fd2JnX25ld19lM2IzMjFkY2ZlZjg5ZmM3AAkDd2JnGl9fd2JnX3NldF9kMjM2NjFkMTkxNDhiMjI5AAoDd2JnHV9fd2JnX2xlbmd0aF82Y2E1Mjc2NjVkODk2OTRkAAsDd2JnMV9fd2JnX25ld3dpdGhieXRlb2Zmc2V0YW5kbGVuZ3RoX2U2YjdlNjlhY2Q0YzczNTQABwN3YmcaX193Ymdfc2V0XzEwYmFkOWJlZTBlOWM1OGIACgN3YmcdX193YmdfbGVuZ3RoXzNiNGYwMjIxODhhZThkYjYACwN3YmcfX193Ymdfc3ViYXJyYXlfNzY5ZTFlMGY4MWJiMjU5YgAHA3diZx9fX3diZ19zdWJhcnJheV8zYWFlZWM4OWJiMjU0NGYwAAcDd2JnJF9fd2JnX25ld3dpdGhsZW5ndGhfNWE1ZWZlMzEzY2ZkNTlmMQARA3diZxBfX3diaW5kZ2VuX3Rocm93AAEDd2JnEV9fd2JpbmRnZW5fbWVtb3J5ABIDd2JnH19fd2JpbmRnZW5faW5pdF9leHRlcm5yZWZfdGFibGUADgNhYAMAAQIIBQQCEwEMAAEBAgAAAQwBBAYFBQQAAQYFFAENBAAGBQQEAQQOAgECAQAIBAAVARYG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ACIDKAIEQXhxRgRAIAMhAgwBCyABQRkgAkEBdmtBACACQR9HG3QhBQNAIAMgBUEddkEEcWpBEGoiBCgCACICRQ0CIAVBAXQhBSACIQMgAigCBEF4cSABRw0ACwsgAigCCCIBIAA2AgwgAiAANgIIIABBADYCGCAAIAI2AgwgACABNgIIDwsgBCAANgIAIAAgAzYCGCAAIAA2AgwgACAANgIIC/MCAQR/IwBBMGsiACQAAkACQEGQksAAKAIARQRAQaiSwAAoAgAhAUGoksAAQQA2AgAgAUUNASAAQRhqIAERBQAgAEEQaiICIABBJGopAgA3AwAgACAAKQIcNwMIIAAoAhghAUGQksAAKAIAIgMNAgJAIANFDQBBlJLAACgCACICRQ0AQZiSwAAoAgAgAkECdBBlC0GUksAAIAE2AgBBkJLAAEEBNgIAQZiSwAAgACkDCDcCAEGgksAAIABBEGopAwA3AgALIABBMGokAEGUksAADwsgAEEANgIoIABBATYCHCAAQaCHwAA2AhggAEIENwIgIABBGGpBiIjAABBDAAsgAEEoaiACKQMANwIAIAAgACkDCDcCICAAIAE2AhwgAEEBNgIYAkAgAEEYaiIBKAIARQ0AIAEoAgQiAkUNACABKAIIIAJBAnQQZQsgAEEANgIoIABBATYCHCAAQaiIwAA2AhggAEIENwIgIAFBsIjAABBDAAuoAgIDfwF+IwBBQGoiAiQAIAEoAgBBgICAgHhGBEAgASgCDCEDIAJBJGoiBEEANgIAIAJCgICAgBA3AhwgAkEwaiADKAIAIgNBCGopAgA3AwAgAkE4aiADQRBqKQIANwMAIAIgAykCADcDKCACQRxqQcCIwAAgAkEoahAYGiACQRhqIAQoAgAiAzYCACACIAIpAhwiBTcDECABQQhqIAM2AgAgASAFNwIACyABKQIAIQUgAUKAgICAEDcCACACQQhqIgMgAUEIaiIBKAIANgIAIAFBADYCAEGxk8AALQAAGiACIAU3AwBBDEEEEF0iAUUEQEEEQQwQbQALIAEgAikDADcCACABQQhqIAMoAgA2AgAgAEHgisAANgIEIAAgATYCACACQUBrJAAL0gECBH8BfiMAQSBrIgMkACABIAEgAmoiAksEQEEAQQAQUgALQQggACgCACIEQQF0IgEgAiABIAJLGyICIAJBCEkbIgKtIgdCIIhQRQRAQQBBABBSAAsCQCAHpyIFQf////8HTQRAIAMgBAR/IAMgBDYCHCADIAAoAgQ2AhRBAQVBAAs2AhggA0EIakEBIAUgA0EUahAwIAMoAghBAUcNASADKAIMIQYgAygCECEBCyAGIAEQUgALIAMoAgwhASAAIAI2AgAgACABNgIEIANBIGokAAvrAQIEfwF+IwBBIGsiBSQAIAEgASACaiICSwRAQQBBABBSAAtBACEBIAMgBGpBAWtBACADa3GtQQQgACgCACIHQQF0IgYgAiACIAZJGyICIAJBBE0bIgKtfiIJQiCIUEUEQEEAQQAQUgALAkAgCaciBkGAgICAeCADa00EfyAFIAcEfyAFIAQgB2w2AhwgBSAAKAIENgIUIAMFQQALNgIYIAVBCGogAyAGIAVBFGoQMCAFKAIIQQFHDQEgBSgCECEIIAUoAgwFIAELIAgQUgALIAUoAgwhASAAIAI2AgAgACABNgIEIAVBIGokAAvTAQEFfyMAQSBrIgEkACAAKAIAIgJBf0YEQEEAQQAQUgALIAJBAXQiAyACQQFqIgUgAyAFSxsiA0H/////A0sEQEEAQQAQUgALAkBBBCADIANBBE0bIgNBAnQiBUH8////B00EfyABIAIEfyABIAJBAnQ2AhwgASAAKAIENgIUQQQFQQALNgIYIAFBCGpBBCAFIAFBFGoQMCABKAIIQQFHDQEgASgCECEEIAEoAgwFIAQLIAQQUgALIAEoAgwhAiAAIAM2AgAgACACNgIEIAFBIGokAAuyAQEEfyMAQSBrIgEkACAAKAIAIgJBf0YEQEEAQQAQUgALQQggAkEBdCIDIAJBAWoiBCADIARLGyIDIANBCE0bIgNBAEgEQEEAQQAQUgALIAEgAgR/IAEgAjYCHCABIAAoAgQ2AhRBAQVBAAs2AhggAUEIakEBIAMgAUEUahAwIAEoAghBAUYEQCABKAIMIAEoAhAQUgALIAEoAgwhAiAAIAM2AgAgACACNgIEIAFBIGokAAuyAQECfyMAQSBrIgMkACABIAEgAmoiAksEQEEAQQAQUgALQQggACgCACIBQQF0IgQgAiACIARJGyICIAJBCE0bIgRBAEgEQEEAQQAQUgALIAMgAQR/IAMgATYCHCADIAAoAgQ2AhRBAQVBAAs2AhggA0EIakEBIAQgA0EUahAwIAMoAghBAUYEQCADKAIMIAMoAhAQUgALIAMoAgwhASAAIAQ2AgAgACABNgIEIANBIGokAAudAQEDfwJAIAFBEEkEQCAAIQIMAQsgAEEAIABrQQNxIgRqIQMgBARAIAAhAgNAIAJBADoAACACQQFqIgIgA0kNAAsLIAMgASAEayIBQXxxIgRqIQIgBEEASgRAA0AgA0EANgIAIANBBGoiAyACSQ0ACwsgAUEDcSEBCyABBEAgASACaiEBA0AgAkEAOgAAIAJBAWoiAiABSQ0ACwsgAAvBAQIDfwF+IwBBMGsiAiQAIAEoAgBBgICAgHhGBEAgASgCDCEDIAJBFGoiBEEANgIAIAJCgICAgBA3AgwgAkEgaiADKAIAIgNBCGopAgA3AwAgAkEoaiADQRBqKQIANwMAIAIgAykCADcDGCACQQxqQcCIwAAgAkEYahAYGiACQQhqIAQoAgAiAzYCACACIAIpAgwiBTcDACABQQhqIAM2AgAgASAFNwIACyAAQeCKwAA2AgQgACABNgIAIAJBMGokAAuWAgECfyMAQSBrIgUkAEHMk8AAQcyTwAAoAgAiBkEBajYCAAJAAn9BACAGQQBIDQAaQQFBmJfAAC0AAA0AGkGYl8AAQQE6AABBlJfAAEGUl8AAKAIAQQFqNgIAQQILQf8BcSIGQQJHBEAgBkEBcUUNASAFQQhqIAAgASgCGBEBAAALQcCTwAAoAgAiBkEASA0AQcCTwAAgBkEBajYCAEHAk8AAQcSTwAAoAgAEfyAFIAAgASgCFBEBACAFIAQ6AB0gBSADOgAcIAUgAjYCGCAFIAUpAwA3AhBBxJPAACgCACAFQRBqQciTwAAoAgAoAhQRAQBBwJPAACgCAEEBawUgBgs2AgBBmJfAAEEAOgAAIANFDQAACwALrwEBBn8CQAJAIABBhAFJDQAgANBvJgEQIyIBKAIMIQUgASgCECECIAFCADcCDCABKAIIIQMgASgCBCEEIAFCBDcCBCABKAIAIQYgAUEANgIAIAAgAkkNASAAIAJrIgAgA08NASAEIABBAnRqIAU2AgAgASACNgIQIAEgADYCDCABIAM2AgggASgCBCABIAQ2AgQgASgCACEAIAEgBjYCACAARQ0AIABBAnQQZQsPCwALowEBAX8jAEEQayIGJAACQCABBEAgBkEEaiABIAMgBCAFIAIoAhARBgACQCAGKAIEIgIgBigCDCIBTQRAIAYoAgghBQwBCyACQQJ0IQIgBigCCCEDIAFFBEBBBCEFIAMgAhBlDAELIAMgAkEEIAFBAnQiAhBUIgVFDQILIAAgATYCBCAAIAU2AgAgBkEQaiQADwtBxIbAAEEyEGgAC0EEIAIQUgALrAEBA38gASgCDCECAkACQAJAAkACQAJAIAEoAgQOAgABAgsgAg0BQQEhA0EAIQFBASECDAMLIAJFDQELIAAgARAdDwsgASgCACICKAIEIgFBAEgNASACKAIAIQMgAUUEQEEBIQJBACEBDAELQbGTwAAtAAAaQQEhBCABQQEQXSICRQ0BCyACIAMgARAfIQIgACABNgIIIAAgAjYCBCAAIAE2AgAPCyAEIAEQUgALiQEBAX8CQCACQQBOBEACfyADKAIEBEACQCADKAIIIgRFBEAMAQsgAygCACAEIAEgAhBUDAILCyABIAJFDQAaQbGTwAAtAAAaIAIgARBdCyIDBEAgACACNgIIIAAgAzYCBCAAQQA2AgAPCyAAIAI2AgggACABNgIEDAELIABBADYCBAsgAEEBNgIAC5cBAgR/AW8jAEEgayIDJAAgACgCACIGEHAhACADIAI2AgQgAyAANgIAIAAgAkYEQBBbIgQQUyIFJQEgASACEAQhBxAbIgAgByYBIARBhAFPBEAgBBAtCyAFQYQBTwRAIAUQLQsgBiAAQQAQZCAAQYQBTwRAIAAQLQsgA0EgaiQADwsgA0EANgIIIAMgA0EEaiADQQhqEEAAC3kBAX8jAEEgayICJAACfyAAKAIAQYCAgIB4RwRAIAEgACgCBCAAKAIIEFYMAQsgAkEQaiAAKAIMKAIAIgBBCGopAgA3AwAgAkEYaiAAQRBqKQIANwMAIAIgACkCADcDCCABKAIUIAEoAhggAkEIahAYCyACQSBqJAALewEBfyMAQUBqIgUkACAFIAE2AgwgBSAANgIIIAUgAzYCFCAFIAI2AhAgBUECNgIcIAVBoI/AADYCGCAFQgI3AiQgBSAFQRBqrUKAgICAsAWENwM4IAUgBUEIaq1CgICAgMAFhDcDMCAFIAVBMGo2AiAgBUEYaiAEEEMAC24BAX8jAEEwayIBJAAgASAANgIAIAFBgAE2AgQgAUECNgIMIAFB2JHAADYCCCABQgI3AhQgASABQQRqrUKAgICA4ACENwMoIAEgAa1CgICAgOAAhDcDICABIAFBIGo2AhAgAUEIakHIj8AAEEMAC2kCAX8BfiMAQTBrIgMkACADIAE2AgQgAyAANgIAIANBAjYCDCADQfyNwAA2AgggA0ICNwIUIANCgICAgOAAIgQgA62ENwMoIAMgBCADQQRqrYQ3AyAgAyADQSBqNgIQIANBCGogAhBDAAtpAgF/AX4jAEEwayIDJAAgAyAANgIAIAMgATYCBCADQQI2AgwgA0H4kcAANgIIIANCAjcCFCADQoCAgIDgACIEIANBBGqthDcDKCADIAQgA62ENwMgIAMgA0EgajYCECADQQhqIAIQQwALZgAjAEEwayIAJABBsJPAAC0AAARAIABBAjYCDCAAQbCKwAA2AgggAEIBNwIUIAAgATYCLCAAIABBLGqtQoCAgIDgAIQ3AyAgACAAQSBqNgIQIABBCGpB0IrAABBDAAsgAEEwaiQAC5QBAgN/AW8jAEEgayIDJAAgAyAAKAIAEHAiBDYCACADIAI2AgQgAiAERwRAIANBADYCCCADIANBBGogA0EIahBAAAsQWyIEEFMiBSUBEAUhBhAbIgIgBiYBIAVBhAFPBEAgBRAtCyACIAAoAgAgAUECdhBkIAJBhAFPBEAgAhAtCyAEQYQBTwRAIAQQLQsgA0EgaiQAC08BAX8jAEEwayIAJAAgAEEBNgIMIABBwI3AADYCCCAAQgE3AhQgACAAQS9qrUKAgICAoAWENwMgIAAgAEEgajYCECAAQQhqQcSBwAAQQwALQQEBfyACIAAoAgAgACgCCCIDa0sEQCAAIAMgAhAlIAAoAgghAwsgACgCBCADaiABIAIQHxogACACIANqNgIIQQALTQECf0Gxk8AALQAAGiABKAIEIQIgASgCACEDQQhBBBBdIgFFBEBBBEEIEG0ACyABIAI2AgQgASADNgIAIABB8IrAADYCBCAAIAE2AgALQQEBfyACIAAoAgAgACgCCCIDa0sEQCAAIAMgAhApIAAoAgghAwsgACgCBCADaiABIAIQHxogACACIANqNgIIQQALQQEBfyMAQSBrIgIkACACQQA2AhAgAkEBNgIEIAJCBDcCCCACQS42AhwgAiAANgIYIAIgAkEYajYCACACIAEQQwALswIBA38gACgCACECIAEoAhwiAEEQcUUE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ZCByZWN1cnNpdmVseSBvciBhZnRlciBiZWluZyBkcm9wcGVkTGF6eSBpbnN0YW5jZSBoYXMgcHJldmlvdXNseSBiZWVuIHBvaXNvbmVkdgMQACoAAAAvVXNlcnMvZG1hcmNvcy8uY2FyZ28vcmVnaXN0cnkvc3JjL2luZGV4LmNyYXRlcy5pby02ZjE3ZDIyYmJhMTUwMDFmL29uY2VfY2VsbC0xLjIxLjMvc3JjL2xpYi5ycwCoAxAAXwAAAAgDAAAZAAAAcmVlbnRyYW50IGluaXQAABgEEAAOAAAAqAMQAF8AAAB6AgAADQAAABYAAAAMAAAABAAAABcAAAAYAAAAGQAAAC9ydXN0L2RlcHMvZGxtYWxsb2MtMC4yLjYvc3JjL2RsbWFsbG9jLnJzYXNzZXJ0aW9uIGZhaWxlZDogcHNpemUgPj0gc2l6ZSArIG1pbl9vdmVyaGVhZABYBBAAKQAAAKgEAAAJAAAAYXNzZXJ0aW9uIGZhaWxlZDogcHNpemUgPD0gc2l6ZSArIG1heF9vdmVyaGVhZAAAWAQQACkAAACuBAAADQAAAEFjY2Vzc0Vycm9ybWVtb3J5IGFsbG9jYXRpb24gb2YgIGJ5dGVzIGZhaWxlZAAAAAsFEAAVAAAAIAUQAA0AAABzdGQvc3JjL2FsbG9jLnJzQAUQABAAAABjAQAACQAAABYAAAAMAAAABAAAABoAAAAAAAAACAAAAAQAAAAbAAAAAAAAAAgAAAAEAAAAHAAAAB0AAAAeAAAAHwAAACAAAAAQAAAABAAAACEAAAAiAAAAIwAAACQAAABFcnJvcgAAACUAAAAMAAAABAAAACYAAAAnAAAAKAAAAGNhcGFjaXR5IG92ZXJmbG93AAAA2AUQABEAAABhbGxvYy9zcmMvcmF3X3ZlYy5yc/QFEAAUAAAAGAAAAAUAQaCMwAAL8AUBAAAAKQAAAGEgZm9ybWF0dGluZyB0cmFpdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5lZCBhbiBlcnJvciB3aGVuIHRoZSB1bmRlcmx5aW5nIHN0cmVhbSBkaWQgbm90YWxsb2Mvc3JjL2ZtdC5ycwAAfgYQABAAAAB+AgAADgAAAEJvcnJvd011dEVycm9yYWxyZWFkeSBib3Jyb3dlZDogrgYQABIAAABpbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIAAAyAYQACAAAADoBhAAEgAAAD09IT1tYXRjaGVzYXNzZXJ0aW9uIGBsZWZ0ICByaWdodGAgZmFpbGVkCiAgbGVmdDogCiByaWdodDogABcHEAAQAAAAJwcQABcAAAA+BxAACQAAACByaWdodGAgZmFpbGVkOiAKICBsZWZ0OiAAAAAXBxAAEAAAAGAHEAAQAAAAcAcQAAkAAAA+BxAACQAAADogAAABAAAAAAAAAJwHEAACAAAAfSB9Y29yZS9zcmMvZm10L251bS5ycwAAswcQABMAAABmAAAAFwAAADB4MDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlyYW5nZSBzdGFydCBpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggAACiCBAAEgAAALQIEAAiAAAAcmFuZ2UgZW5kIGluZGV4IOgIEAAQAAAAtAgQACIAAAAAAAA/AAAAvwBBqJLAAAsBFABwCXByb2R1Y2VycwIIbGFuZ3VhZ2UBBFJ1c3QADHByb2Nlc3NlZC1ieQMFcnVzdGMdMS44My4wICg5MGIzNWE2MjMgMjAyNC0xMS0yNikGd2FscnVzBjAuMjMuMwx3YXNtLWJpbmRnZW4HMC4yLjEwMABJD3RhcmdldF9mZWF0dXJlcwQrD211dGFibGUtZ2xvYmFscysIc2lnbi1leHQrD3JlZmVyZW5jZS10eXBlcysKbXVsdGl2YWx1ZQ==", self.location.href);\n }\n const imports = __wbg_get_imports();\n if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) {\n module_or_path = fetch(module_or_path);\n }\n const { instance, module } = await __wbg_load(await module_or_path, imports);\n return __wbg_finalize_init(instance, module);\n }\n var ch2 = {};\n var wk = function(c, id, msg, transfer, cb) {\n var w = new Worker(ch2[id] || (ch2[id] = URL.createObjectURL(new Blob([\n c + \';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})\'\n ], { type: "text/javascript" }))));\n w.onmessage = function(e) {\n var d = e.data, ed = d.$e$;\n if (ed) {\n var err2 = new Error(ed[0]);\n err2["code"] = ed[1];\n err2.stack = ed[2];\n cb(err2, null);\n } else\n cb(null, d);\n };\n w.postMessage(msg, transfer);\n return w;\n };\n var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;\n var fleb = new u8([\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 1,\n 1,\n 1,\n 1,\n 2,\n 2,\n 2,\n 2,\n 3,\n 3,\n 3,\n 3,\n 4,\n 4,\n 4,\n 4,\n 5,\n 5,\n 5,\n 5,\n 0,\n /* unused */\n 0,\n 0,\n /* impossible */\n 0\n ]);\n var fdeb = new u8([\n 0,\n 0,\n 0,\n 0,\n 1,\n 1,\n 2,\n 2,\n 3,\n 3,\n 4,\n 4,\n 5,\n 5,\n 6,\n 6,\n 7,\n 7,\n 8,\n 8,\n 9,\n 9,\n 10,\n 10,\n 11,\n 11,\n 12,\n 12,\n 13,\n 13,\n /* unused */\n 0,\n 0\n ]);\n var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n var freb = function(eb, start) {\n var b = new u16(31);\n for (var i2 = 0; i2 < 31; ++i2) {\n b[i2] = start += 1 << eb[i2 - 1];\n }\n var r = new i32(b[30]);\n for (var i2 = 1; i2 < 30; ++i2) {\n for (var j = b[i2]; j < b[i2 + 1]; ++j) {\n r[j] = j - b[i2] << 5 | i2;\n }\n }\n return { b, r };\n };\n var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;\n fl[28] = 258, revfl[258] = 28;\n var _b = freb(fdeb, 0), fd = _b.b;\n var rev = new u16(32768);\n for (var i = 0; i < 32768; ++i) {\n var x = (i & 43690) >> 1 | (i & 21845) << 1;\n x = (x & 52428) >> 2 | (x & 13107) << 2;\n x = (x & 61680) >> 4 | (x & 3855) << 4;\n rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;\n }\n var hMap = function(cd, mb, r) {\n var s = cd.length;\n var i2 = 0;\n var l = new u16(mb);\n for (; i2 < s; ++i2) {\n if (cd[i2])\n ++l[cd[i2] - 1];\n }\n var le = new u16(mb);\n for (i2 = 1; i2 < mb; ++i2) {\n le[i2] = le[i2 - 1] + l[i2 - 1] << 1;\n }\n var co;\n if (r) {\n co = new u16(1 << mb);\n var rvb = 15 - mb;\n for (i2 = 0; i2 < s; ++i2) {\n if (cd[i2]) {\n var sv = i2 << 4 | cd[i2];\n var r_1 = mb - cd[i2];\n var v = le[cd[i2] - 1]++ << r_1;\n for (var m = v | (1 << r_1) - 1; v <= m; ++v) {\n co[rev[v] >> rvb] = sv;\n }\n }\n }\n } else {\n co = new u16(s);\n for (i2 = 0; i2 < s; ++i2) {\n if (cd[i2]) {\n co[i2] = rev[le[cd[i2] - 1]++] >> 15 - cd[i2];\n }\n }\n }\n return co;\n };\n var flt = new u8(288);\n for (var i = 0; i < 144; ++i)\n flt[i] = 8;\n for (var i = 144; i < 256; ++i)\n flt[i] = 9;\n for (var i = 256; i < 280; ++i)\n flt[i] = 7;\n for (var i = 280; i < 288; ++i)\n flt[i] = 8;\n var fdt = new u8(32);\n for (var i = 0; i < 32; ++i)\n fdt[i] = 5;\n var flrm = /* @__PURE__ */ hMap(flt, 9, 1);\n var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);\n var max = function(a) {\n var m = a[0];\n for (var i2 = 1; i2 < a.length; ++i2) {\n if (a[i2] > m)\n m = a[i2];\n }\n return m;\n };\n var bits = function(d, p, m) {\n var o = p / 8 | 0;\n return (d[o] | d[o + 1] << 8) >> (p & 7) & m;\n };\n var bits16 = function(d, p) {\n var o = p / 8 | 0;\n return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);\n };\n var shft = function(p) {\n return (p + 7) / 8 | 0;\n };\n var slc = function(v, s, e) {\n if (s == null || s < 0)\n s = 0;\n if (e == null || e > v.length)\n e = v.length;\n return new u8(v.subarray(s, e));\n };\n var ec = [\n "unexpected EOF",\n "invalid block type",\n "invalid length/literal",\n "invalid distance",\n "stream finished",\n "no stream handler",\n ,\n "no callback",\n "invalid UTF-8 data",\n "extra field too long",\n "date not in range 1980-2099",\n "filename too long",\n "stream finishing",\n "invalid zip data"\n // determined by unknown compression method\n ];\n var err = function(ind, msg, nt) {\n var e = new Error(msg || ec[ind]);\n e.code = ind;\n if (Error.captureStackTrace)\n Error.captureStackTrace(e, err);\n if (!nt)\n throw e;\n return e;\n };\n var inflt = function(dat, st, buf, dict) {\n var sl = dat.length, dl = dict ? dict.length : 0;\n if (!sl || st.f && !st.l)\n return buf || new u8(0);\n var noBuf = !buf;\n var resize = noBuf || st.i != 2;\n var noSt = st.i;\n if (noBuf)\n buf = new u8(sl * 3);\n var cbuf = function(l2) {\n var bl = buf.length;\n if (l2 > bl) {\n var nbuf = new u8(Math.max(bl * 2, l2));\n nbuf.set(buf);\n buf = nbuf;\n }\n };\n var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;\n var tbts = sl * 8;\n do {\n if (!lm) {\n final = bits(dat, pos, 1);\n var type = bits(dat, pos + 1, 3);\n pos += 3;\n if (!type) {\n var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;\n if (t > sl) {\n if (noSt)\n err(0);\n break;\n }\n if (resize)\n cbuf(bt + l);\n buf.set(dat.subarray(s, t), bt);\n st.b = bt += l, st.p = pos = t * 8, st.f = final;\n continue;\n } else if (type == 1)\n lm = flrm, dm = fdrm, lbt = 9, dbt = 5;\n else if (type == 2) {\n var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;\n var tl = hLit + bits(dat, pos + 5, 31) + 1;\n pos += 14;\n var ldt = new u8(tl);\n var clt = new u8(19);\n for (var i2 = 0; i2 < hcLen; ++i2) {\n clt[clim[i2]] = bits(dat, pos + i2 * 3, 7);\n }\n pos += hcLen * 3;\n var clb = max(clt), clbmsk = (1 << clb) - 1;\n var clm = hMap(clt, clb, 1);\n for (var i2 = 0; i2 < tl; ) {\n var r = clm[bits(dat, pos, clbmsk)];\n pos += r & 15;\n var s = r >> 4;\n if (s < 16) {\n ldt[i2++] = s;\n } else {\n var c = 0, n = 0;\n if (s == 16)\n n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i2 - 1];\n else if (s == 17)\n n = 3 + bits(dat, pos, 7), pos += 3;\n else if (s == 18)\n n = 11 + bits(dat, pos, 127), pos += 7;\n while (n--)\n ldt[i2++] = c;\n }\n }\n var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);\n lbt = max(lt);\n dbt = max(dt);\n lm = hMap(lt, lbt, 1);\n dm = hMap(dt, dbt, 1);\n } else\n err(1);\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n }\n if (resize)\n cbuf(bt + 131072);\n var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;\n var lpos = pos;\n for (; ; lpos = pos) {\n var c = lm[bits16(dat, pos) & lms], sym = c >> 4;\n pos += c & 15;\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n if (!c)\n err(2);\n if (sym < 256)\n buf[bt++] = sym;\n else if (sym == 256) {\n lpos = pos, lm = null;\n break;\n } else {\n var add = sym - 254;\n if (sym > 264) {\n var i2 = sym - 257, b = fleb[i2];\n add = bits(dat, pos, (1 << b) - 1) + fl[i2];\n pos += b;\n }\n var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;\n if (!d)\n err(3);\n pos += d & 15;\n var dt = fd[dsym];\n if (dsym > 3) {\n var b = fdeb[dsym];\n dt += bits16(dat, pos) & (1 << b) - 1, pos += b;\n }\n if (pos > tbts) {\n if (noSt)\n err(0);\n break;\n }\n if (resize)\n cbuf(bt + 131072);\n var end = bt + add;\n if (bt < dt) {\n var shift = dl - dt, dend = Math.min(dt, end);\n if (shift + bt < 0)\n err(3);\n for (; bt < dend; ++bt)\n buf[bt] = dict[shift + bt];\n }\n for (; bt < end; ++bt)\n buf[bt] = buf[bt - dt];\n }\n }\n st.l = lm, st.p = lpos, st.b = bt, st.f = final;\n if (lm)\n final = 1, st.m = lbt, st.d = dm, st.n = dbt;\n } while (!final);\n return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);\n };\n var et = /* @__PURE__ */ new u8(0);\n var mrg = function(a, b) {\n var o = {};\n for (var k in a)\n o[k] = a[k];\n for (var k in b)\n o[k] = b[k];\n return o;\n };\n var wcln = function(fn, fnStr, td2) {\n var dt = fn();\n var st = fn.toString();\n var ks = st.slice(st.indexOf("[") + 1, st.lastIndexOf("]")).replace(/\\s+/g, "").split(",");\n for (var i2 = 0; i2 < dt.length; ++i2) {\n var v = dt[i2], k = ks[i2];\n if (typeof v == "function") {\n fnStr += ";" + k + "=";\n var st_1 = v.toString();\n if (v.prototype) {\n if (st_1.indexOf("[native code]") != -1) {\n var spInd = st_1.indexOf(" ", 8) + 1;\n fnStr += st_1.slice(spInd, st_1.indexOf("(", spInd));\n } else {\n fnStr += st_1;\n for (var t in v.prototype)\n fnStr += ";" + k + ".prototype." + t + "=" + v.prototype[t].toString();\n }\n } else\n fnStr += st_1;\n } else\n td2[k] = v;\n }\n return fnStr;\n };\n var ch = [];\n var cbfs = function(v) {\n var tl = [];\n for (var k in v) {\n if (v[k].buffer) {\n tl.push((v[k] = new v[k].constructor(v[k])).buffer);\n }\n }\n return tl;\n };\n var wrkr = function(fns, init, id, cb) {\n if (!ch[id]) {\n var fnStr = "", td_1 = {}, m = fns.length - 1;\n for (var i2 = 0; i2 < m; ++i2)\n fnStr = wcln(fns[i2], fnStr, td_1);\n ch[id] = { c: wcln(fns[m], fnStr, td_1), e: td_1 };\n }\n var td2 = mrg({}, ch[id].e);\n return wk(ch[id].c + ";onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=" + init.toString() + "}", id, td2, cbfs(td2), cb);\n };\n var bInflt = function() {\n return [u8, u16, i32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gopt];\n };\n var pbf = function(msg) {\n return postMessage(msg, [msg.buffer]);\n };\n var gopt = function(o) {\n return o && {\n out: o.size && new u8(o.size),\n dictionary: o.dictionary\n };\n };\n var cbify = function(dat, opts, fns, init, id, cb) {\n var w = wrkr(fns, init, id, function(err2, dat2) {\n w.terminate();\n cb(err2, dat2);\n });\n w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []);\n return function() {\n w.terminate();\n };\n };\n var b2 = function(d, b) {\n return d[b] | d[b + 1] << 8;\n };\n var b4 = function(d, b) {\n return (d[b] | d[b + 1] << 8 | d[b + 2] << 16 | d[b + 3] << 24) >>> 0;\n };\n var b8 = function(d, b) {\n return b4(d, b) + b4(d, b + 4) * 4294967296;\n };\n var gzs = function(d) {\n if (d[0] != 31 || d[1] != 139 || d[2] != 8)\n err(6, "invalid gzip data");\n var flg = d[3];\n var st = 10;\n if (flg & 4)\n st += (d[10] | d[11] << 8) + 2;\n for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++])\n ;\n return st + (flg & 2);\n };\n var Inflate = /* @__PURE__ */ function() {\n function Inflate2(opts, cb) {\n if (typeof opts == "function")\n cb = opts, opts = {};\n this.ondata = cb;\n var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768);\n this.s = { i: 0, b: dict ? dict.length : 0 };\n this.o = new u8(32768);\n this.p = new u8(0);\n if (dict)\n this.o.set(dict);\n }\n Inflate2.prototype.e = function(c) {\n if (!this.ondata)\n err(5);\n if (this.d)\n err(4);\n if (!this.p.length)\n this.p = c;\n else if (c.length) {\n var n = new u8(this.p.length + c.length);\n n.set(this.p), n.set(c, this.p.length), this.p = n;\n }\n };\n Inflate2.prototype.c = function(final) {\n this.s.i = +(this.d = final || false);\n var bts = this.s.b;\n var dt = inflt(this.p, this.s, this.o);\n this.ondata(slc(dt, bts, this.s.b), this.d);\n this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;\n this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;\n };\n Inflate2.prototype.push = function(chunk, final) {\n this.e(chunk), this.c(final);\n };\n return Inflate2;\n }();\n function inflate(data, opts, cb) {\n if (!cb)\n cb = opts, opts = {};\n if (typeof cb != "function")\n err(7);\n return cbify(data, opts, [\n bInflt\n ], function(ev) {\n return pbf(inflateSync(ev.data[0], gopt(ev.data[1])));\n }, 1, cb);\n }\n function inflateSync(data, opts) {\n return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary);\n }\n var Gunzip = /* @__PURE__ */ function() {\n function Gunzip2(opts, cb) {\n this.v = 1;\n this.r = 0;\n Inflate.call(this, opts, cb);\n }\n Gunzip2.prototype.push = function(chunk, final) {\n Inflate.prototype.e.call(this, chunk);\n this.r += chunk.length;\n if (this.v) {\n var p = this.p.subarray(this.v - 1);\n var s = p.length > 3 ? gzs(p) : 4;\n if (s > p.length) {\n if (!final)\n return;\n } else if (this.v > 1 && this.onmember) {\n this.onmember(this.r - p.length);\n }\n this.p = p.subarray(s), this.v = 0;\n }\n Inflate.prototype.c.call(this, final);\n if (this.s.f && !this.s.l && !final) {\n this.v = shft(this.s.p) + 9;\n this.s = { i: 0 };\n this.o = new u8(0);\n this.push(new u8(0), final);\n }\n };\n return Gunzip2;\n }();\n var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();\n try {\n td.decode(et, { stream: true });\n } catch (e) {\n }\n var dutf8 = function(d) {\n for (var r = "", i2 = 0; ; ) {\n var c = d[i2++];\n var eb = (c > 127) + (c > 223) + (c > 239);\n if (i2 + eb > d.length)\n return { s: r, r: slc(d, i2 - 1) };\n if (!eb)\n r += String.fromCharCode(c);\n else if (eb == 3) {\n c = ((c & 15) << 18 | (d[i2++] & 63) << 12 | (d[i2++] & 63) << 6 | d[i2++] & 63) - 65536, r += String.fromCharCode(55296 | c >> 10, 56320 | c & 1023);\n } else if (eb & 1)\n r += String.fromCharCode((c & 31) << 6 | d[i2++] & 63);\n else\n r += String.fromCharCode((c & 15) << 12 | (d[i2++] & 63) << 6 | d[i2++] & 63);\n }\n };\n function strFromU8(dat, latin1) {\n if (latin1) {\n var r = "";\n for (var i2 = 0; i2 < dat.length; i2 += 16384)\n r += String.fromCharCode.apply(null, dat.subarray(i2, i2 + 16384));\n return r;\n } else if (td) {\n return td.decode(dat);\n } else {\n var _a2 = dutf8(dat), s = _a2.s, r = _a2.r;\n if (r.length)\n err(8);\n return s;\n }\n }\n var slzh = function(d, b) {\n return b + 30 + b2(d, b + 26) + b2(d, b + 28);\n };\n var zh = function(d, b, z) {\n var fnl = b2(d, b + 28), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl, bs = b4(d, b + 20);\n var _a2 = z && bs == 4294967295 ? z64e(d, es) : [bs, b4(d, b + 24), b4(d, b + 42)], sc = _a2[0], su = _a2[1], off = _a2[2];\n return [b2(d, b + 10), sc, su, fn, es + b2(d, b + 30) + b2(d, b + 32), off];\n };\n var z64e = function(d, b) {\n for (; b2(d, b) != 1; b += 4 + b2(d, b + 2))\n ;\n return [b8(d, b + 12), b8(d, b + 4), b8(d, b + 20)];\n };\n var mt = typeof queueMicrotask == "function" ? queueMicrotask : typeof setTimeout == "function" ? setTimeout : function(fn) {\n fn();\n };\n function unzip(data, opts, cb) {\n if (!cb)\n cb = opts, opts = {};\n if (typeof cb != "function")\n err(7);\n var term = [];\n var tAll = function() {\n for (var i3 = 0; i3 < term.length; ++i3)\n term[i3]();\n };\n var files = {};\n var cbd = function(a, b) {\n mt(function() {\n cb(a, b);\n });\n };\n mt(function() {\n cbd = cb;\n });\n var e = data.length - 22;\n for (; b4(data, e) != 101010256; --e) {\n if (!e || data.length - e > 65558) {\n cbd(err(13, 0, 1), null);\n return tAll;\n }\n }\n var lft = b2(data, e + 8);\n if (lft) {\n var c = lft;\n var o = b4(data, e + 16);\n var z = o == 4294967295 || c == 65535;\n if (z) {\n var ze = b4(data, e - 12);\n z = b4(data, ze) == 101075792;\n if (z) {\n c = lft = b4(data, ze + 32);\n o = b4(data, ze + 48);\n }\n }\n var fltr = opts && opts.filter;\n var _loop_3 = function(i3) {\n var _a2 = zh(data, o, z), c_1 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);\n o = no;\n var cbl = function(e2, d) {\n if (e2) {\n tAll();\n cbd(e2, null);\n } else {\n if (d)\n files[fn] = d;\n if (!--lft)\n cbd(null, files);\n }\n };\n if (!fltr || fltr({\n name: fn,\n size: sc,\n originalSize: su,\n compression: c_1\n })) {\n if (!c_1)\n cbl(null, slc(data, b, b + sc));\n else if (c_1 == 8) {\n var infl = data.subarray(b, b + sc);\n if (su < 524288 || sc > 0.8 * su) {\n try {\n cbl(null, inflateSync(infl, { out: new u8(su) }));\n } catch (e2) {\n cbl(e2, null);\n }\n } else\n term.push(inflate(infl, { size: su }, cbl));\n } else\n cbl(err(14, "unknown compression type " + c_1, 1), null);\n } else\n cbl(null, null);\n };\n for (var i2 = 0; i2 < c; ++i2) {\n _loop_3(i2);\n }\n } else\n cbd(null, {});\n return tAll;\n }\n function unzipSync(data, opts) {\n var files = {};\n var e = data.length - 22;\n for (; b4(data, e) != 101010256; --e) {\n if (!e || data.length - e > 65558)\n err(13);\n }\n var c = b2(data, e + 8);\n if (!c)\n return {};\n var o = b4(data, e + 16);\n var z = o == 4294967295 || c == 65535;\n if (z) {\n var ze = b4(data, e - 12);\n z = b4(data, ze) == 101075792;\n if (z) {\n c = b4(data, ze + 32);\n o = b4(data, ze + 48);\n }\n }\n var fltr = opts && opts.filter;\n for (var i2 = 0; i2 < c; ++i2) {\n var _a2 = zh(data, o, z), c_2 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);\n o = no;\n if (!fltr || fltr({\n name: fn,\n size: sc,\n originalSize: su,\n compression: c_2\n })) {\n if (!c_2)\n files[fn] = slc(data, b, b + sc);\n else if (c_2 == 8)\n files[fn] = inflateSync(data.subarray(b, b + sc), { out: new u8(su) });\n else\n err(14, "unknown compression type " + c_2);\n }\n }\n return files;\n }\n /**\n * @license\n * Copyright 2010-2025 Three.js Authors\n * SPDX-License-Identifier: MIT\n */\n const REVISION = "178";\n const NoColorSpace = "";\n const SRGBColorSpace = "srgb";\n const LinearSRGBColorSpace = "srgb-linear";\n const LinearTransfer = "linear";\n const SRGBTransfer = "srgb";\n function clamp(value, min, max2) {\n return Math.max(min, Math.min(max2, value));\n }\n function euclideanModulo(n, m) {\n return (n % m + m) % m;\n }\n function lerp(x2, y, t) {\n return (1 - t) * x2 + t * y;\n }\n class Quaternion {\n /**\n * Constructs a new quaternion.\n *\n * @param {number} [x=0] - The x value of this quaternion.\n * @param {number} [y=0] - The y value of this quaternion.\n * @param {number} [z=0] - The z value of this quaternion.\n * @param {number} [w=1] - The w value of this quaternion.\n */\n constructor(x2 = 0, y = 0, z = 0, w = 1) {\n this.isQuaternion = true;\n this._x = x2;\n this._y = y;\n this._z = z;\n this._w = w;\n }\n /**\n * Interpolates between two quaternions via SLERP. This implementation assumes the\n * quaternion data are managed in flat arrays.\n *\n * @param {Array<number>} dst - The destination array.\n * @param {number} dstOffset - An offset into the destination array.\n * @param {Array<number>} src0 - The source array of the first quaternion.\n * @param {number} srcOffset0 - An offset into the first source array.\n * @param {Array<number>} src1 - The source array of the second quaternion.\n * @param {number} srcOffset1 - An offset into the second source array.\n * @param {number} t - The interpolation factor in the range `[0,1]`.\n * @see {@link Quaternion#slerp}\n */\n static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {\n let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3];\n const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3];\n if (t === 0) {\n dst[dstOffset + 0] = x0;\n dst[dstOffset + 1] = y0;\n dst[dstOffset + 2] = z0;\n dst[dstOffset + 3] = w0;\n return;\n }\n if (t === 1) {\n dst[dstOffset + 0] = x1;\n dst[dstOffset + 1] = y1;\n dst[dstOffset + 2] = z1;\n dst[dstOffset + 3] = w1;\n return;\n }\n if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {\n let s = 1 - t;\n const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos;\n if (sqrSin > Number.EPSILON) {\n const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir);\n s = Math.sin(s * len) / sin;\n t = Math.sin(t * len) / sin;\n }\n const tDir = t * dir;\n x0 = x0 * s + x1 * tDir;\n y0 = y0 * s + y1 * tDir;\n z0 = z0 * s + z1 * tDir;\n w0 = w0 * s + w1 * tDir;\n if (s === 1 - t) {\n const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);\n x0 *= f;\n y0 *= f;\n z0 *= f;\n w0 *= f;\n }\n }\n dst[dstOffset] = x0;\n dst[dstOffset + 1] = y0;\n dst[dstOffset + 2] = z0;\n dst[dstOffset + 3] = w0;\n }\n /**\n * Multiplies two quaternions. This implementation assumes the quaternion data are managed\n * in flat arrays.\n *\n * @param {Array<number>} dst - The destination array.\n * @param {number} dstOffset - An offset into the destination array.\n * @param {Array<number>} src0 - The source array of the first quaternion.\n * @param {number} srcOffset0 - An offset into the first source array.\n * @param {Array<number>} src1 - The source array of the second quaternion.\n * @param {number} srcOffset1 - An offset into the second source array.\n * @return {Array<number>} The destination array.\n * @see {@link Quaternion#multiplyQuaternions}.\n */\n static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) {\n const x0 = src0[srcOffset0];\n const y0 = src0[srcOffset0 + 1];\n const z0 = src0[srcOffset0 + 2];\n const w0 = src0[srcOffset0 + 3];\n const x1 = src1[srcOffset1];\n const y1 = src1[srcOffset1 + 1];\n const z1 = src1[srcOffset1 + 2];\n const w1 = src1[srcOffset1 + 3];\n dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;\n dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;\n dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;\n dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;\n return dst;\n }\n /**\n * The x value of this quaternion.\n *\n * @type {number}\n * @default 0\n */\n get x() {\n return this._x;\n }\n set x(value) {\n this._x = value;\n this._onChangeCallback();\n }\n /**\n * The y value of this quaternion.\n *\n * @type {number}\n * @default 0\n */\n get y() {\n return this._y;\n }\n set y(value) {\n this._y = value;\n this._onChangeCallback();\n }\n /**\n * The z value of this quaternion.\n *\n * @type {number}\n * @default 0\n */\n get z() {\n return this._z;\n }\n set z(value) {\n this._z = value;\n this._onChangeCallback();\n }\n /**\n * The w value of this quaternion.\n *\n * @type {number}\n * @default 1\n */\n get w() {\n return this._w;\n }\n set w(value) {\n this._w = value;\n this._onChangeCallback();\n }\n /**\n * Sets the quaternion components.\n *\n * @param {number} x - The x value of this quaternion.\n * @param {number} y - The y value of this quaternion.\n * @param {number} z - The z value of this quaternion.\n * @param {number} w - The w value of this quaternion.\n * @return {Quaternion} A reference to this quaternion.\n */\n set(x2, y, z, w) {\n this._x = x2;\n this._y = y;\n this._z = z;\n this._w = w;\n this._onChangeCallback();\n return this;\n }\n /**\n * Returns a new quaternion with copied values from this instance.\n *\n * @return {Quaternion} A clone of this instance.\n */\n clone() {\n return new this.constructor(this._x, this._y, this._z, this._w);\n }\n /**\n * Copies the values of the given quaternion to this instance.\n *\n * @param {Quaternion} quaternion - The quaternion to copy.\n * @return {Quaternion} A reference to this quaternion.\n */\n copy(quaternion) {\n this._x = quaternion.x;\n this._y = quaternion.y;\n this._z = quaternion.z;\n this._w = quaternion.w;\n this._onChangeCallback();\n return this;\n }\n /**\n * Sets this quaternion from the rotation specified by the given\n * Euler angles.\n *\n * @param {Euler} euler - The Euler angles.\n * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.\n * @return {Quaternion} A reference to this quaternion.\n */\n setFromEuler(euler, update = true) {\n const x2 = euler._x, y = euler._y, z = euler._z, order = euler._order;\n const cos = Math.cos;\n const sin = Math.sin;\n const c1 = cos(x2 / 2);\n const c2 = cos(y / 2);\n const c3 = cos(z / 2);\n const s1 = sin(x2 / 2);\n const s2 = sin(y / 2);\n const s3 = sin(z / 2);\n switch (order) {\n case "XYZ":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "YXZ":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case "ZXY":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "ZYX":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case "YZX":\n this._x = s1 * c2 * c3 + c1 * s2 * s3;\n this._y = c1 * s2 * c3 + s1 * c2 * s3;\n this._z = c1 * c2 * s3 - s1 * s2 * c3;\n this._w = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case "XZY":\n this._x = s1 * c2 * c3 - c1 * s2 * s3;\n this._y = c1 * s2 * c3 - s1 * c2 * s3;\n this._z = c1 * c2 * s3 + s1 * s2 * c3;\n this._w = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n default:\n console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: " + order);\n }\n if (update === true) this._onChangeCallback();\n return this;\n }\n /**\n * Sets this quaternion from the given axis and angle.\n *\n * @param {Vector3} axis - The normalized axis.\n * @param {number} angle - The angle in radians.\n * @return {Quaternion} A reference to this quaternion.\n */\n setFromAxisAngle(axis, angle) {\n const halfAngle = angle / 2, s = Math.sin(halfAngle);\n this._x = axis.x * s;\n this._y = axis.y * s;\n this._z = axis.z * s;\n this._w = Math.cos(halfAngle);\n this._onChangeCallback();\n return this;\n }\n /**\n * Sets this quaternion from the given rotation matrix.\n *\n * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).\n * @return {Quaternion} A reference to this quaternion.\n */\n setFromRotationMatrix(m) {\n const te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33;\n if (trace > 0) {\n const s = 0.5 / Math.sqrt(trace + 1);\n this._w = 0.25 / s;\n this._x = (m32 - m23) * s;\n this._y = (m13 - m31) * s;\n this._z = (m21 - m12) * s;\n } else if (m11 > m22 && m11 > m33) {\n const s = 2 * Math.sqrt(1 + m11 - m22 - m33);\n this._w = (m32 - m23) / s;\n this._x = 0.25 * s;\n this._y = (m12 + m21) / s;\n this._z = (m13 + m31) / s;\n } else if (m22 > m33) {\n const s = 2 * Math.sqrt(1 + m22 - m11 - m33);\n this._w = (m13 - m31) / s;\n this._x = (m12 + m21) / s;\n this._y = 0.25 * s;\n this._z = (m23 + m32) / s;\n } else {\n const s = 2 * Math.sqrt(1 + m33 - m11 - m22);\n this._w = (m21 - m12) / s;\n this._x = (m13 + m31) / s;\n this._y = (m23 + m32) / s;\n this._z = 0.25 * s;\n }\n this._onChangeCallback();\n return this;\n }\n /**\n * Sets this quaternion to the rotation required to rotate the direction vector\n * `vFrom` to the direction vector `vTo`.\n *\n * @param {Vector3} vFrom - The first (normalized) direction vector.\n * @param {Vector3} vTo - The second (normalized) direction vector.\n * @return {Quaternion} A reference to this quaternion.\n */\n setFromUnitVectors(vFrom, vTo) {\n let r = vFrom.dot(vTo) + 1;\n if (r < 1e-8) {\n r = 0;\n if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {\n this._x = -vFrom.y;\n this._y = vFrom.x;\n this._z = 0;\n this._w = r;\n } else {\n this._x = 0;\n this._y = -vFrom.z;\n this._z = vFrom.y;\n this._w = r;\n }\n } else {\n this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\n this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\n this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\n this._w = r;\n }\n return this.normalize();\n }\n /**\n * Returns the angle between this quaternion and the given one in radians.\n *\n * @param {Quaternion} q - The quaternion to compute the angle with.\n * @return {number} The angle in radians.\n */\n angleTo(q) {\n return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1)));\n }\n /**\n * Rotates this quaternion by a given angular step to the given quaternion.\n * The method ensures that the final quaternion will not overshoot `q`.\n *\n * @param {Quaternion} q - The target quaternion.\n * @param {number} step - The angular step in radians.\n * @return {Quaternion} A reference to this quaternion.\n */\n rotateTowards(q, step) {\n const angle = this.angleTo(q);\n if (angle === 0) return this;\n const t = Math.min(1, step / angle);\n this.slerp(q, t);\n return this;\n }\n /**\n * Sets this quaternion to the identity quaternion; that is, to the\n * quaternion that represents "no rotation".\n *\n * @return {Quaternion} A reference to this quaternion.\n */\n identity() {\n return this.set(0, 0, 0, 1);\n }\n /**\n * Inverts this quaternion via {@link Quaternion#conjugate}. The\n * quaternion is assumed to have unit length.\n *\n * @return {Quaternion} A reference to this quaternion.\n */\n invert() {\n return this.conjugate();\n }\n /**\n * Returns the rotational conjugate of this quaternion. The conjugate of a\n * quaternion represents the same rotation in the opposite direction about\n * the rotational axis.\n *\n * @return {Quaternion} A reference to this quaternion.\n */\n conjugate() {\n this._x *= -1;\n this._y *= -1;\n this._z *= -1;\n this._onChangeCallback();\n return this;\n }\n /**\n * Calculates the dot product of this quaternion and the given one.\n *\n * @param {Quaternion} v - The quaternion to compute the dot product with.\n * @return {number} The result of the dot product.\n */\n dot(v) {\n return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\n }\n /**\n * Computes the squared Euclidean length (straight-line length) of this quaternion,\n * considered as a 4 dimensional vector. This can be useful if you are comparing the\n * lengths of two quaternions, as this is a slightly more efficient calculation than\n * {@link Quaternion#length}.\n *\n * @return {number} The squared Euclidean length.\n */\n lengthSq() {\n return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\n }\n /**\n * Computes the Euclidean length (straight-line length) of this quaternion,\n * considered as a 4 dimensional vector.\n *\n * @return {number} The Euclidean length.\n */\n length() {\n return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);\n }\n /**\n * Normalizes this quaternion - that is, calculated the quaternion that performs\n * the same rotation as this one, but has a length equal to `1`.\n *\n * @return {Quaternion} A reference to this quaternion.\n */\n normalize() {\n let l = this.length();\n if (l === 0) {\n this._x = 0;\n this._y = 0;\n this._z = 0;\n this._w = 1;\n } else {\n l = 1 / l;\n this._x = this._x * l;\n this._y = this._y * l;\n this._z = this._z * l;\n this._w = this._w * l;\n }\n this._onChangeCallback();\n return this;\n }\n /**\n * Multiplies this quaternion by the given one.\n *\n * @param {Quaternion} q - The quaternion.\n * @return {Quaternion} A reference to this quaternion.\n */\n multiply(q) {\n return this.multiplyQuaternions(this, q);\n }\n /**\n * Pre-multiplies this quaternion by the given one.\n *\n * @param {Quaternion} q - The quaternion.\n * @return {Quaternion} A reference to this quaternion.\n */\n premultiply(q) {\n return this.multiplyQuaternions(q, this);\n }\n /**\n * Multiplies the given quaternions and stores the result in this instance.\n *\n * @param {Quaternion} a - The first quaternion.\n * @param {Quaternion} b - The second quaternion.\n * @return {Quaternion} A reference to this quaternion.\n */\n multiplyQuaternions(a, b) {\n const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\n const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\n this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\n this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\n this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\n this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\n this._onChangeCallback();\n return this;\n }\n /**\n * Performs a spherical linear interpolation between quaternions.\n *\n * @param {Quaternion} qb - The target quaternion.\n * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.\n * @return {Quaternion} A reference to this quaternion.\n */\n slerp(qb, t) {\n if (t === 0) return this;\n if (t === 1) return this.copy(qb);\n const x2 = this._x, y = this._y, z = this._z, w = this._w;\n let cosHalfTheta = w * qb._w + x2 * qb._x + y * qb._y + z * qb._z;\n if (cosHalfTheta < 0) {\n this._w = -qb._w;\n this._x = -qb._x;\n this._y = -qb._y;\n this._z = -qb._z;\n cosHalfTheta = -cosHalfTheta;\n } else {\n this.copy(qb);\n }\n if (cosHalfTheta >= 1) {\n this._w = w;\n this._x = x2;\n this._y = y;\n this._z = z;\n return this;\n }\n const sqrSinHalfTheta = 1 - cosHalfTheta * cosHalfTheta;\n if (sqrSinHalfTheta <= Number.EPSILON) {\n const s = 1 - t;\n this._w = s * w + t * this._w;\n this._x = s * x2 + t * this._x;\n this._y = s * y + t * this._y;\n this._z = s * z + t * this._z;\n this.normalize();\n return this;\n }\n const sinHalfTheta = Math.sqrt(sqrSinHalfTheta);\n const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);\n const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta;\n this._w = w * ratioA + this._w * ratioB;\n this._x = x2 * ratioA + this._x * ratioB;\n this._y = y * ratioA + this._y * ratioB;\n this._z = z * ratioA + this._z * ratioB;\n this._onChangeCallback();\n return this;\n }\n /**\n * Performs a spherical linear interpolation between the given quaternions\n * and stores the result in this quaternion.\n *\n * @param {Quaternion} qa - The source quaternion.\n * @param {Quaternion} qb - The target quaternion.\n * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.\n * @return {Quaternion} A reference to this quaternion.\n */\n slerpQuaternions(qa, qb, t) {\n return this.copy(qa).slerp(qb, t);\n }\n /**\n * Sets this quaternion to a uniformly random, normalized quaternion.\n *\n * @return {Quaternion} A reference to this quaternion.\n */\n random() {\n const theta1 = 2 * Math.PI * Math.random();\n const theta2 = 2 * Math.PI * Math.random();\n const x0 = Math.random();\n const r1 = Math.sqrt(1 - x0);\n const r2 = Math.sqrt(x0);\n return this.set(\n r1 * Math.sin(theta1),\n r1 * Math.cos(theta1),\n r2 * Math.sin(theta2),\n r2 * Math.cos(theta2)\n );\n }\n /**\n * Returns `true` if this quaternion is equal with the given one.\n *\n * @param {Quaternion} quaternion - The quaternion to test for equality.\n * @return {boolean} Whether this quaternion is equal with the given one.\n */\n equals(quaternion) {\n return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w;\n }\n /**\n * Sets this quaternion\'s components from the given array.\n *\n * @param {Array<number>} array - An array holding the quaternion component values.\n * @param {number} [offset=0] - The offset into the array.\n * @return {Quaternion} A reference to this quaternion.\n */\n fromArray(array, offset = 0) {\n this._x = array[offset];\n this._y = array[offset + 1];\n this._z = array[offset + 2];\n this._w = array[offset + 3];\n this._onChangeCallback();\n return this;\n }\n /**\n * Writes the components of this quaternion to the given array. If no array is provided,\n * the method returns a new instance.\n *\n * @param {Array<number>} [array=[]] - The target array holding the quaternion components.\n * @param {number} [offset=0] - Index of the first element in the array.\n * @return {Array<number>} The quaternion components.\n */\n toArray(array = [], offset = 0) {\n array[offset] = this._x;\n array[offset + 1] = this._y;\n array[offset + 2] = this._z;\n array[offset + 3] = this._w;\n return array;\n }\n /**\n * Sets the components of this quaternion from the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - The buffer attribute holding quaternion data.\n * @param {number} index - The index into the attribute.\n * @return {Quaternion} A reference to this quaternion.\n */\n fromBufferAttribute(attribute, index) {\n this._x = attribute.getX(index);\n this._y = attribute.getY(index);\n this._z = attribute.getZ(index);\n this._w = attribute.getW(index);\n this._onChangeCallback();\n return this;\n }\n /**\n * This methods defines the serialization result of this class. Returns the\n * numerical elements of this quaternion in an array of format `[x, y, z, w]`.\n *\n * @return {Array<number>} The serialized quaternion.\n */\n toJSON() {\n return this.toArray();\n }\n _onChange(callback) {\n this._onChangeCallback = callback;\n return this;\n }\n _onChangeCallback() {\n }\n *[Symbol.iterator]() {\n yield this._x;\n yield this._y;\n yield this._z;\n yield this._w;\n }\n }\n class Vector3 {\n /**\n * Constructs a new 3D vector.\n *\n * @param {number} [x=0] - The x value of this vector.\n * @param {number} [y=0] - The y value of this vector.\n * @param {number} [z=0] - The z value of this vector.\n */\n constructor(x2 = 0, y = 0, z = 0) {\n Vector3.prototype.isVector3 = true;\n this.x = x2;\n this.y = y;\n this.z = z;\n }\n /**\n * Sets the vector components.\n *\n * @param {number} x - The value of the x component.\n * @param {number} y - The value of the y component.\n * @param {number} z - The value of the z component.\n * @return {Vector3} A reference to this vector.\n */\n set(x2, y, z) {\n if (z === void 0) z = this.z;\n this.x = x2;\n this.y = y;\n this.z = z;\n return this;\n }\n /**\n * Sets the vector components to the same value.\n *\n * @param {number} scalar - The value to set for all vector components.\n * @return {Vector3} A reference to this vector.\n */\n setScalar(scalar) {\n this.x = scalar;\n this.y = scalar;\n this.z = scalar;\n return this;\n }\n /**\n * Sets the vector\'s x component to the given value\n *\n * @param {number} x - The value to set.\n * @return {Vector3} A reference to this vector.\n */\n setX(x2) {\n this.x = x2;\n return this;\n }\n /**\n * Sets the vector\'s y component to the given value\n *\n * @param {number} y - The value to set.\n * @return {Vector3} A reference to this vector.\n */\n setY(y) {\n this.y = y;\n return this;\n }\n /**\n * Sets the vector\'s z component to the given value\n *\n * @param {number} z - The value to set.\n * @return {Vector3} A reference to this vector.\n */\n setZ(z) {\n this.z = z;\n return this;\n }\n /**\n * Allows to set a vector component with an index.\n *\n * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.\n * @param {number} value - The value to set.\n * @return {Vector3} A reference to this vector.\n */\n setComponent(index, value) {\n switch (index) {\n case 0:\n this.x = value;\n break;\n case 1:\n this.y = value;\n break;\n case 2:\n this.z = value;\n break;\n default:\n throw new Error("index is out of range: " + index);\n }\n return this;\n }\n /**\n * Returns the value of the vector component which matches the given index.\n *\n * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.\n * @return {number} A vector component value.\n */\n getComponent(index) {\n switch (index) {\n case 0:\n return this.x;\n case 1:\n return this.y;\n case 2:\n return this.z;\n default:\n throw new Error("index is out of range: " + index);\n }\n }\n /**\n * Returns a new vector with copied values from this instance.\n *\n * @return {Vector3} A clone of this instance.\n */\n clone() {\n return new this.constructor(this.x, this.y, this.z);\n }\n /**\n * Copies the values of the given vector to this instance.\n *\n * @param {Vector3} v - The vector to copy.\n * @return {Vector3} A reference to this vector.\n */\n copy(v) {\n this.x = v.x;\n this.y = v.y;\n this.z = v.z;\n return this;\n }\n /**\n * Adds the given vector to this instance.\n *\n * @param {Vector3} v - The vector to add.\n * @return {Vector3} A reference to this vector.\n */\n add(v) {\n this.x += v.x;\n this.y += v.y;\n this.z += v.z;\n return this;\n }\n /**\n * Adds the given scalar value to all components of this instance.\n *\n * @param {number} s - The scalar to add.\n * @return {Vector3} A reference to this vector.\n */\n addScalar(s) {\n this.x += s;\n this.y += s;\n this.z += s;\n return this;\n }\n /**\n * Adds the given vectors and stores the result in this instance.\n *\n * @param {Vector3} a - The first vector.\n * @param {Vector3} b - The second vector.\n * @return {Vector3} A reference to this vector.\n */\n addVectors(a, b) {\n this.x = a.x + b.x;\n this.y = a.y + b.y;\n this.z = a.z + b.z;\n return this;\n }\n /**\n * Adds the given vector scaled by the given factor to this instance.\n *\n * @param {Vector3|Vector4} v - The vector.\n * @param {number} s - The factor that scales `v`.\n * @return {Vector3} A reference to this vector.\n */\n addScaledVector(v, s) {\n this.x += v.x * s;\n this.y += v.y * s;\n this.z += v.z * s;\n return this;\n }\n /**\n * Subtracts the given vector from this instance.\n *\n * @param {Vector3} v - The vector to subtract.\n * @return {Vector3} A reference to this vector.\n */\n sub(v) {\n this.x -= v.x;\n this.y -= v.y;\n this.z -= v.z;\n return this;\n }\n /**\n * Subtracts the given scalar value from all components of this instance.\n *\n * @param {number} s - The scalar to subtract.\n * @return {Vector3} A reference to this vector.\n */\n subScalar(s) {\n this.x -= s;\n this.y -= s;\n this.z -= s;\n return this;\n }\n /**\n * Subtracts the given vectors and stores the result in this instance.\n *\n * @param {Vector3} a - The first vector.\n * @param {Vector3} b - The second vector.\n * @return {Vector3} A reference to this vector.\n */\n subVectors(a, b) {\n this.x = a.x - b.x;\n this.y = a.y - b.y;\n this.z = a.z - b.z;\n return this;\n }\n /**\n * Multiplies the given vector with this instance.\n *\n * @param {Vector3} v - The vector to multiply.\n * @return {Vector3} A reference to this vector.\n */\n multiply(v) {\n this.x *= v.x;\n this.y *= v.y;\n this.z *= v.z;\n return this;\n }\n /**\n * Multiplies the given scalar value with all components of this instance.\n *\n * @param {number} scalar - The scalar to multiply.\n * @return {Vector3} A reference to this vector.\n */\n multiplyScalar(scalar) {\n this.x *= scalar;\n this.y *= scalar;\n this.z *= scalar;\n return this;\n }\n /**\n * Multiplies the given vectors and stores the result in this instance.\n *\n * @param {Vector3} a - The first vector.\n * @param {Vector3} b - The second vector.\n * @return {Vector3} A reference to this vector.\n */\n multiplyVectors(a, b) {\n this.x = a.x * b.x;\n this.y = a.y * b.y;\n this.z = a.z * b.z;\n return this;\n }\n /**\n * Applies the given Euler rotation to this vector.\n *\n * @param {Euler} euler - The Euler angles.\n * @return {Vector3} A reference to this vector.\n */\n applyEuler(euler) {\n return this.applyQuaternion(_quaternion$4.setFromEuler(euler));\n }\n /**\n * Applies a rotation specified by an axis and an angle to this vector.\n *\n * @param {Vector3} axis - A normalized vector representing the rotation axis.\n * @param {number} angle - The angle in radians.\n * @return {Vector3} A reference to this vector.\n */\n applyAxisAngle(axis, angle) {\n return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle));\n }\n /**\n * Multiplies this vector with the given 3x3 matrix.\n *\n * @param {Matrix3} m - The 3x3 matrix.\n * @return {Vector3} A reference to this vector.\n */\n applyMatrix3(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n this.x = e[0] * x2 + e[3] * y + e[6] * z;\n this.y = e[1] * x2 + e[4] * y + e[7] * z;\n this.z = e[2] * x2 + e[5] * y + e[8] * z;\n return this;\n }\n /**\n * Multiplies this vector by the given normal matrix and normalizes\n * the result.\n *\n * @param {Matrix3} m - The normal matrix.\n * @return {Vector3} A reference to this vector.\n */\n applyNormalMatrix(m) {\n return this.applyMatrix3(m).normalize();\n }\n /**\n * Multiplies this vector (with an implicit 1 in the 4th dimension) by m, and\n * divides by perspective.\n *\n * @param {Matrix4} m - The matrix to apply.\n * @return {Vector3} A reference to this vector.\n */\n applyMatrix4(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n const w = 1 / (e[3] * x2 + e[7] * y + e[11] * z + e[15]);\n this.x = (e[0] * x2 + e[4] * y + e[8] * z + e[12]) * w;\n this.y = (e[1] * x2 + e[5] * y + e[9] * z + e[13]) * w;\n this.z = (e[2] * x2 + e[6] * y + e[10] * z + e[14]) * w;\n return this;\n }\n /**\n * Applies the given Quaternion to this vector.\n *\n * @param {Quaternion} q - The Quaternion.\n * @return {Vector3} A reference to this vector.\n */\n applyQuaternion(q) {\n const vx = this.x, vy = this.y, vz = this.z;\n const qx = q.x, qy = q.y, qz = q.z, qw = q.w;\n const tx = 2 * (qy * vz - qz * vy);\n const ty = 2 * (qz * vx - qx * vz);\n const tz = 2 * (qx * vy - qy * vx);\n this.x = vx + qw * tx + qy * tz - qz * ty;\n this.y = vy + qw * ty + qz * tx - qx * tz;\n this.z = vz + qw * tz + qx * ty - qy * tx;\n return this;\n }\n /**\n * Projects this vector from world space into the camera\'s normalized\n * device coordinate (NDC) space.\n *\n * @param {Camera} camera - The camera.\n * @return {Vector3} A reference to this vector.\n */\n project(camera) {\n return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);\n }\n /**\n * Unprojects this vector from the camera\'s normalized device coordinate (NDC)\n * space into world space.\n *\n * @param {Camera} camera - The camera.\n * @return {Vector3} A reference to this vector.\n */\n unproject(camera) {\n return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld);\n }\n /**\n * Transforms the direction of this vector by a matrix (the upper left 3 x 3\n * subset of the given 4x4 matrix and then normalizes the result.\n *\n * @param {Matrix4} m - The matrix.\n * @return {Vector3} A reference to this vector.\n */\n transformDirection(m) {\n const x2 = this.x, y = this.y, z = this.z;\n const e = m.elements;\n this.x = e[0] * x2 + e[4] * y + e[8] * z;\n this.y = e[1] * x2 + e[5] * y + e[9] * z;\n this.z = e[2] * x2 + e[6] * y + e[10] * z;\n return this.normalize();\n }\n /**\n * Divides this instance by the given vector.\n *\n * @param {Vector3} v - The vector to divide.\n * @return {Vector3} A reference to this vector.\n */\n divide(v) {\n this.x /= v.x;\n this.y /= v.y;\n this.z /= v.z;\n return this;\n }\n /**\n * Divides this vector by the given scalar.\n *\n * @param {number} scalar - The scalar to divide.\n * @return {Vector3} A reference to this vector.\n */\n divideScalar(scalar) {\n return this.multiplyScalar(1 / scalar);\n }\n /**\n * If this vector\'s x, y or z value is greater than the given vector\'s x, y or z\n * value, replace that value with the corresponding min value.\n *\n * @param {Vector3} v - The vector.\n * @return {Vector3} A reference to this vector.\n */\n min(v) {\n this.x = Math.min(this.x, v.x);\n this.y = Math.min(this.y, v.y);\n this.z = Math.min(this.z, v.z);\n return this;\n }\n /**\n * If this vector\'s x, y or z value is less than the given vector\'s x, y or z\n * value, replace that value with the corresponding max value.\n *\n * @param {Vector3} v - The vector.\n * @return {Vector3} A reference to this vector.\n */\n max(v) {\n this.x = Math.max(this.x, v.x);\n this.y = Math.max(this.y, v.y);\n this.z = Math.max(this.z, v.z);\n return this;\n }\n /**\n * If this vector\'s x, y or z value is greater than the max vector\'s x, y or z\n * value, it is replaced by the corresponding value.\n * If this vector\'s x, y or z value is less than the min vector\'s x, y or z value,\n * it is replaced by the corresponding value.\n *\n * @param {Vector3} min - The minimum x, y and z values.\n * @param {Vector3} max - The maximum x, y and z values in the desired range.\n * @return {Vector3} A reference to this vector.\n */\n clamp(min, max2) {\n this.x = clamp(this.x, min.x, max2.x);\n this.y = clamp(this.y, min.y, max2.y);\n this.z = clamp(this.z, min.z, max2.z);\n return this;\n }\n /**\n * If this vector\'s x, y or z values are greater than the max value, they are\n * replaced by the max value.\n * If this vector\'s x, y or z values are less than the min value, they are\n * replaced by the min value.\n *\n * @param {number} minVal - The minimum value the components will be clamped to.\n * @param {number} maxVal - The maximum value the components will be clamped to.\n * @return {Vector3} A reference to this vector.\n */\n clampScalar(minVal, maxVal) {\n this.x = clamp(this.x, minVal, maxVal);\n this.y = clamp(this.y, minVal, maxVal);\n this.z = clamp(this.z, minVal, maxVal);\n return this;\n }\n /**\n * If this vector\'s length is greater than the max value, it is replaced by\n * the max value.\n * If this vector\'s length is less than the min value, it is replaced by the\n * min value.\n *\n * @param {number} min - The minimum value the vector length will be clamped to.\n * @param {number} max - The maximum value the vector length will be clamped to.\n * @return {Vector3} A reference to this vector.\n */\n clampLength(min, max2) {\n const length = this.length();\n return this.divideScalar(length || 1).multiplyScalar(clamp(length, min, max2));\n }\n /**\n * The components of this vector are rounded down to the nearest integer value.\n *\n * @return {Vector3} A reference to this vector.\n */\n floor() {\n this.x = Math.floor(this.x);\n this.y = Math.floor(this.y);\n this.z = Math.floor(this.z);\n return this;\n }\n /**\n * The components of this vector are rounded up to the nearest integer value.\n *\n * @return {Vector3} A reference to this vector.\n */\n ceil() {\n this.x = Math.ceil(this.x);\n this.y = Math.ceil(this.y);\n this.z = Math.ceil(this.z);\n return this;\n }\n /**\n * The components of this vector are rounded to the nearest integer value\n *\n * @return {Vector3} A reference to this vector.\n */\n round() {\n this.x = Math.round(this.x);\n this.y = Math.round(this.y);\n this.z = Math.round(this.z);\n return this;\n }\n /**\n * The components of this vector are rounded towards zero (up if negative,\n * down if positive) to an integer value.\n *\n * @return {Vector3} A reference to this vector.\n */\n roundToZero() {\n this.x = Math.trunc(this.x);\n this.y = Math.trunc(this.y);\n this.z = Math.trunc(this.z);\n return this;\n }\n /**\n * Inverts this vector - i.e. sets x = -x, y = -y and z = -z.\n *\n * @return {Vector3} A reference to this vector.\n */\n negate() {\n this.x = -this.x;\n this.y = -this.y;\n this.z = -this.z;\n return this;\n }\n /**\n * Calculates the dot product of the given vector with this instance.\n *\n * @param {Vector3} v - The vector to compute the dot product with.\n * @return {number} The result of the dot product.\n */\n dot(v) {\n return this.x * v.x + this.y * v.y + this.z * v.z;\n }\n // TODO lengthSquared?\n /**\n * Computes the square of the Euclidean length (straight-line length) from\n * (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should\n * compare the length squared instead as it is slightly more efficient to calculate.\n *\n * @return {number} The square length of this vector.\n */\n lengthSq() {\n return this.x * this.x + this.y * this.y + this.z * this.z;\n }\n /**\n * Computes the Euclidean length (straight-line length) from (0, 0, 0) to (x, y, z).\n *\n * @return {number} The length of this vector.\n */\n length() {\n return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n }\n /**\n * Computes the Manhattan length of this vector.\n *\n * @return {number} The length of this vector.\n */\n manhattanLength() {\n return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);\n }\n /**\n * Converts this vector to a unit vector - that is, sets it equal to a vector\n * with the same direction as this one, but with a vector length of `1`.\n *\n * @return {Vector3} A reference to this vector.\n */\n normalize() {\n return this.divideScalar(this.length() || 1);\n }\n /**\n * Sets this vector to a vector with the same direction as this one, but\n * with the specified length.\n *\n * @param {number} length - The new length of this vector.\n * @return {Vector3} A reference to this vector.\n */\n setLength(length) {\n return this.normalize().multiplyScalar(length);\n }\n /**\n * Linearly interpolates between the given vector and this instance, where\n * alpha is the percent distance along the line - alpha = 0 will be this\n * vector, and alpha = 1 will be the given one.\n *\n * @param {Vector3} v - The vector to interpolate towards.\n * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.\n * @return {Vector3} A reference to this vector.\n */\n lerp(v, alpha) {\n this.x += (v.x - this.x) * alpha;\n this.y += (v.y - this.y) * alpha;\n this.z += (v.z - this.z) * alpha;\n return this;\n }\n /**\n * Linearly interpolates between the given vectors, where alpha is the percent\n * distance along the line - alpha = 0 will be first vector, and alpha = 1 will\n * be the second one. The result is stored in this instance.\n *\n * @param {Vector3} v1 - The first vector.\n * @param {Vector3} v2 - The second vector.\n * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.\n * @return {Vector3} A reference to this vector.\n */\n lerpVectors(v1, v2, alpha) {\n this.x = v1.x + (v2.x - v1.x) * alpha;\n this.y = v1.y + (v2.y - v1.y) * alpha;\n this.z = v1.z + (v2.z - v1.z) * alpha;\n return this;\n }\n /**\n * Calculates the cross product of the given vector with this instance.\n *\n * @param {Vector3} v - The vector to compute the cross product with.\n * @return {Vector3} The result of the cross product.\n */\n cross(v) {\n return this.crossVectors(this, v);\n }\n /**\n * Calculates the cross product of the given vectors and stores the result\n * in this instance.\n *\n * @param {Vector3} a - The first vector.\n * @param {Vector3} b - The second vector.\n * @return {Vector3} A reference to this vector.\n */\n crossVectors(a, b) {\n const ax = a.x, ay = a.y, az = a.z;\n const bx = b.x, by = b.y, bz = b.z;\n this.x = ay * bz - az * by;\n this.y = az * bx - ax * bz;\n this.z = ax * by - ay * bx;\n return this;\n }\n /**\n * Projects this vector onto the given one.\n *\n * @param {Vector3} v - The vector to project to.\n * @return {Vector3} A reference to this vector.\n */\n projectOnVector(v) {\n const denominator = v.lengthSq();\n if (denominator === 0) return this.set(0, 0, 0);\n const scalar = v.dot(this) / denominator;\n return this.copy(v).multiplyScalar(scalar);\n }\n /**\n * Projects this vector onto a plane by subtracting this\n * vector projected onto the plane\'s normal from this vector.\n *\n * @param {Vector3} planeNormal - The plane normal.\n * @return {Vector3} A reference to this vector.\n */\n projectOnPlane(planeNormal) {\n _vector$c.copy(this).projectOnVector(planeNormal);\n return this.sub(_vector$c);\n }\n /**\n * Reflects this vector off a plane orthogonal to the given normal vector.\n *\n * @param {Vector3} normal - The (normalized) normal vector.\n * @return {Vector3} A reference to this vector.\n */\n reflect(normal) {\n return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)));\n }\n /**\n * Returns the angle between the given vector and this instance in radians.\n *\n * @param {Vector3} v - The vector to compute the angle with.\n * @return {number} The angle in radians.\n */\n angleTo(v) {\n const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());\n if (denominator === 0) return Math.PI / 2;\n const theta = this.dot(v) / denominator;\n return Math.acos(clamp(theta, -1, 1));\n }\n /**\n * Computes the distance from the given vector to this instance.\n *\n * @param {Vector3} v - The vector to compute the distance to.\n * @return {number} The distance.\n */\n distanceTo(v) {\n return Math.sqrt(this.distanceToSquared(v));\n }\n /**\n * Computes the squared distance from the given vector to this instance.\n * If you are just comparing the distance with another distance, you should compare\n * the distance squared instead as it is slightly more efficient to calculate.\n *\n * @param {Vector3} v - The vector to compute the squared distance to.\n * @return {number} The squared distance.\n */\n distanceToSquared(v) {\n const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\n return dx * dx + dy * dy + dz * dz;\n }\n /**\n * Computes the Manhattan distance from the given vector to this instance.\n *\n * @param {Vector3} v - The vector to compute the Manhattan distance to.\n * @return {number} The Manhattan distance.\n */\n manhattanDistanceTo(v) {\n return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);\n }\n /**\n * Sets the vector components from the given spherical coordinates.\n *\n * @param {Spherical} s - The spherical coordinates.\n * @return {Vector3} A reference to this vector.\n */\n setFromSpherical(s) {\n return this.setFromSphericalCoords(s.radius, s.phi, s.theta);\n }\n /**\n * Sets the vector components from the given spherical coordinates.\n *\n * @param {number} radius - The radius.\n * @param {number} phi - The phi angle in radians.\n * @param {number} theta - The theta angle in radians.\n * @return {Vector3} A reference to this vector.\n */\n setFromSphericalCoords(radius, phi, theta) {\n const sinPhiRadius = Math.sin(phi) * radius;\n this.x = sinPhiRadius * Math.sin(theta);\n this.y = Math.cos(phi) * radius;\n this.z = sinPhiRadius * Math.cos(theta);\n return this;\n }\n /**\n * Sets the vector components from the given cylindrical coordinates.\n *\n * @param {Cylindrical} c - The cylindrical coordinates.\n * @return {Vector3} A reference to this vector.\n */\n setFromCylindrical(c) {\n return this.setFromCylindricalCoords(c.radius, c.theta, c.y);\n }\n /**\n * Sets the vector components from the given cylindrical coordinates.\n *\n * @param {number} radius - The radius.\n * @param {number} theta - The theta angle in radians.\n * @param {number} y - The y value.\n * @return {Vector3} A reference to this vector.\n */\n setFromCylindricalCoords(radius, theta, y) {\n this.x = radius * Math.sin(theta);\n this.y = y;\n this.z = radius * Math.cos(theta);\n return this;\n }\n /**\n * Sets the vector components to the position elements of the\n * given transformation matrix.\n *\n * @param {Matrix4} m - The 4x4 matrix.\n * @return {Vector3} A reference to this vector.\n */\n setFromMatrixPosition(m) {\n const e = m.elements;\n this.x = e[12];\n this.y = e[13];\n this.z = e[14];\n return this;\n }\n /**\n * Sets the vector components to the scale elements of the\n * given transformation matrix.\n *\n * @param {Matrix4} m - The 4x4 matrix.\n * @return {Vector3} A reference to this vector.\n */\n setFromMatrixScale(m) {\n const sx = this.setFromMatrixColumn(m, 0).length();\n const sy = this.setFromMatrixColumn(m, 1).length();\n const sz = this.setFromMatrixColumn(m, 2).length();\n this.x = sx;\n this.y = sy;\n this.z = sz;\n return this;\n }\n /**\n * Sets the vector components from the specified matrix column.\n *\n * @param {Matrix4} m - The 4x4 matrix.\n * @param {number} index - The column index.\n * @return {Vector3} A reference to this vector.\n */\n setFromMatrixColumn(m, index) {\n return this.fromArray(m.elements, index * 4);\n }\n /**\n * Sets the vector components from the specified matrix column.\n *\n * @param {Matrix3} m - The 3x3 matrix.\n * @param {number} index - The column index.\n * @return {Vector3} A reference to this vector.\n */\n setFromMatrix3Column(m, index) {\n return this.fromArray(m.elements, index * 3);\n }\n /**\n * Sets the vector components from the given Euler angles.\n *\n * @param {Euler} e - The Euler angles to set.\n * @return {Vector3} A reference to this vector.\n */\n setFromEuler(e) {\n this.x = e._x;\n this.y = e._y;\n this.z = e._z;\n return this;\n }\n /**\n * Sets the vector components from the RGB components of the\n * given color.\n *\n * @param {Color} c - The color to set.\n * @return {Vector3} A reference to this vector.\n */\n setFromColor(c) {\n this.x = c.r;\n this.y = c.g;\n this.z = c.b;\n return this;\n }\n /**\n * Returns `true` if this vector is equal with the given one.\n *\n * @param {Vector3} v - The vector to test for equality.\n * @return {boolean} Whether this vector is equal with the given one.\n */\n equals(v) {\n return v.x === this.x && v.y === this.y && v.z === this.z;\n }\n /**\n * Sets this vector\'s x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`\n * and z value to be `array[ offset + 2 ]`.\n *\n * @param {Array<number>} array - An array holding the vector component values.\n * @param {number} [offset=0] - The offset into the array.\n * @return {Vector3} A reference to this vector.\n */\n fromArray(array, offset = 0) {\n this.x = array[offset];\n this.y = array[offset + 1];\n this.z = array[offset + 2];\n return this;\n }\n /**\n * Writes the components of this vector to the given array. If no array is provided,\n * the method returns a new instance.\n *\n * @param {Array<number>} [array=[]] - The target array holding the vector components.\n * @param {number} [offset=0] - Index of the first element in the array.\n * @return {Array<number>} The vector components.\n */\n toArray(array = [], offset = 0) {\n array[offset] = this.x;\n array[offset + 1] = this.y;\n array[offset + 2] = this.z;\n return array;\n }\n /**\n * Sets the components of this vector from the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - The buffer attribute holding vector data.\n * @param {number} index - The index into the attribute.\n * @return {Vector3} A reference to this vector.\n */\n fromBufferAttribute(attribute, index) {\n this.x = attribute.getX(index);\n this.y = attribute.getY(index);\n this.z = attribute.getZ(index);\n return this;\n }\n /**\n * Sets each component of this vector to a pseudo-random value between `0` and\n * `1`, excluding `1`.\n *\n * @return {Vector3} A reference to this vector.\n */\n random() {\n this.x = Math.random();\n this.y = Math.random();\n this.z = Math.random();\n return this;\n }\n /**\n * Sets this vector to a uniformly random point on a unit sphere.\n *\n * @return {Vector3} A reference to this vector.\n */\n randomDirection() {\n const theta = Math.random() * Math.PI * 2;\n const u = Math.random() * 2 - 1;\n const c = Math.sqrt(1 - u * u);\n this.x = c * Math.cos(theta);\n this.y = u;\n this.z = c * Math.sin(theta);\n return this;\n }\n *[Symbol.iterator]() {\n yield this.x;\n yield this.y;\n yield this.z;\n }\n }\n const _vector$c = /* @__PURE__ */ new Vector3();\n const _quaternion$4 = /* @__PURE__ */ new Quaternion();\n class Matrix3 {\n /**\n * Constructs a new 3x3 matrix. The arguments are supposed to be\n * in row-major order. If no arguments are provided, the constructor\n * initializes the matrix as an identity matrix.\n *\n * @param {number} [n11] - 1-1 matrix element.\n * @param {number} [n12] - 1-2 matrix element.\n * @param {number} [n13] - 1-3 matrix element.\n * @param {number} [n21] - 2-1 matrix element.\n * @param {number} [n22] - 2-2 matrix element.\n * @param {number} [n23] - 2-3 matrix element.\n * @param {number} [n31] - 3-1 matrix element.\n * @param {number} [n32] - 3-2 matrix element.\n * @param {number} [n33] - 3-3 matrix element.\n */\n constructor(n11, n12, n13, n21, n22, n23, n31, n32, n33) {\n Matrix3.prototype.isMatrix3 = true;\n this.elements = [\n 1,\n 0,\n 0,\n 0,\n 1,\n 0,\n 0,\n 0,\n 1\n ];\n if (n11 !== void 0) {\n this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);\n }\n }\n /**\n * Sets the elements of the matrix.The arguments are supposed to be\n * in row-major order.\n *\n * @param {number} [n11] - 1-1 matrix element.\n * @param {number} [n12] - 1-2 matrix element.\n * @param {number} [n13] - 1-3 matrix element.\n * @param {number} [n21] - 2-1 matrix element.\n * @param {number} [n22] - 2-2 matrix element.\n * @param {number} [n23] - 2-3 matrix element.\n * @param {number} [n31] - 3-1 matrix element.\n * @param {number} [n32] - 3-2 matrix element.\n * @param {number} [n33] - 3-3 matrix element.\n * @return {Matrix3} A reference to this matrix.\n */\n set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {\n const te = this.elements;\n te[0] = n11;\n te[1] = n21;\n te[2] = n31;\n te[3] = n12;\n te[4] = n22;\n te[5] = n32;\n te[6] = n13;\n te[7] = n23;\n te[8] = n33;\n return this;\n }\n /**\n * Sets this matrix to the 3x3 identity matrix.\n *\n * @return {Matrix3} A reference to this matrix.\n */\n identity() {\n this.set(\n 1,\n 0,\n 0,\n 0,\n 1,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n /**\n * Copies the values of the given matrix to this instance.\n *\n * @param {Matrix3} m - The matrix to copy.\n * @return {Matrix3} A reference to this matrix.\n */\n copy(m) {\n const te = this.elements;\n const me = m.elements;\n te[0] = me[0];\n te[1] = me[1];\n te[2] = me[2];\n te[3] = me[3];\n te[4] = me[4];\n te[5] = me[5];\n te[6] = me[6];\n te[7] = me[7];\n te[8] = me[8];\n return this;\n }\n /**\n * Extracts the basis of this matrix into the three axis vectors provided.\n *\n * @param {Vector3} xAxis - The basis\'s x axis.\n * @param {Vector3} yAxis - The basis\'s y axis.\n * @param {Vector3} zAxis - The basis\'s z axis.\n * @return {Matrix3} A reference to this matrix.\n */\n extractBasis(xAxis, yAxis, zAxis) {\n xAxis.setFromMatrix3Column(this, 0);\n yAxis.setFromMatrix3Column(this, 1);\n zAxis.setFromMatrix3Column(this, 2);\n return this;\n }\n /**\n * Set this matrix to the upper 3x3 matrix of the given 4x4 matrix.\n *\n * @param {Matrix4} m - The 4x4 matrix.\n * @return {Matrix3} A reference to this matrix.\n */\n setFromMatrix4(m) {\n const me = m.elements;\n this.set(\n me[0],\n me[4],\n me[8],\n me[1],\n me[5],\n me[9],\n me[2],\n me[6],\n me[10]\n );\n return this;\n }\n /**\n * Post-multiplies this matrix by the given 3x3 matrix.\n *\n * @param {Matrix3} m - The matrix to multiply with.\n * @return {Matrix3} A reference to this matrix.\n */\n multiply(m) {\n return this.multiplyMatrices(this, m);\n }\n /**\n * Pre-multiplies this matrix by the given 3x3 matrix.\n *\n * @param {Matrix3} m - The matrix to multiply with.\n * @return {Matrix3} A reference to this matrix.\n */\n premultiply(m) {\n return this.multiplyMatrices(m, this);\n }\n /**\n * Multiples the given 3x3 matrices and stores the result\n * in this matrix.\n *\n * @param {Matrix3} a - The first matrix.\n * @param {Matrix3} b - The second matrix.\n * @return {Matrix3} A reference to this matrix.\n */\n multiplyMatrices(a, b) {\n const ae = a.elements;\n const be = b.elements;\n const te = this.elements;\n const a11 = ae[0], a12 = ae[3], a13 = ae[6];\n const a21 = ae[1], a22 = ae[4], a23 = ae[7];\n const a31 = ae[2], a32 = ae[5], a33 = ae[8];\n const b11 = be[0], b12 = be[3], b13 = be[6];\n const b21 = be[1], b22 = be[4], b23 = be[7];\n const b31 = be[2], b32 = be[5], b33 = be[8];\n te[0] = a11 * b11 + a12 * b21 + a13 * b31;\n te[3] = a11 * b12 + a12 * b22 + a13 * b32;\n te[6] = a11 * b13 + a12 * b23 + a13 * b33;\n te[1] = a21 * b11 + a22 * b21 + a23 * b31;\n te[4] = a21 * b12 + a22 * b22 + a23 * b32;\n te[7] = a21 * b13 + a22 * b23 + a23 * b33;\n te[2] = a31 * b11 + a32 * b21 + a33 * b31;\n te[5] = a31 * b12 + a32 * b22 + a33 * b32;\n te[8] = a31 * b13 + a32 * b23 + a33 * b33;\n return this;\n }\n /**\n * Multiplies every component of the matrix by the given scalar.\n *\n * @param {number} s - The scalar.\n * @return {Matrix3} A reference to this matrix.\n */\n multiplyScalar(s) {\n const te = this.elements;\n te[0] *= s;\n te[3] *= s;\n te[6] *= s;\n te[1] *= s;\n te[4] *= s;\n te[7] *= s;\n te[2] *= s;\n te[5] *= s;\n te[8] *= s;\n return this;\n }\n /**\n * Computes and returns the determinant of this matrix.\n *\n * @return {number} The determinant.\n */\n determinant() {\n const te = this.elements;\n const a = te[0], b = te[1], c = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i2 = te[8];\n return a * e * i2 - a * f * h - b * d * i2 + b * f * g + c * d * h - c * e * g;\n }\n /**\n * Inverts this matrix, using the [analytic method]{@link https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution}.\n * You can not invert with a determinant of zero. If you attempt this, the method produces\n * a zero matrix instead.\n *\n * @return {Matrix3} A reference to this matrix.\n */\n invert() {\n const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13;\n if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);\n const detInv = 1 / det;\n te[0] = t11 * detInv;\n te[1] = (n31 * n23 - n33 * n21) * detInv;\n te[2] = (n32 * n21 - n31 * n22) * detInv;\n te[3] = t12 * detInv;\n te[4] = (n33 * n11 - n31 * n13) * detInv;\n te[5] = (n31 * n12 - n32 * n11) * detInv;\n te[6] = t13 * detInv;\n te[7] = (n21 * n13 - n23 * n11) * detInv;\n te[8] = (n22 * n11 - n21 * n12) * detInv;\n return this;\n }\n /**\n * Transposes this matrix in place.\n *\n * @return {Matrix3} A reference to this matrix.\n */\n transpose() {\n let tmp;\n const m = this.elements;\n tmp = m[1];\n m[1] = m[3];\n m[3] = tmp;\n tmp = m[2];\n m[2] = m[6];\n m[6] = tmp;\n tmp = m[5];\n m[5] = m[7];\n m[7] = tmp;\n return this;\n }\n /**\n * Computes the normal matrix which is the inverse transpose of the upper\n * left 3x3 portion of the given 4x4 matrix.\n *\n * @param {Matrix4} matrix4 - The 4x4 matrix.\n * @return {Matrix3} A reference to this matrix.\n */\n getNormalMatrix(matrix4) {\n return this.setFromMatrix4(matrix4).invert().transpose();\n }\n /**\n * Transposes this matrix into the supplied array, and returns itself unchanged.\n *\n * @param {Array<number>} r - An array to store the transposed matrix elements.\n * @return {Matrix3} A reference to this matrix.\n */\n transposeIntoArray(r) {\n const m = this.elements;\n r[0] = m[0];\n r[1] = m[3];\n r[2] = m[6];\n r[3] = m[1];\n r[4] = m[4];\n r[5] = m[7];\n r[6] = m[2];\n r[7] = m[5];\n r[8] = m[8];\n return this;\n }\n /**\n * Sets the UV transform matrix from offset, repeat, rotation, and center.\n *\n * @param {number} tx - Offset x.\n * @param {number} ty - Offset y.\n * @param {number} sx - Repeat x.\n * @param {number} sy - Repeat y.\n * @param {number} rotation - Rotation, in radians. Positive values rotate counterclockwise.\n * @param {number} cx - Center x of rotation.\n * @param {number} cy - Center y of rotation\n * @return {Matrix3} A reference to this matrix.\n */\n setUvTransform(tx, ty, sx, sy, rotation, cx, cy) {\n const c = Math.cos(rotation);\n const s = Math.sin(rotation);\n this.set(\n sx * c,\n sx * s,\n -sx * (c * cx + s * cy) + cx + tx,\n -sy * s,\n sy * c,\n -sy * (-s * cx + c * cy) + cy + ty,\n 0,\n 0,\n 1\n );\n return this;\n }\n /**\n * Scales this matrix with the given scalar values.\n *\n * @param {number} sx - The amount to scale in the X axis.\n * @param {number} sy - The amount to scale in the Y axis.\n * @return {Matrix3} A reference to this matrix.\n */\n scale(sx, sy) {\n this.premultiply(_m3.makeScale(sx, sy));\n return this;\n }\n /**\n * Rotates this matrix by the given angle.\n *\n * @param {number} theta - The rotation in radians.\n * @return {Matrix3} A reference to this matrix.\n */\n rotate(theta) {\n this.premultiply(_m3.makeRotation(-theta));\n return this;\n }\n /**\n * Translates this matrix by the given scalar values.\n *\n * @param {number} tx - The amount to translate in the X axis.\n * @param {number} ty - The amount to translate in the Y axis.\n * @return {Matrix3} A reference to this matrix.\n */\n translate(tx, ty) {\n this.premultiply(_m3.makeTranslation(tx, ty));\n return this;\n }\n // for 2D Transforms\n /**\n * Sets this matrix as a 2D translation transform.\n *\n * @param {number|Vector2} x - The amount to translate in the X axis or alternatively a translation vector.\n * @param {number} y - The amount to translate in the Y axis.\n * @return {Matrix3} A reference to this matrix.\n */\n makeTranslation(x2, y) {\n if (x2.isVector2) {\n this.set(\n 1,\n 0,\n x2.x,\n 0,\n 1,\n x2.y,\n 0,\n 0,\n 1\n );\n } else {\n this.set(\n 1,\n 0,\n x2,\n 0,\n 1,\n y,\n 0,\n 0,\n 1\n );\n }\n return this;\n }\n /**\n * Sets this matrix as a 2D rotational transformation.\n *\n * @param {number} theta - The rotation in radians.\n * @return {Matrix3} A reference to this matrix.\n */\n makeRotation(theta) {\n const c = Math.cos(theta);\n const s = Math.sin(theta);\n this.set(\n c,\n -s,\n 0,\n s,\n c,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n /**\n * Sets this matrix as a 2D scale transform.\n *\n * @param {number} x - The amount to scale in the X axis.\n * @param {number} y - The amount to scale in the Y axis.\n * @return {Matrix3} A reference to this matrix.\n */\n makeScale(x2, y) {\n this.set(\n x2,\n 0,\n 0,\n 0,\n y,\n 0,\n 0,\n 0,\n 1\n );\n return this;\n }\n /**\n * Returns `true` if this matrix is equal with the given one.\n *\n * @param {Matrix3} matrix - The matrix to test for equality.\n * @return {boolean} Whether this matrix is equal with the given one.\n */\n equals(matrix) {\n const te = this.elements;\n const me = matrix.elements;\n for (let i2 = 0; i2 < 9; i2++) {\n if (te[i2] !== me[i2]) return false;\n }\n return true;\n }\n /**\n * Sets the elements of the matrix from the given array.\n *\n * @param {Array<number>} array - The matrix elements in column-major order.\n * @param {number} [offset=0] - Index of the first element in the array.\n * @return {Matrix3} A reference to this matrix.\n */\n fromArray(array, offset = 0) {\n for (let i2 = 0; i2 < 9; i2++) {\n this.elements[i2] = array[i2 + offset];\n }\n return this;\n }\n /**\n * Writes the elements of this matrix to the given array. If no array is provided,\n * the method returns a new instance.\n *\n * @param {Array<number>} [array=[]] - The target array holding the matrix elements in column-major order.\n * @param {number} [offset=0] - Index of the first element in the array.\n * @return {Array<number>} The matrix elements in column-major order.\n */\n toArray(array = [], offset = 0) {\n const te = this.elements;\n array[offset] = te[0];\n array[offset + 1] = te[1];\n array[offset + 2] = te[2];\n array[offset + 3] = te[3];\n array[offset + 4] = te[4];\n array[offset + 5] = te[5];\n array[offset + 6] = te[6];\n array[offset + 7] = te[7];\n array[offset + 8] = te[8];\n return array;\n }\n /**\n * Returns a matrix with copied values from this instance.\n *\n * @return {Matrix3} A clone of this instance.\n */\n clone() {\n return new this.constructor().fromArray(this.elements);\n }\n }\n const _m3 = /* @__PURE__ */ new Matrix3();\n const _cache = {};\n function warnOnce(message) {\n if (message in _cache) return;\n _cache[message] = true;\n console.warn(message);\n }\n const LINEAR_REC709_TO_XYZ = /* @__PURE__ */ new Matrix3().set(\n 0.4123908,\n 0.3575843,\n 0.1804808,\n 0.212639,\n 0.7151687,\n 0.0721923,\n 0.0193308,\n 0.1191948,\n 0.9505322\n );\n const XYZ_TO_LINEAR_REC709 = /* @__PURE__ */ new Matrix3().set(\n 3.2409699,\n -1.5373832,\n -0.4986108,\n -0.9692436,\n 1.8759675,\n 0.0415551,\n 0.0556301,\n -0.203977,\n 1.0569715\n );\n function createColorManagement() {\n const ColorManagement2 = {\n enabled: true,\n workingColorSpace: LinearSRGBColorSpace,\n /**\n * Implementations of supported color spaces.\n *\n * Required:\n * - primaries: chromaticity coordinates [ rx ry gx gy bx by ]\n * - whitePoint: reference white [ x y ]\n * - transfer: transfer function (pre-defined)\n * - toXYZ: Matrix3 RGB to XYZ transform\n * - fromXYZ: Matrix3 XYZ to RGB transform\n * - luminanceCoefficients: RGB luminance coefficients\n *\n * Optional:\n * - outputColorSpaceConfig: { drawingBufferColorSpace: ColorSpace }\n * - workingColorSpaceConfig: { unpackColorSpace: ColorSpace }\n *\n * Reference:\n * - https://www.russellcottrell.com/photo/matrixCalculator.htm\n */\n spaces: {},\n convert: function(color, sourceColorSpace, targetColorSpace) {\n if (this.enabled === false || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) {\n return color;\n }\n if (this.spaces[sourceColorSpace].transfer === SRGBTransfer) {\n color.r = SRGBToLinear(color.r);\n color.g = SRGBToLinear(color.g);\n color.b = SRGBToLinear(color.b);\n }\n if (this.spaces[sourceColorSpace].primaries !== this.spaces[targetColorSpace].primaries) {\n color.applyMatrix3(this.spaces[sourceColorSpace].toXYZ);\n color.applyMatrix3(this.spaces[targetColorSpace].fromXYZ);\n }\n if (this.spaces[targetColorSpace].transfer === SRGBTransfer) {\n color.r = LinearToSRGB(color.r);\n color.g = LinearToSRGB(color.g);\n color.b = LinearToSRGB(color.b);\n }\n return color;\n },\n workingToColorSpace: function(color, targetColorSpace) {\n return this.convert(color, this.workingColorSpace, targetColorSpace);\n },\n colorSpaceToWorking: function(color, sourceColorSpace) {\n return this.convert(color, sourceColorSpace, this.workingColorSpace);\n },\n getPrimaries: function(colorSpace) {\n return this.spaces[colorSpace].primaries;\n },\n getTransfer: function(colorSpace) {\n if (colorSpace === NoColorSpace) return LinearTransfer;\n return this.spaces[colorSpace].transfer;\n },\n getLuminanceCoefficients: function(target, colorSpace = this.workingColorSpace) {\n return target.fromArray(this.spaces[colorSpace].luminanceCoefficients);\n },\n define: function(colorSpaces) {\n Object.assign(this.spaces, colorSpaces);\n },\n // Internal APIs\n _getMatrix: function(targetMatrix, sourceColorSpace, targetColorSpace) {\n return targetMatrix.copy(this.spaces[sourceColorSpace].toXYZ).multiply(this.spaces[targetColorSpace].fromXYZ);\n },\n _getDrawingBufferColorSpace: function(colorSpace) {\n return this.spaces[colorSpace].outputColorSpaceConfig.drawingBufferColorSpace;\n },\n _getUnpackColorSpace: function(colorSpace = this.workingColorSpace) {\n return this.spaces[colorSpace].workingColorSpaceConfig.unpackColorSpace;\n },\n // Deprecated\n fromWorkingColorSpace: function(color, targetColorSpace) {\n warnOnce("THREE.ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().");\n return ColorManagement2.workingToColorSpace(color, targetColorSpace);\n },\n toWorkingColorSpace: function(color, sourceColorSpace) {\n warnOnce("THREE.ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().");\n return ColorManagement2.colorSpaceToWorking(color, sourceColorSpace);\n }\n };\n const REC709_PRIMARIES = [0.64, 0.33, 0.3, 0.6, 0.15, 0.06];\n const REC709_LUMINANCE_COEFFICIENTS = [0.2126, 0.7152, 0.0722];\n const D65 = [0.3127, 0.329];\n ColorManagement2.define({\n [LinearSRGBColorSpace]: {\n primaries: REC709_PRIMARIES,\n whitePoint: D65,\n transfer: LinearTransfer,\n toXYZ: LINEAR_REC709_TO_XYZ,\n fromXYZ: XYZ_TO_LINEAR_REC709,\n luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,\n workingColorSpaceConfig: { unpackColorSpace: SRGBColorSpace },\n outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }\n },\n [SRGBColorSpace]: {\n primaries: REC709_PRIMARIES,\n whitePoint: D65,\n transfer: SRGBTransfer,\n toXYZ: LINEAR_REC709_TO_XYZ,\n fromXYZ: XYZ_TO_LINEAR_REC709,\n luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,\n outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }\n }\n });\n return ColorManagement2;\n }\n const ColorManagement = /* @__PURE__ */ createColorManagement();\n function SRGBToLinear(c) {\n return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);\n }\n function LinearToSRGB(c) {\n return c < 31308e-7 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055;\n }\n class Box3 {\n /**\n * Constructs a new bounding box.\n *\n * @param {Vector3} [min=(Infinity,Infinity,Infinity)] - A vector representing the lower boundary of the box.\n * @param {Vector3} [max=(-Infinity,-Infinity,-Infinity)] - A vector representing the upper boundary of the box.\n */\n constructor(min = new Vector3(Infinity, Infinity, Infinity), max2 = new Vector3(-Infinity, -Infinity, -Infinity)) {\n this.isBox3 = true;\n this.min = min;\n this.max = max2;\n }\n /**\n * Sets the lower and upper boundaries of this box.\n * Please note that this method only copies the values from the given objects.\n *\n * @param {Vector3} min - The lower boundary of the box.\n * @param {Vector3} max - The upper boundary of the box.\n * @return {Box3} A reference to this bounding box.\n */\n set(min, max2) {\n this.min.copy(min);\n this.max.copy(max2);\n return this;\n }\n /**\n * Sets the upper and lower bounds of this box so it encloses the position data\n * in the given array.\n *\n * @param {Array<number>} array - An array holding 3D position data.\n * @return {Box3} A reference to this bounding box.\n */\n setFromArray(array) {\n this.makeEmpty();\n for (let i2 = 0, il = array.length; i2 < il; i2 += 3) {\n this.expandByPoint(_vector$b.fromArray(array, i2));\n }\n return this;\n }\n /**\n * Sets the upper and lower bounds of this box so it encloses the position data\n * in the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - A buffer attribute holding 3D position data.\n * @return {Box3} A reference to this bounding box.\n */\n setFromBufferAttribute(attribute) {\n this.makeEmpty();\n for (let i2 = 0, il = attribute.count; i2 < il; i2++) {\n this.expandByPoint(_vector$b.fromBufferAttribute(attribute, i2));\n }\n return this;\n }\n /**\n * Sets the upper and lower bounds of this box so it encloses the position data\n * in the given array.\n *\n * @param {Array<Vector3>} points - An array holding 3D position data as instances of {@link Vector3}.\n * @return {Box3} A reference to this bounding box.\n */\n setFromPoints(points) {\n this.makeEmpty();\n for (let i2 = 0, il = points.length; i2 < il; i2++) {\n this.expandByPoint(points[i2]);\n }\n return this;\n }\n /**\n * Centers this box on the given center vector and sets this box\'s width, height and\n * depth to the given size values.\n *\n * @param {Vector3} center - The center of the box.\n * @param {Vector3} size - The x, y and z dimensions of the box.\n * @return {Box3} A reference to this bounding box.\n */\n setFromCenterAndSize(center, size) {\n const halfSize = _vector$b.copy(size).multiplyScalar(0.5);\n this.min.copy(center).sub(halfSize);\n this.max.copy(center).add(halfSize);\n return this;\n }\n /**\n * Computes the world-axis-aligned bounding box for the given 3D object\n * (including its children), accounting for the object\'s, and children\'s,\n * world transforms. The function may result in a larger box than strictly necessary.\n *\n * @param {Object3D} object - The 3D object to compute the bounding box for.\n * @param {boolean} [precise=false] - If set to `true`, the method computes the smallest\n * world-axis-aligned bounding box at the expense of more computation.\n * @return {Box3} A reference to this bounding box.\n */\n setFromObject(object, precise = false) {\n this.makeEmpty();\n return this.expandByObject(object, precise);\n }\n /**\n * Returns a new box with copied values from this instance.\n *\n * @return {Box3} A clone of this instance.\n */\n clone() {\n return new this.constructor().copy(this);\n }\n /**\n * Copies the values of the given box to this instance.\n *\n * @param {Box3} box - The box to copy.\n * @return {Box3} A reference to this bounding box.\n */\n copy(box) {\n this.min.copy(box.min);\n this.max.copy(box.max);\n return this;\n }\n /**\n * Makes this box empty which means in encloses a zero space in 3D.\n *\n * @return {Box3} A reference to this bounding box.\n */\n makeEmpty() {\n this.min.x = this.min.y = this.min.z = Infinity;\n this.max.x = this.max.y = this.max.z = -Infinity;\n return this;\n }\n /**\n * Returns true if this box includes zero points within its bounds.\n * Note that a box with equal lower and upper bounds still includes one\n * point, the one both bounds share.\n *\n * @return {boolean} Whether this box is empty or not.\n */\n isEmpty() {\n return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z;\n }\n /**\n * Returns the center point of this box.\n *\n * @param {Vector3} target - The target vector that is used to store the method\'s result.\n * @return {Vector3} The center point.\n */\n getCenter(target) {\n return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);\n }\n /**\n * Returns the dimensions of this box.\n *\n * @param {Vector3} target - The target vector that is used to store the method\'s result.\n * @return {Vector3} The size.\n */\n getSize(target) {\n return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min);\n }\n /**\n * Expands the boundaries of this box to include the given point.\n *\n * @param {Vector3} point - The point that should be included by the bounding box.\n * @return {Box3} A reference to this bounding box.\n */\n expandByPoint(point) {\n this.min.min(point);\n this.max.max(point);\n return this;\n }\n /**\n * Expands this box equilaterally by the given vector. The width of this\n * box will be expanded by the x component of the vector in both\n * directions. The height of this box will be expanded by the y component of\n * the vector in both directions. The depth of this box will be\n * expanded by the z component of the vector in both directions.\n *\n * @param {Vector3} vector - The vector that should expand the bounding box.\n * @return {Box3} A reference to this bounding box.\n */\n expandByVector(vector) {\n this.min.sub(vector);\n this.max.add(vector);\n return this;\n }\n /**\n * Expands each dimension of the box by the given scalar. If negative, the\n * dimensions of the box will be contracted.\n *\n * @param {number} scalar - The scalar value that should expand the bounding box.\n * @return {Box3} A reference to this bounding box.\n */\n expandByScalar(scalar) {\n this.min.addScalar(-scalar);\n this.max.addScalar(scalar);\n return this;\n }\n /**\n * Expands the boundaries of this box to include the given 3D object and\n * its children, accounting for the object\'s, and children\'s, world\n * transforms. The function may result in a larger box than strictly\n * necessary (unless the precise parameter is set to true).\n *\n * @param {Object3D} object - The 3D object that should expand the bounding box.\n * @param {boolean} precise - If set to `true`, the method expands the bounding box\n * as little as necessary at the expense of more computation.\n * @return {Box3} A reference to this bounding box.\n */\n expandByObject(object, precise = false) {\n object.updateWorldMatrix(false, false);\n const geometry = object.geometry;\n if (geometry !== void 0) {\n const positionAttribute = geometry.getAttribute("position");\n if (precise === true && positionAttribute !== void 0 && object.isInstancedMesh !== true) {\n for (let i2 = 0, l = positionAttribute.count; i2 < l; i2++) {\n if (object.isMesh === true) {\n object.getVertexPosition(i2, _vector$b);\n } else {\n _vector$b.fromBufferAttribute(positionAttribute, i2);\n }\n _vector$b.applyMatrix4(object.matrixWorld);\n this.expandByPoint(_vector$b);\n }\n } else {\n if (object.boundingBox !== void 0) {\n if (object.boundingBox === null) {\n object.computeBoundingBox();\n }\n _box$4.copy(object.boundingBox);\n } else {\n if (geometry.boundingBox === null) {\n geometry.computeBoundingBox();\n }\n _box$4.copy(geometry.boundingBox);\n }\n _box$4.applyMatrix4(object.matrixWorld);\n this.union(_box$4);\n }\n }\n const children = object.children;\n for (let i2 = 0, l = children.length; i2 < l; i2++) {\n this.expandByObject(children[i2], precise);\n }\n return this;\n }\n /**\n * Returns `true` if the given point lies within or on the boundaries of this box.\n *\n * @param {Vector3} point - The point to test.\n * @return {boolean} Whether the bounding box contains the given point or not.\n */\n containsPoint(point) {\n return point.x >= this.min.x && point.x <= this.max.x && point.y >= this.min.y && point.y <= this.max.y && point.z >= this.min.z && point.z <= this.max.z;\n }\n /**\n * Returns `true` if this bounding box includes the entirety of the given bounding box.\n * If this box and the given one are identical, this function also returns `true`.\n *\n * @param {Box3} box - The bounding box to test.\n * @return {boolean} Whether the bounding box contains the given bounding box or not.\n */\n containsBox(box) {\n return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z;\n }\n /**\n * Returns a point as a proportion of this box\'s width, height and depth.\n *\n * @param {Vector3} point - A point in 3D space.\n * @param {Vector3} target - The target vector that is used to store the method\'s result.\n * @return {Vector3} A point as a proportion of this box\'s width, height and depth.\n */\n getParameter(point, target) {\n return target.set(\n (point.x - this.min.x) / (this.max.x - this.min.x),\n (point.y - this.min.y) / (this.max.y - this.min.y),\n (point.z - this.min.z) / (this.max.z - this.min.z)\n );\n }\n /**\n * Returns `true` if the given bounding box intersects with this bounding box.\n *\n * @param {Box3} box - The bounding box to test.\n * @return {boolean} Whether the given bounding box intersects with this bounding box.\n */\n intersectsBox(box) {\n return box.max.x >= this.min.x && box.min.x <= this.max.x && box.max.y >= this.min.y && box.min.y <= this.max.y && box.max.z >= this.min.z && box.min.z <= this.max.z;\n }\n /**\n * Returns `true` if the given bounding sphere intersects with this bounding box.\n *\n * @param {Sphere} sphere - The bounding sphere to test.\n * @return {boolean} Whether the given bounding sphere intersects with this bounding box.\n */\n intersectsSphere(sphere) {\n this.clampPoint(sphere.center, _vector$b);\n return _vector$b.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;\n }\n /**\n * Returns `true` if the given plane intersects with this bounding box.\n *\n * @param {Plane} plane - The plane to test.\n * @return {boolean} Whether the given plane intersects with this bounding box.\n */\n intersectsPlane(plane) {\n let min, max2;\n if (plane.normal.x > 0) {\n min = plane.normal.x * this.min.x;\n max2 = plane.normal.x * this.max.x;\n } else {\n min = plane.normal.x * this.max.x;\n max2 = plane.normal.x * this.min.x;\n }\n if (plane.normal.y > 0) {\n min += plane.normal.y * this.min.y;\n max2 += plane.normal.y * this.max.y;\n } else {\n min += plane.normal.y * this.max.y;\n max2 += plane.normal.y * this.min.y;\n }\n if (plane.normal.z > 0) {\n min += plane.normal.z * this.min.z;\n max2 += plane.normal.z * this.max.z;\n } else {\n min += plane.normal.z * this.max.z;\n max2 += plane.normal.z * this.min.z;\n }\n return min <= -plane.constant && max2 >= -plane.constant;\n }\n /**\n * Returns `true` if the given triangle intersects with this bounding box.\n *\n * @param {Triangle} triangle - The triangle to test.\n * @return {boolean} Whether the given triangle intersects with this bounding box.\n */\n intersectsTriangle(triangle) {\n if (this.isEmpty()) {\n return false;\n }\n this.getCenter(_center);\n _extents.subVectors(this.max, _center);\n _v0$2.subVectors(triangle.a, _center);\n _v1$7.subVectors(triangle.b, _center);\n _v2$4.subVectors(triangle.c, _center);\n _f0.subVectors(_v1$7, _v0$2);\n _f1.subVectors(_v2$4, _v1$7);\n _f2.subVectors(_v0$2, _v2$4);\n let axes = [\n 0,\n -_f0.z,\n _f0.y,\n 0,\n -_f1.z,\n _f1.y,\n 0,\n -_f2.z,\n _f2.y,\n _f0.z,\n 0,\n -_f0.x,\n _f1.z,\n 0,\n -_f1.x,\n _f2.z,\n 0,\n -_f2.x,\n -_f0.y,\n _f0.x,\n 0,\n -_f1.y,\n _f1.x,\n 0,\n -_f2.y,\n _f2.x,\n 0\n ];\n if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {\n return false;\n }\n axes = [1, 0, 0, 0, 1, 0, 0, 0, 1];\n if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {\n return false;\n }\n _triangleNormal.crossVectors(_f0, _f1);\n axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z];\n return satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents);\n }\n /**\n * Clamps the given point within the bounds of this box.\n *\n * @param {Vector3} point - The point to clamp.\n * @param {Vector3} target - The target vector that is used to store the method\'s result.\n * @return {Vector3} The clamped point.\n */\n clampPoint(point, target) {\n return target.copy(point).clamp(this.min, this.max);\n }\n /**\n * Returns the euclidean distance from any edge of this box to the specified point. If\n * the given point lies inside of this box, the distance will be `0`.\n *\n * @param {Vector3} point - The point to compute the distance to.\n * @return {number} The euclidean distance.\n */\n distanceToPoint(point) {\n return this.clampPoint(point, _vector$b).distanceTo(point);\n }\n /**\n * Returns a bounding sphere that encloses this bounding box.\n *\n * @param {Sphere} target - The target sphere that is used to store the method\'s result.\n * @return {Sphere} The bounding sphere that encloses this bounding box.\n */\n getBoundingSphere(target) {\n if (this.isEmpty()) {\n target.makeEmpty();\n } else {\n this.getCenter(target.center);\n target.radius = this.getSize(_vector$b).length() * 0.5;\n }\n return target;\n }\n /**\n * Computes the intersection of this bounding box and the given one, setting the upper\n * bound of this box to the lesser of the two boxes\' upper bounds and the\n * lower bound of this box to the greater of the two boxes\' lower bounds. If\n * there\'s no overlap, makes this box empty.\n *\n * @param {Box3} box - The bounding box to intersect with.\n * @return {Box3} A reference to this bounding box.\n */\n intersect(box) {\n this.min.max(box.min);\n this.max.min(box.max);\n if (this.isEmpty()) this.makeEmpty();\n return this;\n }\n /**\n * Computes the union of this box and another and the given one, setting the upper\n * bound of this box to the greater of the two boxes\' upper bounds and the\n * lower bound of this box to the lesser of the two boxes\' lower bounds.\n *\n * @param {Box3} box - The bounding box that will be unioned with this instance.\n * @return {Box3} A reference to this bounding box.\n */\n union(box) {\n this.min.min(box.min);\n this.max.max(box.max);\n return this;\n }\n /**\n * Transforms this bounding box by the given 4x4 transformation matrix.\n *\n * @param {Matrix4} matrix - The transformation matrix.\n * @return {Box3} A reference to this bounding box.\n */\n applyMatrix4(matrix) {\n if (this.isEmpty()) return this;\n _points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix);\n _points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix);\n _points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix);\n _points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix);\n _points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix);\n _points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix);\n _points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix);\n _points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix);\n this.setFromPoints(_points);\n return this;\n }\n /**\n * Adds the given offset to both the upper and lower bounds of this bounding box,\n * effectively moving it in 3D space.\n *\n * @param {Vector3} offset - The offset that should be used to translate the bounding box.\n * @return {Box3} A reference to this bounding box.\n */\n translate(offset) {\n this.min.add(offset);\n this.max.add(offset);\n return this;\n }\n /**\n * Returns `true` if this bounding box is equal with the given one.\n *\n * @param {Box3} box - The box to test for equality.\n * @return {boolean} Whether this bounding box is equal with the given one.\n */\n equals(box) {\n return box.min.equals(this.min) && box.max.equals(this.max);\n }\n /**\n * Returns a serialized structure of the bounding box.\n *\n * @return {Object} Serialized structure with fields representing the object state.\n */\n toJSON() {\n return {\n min: this.min.toArray(),\n max: this.max.toArray()\n };\n }\n /**\n * Returns a serialized structure of the bounding box.\n *\n * @param {Object} json - The serialized json to set the box from.\n * @return {Box3} A reference to this bounding box.\n */\n fromJSON(json) {\n this.min.fromArray(json.min);\n this.max.fromArray(json.max);\n return this;\n }\n }\n const _points = [\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3(),\n /* @__PURE__ */ new Vector3()\n ];\n const _vector$b = /* @__PURE__ */ new Vector3();\n const _box$4 = /* @__PURE__ */ new Box3();\n const _v0$2 = /* @__PURE__ */ new Vector3();\n const _v1$7 = /* @__PURE__ */ new Vector3();\n const _v2$4 = /* @__PURE__ */ new Vector3();\n const _f0 = /* @__PURE__ */ new Vector3();\n const _f1 = /* @__PURE__ */ new Vector3();\n const _f2 = /* @__PURE__ */ new Vector3();\n const _center = /* @__PURE__ */ new Vector3();\n const _extents = /* @__PURE__ */ new Vector3();\n const _triangleNormal = /* @__PURE__ */ new Vector3();\n const _testAxis = /* @__PURE__ */ new Vector3();\n function satForAxes(axes, v0, v1, v2, extents) {\n for (let i2 = 0, j = axes.length - 3; i2 <= j; i2 += 3) {\n _testAxis.fromArray(axes, i2);\n const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z);\n const p0 = v0.dot(_testAxis);\n const p1 = v1.dot(_testAxis);\n const p2 = v2.dot(_testAxis);\n if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {\n return false;\n }\n }\n return true;\n }\n const _colorKeywords = {\n "aliceblue": 15792383,\n "antiquewhite": 16444375,\n "aqua": 65535,\n "aquamarine": 8388564,\n "azure": 15794175,\n "beige": 16119260,\n "bisque": 16770244,\n "black": 0,\n "blanchedalmond": 16772045,\n "blue": 255,\n "blueviolet": 9055202,\n "brown": 10824234,\n "burlywood": 14596231,\n "cadetblue": 6266528,\n "chartreuse": 8388352,\n "chocolate": 13789470,\n "coral": 16744272,\n "cornflowerblue": 6591981,\n "cornsilk": 16775388,\n "crimson": 14423100,\n "cyan": 65535,\n "darkblue": 139,\n "darkcyan": 35723,\n "darkgoldenrod": 12092939,\n "darkgray": 11119017,\n "darkgreen": 25600,\n "darkgrey": 11119017,\n "darkkhaki": 12433259,\n "darkmagenta": 9109643,\n "darkolivegreen": 5597999,\n "darkorange": 16747520,\n "darkorchid": 10040012,\n "darkred": 9109504,\n "darksalmon": 15308410,\n "darkseagreen": 9419919,\n "darkslateblue": 4734347,\n "darkslategray": 3100495,\n "darkslategrey": 3100495,\n "darkturquoise": 52945,\n "darkviolet": 9699539,\n "deeppink": 16716947,\n "deepskyblue": 49151,\n "dimgray": 6908265,\n "dimgrey": 6908265,\n "dodgerblue": 2003199,\n "firebrick": 11674146,\n "floralwhite": 16775920,\n "forestgreen": 2263842,\n "fuchsia": 16711935,\n "gainsboro": 14474460,\n "ghostwhite": 16316671,\n "gold": 16766720,\n "goldenrod": 14329120,\n "gray": 8421504,\n "green": 32768,\n "greenyellow": 11403055,\n "grey": 8421504,\n "honeydew": 15794160,\n "hotpink": 16738740,\n "indianred": 13458524,\n "indigo": 4915330,\n "ivory": 16777200,\n "khaki": 15787660,\n "lavender": 15132410,\n "lavenderblush": 16773365,\n "lawngreen": 8190976,\n "lemonchiffon": 16775885,\n "lightblue": 11393254,\n "lightcoral": 15761536,\n "lightcyan": 14745599,\n "lightgoldenrodyellow": 16448210,\n "lightgray": 13882323,\n "lightgreen": 9498256,\n "lightgrey": 13882323,\n "lightpink": 16758465,\n "lightsalmon": 16752762,\n "lightseagreen": 2142890,\n "lightskyblue": 8900346,\n "lightslategray": 7833753,\n "lightslategrey": 7833753,\n "lightsteelblue": 11584734,\n "lightyellow": 16777184,\n "lime": 65280,\n "limegreen": 3329330,\n "linen": 16445670,\n "magenta": 16711935,\n "maroon": 8388608,\n "mediumaquamarine": 6737322,\n "mediumblue": 205,\n "mediumorchid": 12211667,\n "mediumpurple": 9662683,\n "mediumseagreen": 3978097,\n "mediumslateblue": 8087790,\n "mediumspringgreen": 64154,\n "mediumturquoise": 4772300,\n "mediumvioletred": 13047173,\n "midnightblue": 1644912,\n "mintcream": 16121850,\n "mistyrose": 16770273,\n "moccasin": 16770229,\n "navajowhite": 16768685,\n "navy": 128,\n "oldlace": 16643558,\n "olive": 8421376,\n "olivedrab": 7048739,\n "orange": 16753920,\n "orangered": 16729344,\n "orchid": 14315734,\n "palegoldenrod": 15657130,\n "palegreen": 10025880,\n "paleturquoise": 11529966,\n "palevioletred": 14381203,\n "papayawhip": 16773077,\n "peachpuff": 16767673,\n "peru": 13468991,\n "pink": 16761035,\n "plum": 14524637,\n "powderblue": 11591910,\n "purple": 8388736,\n "rebeccapurple": 6697881,\n "red": 16711680,\n "rosybrown": 12357519,\n "royalblue": 4286945,\n "saddlebrown": 9127187,\n "salmon": 16416882,\n "sandybrown": 16032864,\n "seagreen": 3050327,\n "seashell": 16774638,\n "sienna": 10506797,\n "silver": 12632256,\n "skyblue": 8900331,\n "slateblue": 6970061,\n "slategray": 7372944,\n "slategrey": 7372944,\n "snow": 16775930,\n "springgreen": 65407,\n "steelblue": 4620980,\n "tan": 13808780,\n "teal": 32896,\n "thistle": 14204888,\n "tomato": 16737095,\n "turquoise": 4251856,\n "violet": 15631086,\n "wheat": 16113331,\n "white": 16777215,\n "whitesmoke": 16119285,\n "yellow": 16776960,\n "yellowgreen": 10145074\n };\n const _hslA = { h: 0, s: 0, l: 0 };\n const _hslB = { h: 0, s: 0, l: 0 };\n function hue2rgb(p, q, t) {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * 6 * (2 / 3 - t);\n return p;\n }\n class Color {\n /**\n * Constructs a new color.\n *\n * Note that standard method of specifying color in three.js is with a hexadecimal triplet,\n * and that method is used throughout the rest of the documentation.\n *\n * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are\n * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.\n * @param {number} [g] - The green component.\n * @param {number} [b] - The blue component.\n */\n constructor(r, g, b) {\n this.isColor = true;\n this.r = 1;\n this.g = 1;\n this.b = 1;\n return this.set(r, g, b);\n }\n /**\n * Sets the colors\'s components from the given values.\n *\n * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are\n * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.\n * @param {number} [g] - The green component.\n * @param {number} [b] - The blue component.\n * @return {Color} A reference to this color.\n */\n set(r, g, b) {\n if (g === void 0 && b === void 0) {\n const value = r;\n if (value && value.isColor) {\n this.copy(value);\n } else if (typeof value === "number") {\n this.setHex(value);\n } else if (typeof value === "string") {\n this.setStyle(value);\n }\n } else {\n this.setRGB(r, g, b);\n }\n return this;\n }\n /**\n * Sets the colors\'s components to the given scalar value.\n *\n * @param {number} scalar - The scalar value.\n * @return {Color} A reference to this color.\n */\n setScalar(scalar) {\n this.r = scalar;\n this.g = scalar;\n this.b = scalar;\n return this;\n }\n /**\n * Sets this color from a hexadecimal value.\n *\n * @param {number} hex - The hexadecimal value.\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {Color} A reference to this color.\n */\n setHex(hex, colorSpace = SRGBColorSpace) {\n hex = Math.floor(hex);\n this.r = (hex >> 16 & 255) / 255;\n this.g = (hex >> 8 & 255) / 255;\n this.b = (hex & 255) / 255;\n ColorManagement.colorSpaceToWorking(this, colorSpace);\n return this;\n }\n /**\n * Sets this color from RGB values.\n *\n * @param {number} r - Red channel value between `0.0` and `1.0`.\n * @param {number} g - Green channel value between `0.0` and `1.0`.\n * @param {number} b - Blue channel value between `0.0` and `1.0`.\n * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.\n * @return {Color} A reference to this color.\n */\n setRGB(r, g, b, colorSpace = ColorManagement.workingColorSpace) {\n this.r = r;\n this.g = g;\n this.b = b;\n ColorManagement.colorSpaceToWorking(this, colorSpace);\n return this;\n }\n /**\n * Sets this color from RGB values.\n *\n * @param {number} h - Hue value between `0.0` and `1.0`.\n * @param {number} s - Saturation value between `0.0` and `1.0`.\n * @param {number} l - Lightness value between `0.0` and `1.0`.\n * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.\n * @return {Color} A reference to this color.\n */\n setHSL(h, s, l, colorSpace = ColorManagement.workingColorSpace) {\n h = euclideanModulo(h, 1);\n s = clamp(s, 0, 1);\n l = clamp(l, 0, 1);\n if (s === 0) {\n this.r = this.g = this.b = l;\n } else {\n const p = l <= 0.5 ? l * (1 + s) : l + s - l * s;\n const q = 2 * l - p;\n this.r = hue2rgb(q, p, h + 1 / 3);\n this.g = hue2rgb(q, p, h);\n this.b = hue2rgb(q, p, h - 1 / 3);\n }\n ColorManagement.colorSpaceToWorking(this, colorSpace);\n return this;\n }\n /**\n * Sets this color from a CSS-style string. For example, `rgb(250, 0,0)`,\n * `rgb(100%, 0%, 0%)`, `hsl(0, 100%, 50%)`, `#ff0000`, `#f00`, or `red` ( or\n * any [X11 color name]{@link https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart} -\n * all 140 color names are supported).\n *\n * @param {string} style - Color as a CSS-style string.\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {Color} A reference to this color.\n */\n setStyle(style, colorSpace = SRGBColorSpace) {\n function handleAlpha(string) {\n if (string === void 0) return;\n if (parseFloat(string) < 1) {\n console.warn("THREE.Color: Alpha component of " + style + " will be ignored.");\n }\n }\n let m;\n if (m = /^(\\w+)\\(([^\\)]*)\\)/.exec(style)) {\n let color;\n const name = m[1];\n const components = m[2];\n switch (name) {\n case "rgb":\n case "rgba":\n if (color = /^\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setRGB(\n Math.min(255, parseInt(color[1], 10)) / 255,\n Math.min(255, parseInt(color[2], 10)) / 255,\n Math.min(255, parseInt(color[3], 10)) / 255,\n colorSpace\n );\n }\n if (color = /^\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setRGB(\n Math.min(100, parseInt(color[1], 10)) / 100,\n Math.min(100, parseInt(color[2], 10)) / 100,\n Math.min(100, parseInt(color[3], 10)) / 100,\n colorSpace\n );\n }\n break;\n case "hsl":\n case "hsla":\n if (color = /^\\s*(\\d*\\.?\\d+)\\s*,\\s*(\\d*\\.?\\d+)\\%\\s*,\\s*(\\d*\\.?\\d+)\\%\\s*(?:,\\s*(\\d*\\.?\\d+)\\s*)?$/.exec(components)) {\n handleAlpha(color[4]);\n return this.setHSL(\n parseFloat(color[1]) / 360,\n parseFloat(color[2]) / 100,\n parseFloat(color[3]) / 100,\n colorSpace\n );\n }\n break;\n default:\n console.warn("THREE.Color: Unknown color model " + style);\n }\n } else if (m = /^\\#([A-Fa-f\\d]+)$/.exec(style)) {\n const hex = m[1];\n const size = hex.length;\n if (size === 3) {\n return this.setRGB(\n parseInt(hex.charAt(0), 16) / 15,\n parseInt(hex.charAt(1), 16) / 15,\n parseInt(hex.charAt(2), 16) / 15,\n colorSpace\n );\n } else if (size === 6) {\n return this.setHex(parseInt(hex, 16), colorSpace);\n } else {\n console.warn("THREE.Color: Invalid hex color " + style);\n }\n } else if (style && style.length > 0) {\n return this.setColorName(style, colorSpace);\n }\n return this;\n }\n /**\n * Sets this color from a color name. Faster than {@link Color#setStyle} if\n * you don\'t need the other CSS-style formats.\n *\n * For convenience, the list of names is exposed in `Color.NAMES` as a hash.\n * ```js\n * Color.NAMES.aliceblue // returns 0xF0F8FF\n * ```\n *\n * @param {string} style - The color name.\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {Color} A reference to this color.\n */\n setColorName(style, colorSpace = SRGBColorSpace) {\n const hex = _colorKeywords[style.toLowerCase()];\n if (hex !== void 0) {\n this.setHex(hex, colorSpace);\n } else {\n console.warn("THREE.Color: Unknown color " + style);\n }\n return this;\n }\n /**\n * Returns a new color with copied values from this instance.\n *\n * @return {Color} A clone of this instance.\n */\n clone() {\n return new this.constructor(this.r, this.g, this.b);\n }\n /**\n * Copies the values of the given color to this instance.\n *\n * @param {Color} color - The color to copy.\n * @return {Color} A reference to this color.\n */\n copy(color) {\n this.r = color.r;\n this.g = color.g;\n this.b = color.b;\n return this;\n }\n /**\n * Copies the given color into this color, and then converts this color from\n * `SRGBColorSpace` to `LinearSRGBColorSpace`.\n *\n * @param {Color} color - The color to copy/convert.\n * @return {Color} A reference to this color.\n */\n copySRGBToLinear(color) {\n this.r = SRGBToLinear(color.r);\n this.g = SRGBToLinear(color.g);\n this.b = SRGBToLinear(color.b);\n return this;\n }\n /**\n * Copies the given color into this color, and then converts this color from\n * `LinearSRGBColorSpace` to `SRGBColorSpace`.\n *\n * @param {Color} color - The color to copy/convert.\n * @return {Color} A reference to this color.\n */\n copyLinearToSRGB(color) {\n this.r = LinearToSRGB(color.r);\n this.g = LinearToSRGB(color.g);\n this.b = LinearToSRGB(color.b);\n return this;\n }\n /**\n * Converts this color from `SRGBColorSpace` to `LinearSRGBColorSpace`.\n *\n * @return {Color} A reference to this color.\n */\n convertSRGBToLinear() {\n this.copySRGBToLinear(this);\n return this;\n }\n /**\n * Converts this color from `LinearSRGBColorSpace` to `SRGBColorSpace`.\n *\n * @return {Color} A reference to this color.\n */\n convertLinearToSRGB() {\n this.copyLinearToSRGB(this);\n return this;\n }\n /**\n * Returns the hexadecimal value of this color.\n *\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {number} The hexadecimal value.\n */\n getHex(colorSpace = SRGBColorSpace) {\n ColorManagement.workingToColorSpace(_color.copy(this), colorSpace);\n return Math.round(clamp(_color.r * 255, 0, 255)) * 65536 + Math.round(clamp(_color.g * 255, 0, 255)) * 256 + Math.round(clamp(_color.b * 255, 0, 255));\n }\n /**\n * Returns the hexadecimal value of this color as a string (for example, \'FFFFFF\').\n *\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {string} The hexadecimal value as a string.\n */\n getHexString(colorSpace = SRGBColorSpace) {\n return ("000000" + this.getHex(colorSpace).toString(16)).slice(-6);\n }\n /**\n * Converts the colors RGB values into the HSL format and stores them into the\n * given target object.\n *\n * @param {{h:number,s:number,l:number}} target - The target object that is used to store the method\'s result.\n * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.\n * @return {{h:number,s:number,l:number}} The HSL representation of this color.\n */\n getHSL(target, colorSpace = ColorManagement.workingColorSpace) {\n ColorManagement.workingToColorSpace(_color.copy(this), colorSpace);\n const r = _color.r, g = _color.g, b = _color.b;\n const max2 = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let hue, saturation;\n const lightness = (min + max2) / 2;\n if (min === max2) {\n hue = 0;\n saturation = 0;\n } else {\n const delta = max2 - min;\n saturation = lightness <= 0.5 ? delta / (max2 + min) : delta / (2 - max2 - min);\n switch (max2) {\n case r:\n hue = (g - b) / delta + (g < b ? 6 : 0);\n break;\n case g:\n hue = (b - r) / delta + 2;\n break;\n case b:\n hue = (r - g) / delta + 4;\n break;\n }\n hue /= 6;\n }\n target.h = hue;\n target.s = saturation;\n target.l = lightness;\n return target;\n }\n /**\n * Returns the RGB values of this color and stores them into the given target object.\n *\n * @param {Color} target - The target color that is used to store the method\'s result.\n * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.\n * @return {Color} The RGB representation of this color.\n */\n getRGB(target, colorSpace = ColorManagement.workingColorSpace) {\n ColorManagement.workingToColorSpace(_color.copy(this), colorSpace);\n target.r = _color.r;\n target.g = _color.g;\n target.b = _color.b;\n return target;\n }\n /**\n * Returns the value of this color as a CSS style string. Example: `rgb(255,0,0)`.\n *\n * @param {string} [colorSpace=SRGBColorSpace] - The color space.\n * @return {string} The CSS representation of this color.\n */\n getStyle(colorSpace = SRGBColorSpace) {\n ColorManagement.workingToColorSpace(_color.copy(this), colorSpace);\n const r = _color.r, g = _color.g, b = _color.b;\n if (colorSpace !== SRGBColorSpace) {\n return `color(${colorSpace} ${r.toFixed(3)} ${g.toFixed(3)} ${b.toFixed(3)})`;\n }\n return `rgb(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)})`;\n }\n /**\n * Adds the given HSL values to this color\'s values.\n * Internally, this converts the color\'s RGB values to HSL, adds HSL\n * and then converts the color back to RGB.\n *\n * @param {number} h - Hue value between `0.0` and `1.0`.\n * @param {number} s - Saturation value between `0.0` and `1.0`.\n * @param {number} l - Lightness value between `0.0` and `1.0`.\n * @return {Color} A reference to this color.\n */\n offsetHSL(h, s, l) {\n this.getHSL(_hslA);\n return this.setHSL(_hslA.h + h, _hslA.s + s, _hslA.l + l);\n }\n /**\n * Adds the RGB values of the given color to the RGB values of this color.\n *\n * @param {Color} color - The color to add.\n * @return {Color} A reference to this color.\n */\n add(color) {\n this.r += color.r;\n this.g += color.g;\n this.b += color.b;\n return this;\n }\n /**\n * Adds the RGB values of the given colors and stores the result in this instance.\n *\n * @param {Color} color1 - The first color.\n * @param {Color} color2 - The second color.\n * @return {Color} A reference to this color.\n */\n addColors(color1, color2) {\n this.r = color1.r + color2.r;\n this.g = color1.g + color2.g;\n this.b = color1.b + color2.b;\n return this;\n }\n /**\n * Adds the given scalar value to the RGB values of this color.\n *\n * @param {number} s - The scalar to add.\n * @return {Color} A reference to this color.\n */\n addScalar(s) {\n this.r += s;\n this.g += s;\n this.b += s;\n return this;\n }\n /**\n * Subtracts the RGB values of the given color from the RGB values of this color.\n *\n * @param {Color} color - The color to subtract.\n * @return {Color} A reference to this color.\n */\n sub(color) {\n this.r = Math.max(0, this.r - color.r);\n this.g = Math.max(0, this.g - color.g);\n this.b = Math.max(0, this.b - color.b);\n return this;\n }\n /**\n * Multiplies the RGB values of the given color with the RGB values of this color.\n *\n * @param {Color} color - The color to multiply.\n * @return {Color} A reference to this color.\n */\n multiply(color) {\n this.r *= color.r;\n this.g *= color.g;\n this.b *= color.b;\n return this;\n }\n /**\n * Multiplies the given scalar value with the RGB values of this color.\n *\n * @param {number} s - The scalar to multiply.\n * @return {Color} A reference to this color.\n */\n multiplyScalar(s) {\n this.r *= s;\n this.g *= s;\n this.b *= s;\n return this;\n }\n /**\n * Linearly interpolates this color\'s RGB values toward the RGB values of the\n * given color. The alpha argument can be thought of as the ratio between\n * the two colors, where `0.0` is this color and `1.0` is the first argument.\n *\n * @param {Color} color - The color to converge on.\n * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.\n * @return {Color} A reference to this color.\n */\n lerp(color, alpha) {\n this.r += (color.r - this.r) * alpha;\n this.g += (color.g - this.g) * alpha;\n this.b += (color.b - this.b) * alpha;\n return this;\n }\n /**\n * Linearly interpolates between the given colors and stores the result in this instance.\n * The alpha argument can be thought of as the ratio between the two colors, where `0.0`\n * is the first and `1.0` is the second color.\n *\n * @param {Color} color1 - The first color.\n * @param {Color} color2 - The second color.\n * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.\n * @return {Color} A reference to this color.\n */\n lerpColors(color1, color2, alpha) {\n this.r = color1.r + (color2.r - color1.r) * alpha;\n this.g = color1.g + (color2.g - color1.g) * alpha;\n this.b = color1.b + (color2.b - color1.b) * alpha;\n return this;\n }\n /**\n * Linearly interpolates this color\'s HSL values toward the HSL values of the\n * given color. It differs from {@link Color#lerp} by not interpolating straight\n * from one color to the other, but instead going through all the hues in between\n * those two colors. The alpha argument can be thought of as the ratio between\n * the two colors, where 0.0 is this color and 1.0 is the first argument.\n *\n * @param {Color} color - The color to converge on.\n * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.\n * @return {Color} A reference to this color.\n */\n lerpHSL(color, alpha) {\n this.getHSL(_hslA);\n color.getHSL(_hslB);\n const h = lerp(_hslA.h, _hslB.h, alpha);\n const s = lerp(_hslA.s, _hslB.s, alpha);\n const l = lerp(_hslA.l, _hslB.l, alpha);\n this.setHSL(h, s, l);\n return this;\n }\n /**\n * Sets the color\'s RGB components from the given 3D vector.\n *\n * @param {Vector3} v - The vector to set.\n * @return {Color} A reference to this color.\n */\n setFromVector3(v) {\n this.r = v.x;\n this.g = v.y;\n this.b = v.z;\n return this;\n }\n /**\n * Transforms this color with the given 3x3 matrix.\n *\n * @param {Matrix3} m - The matrix.\n * @return {Color} A reference to this color.\n */\n applyMatrix3(m) {\n const r = this.r, g = this.g, b = this.b;\n const e = m.elements;\n this.r = e[0] * r + e[3] * g + e[6] * b;\n this.g = e[1] * r + e[4] * g + e[7] * b;\n this.b = e[2] * r + e[5] * g + e[8] * b;\n return this;\n }\n /**\n * Returns `true` if this color is equal with the given one.\n *\n * @param {Color} c - The color to test for equality.\n * @return {boolean} Whether this bounding color is equal with the given one.\n */\n equals(c) {\n return c.r === this.r && c.g === this.g && c.b === this.b;\n }\n /**\n * Sets this color\'s RGB components from the given array.\n *\n * @param {Array<number>} array - An array holding the RGB values.\n * @param {number} [offset=0] - The offset into the array.\n * @return {Color} A reference to this color.\n */\n fromArray(array, offset = 0) {\n this.r = array[offset];\n this.g = array[offset + 1];\n this.b = array[offset + 2];\n return this;\n }\n /**\n * Writes the RGB components of this color to the given array. If no array is provided,\n * the method returns a new instance.\n *\n * @param {Array<number>} [array=[]] - The target array holding the color components.\n * @param {number} [offset=0] - Index of the first element in the array.\n * @return {Array<number>} The color components.\n */\n toArray(array = [], offset = 0) {\n array[offset] = this.r;\n array[offset + 1] = this.g;\n array[offset + 2] = this.b;\n return array;\n }\n /**\n * Sets the components of this color from the given buffer attribute.\n *\n * @param {BufferAttribute} attribute - The buffer attribute holding color data.\n * @param {number} index - The index into the attribute.\n * @return {Color} A reference to this color.\n */\n fromBufferAttribute(attribute, index) {\n this.r = attribute.getX(index);\n this.g = attribute.getY(index);\n this.b = attribute.getZ(index);\n return this;\n }\n /**\n * This methods defines the serialization result of this class. Returns the color\n * as a hexadecimal value.\n *\n * @return {number} The hexadecimal value.\n */\n toJSON() {\n return this.getHex();\n }\n *[Symbol.iterator]() {\n yield this.r;\n yield this.g;\n yield this.b;\n }\n }\n const _color = /* @__PURE__ */ new Color();\n Color.NAMES = _colorKeywords;\n if (typeof __THREE_DEVTOOLS__ !== "undefined") {\n __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { detail: {\n revision: REVISION\n } }));\n }\n if (typeof window !== "undefined") {\n if (window.__THREE__) {\n console.warn("WARNING: Multiple instances of Three.js being imported.");\n } else {\n window.__THREE__ = REVISION;\n }\n }\n const LN_SCALE_MIN = -12;\n const LN_SCALE_MAX = 9;\n const LN_SCALE_ZERO = -30;\n const SCALE_ZERO = Math.exp(LN_SCALE_ZERO);\n const SPLAT_TEX_WIDTH_BITS = 11;\n const SPLAT_TEX_HEIGHT_BITS = 11;\n const SPLAT_TEX_WIDTH = 1 << SPLAT_TEX_WIDTH_BITS;\n const SPLAT_TEX_HEIGHT = 1 << SPLAT_TEX_HEIGHT_BITS;\n const SPLAT_TEX_MIN_HEIGHT = 1;\n function unindentLines(s) {\n var _a2;\n let seenNonEmpty = false;\n const lines = s.split("\\n").map((line) => {\n const trimmedLine = line.trimEnd();\n if (seenNonEmpty) {\n return trimmedLine;\n }\n if (trimmedLine.length > 0) {\n seenNonEmpty = true;\n return trimmedLine;\n }\n return null;\n }).filter((line) => line != null);\n while (lines.length > 0 && lines[lines.length - 1].length === 0) {\n lines.pop();\n }\n if (lines.length === 0) {\n return [];\n }\n const indent = (_a2 = lines[0].match(/^\\s*/)) == null ? void 0 : _a2[0];\n if (!indent) {\n return lines;\n }\n const regex = new RegExp(`^${indent}`);\n return lines.map((line) => line.replace(regex, ""));\n }\n function unindent(s) {\n return unindentLines(s).join("\\n");\n }\n const f32buffer = new Float32Array(1);\n const u32buffer = new Uint32Array(f32buffer.buffer);\n const supportsFloat16Array = "Float16Array" in globalThis;\n const f16buffer = supportsFloat16Array ? new globalThis["Float16Array"](1) : null;\n const u16buffer = new Uint16Array(f16buffer == null ? void 0 : f16buffer.buffer);\n function normalize(vec) {\n const norm = Math.sqrt(vec.reduce((acc, v) => acc + v * v, 0));\n return vec.map((v) => v / norm);\n }\n const toHalf = supportsFloat16Array ? toHalfNative : toHalfJS;\n const fromHalf = supportsFloat16Array ? fromHalfNative : fromHalfJS;\n function toHalfNative(f) {\n f16buffer[0] = f;\n return u16buffer[0];\n }\n function toHalfJS(f) {\n f32buffer[0] = f;\n const bits2 = u32buffer[0];\n const sign = bits2 >> 31 & 1;\n const exp = bits2 >> 23 & 255;\n const frac = bits2 & 8388607;\n const halfSign = sign << 15;\n if (exp === 255) {\n if (frac !== 0) {\n return halfSign | 32767;\n }\n return halfSign | 31744;\n }\n const newExp = exp - 127 + 15;\n if (newExp >= 31) {\n return halfSign | 31744;\n }\n if (newExp <= 0) {\n if (newExp < -10) {\n return halfSign;\n }\n const subFrac = (frac | 8388608) >> 1 - newExp + 13;\n return halfSign | subFrac;\n }\n const halfFrac = frac >> 13;\n return halfSign | newExp << 10 | halfFrac;\n }\n function fromHalfNative(u) {\n u16buffer[0] = u;\n return f16buffer[0];\n }\n function fromHalfJS(h) {\n const sign = h >> 15 & 1;\n const exp = h >> 10 & 31;\n const frac = h & 1023;\n let f32bits;\n if (exp === 0) {\n if (frac === 0) {\n f32bits = sign << 31;\n } else {\n let mant = frac;\n let e = -14;\n while ((mant & 1024) === 0) {\n mant <<= 1;\n e--;\n }\n mant &= 1023;\n const newExp = e + 127;\n const newFrac = mant << 13;\n f32bits = sign << 31 | newExp << 23 | newFrac;\n }\n } else if (exp === 31) {\n if (frac === 0) {\n f32bits = sign << 31 | 2139095040;\n } else {\n f32bits = sign << 31 | 2143289344;\n }\n } else {\n const newExp = exp - 15 + 127;\n const newFrac = frac << 13;\n f32bits = sign << 31 | newExp << 23 | newFrac;\n }\n u32buffer[0] = f32bits;\n return f32buffer[0];\n }\n function floatToUint8(v) {\n return Math.max(0, Math.min(255, Math.round(v * 255)));\n }\n function getArrayBuffers(ctx) {\n const buffers = [];\n const seen = /* @__PURE__ */ new Set();\n function traverse(obj) {\n if (obj && typeof obj === "object" && !seen.has(obj)) {\n seen.add(obj);\n if (obj instanceof ArrayBuffer) {\n buffers.push(obj);\n } else if (ArrayBuffer.isView(obj)) {\n buffers.push(obj.buffer);\n } else if (Array.isArray(obj)) {\n obj.forEach(traverse);\n } else {\n Object.values(obj).forEach(traverse);\n }\n }\n }\n traverse(ctx);\n return buffers;\n }\n function setPackedSplat(packedSplats, index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const uA = floatToUint8(opacity);\n const uQuat = encodeQuatOctXy88R8(\n tempQuaternion.set(quatX, quatY, quatZ, quatW)\n );\n const uQuatX = uQuat & 255;\n const uQuatY = uQuat >>> 8 & 255;\n const uQuatZ = uQuat >>> 16 & 255;\n const lnScaleMin = (encoding == null ? void 0 : encoding.lnScaleMin) ?? LN_SCALE_MIN;\n const lnScaleMax = (encoding == null ? void 0 : encoding.lnScaleMax) ?? LN_SCALE_MAX;\n const lnScaleScale = 254 / (lnScaleMax - lnScaleMin);\n const uScaleX = scaleX < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleX) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleY = scaleY < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleY) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleZ = scaleZ < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleZ) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uCenterX = toHalf(x2);\n const uCenterY = toHalf(y);\n const uCenterZ = toHalf(z);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | uA << 24;\n packedSplats[i4 + 1] = uCenterX | uCenterY << 16;\n packedSplats[i4 + 2] = uCenterZ | uQuatX << 16 | uQuatY << 24;\n packedSplats[i4 + 3] = uScaleX | uScaleY << 8 | uScaleZ << 16 | uQuatZ << 24;\n }\n function setPackedSplatCenter(packedSplats, index, x2, y, z) {\n const uCenterX = toHalf(x2);\n const uCenterY = toHalf(y);\n const uCenterZ = toHalf(z);\n const i4 = index * 4;\n packedSplats[i4 + 1] = uCenterX | uCenterY << 16;\n packedSplats[i4 + 2] = uCenterZ | packedSplats[i4 + 2] & 4294901760;\n }\n function setPackedSplatScales(packedSplats, index, scaleX, scaleY, scaleZ, encoding) {\n const lnScaleMin = (encoding == null ? void 0 : encoding.lnScaleMin) ?? LN_SCALE_MIN;\n const lnScaleMax = (encoding == null ? void 0 : encoding.lnScaleMax) ?? LN_SCALE_MAX;\n const lnScaleScale = 254 / (lnScaleMax - lnScaleMin);\n const uScaleX = scaleX < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleX) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleY = scaleY < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleY) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const uScaleZ = scaleZ < SCALE_ZERO ? 0 : Math.min(\n 255,\n Math.max(\n 1,\n Math.round((Math.log(scaleZ) - lnScaleMin) * lnScaleScale) + 1\n )\n );\n const i4 = index * 4;\n packedSplats[i4 + 3] = uScaleX | uScaleY << 8 | uScaleZ << 16 | packedSplats[i4 + 3] & 4278190080;\n }\n const tempQuaternion = new Quaternion();\n function setPackedSplatQuat(packedSplats, index, quatX, quatY, quatZ, quatW) {\n const uQuat = encodeQuatOctXy88R8(\n tempQuaternion.set(quatX, quatY, quatZ, quatW)\n );\n const uQuatX = uQuat & 255;\n const uQuatY = uQuat >>> 8 & 255;\n const uQuatZ = uQuat >>> 16 & 255;\n const i4 = index * 4;\n packedSplats[i4 + 2] = packedSplats[i4 + 2] & 65535 | uQuatX << 16 | uQuatY << 24;\n packedSplats[i4 + 3] = packedSplats[i4 + 3] & 16777215 | uQuatZ << 24;\n }\n function setPackedSplatRgba(packedSplats, index, r, g, b, a, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const uA = floatToUint8(a);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | uA << 24;\n }\n function setPackedSplatRgb(packedSplats, index, r, g, b, encoding) {\n const rgbMin = (encoding == null ? void 0 : encoding.rgbMin) ?? 0;\n const rgbMax = (encoding == null ? void 0 : encoding.rgbMax) ?? 1;\n const rgbRange = rgbMax - rgbMin;\n const uR = floatToUint8((r - rgbMin) / rgbRange);\n const uG = floatToUint8((g - rgbMin) / rgbRange);\n const uB = floatToUint8((b - rgbMin) / rgbRange);\n const i4 = index * 4;\n packedSplats[i4] = uR | uG << 8 | uB << 16 | packedSplats[i4] & 4278190080;\n }\n function setPackedSplatOpacity(packedSplats, index, opacity) {\n const uA = floatToUint8(opacity);\n const i4 = index * 4;\n packedSplats[i4] = packedSplats[i4] & 16777215 | uA << 24;\n }\n new Vector3();\n new Vector3();\n new Color();\n function getTextureSize(numSplats) {\n const width = SPLAT_TEX_WIDTH;\n const height = Math.max(\n SPLAT_TEX_MIN_HEIGHT,\n Math.min(SPLAT_TEX_HEIGHT, Math.ceil(numSplats / width))\n );\n const depth = Math.ceil(numSplats / (width * height));\n const maxSplats = width * height * depth;\n return { width, height, depth, maxSplats };\n }\n function computeMaxSplats(numSplats) {\n const width = SPLAT_TEX_WIDTH;\n const height = Math.max(\n SPLAT_TEX_MIN_HEIGHT,\n Math.min(SPLAT_TEX_HEIGHT, Math.ceil(numSplats / width))\n );\n const depth = Math.ceil(numSplats / (width * height));\n return width * height * depth;\n }\n unindent(`\n precision highp float;\n\n in vec3 position;\n\n void main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n }\n`);\n const tempNormalizedQuaternion = new Quaternion();\n const tempAxis = new Vector3();\n function encodeQuatOctXy88R8(q) {\n const qnorm = tempNormalizedQuaternion.copy(q).normalize();\n if (qnorm.w < 0) {\n qnorm.set(-qnorm.x, -qnorm.y, -qnorm.z, -qnorm.w);\n }\n const theta = 2 * Math.acos(qnorm.w);\n const xyz_norm = Math.sqrt(\n qnorm.x * qnorm.x + qnorm.y * qnorm.y + qnorm.z * qnorm.z\n );\n const axis = xyz_norm < 1e-6 ? tempAxis.set(1, 0, 0) : tempAxis.set(qnorm.x, qnorm.y, qnorm.z).divideScalar(xyz_norm);\n const sum = Math.abs(axis.x) + Math.abs(axis.y) + Math.abs(axis.z);\n let p_x = axis.x / sum;\n let p_y = axis.y / sum;\n if (axis.z < 0) {\n const tmp = p_x;\n p_x = (1 - Math.abs(p_y)) * (p_x >= 0 ? 1 : -1);\n p_y = (1 - Math.abs(tmp)) * (p_y >= 0 ? 1 : -1);\n }\n const u_f = p_x * 0.5 + 0.5;\n const v_f = p_y * 0.5 + 0.5;\n const quantU = Math.round(u_f * 255);\n const quantV = Math.round(v_f * 255);\n const angleInt = Math.round(theta * (255 / Math.PI));\n return angleInt << 16 | quantV << 8 | quantU;\n }\n function packSint8Bytes(b0, b1, b22, b3) {\n const clampedB0 = Math.max(-127, Math.min(127, b0 * 127));\n const clampedB1 = Math.max(-127, Math.min(127, b1 * 127));\n const clampedB2 = Math.max(-127, Math.min(127, b22 * 127));\n const clampedB3 = Math.max(-127, Math.min(127, b3 * 127));\n return clampedB0 & 255 | (clampedB1 & 255) << 8 | (clampedB2 & 255) << 16 | (clampedB3 & 255) << 24;\n }\n function encodeSh1Rgb(sh1Array, index, sh1Rgb, encoding) {\n const sh1Min = (encoding == null ? void 0 : encoding.sh1Min) ?? -1;\n const sh1Max = (encoding == null ? void 0 : encoding.sh1Max) ?? 1;\n const sh1Mid = 0.5 * (sh1Min + sh1Max);\n const sh1Scale = 126 / (sh1Max - sh1Min);\n const base = index * 2;\n for (let i2 = 0; i2 < 9; ++i2) {\n const s = (sh1Rgb[i2] - sh1Mid) * sh1Scale;\n const value = Math.round(Math.max(-63, Math.min(63, s))) & 127;\n const bitStart = i2 * 7;\n const bitEnd = bitStart + 7;\n const wordStart = Math.floor(bitStart / 32);\n const bitOffset = bitStart - wordStart * 32;\n const firstWord = value << bitOffset & 4294967295;\n sh1Array[base + wordStart] |= firstWord;\n if (bitEnd > wordStart * 32 + 32) {\n const secondWord = value >>> 32 - bitOffset & 4294967295;\n sh1Array[base + wordStart + 1] |= secondWord;\n }\n }\n }\n function encodeSh2Rgb(sh2Array, index, sh2Rgb, encoding) {\n const sh2Min = (encoding == null ? void 0 : encoding.sh2Min) ?? -1;\n const sh2Max = (encoding == null ? void 0 : encoding.sh2Max) ?? 1;\n const sh2Mid = 0.5 * (sh2Min + sh2Max);\n const sh2Scale = 2 / (sh2Max - sh2Min);\n sh2Array[index * 4 + 0] = packSint8Bytes(\n (sh2Rgb[0] - sh2Mid) * sh2Scale,\n (sh2Rgb[1] - sh2Mid) * sh2Scale,\n (sh2Rgb[2] - sh2Mid) * sh2Scale,\n (sh2Rgb[3] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 1] = packSint8Bytes(\n (sh2Rgb[4] - sh2Mid) * sh2Scale,\n (sh2Rgb[5] - sh2Mid) * sh2Scale,\n (sh2Rgb[6] - sh2Mid) * sh2Scale,\n (sh2Rgb[7] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 2] = packSint8Bytes(\n (sh2Rgb[8] - sh2Mid) * sh2Scale,\n (sh2Rgb[9] - sh2Mid) * sh2Scale,\n (sh2Rgb[10] - sh2Mid) * sh2Scale,\n (sh2Rgb[11] - sh2Mid) * sh2Scale\n );\n sh2Array[index * 4 + 3] = packSint8Bytes(\n (sh2Rgb[12] - sh2Mid) * sh2Scale,\n (sh2Rgb[13] - sh2Mid) * sh2Scale,\n (sh2Rgb[14] - sh2Mid) * sh2Scale,\n 0\n );\n }\n function encodeSh3Rgb(sh3Array, index, sh3Rgb, encoding) {\n const sh3Min = (encoding == null ? void 0 : encoding.sh3Min) ?? -1;\n const sh3Max = (encoding == null ? void 0 : encoding.sh3Max) ?? 1;\n const sh3Mid = 0.5 * (sh3Min + sh3Max);\n const sh3Scale = 62 / (sh3Max - sh3Min);\n const base = index * 4;\n for (let i2 = 0; i2 < 21; ++i2) {\n const s = (sh3Rgb[i2] - sh3Mid) * sh3Scale;\n const value = Math.round(Math.max(-31, Math.min(31, s))) & 63;\n const bitStart = i2 * 6;\n const bitEnd = bitStart + 6;\n const wordStart = Math.floor(bitStart / 32);\n const bitOffset = bitStart - wordStart * 32;\n const firstWord = value << bitOffset & 4294967295;\n sh3Array[base + wordStart] |= firstWord;\n if (bitEnd > wordStart * 32 + 32) {\n const secondWord = value >>> 32 - bitOffset & 4294967295;\n sh3Array[base + wordStart + 1] |= secondWord;\n }\n }\n }\n function decompressPartialGzip(fileBytes, numBytes) {\n const chunks = [];\n let totalBytes = 0;\n let result = null;\n const gunzip = new Gunzip((data, final) => {\n chunks.push(data);\n totalBytes += data.length;\n if (final || totalBytes >= numBytes) {\n const allBytes = new Uint8Array(totalBytes);\n let offset2 = 0;\n for (const chunk of chunks) {\n allBytes.set(chunk, offset2);\n offset2 += chunk.length;\n }\n result = allBytes.slice(0, numBytes);\n }\n });\n const CHUNK_SIZE = 1024;\n let offset = 0;\n while (result == null && offset < fileBytes.length) {\n const chunk = fileBytes.slice(offset, offset + CHUNK_SIZE);\n gunzip.push(chunk, false);\n offset += CHUNK_SIZE;\n }\n if (result == null) {\n gunzip.push(new Uint8Array(), true);\n if (result == null) {\n throw new Error("Failed to decompress partial gzip");\n }\n }\n return result;\n }\n class GunzipReader {\n constructor({\n fileBytes,\n chunkBytes = 64 * 1024\n }) {\n this.fileBytes = fileBytes;\n this.chunkBytes = chunkBytes;\n this.chunks = [];\n this.totalBytes = 0;\n const ds = new DecompressionStream("gzip");\n const decompressionStream = new Blob([fileBytes]).stream().pipeThrough(ds);\n this.reader = decompressionStream.getReader();\n }\n async read(numBytes) {\n while (this.totalBytes < numBytes) {\n const { value: chunk, done: readerDone } = await this.reader.read();\n if (readerDone) {\n break;\n }\n this.chunks.push(chunk);\n this.totalBytes += chunk.length;\n }\n if (this.totalBytes < numBytes) {\n throw new Error(\n `Unexpected EOF: needed ${numBytes}, got ${this.totalBytes}`\n );\n }\n const allBytes = new Uint8Array(this.totalBytes);\n let outOffset = 0;\n for (const chunk of this.chunks) {\n allBytes.set(chunk, outOffset);\n outOffset += chunk.length;\n }\n const result = allBytes.subarray(0, numBytes);\n this.chunks = [allBytes.subarray(numBytes)];\n this.totalBytes -= numBytes;\n return result;\n }\n }\n function decodeAntiSplat(fileBytes, initNumSplats, splatCallback) {\n const numSplats = Math.floor(fileBytes.length / 32);\n if (numSplats * 32 !== fileBytes.length) {\n throw new Error("Invalid .splat file size");\n }\n initNumSplats(numSplats);\n const f32 = new Float32Array(fileBytes.buffer);\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i322 = i2 * 32;\n const i8 = i2 * 8;\n const x2 = f32[i8 + 0];\n const y = f32[i8 + 1];\n const z = f32[i8 + 2];\n const scaleX = f32[i8 + 3];\n const scaleY = f32[i8 + 4];\n const scaleZ = f32[i8 + 5];\n const r = fileBytes[i322 + 24] / 255;\n const g = fileBytes[i322 + 25] / 255;\n const b = fileBytes[i322 + 26] / 255;\n const opacity = fileBytes[i322 + 27] / 255;\n const quatW = (fileBytes[i322 + 28] - 128) / 128;\n const quatX = (fileBytes[i322 + 29] - 128) / 128;\n const quatY = (fileBytes[i322 + 30] - 128) / 128;\n const quatZ = (fileBytes[i322 + 31] - 128) / 128;\n splatCallback(\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n }\n }\n function unpackAntiSplat(fileBytes, splatEncoding) {\n let numSplats = 0;\n let maxSplats = 0;\n let packedArray = new Uint32Array(0);\n decodeAntiSplat(\n fileBytes,\n (cbNumSplats) => {\n numSplats = cbNumSplats;\n maxSplats = computeMaxSplats(numSplats);\n packedArray = new Uint32Array(maxSplats * 4);\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n setPackedSplat(\n packedArray,\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n }\n );\n return { packedArray, numSplats };\n }\n const KSPLAT_COMPRESSION = {\n 0: {\n bytesPerCenter: 12,\n bytesPerScale: 12,\n bytesPerRotation: 16,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 4,\n scaleOffsetBytes: 12,\n rotationOffsetBytes: 24,\n colorOffsetBytes: 40,\n sphericalHarmonicsOffsetBytes: 44,\n scaleRange: 1\n },\n 1: {\n bytesPerCenter: 6,\n bytesPerScale: 6,\n bytesPerRotation: 8,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 2,\n scaleOffsetBytes: 6,\n rotationOffsetBytes: 12,\n colorOffsetBytes: 20,\n sphericalHarmonicsOffsetBytes: 24,\n scaleRange: 32767\n },\n 2: {\n bytesPerCenter: 6,\n bytesPerScale: 6,\n bytesPerRotation: 8,\n bytesPerColor: 4,\n bytesPerSphericalHarmonicsComponent: 1,\n scaleOffsetBytes: 6,\n rotationOffsetBytes: 12,\n colorOffsetBytes: 20,\n sphericalHarmonicsOffsetBytes: 24,\n scaleRange: 32767\n }\n };\n const KSPLAT_SH_DEGREE_TO_COMPONENTS = {\n 0: 0,\n 1: 9,\n 2: 24,\n 3: 45\n };\n function decodeKsplat(fileBytes, initNumSplats, splatCallback, shCallback) {\n var _a2;\n const HEADER_BYTES = 4096;\n const SECTION_BYTES = 1024;\n let headerOffset = 0;\n const header = new DataView(fileBytes.buffer, headerOffset, HEADER_BYTES);\n headerOffset += HEADER_BYTES;\n const versionMajor = header.getUint8(0);\n const versionMinor = header.getUint8(1);\n if (versionMajor !== 0 || versionMinor < 1) {\n throw new Error(\n `Unsupported .ksplat version: ${versionMajor}.${versionMinor}`\n );\n }\n const maxSectionCount = header.getUint32(4, true);\n header.getUint32(16, true);\n const compressionLevel = header.getUint16(20, true);\n if (compressionLevel < 0 || compressionLevel > 2) {\n throw new Error(`Invalid .ksplat compression level: ${compressionLevel}`);\n }\n const minSphericalHarmonicsCoeff = header.getFloat32(36, true) || -1.5;\n const maxSphericalHarmonicsCoeff = header.getFloat32(40, true) || 1.5;\n let sectionBase = HEADER_BYTES + maxSectionCount * SECTION_BYTES;\n for (let section = 0; section < maxSectionCount; ++section) {\n let getSh = function(splatOffset, component) {\n if (compressionLevel === 0) {\n return data.getFloat32(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 4,\n true\n );\n }\n if (compressionLevel === 1) {\n return fromHalf(\n data.getUint16(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 2,\n true\n )\n );\n }\n const t = data.getUint8(splatOffset + sphericalHarmonicsOffsetBytes + component) / 255;\n return minSphericalHarmonicsCoeff + t * (maxSphericalHarmonicsCoeff - minSphericalHarmonicsCoeff);\n };\n const section2 = new DataView(fileBytes.buffer, headerOffset, SECTION_BYTES);\n headerOffset += SECTION_BYTES;\n const sectionSplatCount = section2.getUint32(0, true);\n const sectionMaxSplatCount = section2.getUint32(4, true);\n const bucketSize = section2.getUint32(8, true);\n const bucketCount = section2.getUint32(12, true);\n const bucketBlockSize = section2.getFloat32(16, true);\n const bucketStorageSizeBytes = section2.getUint16(20, true);\n const compressionScaleRange = (section2.getUint32(24, true) || ((_a2 = KSPLAT_COMPRESSION[compressionLevel]) == null ? void 0 : _a2.scaleRange)) ?? 1;\n const fullBucketCount = section2.getUint32(32, true);\n const fullBucketSplats = fullBucketCount * bucketSize;\n const partiallyFilledBucketCount = section2.getUint32(36, true);\n const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;\n const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;\n const sphericalHarmonicsDegree = section2.getUint16(40, true);\n const shComponents = KSPLAT_SH_DEGREE_TO_COMPONENTS[sphericalHarmonicsDegree];\n const {\n bytesPerCenter,\n bytesPerScale,\n bytesPerRotation,\n bytesPerColor,\n bytesPerSphericalHarmonicsComponent,\n scaleOffsetBytes,\n rotationOffsetBytes,\n colorOffsetBytes,\n sphericalHarmonicsOffsetBytes\n } = KSPLAT_COMPRESSION[compressionLevel];\n const bytesPerSplat = bytesPerCenter + bytesPerScale + bytesPerRotation + bytesPerColor + shComponents * bytesPerSphericalHarmonicsComponent;\n const splatDataStorageSizeBytes = bytesPerSplat * sectionMaxSplatCount;\n const storageSizeBytes = splatDataStorageSizeBytes + bucketsStorageSizeBytes;\n const sh1Index = [0, 3, 6, 1, 4, 7, 2, 5, 8];\n const sh2Index = [\n 9,\n 14,\n 19,\n 10,\n 15,\n 20,\n 11,\n 16,\n 21,\n 12,\n 17,\n 22,\n 13,\n 18,\n 23\n ];\n const sh3Index = [\n 24,\n 31,\n 38,\n 25,\n 32,\n 39,\n 26,\n 33,\n 40,\n 27,\n 34,\n 41,\n 28,\n 35,\n 42,\n 29,\n 36,\n 43,\n 30,\n 37,\n 44\n ];\n const sh1 = sphericalHarmonicsDegree >= 1 ? new Float32Array(3 * 3) : void 0;\n const sh2 = sphericalHarmonicsDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = sphericalHarmonicsDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const compressionScaleFactor = bucketBlockSize / 2 / compressionScaleRange;\n const bucketsBase = sectionBase + bucketsMetaDataSizeBytes;\n const dataBase = sectionBase + bucketsStorageSizeBytes;\n const data = new DataView(\n fileBytes.buffer,\n dataBase,\n splatDataStorageSizeBytes\n );\n const bucketArray = new Float32Array(\n fileBytes.buffer,\n bucketsBase,\n bucketCount * 3\n );\n const partiallyFilledBucketLengths = new Uint32Array(\n fileBytes.buffer,\n sectionBase,\n partiallyFilledBucketCount\n );\n let partialBucketIndex = fullBucketCount;\n let partialBucketBase = fullBucketSplats;\n for (let i2 = 0; i2 < sectionSplatCount; ++i2) {\n const splatOffset = i2 * bytesPerSplat;\n let bucketIndex;\n if (i2 < fullBucketSplats) {\n bucketIndex = Math.floor(i2 / bucketSize);\n } else {\n const bucketLength = partiallyFilledBucketLengths[partialBucketIndex - fullBucketCount];\n if (i2 >= partialBucketBase + bucketLength) {\n partialBucketIndex += 1;\n partialBucketBase += bucketLength;\n }\n bucketIndex = partialBucketIndex;\n }\n const x2 = compressionLevel === 0 ? data.getFloat32(splatOffset + 0, true) : (data.getUint16(splatOffset + 0, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 0];\n const y = compressionLevel === 0 ? data.getFloat32(splatOffset + 4, true) : (data.getUint16(splatOffset + 2, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 1];\n const z = compressionLevel === 0 ? data.getFloat32(splatOffset + 8, true) : (data.getUint16(splatOffset + 4, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 2];\n const scaleX = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 0, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 0, true));\n const scaleY = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 4, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 2, true));\n const scaleZ = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 8, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 4, true));\n const quatW = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 0, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 0, true)\n );\n const quatX = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 4, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 2, true)\n );\n const quatY = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 8, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 4, true)\n );\n const quatZ = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 12, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 6, true)\n );\n const r = data.getUint8(splatOffset + colorOffsetBytes + 0) / 255;\n const g = data.getUint8(splatOffset + colorOffsetBytes + 1) / 255;\n const b = data.getUint8(splatOffset + colorOffsetBytes + 2) / 255;\n const opacity = data.getUint8(splatOffset + colorOffsetBytes + 3) / 255;\n splatCallback(\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n if (sphericalHarmonicsDegree >= 1 && sh1) {\n for (const [i22, key] of sh1Index.entries()) {\n sh1[i22] = getSh(splatOffset, key);\n }\n if (sh2) {\n for (const [i22, key] of sh2Index.entries()) {\n sh2[i22] = getSh(splatOffset, key);\n }\n }\n if (sh3) {\n for (const [i22, key] of sh3Index.entries()) {\n sh3[i22] = getSh(splatOffset, key);\n }\n }\n shCallback == null ? void 0 : shCallback(i2, sh1, sh2, sh3);\n }\n }\n sectionBase += storageSizeBytes;\n }\n }\n function unpackKsplat(fileBytes, splatEncoding) {\n var _a2;\n const HEADER_BYTES = 4096;\n const SECTION_BYTES = 1024;\n let headerOffset = 0;\n const header = new DataView(fileBytes.buffer, headerOffset, HEADER_BYTES);\n headerOffset += HEADER_BYTES;\n const versionMajor = header.getUint8(0);\n const versionMinor = header.getUint8(1);\n if (versionMajor !== 0 || versionMinor < 1) {\n throw new Error(\n `Unsupported .ksplat version: ${versionMajor}.${versionMinor}`\n );\n }\n const maxSectionCount = header.getUint32(4, true);\n const splatCount = header.getUint32(16, true);\n const compressionLevel = header.getUint16(20, true);\n if (compressionLevel < 0 || compressionLevel > 2) {\n throw new Error(`Invalid .ksplat compression level: ${compressionLevel}`);\n }\n const minSphericalHarmonicsCoeff = header.getFloat32(36, true) || -1.5;\n const maxSphericalHarmonicsCoeff = header.getFloat32(40, true) || 1.5;\n const numSplats = splatCount;\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n let sectionBase = HEADER_BYTES + maxSectionCount * SECTION_BYTES;\n for (let section = 0; section < maxSectionCount; ++section) {\n let getSh = function(splatOffset, component) {\n if (compressionLevel === 0) {\n return data.getFloat32(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 4,\n true\n );\n }\n if (compressionLevel === 1) {\n return fromHalf(\n data.getUint16(\n splatOffset + sphericalHarmonicsOffsetBytes + component * 2,\n true\n )\n );\n }\n const t = data.getUint8(splatOffset + sphericalHarmonicsOffsetBytes + component) / 255;\n return minSphericalHarmonicsCoeff + t * (maxSphericalHarmonicsCoeff - minSphericalHarmonicsCoeff);\n };\n const section2 = new DataView(fileBytes.buffer, headerOffset, SECTION_BYTES);\n headerOffset += SECTION_BYTES;\n const sectionSplatCount = section2.getUint32(0, true);\n const sectionMaxSplatCount = section2.getUint32(4, true);\n const bucketSize = section2.getUint32(8, true);\n const bucketCount = section2.getUint32(12, true);\n const bucketBlockSize = section2.getFloat32(16, true);\n const bucketStorageSizeBytes = section2.getUint16(20, true);\n const compressionScaleRange = (section2.getUint32(24, true) || ((_a2 = KSPLAT_COMPRESSION[compressionLevel]) == null ? void 0 : _a2.scaleRange)) ?? 1;\n const fullBucketCount = section2.getUint32(32, true);\n const fullBucketSplats = fullBucketCount * bucketSize;\n const partiallyFilledBucketCount = section2.getUint32(36, true);\n const bucketsMetaDataSizeBytes = partiallyFilledBucketCount * 4;\n const bucketsStorageSizeBytes = bucketStorageSizeBytes * bucketCount + bucketsMetaDataSizeBytes;\n const sphericalHarmonicsDegree = section2.getUint16(40, true);\n const shComponents = KSPLAT_SH_DEGREE_TO_COMPONENTS[sphericalHarmonicsDegree];\n const {\n bytesPerCenter,\n bytesPerScale,\n bytesPerRotation,\n bytesPerColor,\n bytesPerSphericalHarmonicsComponent,\n scaleOffsetBytes,\n rotationOffsetBytes,\n colorOffsetBytes,\n sphericalHarmonicsOffsetBytes\n } = KSPLAT_COMPRESSION[compressionLevel];\n const bytesPerSplat = bytesPerCenter + bytesPerScale + bytesPerRotation + bytesPerColor + shComponents * bytesPerSphericalHarmonicsComponent;\n const splatDataStorageSizeBytes = bytesPerSplat * sectionMaxSplatCount;\n const storageSizeBytes = splatDataStorageSizeBytes + bucketsStorageSizeBytes;\n const sh1Index = [0, 3, 6, 1, 4, 7, 2, 5, 8];\n const sh2Index = [\n 9,\n 14,\n 19,\n 10,\n 15,\n 20,\n 11,\n 16,\n 21,\n 12,\n 17,\n 22,\n 13,\n 18,\n 23\n ];\n const sh3Index = [\n 24,\n 31,\n 38,\n 25,\n 32,\n 39,\n 26,\n 33,\n 40,\n 27,\n 34,\n 41,\n 28,\n 35,\n 42,\n 29,\n 36,\n 43,\n 30,\n 37,\n 44\n ];\n const sh1 = sphericalHarmonicsDegree >= 1 ? new Float32Array(3 * 3) : void 0;\n const sh2 = sphericalHarmonicsDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = sphericalHarmonicsDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const compressionScaleFactor = bucketBlockSize / 2 / compressionScaleRange;\n const bucketsBase = sectionBase + bucketsMetaDataSizeBytes;\n const dataBase = sectionBase + bucketsStorageSizeBytes;\n const data = new DataView(\n fileBytes.buffer,\n dataBase,\n splatDataStorageSizeBytes\n );\n const bucketArray = new Float32Array(\n fileBytes.buffer,\n bucketsBase,\n bucketCount * 3\n );\n const partiallyFilledBucketLengths = new Uint32Array(\n fileBytes.buffer,\n sectionBase,\n partiallyFilledBucketCount\n );\n let partialBucketIndex = fullBucketCount;\n let partialBucketBase = fullBucketSplats;\n for (let i2 = 0; i2 < sectionSplatCount; ++i2) {\n const splatOffset = i2 * bytesPerSplat;\n let bucketIndex;\n if (i2 < fullBucketSplats) {\n bucketIndex = Math.floor(i2 / bucketSize);\n } else {\n const bucketLength = partiallyFilledBucketLengths[partialBucketIndex - fullBucketCount];\n if (i2 >= partialBucketBase + bucketLength) {\n partialBucketIndex += 1;\n partialBucketBase += bucketLength;\n }\n bucketIndex = partialBucketIndex;\n }\n const x2 = compressionLevel === 0 ? data.getFloat32(splatOffset + 0, true) : (data.getUint16(splatOffset + 0, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 0];\n const y = compressionLevel === 0 ? data.getFloat32(splatOffset + 4, true) : (data.getUint16(splatOffset + 2, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 1];\n const z = compressionLevel === 0 ? data.getFloat32(splatOffset + 8, true) : (data.getUint16(splatOffset + 4, true) - compressionScaleRange) * compressionScaleFactor + bucketArray[3 * bucketIndex + 2];\n const scaleX = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 0, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 0, true));\n const scaleY = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 4, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 2, true));\n const scaleZ = compressionLevel === 0 ? data.getFloat32(splatOffset + scaleOffsetBytes + 8, true) : fromHalf(data.getUint16(splatOffset + scaleOffsetBytes + 4, true));\n const quatW = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 0, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 0, true)\n );\n const quatX = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 4, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 2, true)\n );\n const quatY = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 8, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 4, true)\n );\n const quatZ = compressionLevel === 0 ? data.getFloat32(splatOffset + rotationOffsetBytes + 12, true) : fromHalf(\n data.getUint16(splatOffset + rotationOffsetBytes + 6, true)\n );\n const r = data.getUint8(splatOffset + colorOffsetBytes + 0) / 255;\n const g = data.getUint8(splatOffset + colorOffsetBytes + 1) / 255;\n const b = data.getUint8(splatOffset + colorOffsetBytes + 2) / 255;\n const opacity = data.getUint8(splatOffset + colorOffsetBytes + 3) / 255;\n setPackedSplat(\n packedArray,\n i2,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n if (sphericalHarmonicsDegree >= 1) {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n for (const [i22, key] of sh1Index.entries()) {\n sh1[i22] = getSh(splatOffset, key);\n }\n encodeSh1Rgb(extra.sh1, i2, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n for (const [i22, key] of sh2Index.entries()) {\n sh2[i22] = getSh(splatOffset, key);\n }\n encodeSh2Rgb(extra.sh2, i2, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n for (const [i22, key] of sh3Index.entries()) {\n sh3[i22] = getSh(splatOffset, key);\n }\n encodeSh3Rgb(extra.sh3, i2, sh3, splatEncoding);\n }\n }\n }\n sectionBase += storageSizeBytes;\n }\n return { packedArray, numSplats, extra };\n }\n const PLY_PROPERTY_TYPES = [\n "char",\n "uchar",\n "short",\n "ushort",\n "int",\n "uint",\n "float",\n "double"\n ];\n const _PlyReader = class _PlyReader {\n // Create a PlyReader from a Uint8Array/ArrayBuffer, no parsing done yet\n constructor({ fileBytes }) {\n this.header = "";\n this.littleEndian = true;\n this.elements = {};\n this.comments = [];\n this.data = null;\n this.numSplats = 0;\n this.fileBytes = fileBytes instanceof ArrayBuffer ? new Uint8Array(fileBytes) : fileBytes;\n }\n // Identify and parse the PLY text header (assumed to be <64KB in size).\n // this.elements will contain all the elements in the file, typically\n // "vertex" contains the Gsplat data.\n async parseHeader() {\n const bufferStream = new ReadableStream({\n start: (controller) => {\n controller.enqueue(this.fileBytes.slice(0, 65536));\n controller.close();\n }\n });\n const decoder = bufferStream.pipeThrough(new TextDecoderStream()).getReader();\n this.header = "";\n const headerTerminator = "end_header\\n";\n while (true) {\n const { value, done } = await decoder.read();\n if (done) {\n throw new Error("Failed to read header");\n }\n this.header += value;\n const endHeader = this.header.indexOf(headerTerminator);\n if (endHeader >= 0) {\n this.header = this.header.slice(0, endHeader + headerTerminator.length);\n break;\n }\n }\n const headerLen = new TextEncoder().encode(this.header).length;\n this.data = new DataView(this.fileBytes.buffer, headerLen);\n this.elements = {};\n let curElement = null;\n this.comments = [];\n this.header.trim().split("\\n").forEach((line, lineIndex) => {\n const trimmedLine = line.trim();\n if (lineIndex === 0) {\n if (trimmedLine !== "ply") {\n throw new Error("Invalid PLY header");\n }\n return;\n }\n if (trimmedLine.length === 0) {\n return;\n }\n const fields = trimmedLine.split(" ");\n switch (fields[0]) {\n case "format":\n if (fields[1] === "binary_little_endian") {\n this.littleEndian = true;\n } else if (fields[1] === "binary_big_endian") {\n this.littleEndian = false;\n } else {\n throw new Error(`Unsupported PLY format: ${fields[1]}`);\n }\n if (fields[2] !== "1.0") {\n throw new Error(`Unsupported PLY version: ${fields[2]}`);\n }\n break;\n case "end_header":\n break;\n case "comment":\n this.comments.push(trimmedLine.slice("comment ".length));\n break;\n case "element": {\n const name = fields[1];\n curElement = {\n name,\n count: Number.parseInt(fields[2]),\n properties: {}\n };\n this.elements[name] = curElement;\n break;\n }\n case "property":\n if (curElement == null) {\n throw new Error("Property must be inside an element");\n }\n if (fields[1] === "list") {\n curElement.properties[fields[4]] = {\n isList: true,\n type: fields[3],\n countType: fields[2]\n };\n } else {\n curElement.properties[fields[2]] = {\n isList: false,\n type: fields[1]\n };\n }\n break;\n }\n });\n if (this.elements.vertex) {\n this.numSplats = this.elements.vertex.count;\n }\n }\n parseData(elementCallback) {\n let offset = 0;\n const data = this.data;\n if (data == null) {\n throw new Error("No data to parse");\n }\n for (const elementName in this.elements) {\n const element = this.elements[elementName];\n const { count, properties } = element;\n const item = createEmptyItem(properties);\n const parseFn = createParseFn(properties, this.littleEndian);\n const callback = elementCallback(element) ?? (() => {\n });\n for (let index = 0; index < count; index++) {\n offset = parseFn(data, offset, item);\n callback(index, item);\n }\n }\n }\n // Parse all the Gsplat data in the PLY file in go, invoking the given\n // callbacks for each Gsplat.\n parseSplats(splatCallback, shCallback) {\n if (this.elements.vertex == null) {\n throw new Error("No vertex element found");\n }\n let isSuperSplat = false;\n const ssChunks = [];\n let numSh = 0;\n let sh1Props = [];\n let sh2Props = [];\n let sh3Props = [];\n let sh1 = void 0;\n let sh2 = void 0;\n let sh3 = void 0;\n function prepareSh() {\n const num_f_rest = NUM_SH_TO_NUM_F_REST[numSh];\n sh1Props = new Array(3).fill(null).flatMap((_, k) => [0, 1, 2].map((_2, d) => k + d * num_f_rest / 3));\n sh2Props = new Array(5).fill(null).flatMap(\n (_, k) => [0, 1, 2].map((_2, d) => 3 + k + d * num_f_rest / 3)\n );\n sh3Props = new Array(7).fill(null).flatMap(\n (_, k) => [0, 1, 2].map((_2, d) => 8 + k + d * num_f_rest / 3)\n );\n sh1 = numSh >= 1 ? new Float32Array(3 * 3) : void 0;\n sh2 = numSh >= 2 ? new Float32Array(5 * 3) : void 0;\n sh3 = numSh >= 3 ? new Float32Array(7 * 3) : void 0;\n }\n function ssShCallback(index, item) {\n if (!sh1) {\n throw new Error("Missing sh1");\n }\n const sh = item.f_rest;\n for (let i2 = 0; i2 < sh1Props.length; i2++) {\n sh1[i2] = sh[sh1Props[i2]] * 8 / 255 - 4;\n }\n if (sh2) {\n for (let i2 = 0; i2 < sh2Props.length; i2++) {\n sh2[i2] = sh[sh2Props[i2]] * 8 / 255 - 4;\n }\n }\n if (sh3) {\n for (let i2 = 0; i2 < sh3Props.length; i2++) {\n sh3[i2] = sh[sh3Props[i2]] * 8 / 255 - 4;\n }\n }\n shCallback == null ? void 0 : shCallback(index, sh1, sh2, sh3);\n }\n function initSuperSplat(element) {\n const {\n min_x,\n min_y,\n min_z,\n max_x,\n max_y,\n max_z,\n min_scale_x,\n min_scale_y,\n min_scale_z,\n max_scale_x,\n max_scale_y,\n max_scale_z\n } = element.properties;\n if (!min_x || !min_y || !min_z || !max_x || !max_y || !max_z || !min_scale_x || !min_scale_y || !min_scale_z || !max_scale_x || !max_scale_y || !max_scale_z) {\n throw new Error("Missing PLY chunk properties");\n }\n isSuperSplat = true;\n return (index, item) => {\n const {\n min_x: min_x2,\n min_y: min_y2,\n min_z: min_z2,\n max_x: max_x2,\n max_y: max_y2,\n max_z: max_z2,\n min_scale_x: min_scale_x2,\n min_scale_y: min_scale_y2,\n min_scale_z: min_scale_z2,\n max_scale_x: max_scale_x2,\n max_scale_y: max_scale_y2,\n max_scale_z: max_scale_z2,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n } = item;\n ssChunks.push({\n min_x: min_x2,\n min_y: min_y2,\n min_z: min_z2,\n max_x: max_x2,\n max_y: max_y2,\n max_z: max_z2,\n min_scale_x: min_scale_x2,\n min_scale_y: min_scale_y2,\n min_scale_z: min_scale_z2,\n max_scale_x: max_scale_x2,\n max_scale_y: max_scale_y2,\n max_scale_z: max_scale_z2,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n });\n };\n }\n function decodeSuperSplat(element) {\n if (shCallback && element.name === "sh") {\n numSh = getNumSh(element.properties);\n prepareSh();\n return ssShCallback;\n }\n if (element.name !== "vertex") {\n return null;\n }\n const { packed_position, packed_rotation, packed_scale, packed_color } = element.properties;\n if (!packed_position || !packed_rotation || !packed_scale || !packed_color) {\n throw new Error(\n "Missing PLY properties: packed_position, packed_rotation, packed_scale, packed_color"\n );\n }\n const SQRT2 = Math.sqrt(2);\n return (index, item) => {\n const chunk = ssChunks[index >>> 8];\n if (chunk == null) {\n throw new Error("Missing PLY chunk");\n }\n const {\n min_x,\n min_y,\n min_z,\n max_x,\n max_y,\n max_z,\n min_scale_x,\n min_scale_y,\n min_scale_z,\n max_scale_x,\n max_scale_y,\n max_scale_z,\n min_r,\n min_g,\n min_b,\n max_r,\n max_g,\n max_b\n } = chunk;\n const { packed_position: packed_position2, packed_rotation: packed_rotation2, packed_scale: packed_scale2, packed_color: packed_color2 } = item;\n const x2 = (packed_position2 >>> 21 & 2047) / 2047 * (max_x - min_x) + min_x;\n const y = (packed_position2 >>> 11 & 1023) / 1023 * (max_y - min_y) + min_y;\n const z = (packed_position2 & 2047) / 2047 * (max_z - min_z) + min_z;\n const r0 = ((packed_rotation2 >>> 20 & 1023) / 1023 - 0.5) * SQRT2;\n const r1 = ((packed_rotation2 >>> 10 & 1023) / 1023 - 0.5) * SQRT2;\n const r2 = ((packed_rotation2 & 1023) / 1023 - 0.5) * SQRT2;\n const rr = Math.sqrt(Math.max(0, 1 - r0 * r0 - r1 * r1 - r2 * r2));\n const rOrder = packed_rotation2 >>> 30;\n const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1;\n const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2;\n const quatZ = rOrder <= 2 ? r2 : rr;\n const quatW = rOrder === 0 ? rr : r0;\n const scaleX = Math.exp(\n (packed_scale2 >>> 21 & 2047) / 2047 * (max_scale_x - min_scale_x) + min_scale_x\n );\n const scaleY = Math.exp(\n (packed_scale2 >>> 11 & 1023) / 1023 * (max_scale_y - min_scale_y) + min_scale_y\n );\n const scaleZ = Math.exp(\n (packed_scale2 & 2047) / 2047 * (max_scale_z - min_scale_z) + min_scale_z\n );\n const r = (packed_color2 >>> 24 & 255) / 255 * ((max_r ?? 1) - (min_r ?? 0)) + (min_r ?? 0);\n const g = (packed_color2 >>> 16 & 255) / 255 * ((max_g ?? 1) - (min_g ?? 0)) + (min_g ?? 0);\n const b = (packed_color2 >>> 8 & 255) / 255 * ((max_b ?? 1) - (min_b ?? 0)) + (min_b ?? 0);\n const opacity = (packed_color2 & 255) / 255;\n splatCallback(\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b\n );\n };\n }\n const elementCallback = (element) => {\n if (element.name === "chunk") {\n return initSuperSplat(element);\n }\n if (isSuperSplat) {\n return decodeSuperSplat(element);\n }\n if (element.name !== "vertex") {\n return null;\n }\n const {\n x: x2,\n y,\n z,\n scale_0,\n scale_1,\n scale_2,\n rot_0,\n rot_1,\n rot_2,\n rot_3,\n opacity,\n f_dc_0,\n f_dc_1,\n f_dc_2,\n red,\n green,\n blue,\n alpha\n } = element.properties;\n if (!x2 || !y || !z) {\n throw new Error("Missing PLY properties: x, y, z");\n }\n const hasScales = scale_0 && scale_1 && scale_2;\n const hasRots = rot_0 && rot_1 && rot_2 && rot_3;\n const alphaDiv = alpha != null ? FIELD_SCALE[alpha.type] : 1;\n const redDiv = red != null ? FIELD_SCALE[red.type] : 1;\n const greenDiv = green != null ? FIELD_SCALE[green.type] : 1;\n const blueDiv = blue != null ? FIELD_SCALE[blue.type] : 1;\n numSh = getNumSh(element.properties);\n prepareSh();\n return (index, item) => {\n const scaleX = hasScales ? Math.exp(item.scale_0) : _PlyReader.defaultPointScale;\n const scaleY = hasScales ? Math.exp(item.scale_1) : _PlyReader.defaultPointScale;\n const scaleZ = hasScales ? Math.exp(item.scale_2) : _PlyReader.defaultPointScale;\n const quatX = hasRots ? item.rot_1 : 0;\n const quatY = hasRots ? item.rot_2 : 0;\n const quatZ = hasRots ? item.rot_3 : 0;\n const quatW = hasRots ? item.rot_0 : 1;\n const op = opacity != null ? 1 / (1 + Math.exp(-item.opacity)) : alpha != null ? item.alpha / alphaDiv : 1;\n const r = f_dc_0 != null ? item.f_dc_0 * SH_C0$1 + 0.5 : red != null ? item.red / redDiv : 1;\n const g = f_dc_1 != null ? item.f_dc_1 * SH_C0$1 + 0.5 : green != null ? item.green / greenDiv : 1;\n const b = f_dc_2 != null ? item.f_dc_2 * SH_C0$1 + 0.5 : blue != null ? item.blue / blueDiv : 1;\n splatCallback(\n index,\n item.x,\n item.y,\n item.z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n op,\n r,\n g,\n b\n );\n if (shCallback && sh1) {\n const sh = item.f_rest;\n if (sh1) {\n for (let i2 = 0; i2 < sh1Props.length; i2++) {\n sh1[i2] = sh[sh1Props[i2]];\n }\n }\n if (sh2) {\n for (let i2 = 0; i2 < sh2Props.length; i2++) {\n sh2[i2] = sh[sh2Props[i2]];\n }\n }\n if (sh3) {\n for (let i2 = 0; i2 < sh3Props.length; i2++) {\n sh3[i2] = sh[sh3Props[i2]];\n }\n }\n shCallback(index, sh1, sh2, sh3);\n }\n };\n };\n this.parseData(elementCallback);\n }\n // Inject RGBA values into original PLY file, which can be used to modify\n // the color/opacity of the Gsplats and write out the modified PLY file.\n injectRgba(rgba) {\n let offset = 0;\n const data = this.data;\n if (data == null) {\n throw new Error("No parsed data");\n }\n if (rgba.length !== this.numSplats * 4) {\n throw new Error("Invalid RGBA array length");\n }\n for (const elementName in this.elements) {\n const element = this.elements[elementName];\n const { count, properties } = element;\n const parsers = [];\n let rgbaOffset = 0;\n const isVertex = elementName === "vertex";\n if (isVertex) {\n for (const name of ["opacity", "f_dc_0", "f_dc_1", "f_dc_2"]) {\n if (!properties[name] || properties[name].type !== "float") {\n throw new Error(`Can\'t injectRgba due to property: ${name}`);\n }\n }\n }\n for (const [propertyName, property] of Object.entries(properties)) {\n if (!property.isList) {\n if (isVertex) {\n if (propertyName === "f_dc_0" || propertyName === "f_dc_1" || propertyName === "f_dc_2") {\n const component = Number.parseInt(\n propertyName.slice("f_dc_".length)\n );\n parsers.push(() => {\n const value = (rgba[rgbaOffset + component] / 255 - 0.5) / SH_C0$1;\n SET_FIELD[property.type](\n data,\n offset,\n this.littleEndian,\n value\n );\n });\n } else if (propertyName === "opacity") {\n parsers.push(() => {\n const value = Math.max(\n -100,\n Math.min(\n 100,\n -Math.log(1 / (rgba[rgbaOffset + 3] / 255) - 1)\n )\n );\n SET_FIELD[property.type](\n data,\n offset,\n this.littleEndian,\n value\n );\n });\n }\n }\n parsers.push(() => {\n offset += FIELD_BYTES[property.type];\n });\n } else {\n parsers.push(() => {\n const length = PARSE_FIELD[property.countType](\n data,\n offset,\n this.littleEndian\n );\n offset += FIELD_BYTES[property.countType];\n offset += length * FIELD_BYTES[property.type];\n });\n }\n }\n for (let index = 0; index < count; index++) {\n for (const parser of parsers) {\n parser();\n }\n if (isVertex) {\n rgbaOffset += 4;\n }\n }\n }\n }\n };\n _PlyReader.defaultPointScale = 1e-3;\n let PlyReader = _PlyReader;\n const SH_C0$1 = 0.28209479177387814;\n const PARSE_FIELD = {\n char: (data, offset, littleEndian) => {\n return data.getInt8(offset);\n },\n uchar: (data, offset, littleEndian) => {\n return data.getUint8(offset);\n },\n short: (data, offset, littleEndian) => {\n return data.getInt16(offset, littleEndian);\n },\n ushort: (data, offset, littleEndian) => {\n return data.getUint16(offset, littleEndian);\n },\n int: (data, offset, littleEndian) => {\n return data.getInt32(offset, littleEndian);\n },\n uint: (data, offset, littleEndian) => {\n return data.getUint32(offset, littleEndian);\n },\n float: (data, offset, littleEndian) => {\n return data.getFloat32(offset, littleEndian);\n },\n double: (data, offset, littleEndian) => {\n return data.getFloat64(offset, littleEndian);\n }\n };\n const SET_FIELD = {\n char: (data, offset, littleEndian, value) => {\n data.setInt8(offset, value);\n },\n uchar: (data, offset, littleEndian, value) => {\n data.setUint8(offset, value);\n },\n short: (data, offset, littleEndian, value) => {\n data.setInt16(offset, value, littleEndian);\n },\n ushort: (data, offset, littleEndian, value) => {\n data.setUint16(offset, value, littleEndian);\n },\n int: (data, offset, littleEndian, value) => {\n data.setInt32(offset, value, littleEndian);\n },\n uint: (data, offset, littleEndian, value) => {\n data.setUint32(offset, value, littleEndian);\n },\n float: (data, offset, littleEndian, value) => {\n data.setFloat32(offset, value, littleEndian);\n },\n double: (data, offset, littleEndian, value) => {\n data.setFloat64(offset, value, littleEndian);\n }\n };\n const FIELD_BYTES = {\n char: 1,\n uchar: 1,\n short: 2,\n ushort: 2,\n int: 4,\n uint: 4,\n float: 4,\n double: 8\n };\n const FIELD_SCALE = {\n char: 127,\n uchar: 255,\n short: 32767,\n ushort: 65535,\n int: 2147483647,\n uint: 4294967295,\n float: 1,\n double: 1\n };\n const NUM_F_REST_TO_NUM_SH = {\n 0: 0,\n 9: 1,\n 24: 2,\n 45: 3\n };\n const NUM_SH_TO_NUM_F_REST = {\n 0: 0,\n 1: 9,\n 2: 24,\n 3: 45\n };\n const F_REST_REGEX = /^f_rest_([0-9]{1,2})$/;\n function createEmptyItem(properties) {\n const item = {};\n for (const [propertyName, property] of Object.entries(properties)) {\n if (F_REST_REGEX.test(propertyName)) {\n item.f_rest = new Array(getNumSh(properties));\n } else {\n item[propertyName] = property.isList ? [] : 0;\n }\n }\n return item;\n }\n function createParseFn(properties, littleEndian) {\n if (safeToCompile(properties)) {\n return createCompiledParserFn(properties, littleEndian);\n }\n return createDynamicParserFn(properties, littleEndian);\n }\n const UNSAFE_EVAL_ALLOWED = (() => {\n try {\n new Function("return 42;");\n } catch (e) {\n return false;\n }\n return true;\n })();\n const PROPERTY_NAME_REGEX = /^[a-zA-Z0-9_]+$/;\n function safeToCompile(properties) {\n if (!UNSAFE_EVAL_ALLOWED) {\n return false;\n }\n for (const [propertyName, property] of Object.entries(properties)) {\n if (!PROPERTY_NAME_REGEX.test(propertyName)) {\n return false;\n }\n if (property.isList && !PLY_PROPERTY_TYPES.includes(property.countType)) {\n return false;\n }\n if (!PLY_PROPERTY_TYPES.includes(property.type)) {\n return false;\n }\n }\n return true;\n }\n function createCompiledParserFn(properties, littleEndian) {\n const parserSrc = ["let list;"];\n for (const [propertyName, property] of Object.entries(properties)) {\n const fRestMatch = propertyName.match(F_REST_REGEX);\n if (fRestMatch) {\n const fRestIndex = +fRestMatch[1];\n parserSrc.push(\n /*js*/\n `\n item.f_rest[${fRestIndex}] = PARSE_FIELD[\'${property.type}\'](data, offset, ${littleEndian});\n offset += ${FIELD_BYTES[property.type]};\n `\n );\n } else if (!property.isList) {\n parserSrc.push(\n /*js*/\n `\n item[\'${propertyName}\'] = PARSE_FIELD[\'${property.type}\'](data, offset, ${littleEndian});\n offset += ${FIELD_BYTES[property.type]};\n `\n );\n } else {\n parserSrc.push(\n /*js*/\n `\n list = item[\'${propertyName}\'];\n list.length = PARSE_FIELD[\'${property.countType}\'](data, offset, ${littleEndian});\n offset += ${FIELD_BYTES[property.countType]};\n for (let i = 0; i < list.length; i++) {\n list[i] = PARSE_FIELD[\'${property.type}\'](data, offset, ${littleEndian});\n offset += ${FIELD_BYTES[property.type]};\n }\n `\n );\n }\n }\n parserSrc.push("return offset;");\n const fn = new Function(\n "data",\n "offset",\n "item",\n "PARSE_FIELD",\n parserSrc.join("\\n")\n );\n return (data, offset, item) => fn(data, offset, item, PARSE_FIELD);\n }\n function createDynamicParserFn(properties, littleEndian) {\n const parsers = [];\n for (const [propertyName, property] of Object.entries(properties)) {\n const fRestMatch = propertyName.match(F_REST_REGEX);\n if (fRestMatch) {\n const fRestIndex = +fRestMatch[1];\n parsers.push(\n (data, offset, item) => {\n item.f_rest[fRestIndex] = PARSE_FIELD[property.type](\n data,\n offset,\n littleEndian\n );\n return offset + FIELD_BYTES[property.type];\n }\n );\n } else if (!property.isList) {\n parsers.push(\n (data, offset, item) => {\n item[propertyName] = PARSE_FIELD[property.type](\n data,\n offset,\n littleEndian\n );\n return offset + FIELD_BYTES[property.type];\n }\n );\n } else {\n parsers.push(\n (data, offset, item) => {\n const list = item[propertyName];\n list.length = PARSE_FIELD[property.countType](\n data,\n offset,\n littleEndian\n );\n let currentOffset = offset + FIELD_BYTES[property.countType];\n for (let i2 = 0; i2 < list.length; i2++) {\n list[i2] = PARSE_FIELD[property.type](\n data,\n currentOffset,\n littleEndian\n );\n currentOffset += FIELD_BYTES[property.type];\n }\n return currentOffset;\n }\n );\n }\n }\n return (data, offset, item) => {\n let currentOffset = offset;\n for (let parserIndex = 0; parserIndex < parsers.length; parserIndex++) {\n currentOffset = parsers[parserIndex](data, currentOffset, item);\n }\n return currentOffset;\n };\n }\n function getNumSh(properties) {\n let num_f_rest = 0;\n while (properties[`f_rest_${num_f_rest}`]) {\n num_f_rest += 1;\n }\n const numSh = NUM_F_REST_TO_NUM_SH[num_f_rest];\n if (numSh == null) {\n throw new Error(`Unsupported number of SH coefficients: ${num_f_rest}`);\n }\n return numSh;\n }\n var SplatFileType = /* @__PURE__ */ ((SplatFileType2) => {\n SplatFileType2["PLY"] = "ply";\n SplatFileType2["SPZ"] = "spz";\n SplatFileType2["SPLAT"] = "splat";\n SplatFileType2["KSPLAT"] = "ksplat";\n SplatFileType2["PCSOGS"] = "pcsogs";\n SplatFileType2["PCSOGSZIP"] = "pcsogszip";\n return SplatFileType2;\n })(SplatFileType || {});\n function getSplatFileType(fileBytes) {\n const view = new DataView(fileBytes.buffer);\n if ((view.getUint32(0, true) & 16777215) === 7957616) {\n return "ply";\n }\n if ((view.getUint32(0, true) & 16777215) === 559903) {\n const header = decompressPartialGzip(fileBytes, 4);\n const gView = new DataView(header.buffer);\n if (gView.getUint32(0, true) === 1347635022) {\n return "spz";\n }\n return void 0;\n }\n if (view.getUint32(0, true) === 67324752) {\n if (tryPcSogsZip(fileBytes)) {\n return "pcsogszip";\n }\n return void 0;\n }\n return void 0;\n }\n function getFileExtension(pathOrUrl) {\n const noTrailing = pathOrUrl.split(/[?#]/, 1)[0];\n const lastSlash = Math.max(\n noTrailing.lastIndexOf("/"),\n noTrailing.lastIndexOf("\\\\")\n );\n const filename = noTrailing.slice(lastSlash + 1);\n const lastDot = filename.lastIndexOf(".");\n if (lastDot <= 0 || lastDot === filename.length - 1) {\n return "";\n }\n return filename.slice(lastDot + 1).toLowerCase();\n }\n function getSplatFileTypeFromPath(pathOrUrl) {\n const extension = getFileExtension(pathOrUrl);\n if (extension === "ply") {\n return "ply";\n }\n if (extension === "spz") {\n return "spz";\n }\n if (extension === "splat") {\n return "splat";\n }\n if (extension === "ksplat") {\n return "ksplat";\n }\n if (extension === "sog") {\n return "pcsogszip";\n }\n return void 0;\n }\n function tryPcSogs(input) {\n try {\n let text;\n if (typeof input === "string") {\n text = input;\n } else {\n const fileBytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input;\n if (fileBytes.length > 65536) {\n return void 0;\n }\n text = new TextDecoder().decode(fileBytes);\n }\n const json = JSON.parse(text);\n if (!json || typeof json !== "object" || Array.isArray(json)) {\n return void 0;\n }\n const isVersion2 = json.version === 2;\n for (const key of ["means", "scales", "quats", "sh0"]) {\n if (!json[key] || typeof json[key] !== "object" || Array.isArray(json[key])) {\n return void 0;\n }\n if (isVersion2) {\n if (!json[key].files) {\n return void 0;\n }\n if ((key === "scales" || key === "sh0") && !json[key].codebook) {\n return void 0;\n }\n if (key === "means" && (!json[key].mins || !json[key].maxs)) {\n return void 0;\n }\n } else {\n if (!json[key].shape || !json[key].files) {\n return void 0;\n }\n if (key !== "quats" && (!json[key].mins || !json[key].maxs)) {\n return void 0;\n }\n }\n }\n return json;\n } catch {\n return void 0;\n }\n }\n function tryPcSogsZip(input) {\n try {\n const fileBytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input;\n let metaFilename = null;\n const unzipped = unzipSync(fileBytes, {\n filter: ({ name }) => {\n const filename = name.split(/[\\\\/]/).pop();\n if (filename === "meta.json") {\n metaFilename = name;\n return true;\n }\n return false;\n }\n });\n if (!metaFilename) {\n return void 0;\n }\n const json = tryPcSogs(unzipped[metaFilename]);\n if (!json) {\n return void 0;\n }\n return { name: metaFilename, json };\n } catch {\n return void 0;\n }\n }\n class SplatData {\n constructor({ maxSplats = 1 } = {}) {\n this.numSplats = 0;\n this.maxSplats = getTextureSize(maxSplats).maxSplats;\n this.centers = new Float32Array(this.maxSplats * 3);\n this.scales = new Float32Array(this.maxSplats * 3);\n this.quaternions = new Float32Array(this.maxSplats * 4);\n this.opacities = new Float32Array(this.maxSplats);\n this.colors = new Float32Array(this.maxSplats * 3);\n }\n pushSplat() {\n const index = this.numSplats;\n this.ensureIndex(index);\n this.numSplats += 1;\n return index;\n }\n unpushSplat(index) {\n if (index === this.numSplats - 1) {\n this.numSplats -= 1;\n } else {\n throw new Error("Cannot unpush splat from non-last position");\n }\n }\n ensureCapacity(numSplats) {\n if (numSplats > this.maxSplats) {\n const targetSplats = Math.max(numSplats, this.maxSplats * 2);\n const newCenters = new Float32Array(targetSplats * 3);\n const newScales = new Float32Array(targetSplats * 3);\n const newQuaternions = new Float32Array(targetSplats * 4);\n const newOpacities = new Float32Array(targetSplats);\n const newColors = new Float32Array(targetSplats * 3);\n newCenters.set(this.centers);\n newScales.set(this.scales);\n newQuaternions.set(this.quaternions);\n newOpacities.set(this.opacities);\n newColors.set(this.colors);\n this.centers = newCenters;\n this.scales = newScales;\n this.quaternions = newQuaternions;\n this.opacities = newOpacities;\n this.colors = newColors;\n if (this.sh1) {\n const newSh1 = new Float32Array(targetSplats * 9);\n newSh1.set(this.sh1);\n this.sh1 = newSh1;\n }\n if (this.sh2) {\n const newSh2 = new Float32Array(targetSplats * 15);\n newSh2.set(this.sh2);\n this.sh2 = newSh2;\n }\n if (this.sh3) {\n const newSh3 = new Float32Array(targetSplats * 21);\n newSh3.set(this.sh3);\n this.sh3 = newSh3;\n }\n this.maxSplats = targetSplats;\n }\n }\n ensureIndex(index) {\n this.ensureCapacity(index + 1);\n }\n setCenter(index, x2, y, z) {\n this.centers[index * 3] = x2;\n this.centers[index * 3 + 1] = y;\n this.centers[index * 3 + 2] = z;\n }\n setScale(index, scaleX, scaleY, scaleZ) {\n this.scales[index * 3] = scaleX;\n this.scales[index * 3 + 1] = scaleY;\n this.scales[index * 3 + 2] = scaleZ;\n }\n setQuaternion(index, x2, y, z, w) {\n this.quaternions[index * 4] = x2;\n this.quaternions[index * 4 + 1] = y;\n this.quaternions[index * 4 + 2] = z;\n this.quaternions[index * 4 + 3] = w;\n }\n setOpacity(index, opacity) {\n this.opacities[index] = opacity;\n }\n setColor(index, r, g, b) {\n this.colors[index * 3] = r;\n this.colors[index * 3 + 1] = g;\n this.colors[index * 3 + 2] = b;\n }\n setSh1(index, sh1) {\n if (!this.sh1) {\n this.sh1 = new Float32Array(this.maxSplats * 9);\n }\n for (let j = 0; j < 9; ++j) {\n this.sh1[index * 9 + j] = sh1[j];\n }\n }\n setSh2(index, sh2) {\n if (!this.sh2) {\n this.sh2 = new Float32Array(this.maxSplats * 15);\n }\n for (let j = 0; j < 15; ++j) {\n this.sh2[index * 15 + j] = sh2[j];\n }\n }\n setSh3(index, sh3) {\n if (!this.sh3) {\n this.sh3 = new Float32Array(this.maxSplats * 21);\n }\n for (let j = 0; j < 21; ++j) {\n this.sh3[index * 21 + j] = sh3[j];\n }\n }\n }\n async function unpackPcSogs(json, extraFiles, splatEncoding) {\n const isVersion2 = "version" in json;\n if (!isVersion2 && json.quats.encoding !== "quaternion_packed") {\n throw new Error("Unsupported quaternion encoding");\n }\n const numSplats = isVersion2 ? json.count : json.means.shape[0];\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n const meansPromise = Promise.all([\n decodeImageRgba(extraFiles[json.means.files[0]]),\n decodeImageRgba(extraFiles[json.means.files[1]])\n ]).then((means) => {\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const fx = (means[0][i4 + 0] + (means[1][i4 + 0] << 8)) / 65535;\n const fy = (means[0][i4 + 1] + (means[1][i4 + 1] << 8)) / 65535;\n const fz = (means[0][i4 + 2] + (means[1][i4 + 2] << 8)) / 65535;\n let x2 = json.means.mins[0] + (json.means.maxs[0] - json.means.mins[0]) * fx;\n let y = json.means.mins[1] + (json.means.maxs[1] - json.means.mins[1]) * fy;\n let z = json.means.mins[2] + (json.means.maxs[2] - json.means.mins[2]) * fz;\n x2 = Math.sign(x2) * (Math.exp(Math.abs(x2)) - 1);\n y = Math.sign(y) * (Math.exp(Math.abs(y)) - 1);\n z = Math.sign(z) * (Math.exp(Math.abs(z)) - 1);\n setPackedSplatCenter(packedArray, i2, x2, y, z);\n }\n });\n const scalesPromise = decodeImageRgba(extraFiles[json.scales.files[0]]).then(\n (scales) => {\n let xLookup;\n let yLookup;\n let zLookup;\n if (isVersion2) {\n xLookup = yLookup = zLookup = json.scales.codebook.map((x2) => Math.exp(x2));\n } else {\n xLookup = new Array(256).fill(0).map(\n (_, i2) => json.scales.mins[0] + (json.scales.maxs[0] - json.scales.mins[0]) * (i2 / 255)\n ).map((x2) => Math.exp(x2));\n yLookup = new Array(256).fill(0).map(\n (_, i2) => json.scales.mins[1] + (json.scales.maxs[1] - json.scales.mins[1]) * (i2 / 255)\n ).map((x2) => Math.exp(x2));\n zLookup = new Array(256).fill(0).map(\n (_, i2) => json.scales.mins[2] + (json.scales.maxs[2] - json.scales.mins[2]) * (i2 / 255)\n ).map((x2) => Math.exp(x2));\n }\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n setPackedSplatScales(\n packedArray,\n i2,\n xLookup[scales[i4 + 0]],\n yLookup[scales[i4 + 1]],\n zLookup[scales[i4 + 2]],\n splatEncoding\n );\n }\n }\n );\n const quatsPromise = decodeImageRgba(extraFiles[json.quats.files[0]]).then(\n (quats) => {\n const SQRT2 = Math.sqrt(2);\n const lookup = new Array(256).fill(0).map((_, i2) => (i2 / 255 - 0.5) * SQRT2);\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const r0 = lookup[quats[i4 + 0]];\n const r1 = lookup[quats[i4 + 1]];\n const r2 = lookup[quats[i4 + 2]];\n const rr = Math.sqrt(Math.max(0, 1 - r0 * r0 - r1 * r1 - r2 * r2));\n const rOrder = quats[i4 + 3] - 252;\n const quatX = rOrder === 0 ? r0 : rOrder === 1 ? rr : r1;\n const quatY = rOrder <= 1 ? r1 : rOrder === 2 ? rr : r2;\n const quatZ = rOrder <= 2 ? r2 : rr;\n const quatW = rOrder === 0 ? rr : r0;\n setPackedSplatQuat(packedArray, i2, quatX, quatY, quatZ, quatW);\n }\n }\n );\n const sh0Promise = decodeImageRgba(extraFiles[json.sh0.files[0]]).then(\n (sh0) => {\n const SH_C02 = 0.28209479177387814;\n let rLookup;\n let gLookup;\n let bLookup;\n let aLookup;\n if (isVersion2) {\n rLookup = gLookup = bLookup = json.sh0.codebook.map((x2) => SH_C02 * x2 + 0.5);\n aLookup = new Array(256).fill(0).map((_, i2) => i2 / 255);\n } else {\n rLookup = new Array(256).fill(0).map(\n (_, i2) => json.sh0.mins[0] + (json.sh0.maxs[0] - json.sh0.mins[0]) * (i2 / 255)\n ).map((x2) => SH_C02 * x2 + 0.5);\n gLookup = new Array(256).fill(0).map(\n (_, i2) => json.sh0.mins[1] + (json.sh0.maxs[1] - json.sh0.mins[1]) * (i2 / 255)\n ).map((x2) => SH_C02 * x2 + 0.5);\n bLookup = new Array(256).fill(0).map(\n (_, i2) => json.sh0.mins[2] + (json.sh0.maxs[2] - json.sh0.mins[2]) * (i2 / 255)\n ).map((x2) => SH_C02 * x2 + 0.5);\n aLookup = new Array(256).fill(0).map(\n (_, i2) => json.sh0.mins[3] + (json.sh0.maxs[3] - json.sh0.mins[3]) * (i2 / 255)\n ).map((x2) => 1 / (1 + Math.exp(-x2)));\n }\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n setPackedSplatRgba(\n packedArray,\n i2,\n rLookup[sh0[i4 + 0]],\n gLookup[sh0[i4 + 1]],\n bLookup[sh0[i4 + 2]],\n aLookup[sh0[i4 + 3]],\n splatEncoding\n );\n }\n }\n );\n const promises = [meansPromise, scalesPromise, quatsPromise, sh0Promise];\n if (json.shN) {\n const useSH3 = isVersion2 ? json.shN.bands >= 3 : json.shN.shape[1] >= 48 - 3;\n const useSH2 = isVersion2 ? json.shN.bands >= 2 : json.shN.shape[1] >= 27 - 3;\n const useSH1 = isVersion2 ? json.shN.bands >= 1 : json.shN.shape[1] >= 12 - 3;\n if (useSH1) extra.sh1 = new Uint32Array(numSplats * 2);\n if (useSH2) extra.sh2 = new Uint32Array(numSplats * 4);\n if (useSH3) extra.sh3 = new Uint32Array(numSplats * 4);\n const sh1 = new Float32Array(9);\n const sh2 = new Float32Array(15);\n const sh3 = new Float32Array(21);\n const shN = json.shN;\n const shNPromise = Promise.all([\n decodeImage(extraFiles[json.shN.files[0]]),\n decodeImage(extraFiles[json.shN.files[1]])\n ]).then(([centroids, labels]) => {\n const lookup = "codebook" in shN ? shN.codebook : new Array(256).fill(0).map((_, i2) => shN.mins + (shN.maxs - shN.mins) * (i2 / 255));\n for (let i2 = 0; i2 < numSplats; ++i2) {\n const i4 = i2 * 4;\n const label = labels.rgba[i4 + 0] + (labels.rgba[i4 + 1] << 8);\n const col = (label & 63) * 15;\n const row = label >>> 6;\n const offset = row * centroids.width + col;\n for (let d = 0; d < 3; ++d) {\n if (useSH1) {\n for (let k = 0; k < 3; ++k) {\n sh1[k * 3 + d] = lookup[centroids.rgba[(offset + k) * 4 + d]];\n }\n }\n if (useSH2) {\n for (let k = 0; k < 5; ++k) {\n sh2[k * 3 + d] = lookup[centroids.rgba[(offset + 3 + k) * 4 + d]];\n }\n }\n if (useSH3) {\n for (let k = 0; k < 7; ++k) {\n sh3[k * 3 + d] = lookup[centroids.rgba[(offset + 8 + k) * 4 + d]];\n }\n }\n }\n if (useSH1)\n encodeSh1Rgb(extra.sh1, i2, sh1, splatEncoding);\n if (useSH2)\n encodeSh2Rgb(extra.sh2, i2, sh2, splatEncoding);\n if (useSH3)\n encodeSh3Rgb(extra.sh3, i2, sh3, splatEncoding);\n }\n });\n promises.push(shNPromise);\n }\n await Promise.all(promises);\n return { packedArray, numSplats, extra };\n }\n let offscreenGlContext = null;\n async function decodeImage(fileBytes) {\n if (!offscreenGlContext) {\n const canvas = new OffscreenCanvas(1, 1);\n offscreenGlContext = canvas.getContext("webgl2");\n if (!offscreenGlContext) {\n throw new Error("Failed to create WebGL2 context");\n }\n }\n const imageBlob = new Blob([fileBytes]);\n const bitmap = await createImageBitmap(imageBlob, {\n premultiplyAlpha: "none"\n });\n const gl = offscreenGlContext;\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n const framebuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n const data = new Uint8Array(bitmap.width * bitmap.height * 4);\n gl.readPixels(\n 0,\n 0,\n bitmap.width,\n bitmap.height,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n data\n );\n gl.deleteTexture(texture);\n gl.deleteFramebuffer(framebuffer);\n return { rgba: data, width: bitmap.width, height: bitmap.height };\n }\n async function decodeImageRgba(fileBytes) {\n const { rgba } = await decodeImage(fileBytes);\n return rgba;\n }\n async function unpackPcSogsZip(fileBytes, splatEncoding) {\n var _a2;\n const nameJson = tryPcSogsZip(fileBytes);\n if (!nameJson) {\n throw new Error("Invalid PC SOGS zip file");\n }\n const { name, json } = nameJson;\n const lastSlash = name.lastIndexOf("/");\n const lastBackslash = name.lastIndexOf("\\\\");\n const prefix = name.slice(0, Math.max(lastSlash, lastBackslash) + 1);\n const fileMap = /* @__PURE__ */ new Map();\n const refFiles = [\n ...json.means.files,\n ...json.scales.files,\n ...json.quats.files,\n ...json.sh0.files,\n ...((_a2 = json.shN) == null ? void 0 : _a2.files) ?? []\n ];\n for (const file of refFiles) {\n fileMap.set(prefix + file, file);\n }\n const unzipped = await new Promise(\n (resolve, reject) => {\n unzip(\n fileBytes,\n {\n filter: ({ name: name2 }) => {\n return fileMap.has(name2);\n }\n },\n (err2, files) => {\n if (err2) {\n reject(err2);\n } else {\n resolve(files);\n }\n }\n );\n }\n );\n const extraFiles = {};\n for (const [full, name2] of fileMap.entries()) {\n extraFiles[name2] = unzipped[full];\n }\n return await unpackPcSogs(json, extraFiles, splatEncoding);\n }\n class SpzReader {\n constructor({ fileBytes }) {\n this.version = -1;\n this.numSplats = 0;\n this.shDegree = 0;\n this.fractionalBits = 0;\n this.flags = 0;\n this.flagAntiAlias = false;\n this.reserved = 0;\n this.headerParsed = false;\n this.parsed = false;\n this.fileBytes = fileBytes instanceof ArrayBuffer ? new Uint8Array(fileBytes) : fileBytes;\n this.reader = new GunzipReader({ fileBytes: this.fileBytes });\n }\n async parseHeader() {\n if (this.headerParsed) {\n throw new Error("SPZ file header already parsed");\n }\n const header = new DataView((await this.reader.read(16)).buffer);\n if (header.getUint32(0, true) !== 1347635022) {\n throw new Error("Invalid SPZ file");\n }\n this.version = header.getUint32(4, true);\n if (this.version < 1 || this.version > 3) {\n throw new Error(`Unsupported SPZ version: ${this.version}`);\n }\n this.numSplats = header.getUint32(8, true);\n this.shDegree = header.getUint8(12);\n this.fractionalBits = header.getUint8(13);\n this.flags = header.getUint8(14);\n this.flagAntiAlias = (this.flags & 1) !== 0;\n this.reserved = header.getUint8(15);\n this.headerParsed = true;\n this.parsed = false;\n }\n async parseSplats(centerCallback, alphaCallback, rgbCallback, scalesCallback, quatCallback, shCallback) {\n if (!this.headerParsed) {\n throw new Error("SPZ file header must be parsed first");\n }\n if (this.parsed) {\n throw new Error("SPZ file already parsed");\n }\n this.parsed = true;\n if (this.version === 1) {\n const centerBytes = await this.reader.read(this.numSplats * 3 * 2);\n const centerUint16 = new Uint16Array(centerBytes.buffer);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const x2 = fromHalf(centerUint16[i3]);\n const y = fromHalf(centerUint16[i3 + 1]);\n const z = fromHalf(centerUint16[i3 + 2]);\n centerCallback == null ? void 0 : centerCallback(i2, x2, y, z);\n }\n } else if (this.version === 2 || this.version === 3) {\n const fixed = 1 << this.fractionalBits;\n const centerBytes = await this.reader.read(this.numSplats * 3 * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i9 = i2 * 9;\n const x2 = ((centerBytes[i9 + 2] << 24 | centerBytes[i9 + 1] << 16 | centerBytes[i9] << 8) >> 8) / fixed;\n const y = ((centerBytes[i9 + 5] << 24 | centerBytes[i9 + 4] << 16 | centerBytes[i9 + 3] << 8) >> 8) / fixed;\n const z = ((centerBytes[i9 + 8] << 24 | centerBytes[i9 + 7] << 16 | centerBytes[i9 + 6] << 8) >> 8) / fixed;\n centerCallback == null ? void 0 : centerCallback(i2, x2, y, z);\n }\n } else {\n throw new Error("Unreachable");\n }\n {\n const bytes = await this.reader.read(this.numSplats);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n alphaCallback == null ? void 0 : alphaCallback(i2, bytes[i2] / 255);\n }\n }\n {\n const rgbBytes = await this.reader.read(this.numSplats * 3);\n const scale = SH_C0 / 0.15;\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const r = (rgbBytes[i3] / 255 - 0.5) * scale + 0.5;\n const g = (rgbBytes[i3 + 1] / 255 - 0.5) * scale + 0.5;\n const b = (rgbBytes[i3 + 2] / 255 - 0.5) * scale + 0.5;\n rgbCallback == null ? void 0 : rgbCallback(i2, r, g, b);\n }\n }\n {\n const scalesBytes = await this.reader.read(this.numSplats * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const scaleX = Math.exp(scalesBytes[i3] / 16 - 10);\n const scaleY = Math.exp(scalesBytes[i3 + 1] / 16 - 10);\n const scaleZ = Math.exp(scalesBytes[i3 + 2] / 16 - 10);\n scalesCallback == null ? void 0 : scalesCallback(i2, scaleX, scaleY, scaleZ);\n }\n }\n if (this.version === 3) {\n const maxValue = 1 / Math.sqrt(2);\n const quatBytes = await this.reader.read(this.numSplats * 4);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 4;\n const quaternion = [0, 0, 0, 0];\n const values = [\n quatBytes[i3],\n quatBytes[i3 + 1],\n quatBytes[i3 + 2],\n quatBytes[i3 + 3]\n ];\n const combinedValues = values[0] + (values[1] << 8) + (values[2] << 16) + (values[3] << 24);\n const valueMask = (1 << 9) - 1;\n const largestIndex = combinedValues >>> 30;\n let remainingValues = combinedValues;\n let sumSquares = 0;\n for (let i22 = 3; i22 >= 0; --i22) {\n if (i22 !== largestIndex) {\n const value = remainingValues & valueMask;\n const sign = remainingValues >>> 9 & 1;\n remainingValues = remainingValues >>> 10;\n quaternion[i22] = maxValue * (value / valueMask);\n quaternion[i22] = sign === 0 ? quaternion[i22] : -quaternion[i22];\n sumSquares += quaternion[i22] * quaternion[i22];\n }\n }\n const square = 1 - sumSquares;\n quaternion[largestIndex] = Math.sqrt(Math.max(square, 0));\n quatCallback == null ? void 0 : quatCallback(\n i2,\n quaternion[0],\n quaternion[1],\n quaternion[2],\n quaternion[3]\n );\n }\n } else {\n const quatBytes = await this.reader.read(this.numSplats * 3);\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n const i3 = i2 * 3;\n const quatX = quatBytes[i3] / 127.5 - 1;\n const quatY = quatBytes[i3 + 1] / 127.5 - 1;\n const quatZ = quatBytes[i3 + 2] / 127.5 - 1;\n const quatW = Math.sqrt(\n Math.max(0, 1 - quatX * quatX - quatY * quatY - quatZ * quatZ)\n );\n quatCallback == null ? void 0 : quatCallback(i2, quatX, quatY, quatZ, quatW);\n }\n }\n if (shCallback && this.shDegree >= 1) {\n const sh1 = new Float32Array(3 * 3);\n const sh2 = this.shDegree >= 2 ? new Float32Array(5 * 3) : void 0;\n const sh3 = this.shDegree >= 3 ? new Float32Array(7 * 3) : void 0;\n const shBytes = await this.reader.read(\n this.numSplats * SH_DEGREE_TO_VECS[this.shDegree] * 3\n );\n let offset = 0;\n for (let i2 = 0; i2 < this.numSplats; i2++) {\n for (let j = 0; j < 9; ++j) {\n sh1[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 9;\n if (sh2) {\n for (let j = 0; j < 15; ++j) {\n sh2[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 15;\n }\n if (sh3) {\n for (let j = 0; j < 21; ++j) {\n sh3[j] = (shBytes[offset + j] - 128) / 128;\n }\n offset += 21;\n }\n shCallback == null ? void 0 : shCallback(i2, sh1, sh2, sh3);\n }\n }\n }\n }\n const SH_DEGREE_TO_VECS = { 1: 3, 2: 8, 3: 15 };\n const SH_C0 = 0.28209479177387814;\n const SPZ_MAGIC = 1347635022;\n const SPZ_VERSION = 3;\n const FLAG_ANTIALIASED = 1;\n class SpzWriter {\n constructor({\n numSplats,\n shDegree,\n fractionalBits = 12,\n flagAntiAlias = true\n }) {\n this.clippedCount = 0;\n const splatSize = 9 + // Position\n 1 + // Opacity\n 3 + // Scale\n 3 + // DC-rgb\n 4 + // Rotation\n (shDegree >= 1 ? 9 : 0) + (shDegree >= 2 ? 15 : 0) + (shDegree >= 3 ? 21 : 0);\n const bufferSize = 16 + numSplats * splatSize;\n this.buffer = new ArrayBuffer(bufferSize);\n this.view = new DataView(this.buffer);\n this.view.setUint32(0, SPZ_MAGIC, true);\n this.view.setUint32(4, SPZ_VERSION, true);\n this.view.setUint32(8, numSplats, true);\n this.view.setUint8(12, shDegree);\n this.view.setUint8(13, fractionalBits);\n this.view.setUint8(14, flagAntiAlias ? FLAG_ANTIALIASED : 0);\n this.view.setUint8(15, 0);\n this.numSplats = numSplats;\n this.shDegree = shDegree;\n this.fractionalBits = fractionalBits;\n this.fraction = 1 << fractionalBits;\n this.flagAntiAlias = flagAntiAlias;\n }\n setCenter(index, x2, y, z) {\n const xRounded = Math.round(x2 * this.fraction);\n const xInt = Math.max(-8388607, Math.min(8388607, xRounded));\n const yRounded = Math.round(y * this.fraction);\n const yInt = Math.max(-8388607, Math.min(8388607, yRounded));\n const zRounded = Math.round(z * this.fraction);\n const zInt = Math.max(-8388607, Math.min(8388607, zRounded));\n const clipped = xRounded !== xInt || yRounded !== yInt || zRounded !== zInt;\n if (clipped) {\n this.clippedCount += 1;\n }\n const i9 = index * 9;\n const base = 16 + i9;\n this.view.setUint8(base, xInt & 255);\n this.view.setUint8(base + 1, xInt >> 8 & 255);\n this.view.setUint8(base + 2, xInt >> 16 & 255);\n this.view.setUint8(base + 3, yInt & 255);\n this.view.setUint8(base + 4, yInt >> 8 & 255);\n this.view.setUint8(base + 5, yInt >> 16 & 255);\n this.view.setUint8(base + 6, zInt & 255);\n this.view.setUint8(base + 7, zInt >> 8 & 255);\n this.view.setUint8(base + 8, zInt >> 16 & 255);\n }\n setAlpha(index, alpha) {\n const base = 16 + this.numSplats * 9 + index;\n this.view.setUint8(\n base,\n Math.max(0, Math.min(255, Math.round(alpha * 255)))\n );\n }\n static scaleRgb(r) {\n const v = ((r - 0.5) / (SH_C0 / 0.15) + 0.5) * 255;\n return Math.max(0, Math.min(255, Math.round(v)));\n }\n setRgb(index, r, g, b) {\n const base = 16 + this.numSplats * 10 + index * 3;\n this.view.setUint8(base, SpzWriter.scaleRgb(r));\n this.view.setUint8(base + 1, SpzWriter.scaleRgb(g));\n this.view.setUint8(base + 2, SpzWriter.scaleRgb(b));\n }\n setScale(index, scaleX, scaleY, scaleZ) {\n const base = 16 + this.numSplats * 13 + index * 3;\n this.view.setUint8(\n base,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleX) + 10) * 16)))\n );\n this.view.setUint8(\n base + 1,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleY) + 10) * 16)))\n );\n this.view.setUint8(\n base + 2,\n Math.max(0, Math.min(255, Math.round((Math.log(scaleZ) + 10) * 16)))\n );\n }\n setQuat(index, ...q) {\n const base = 16 + this.numSplats * 16 + index * 4;\n const quat = normalize(q);\n let iLargest = 0;\n for (let i2 = 1; i2 < 4; ++i2) {\n if (Math.abs(quat[i2]) > Math.abs(quat[iLargest])) {\n iLargest = i2;\n }\n }\n const negate = quat[iLargest] < 0 ? 1 : 0;\n let comp = iLargest;\n for (let i2 = 0; i2 < 4; ++i2) {\n if (i2 !== iLargest) {\n const negbit = (quat[i2] < 0 ? 1 : 0) ^ negate;\n const mag = Math.floor(\n ((1 << 9) - 1) * (Math.abs(quat[i2]) / Math.SQRT1_2) + 0.5\n );\n comp = comp << 10 | negbit << 9 | mag;\n }\n }\n this.view.setUint8(base, comp & 255);\n this.view.setUint8(base + 1, comp >> 8 & 255);\n this.view.setUint8(base + 2, comp >> 16 & 255);\n this.view.setUint8(base + 3, comp >>> 24 & 255);\n }\n static quantizeSh(sh, bits2) {\n const value = Math.round(sh * 128) + 128;\n const bucketSize = 1 << 8 - bits2;\n const quantized = Math.floor((value + bucketSize / 2) / bucketSize) * bucketSize;\n return Math.max(0, Math.min(255, quantized));\n }\n setSh(index, sh1, sh2, sh3) {\n const shVecs = SH_DEGREE_TO_VECS[this.shDegree] || 0;\n const base1 = 16 + this.numSplats * 20 + index * shVecs * 3;\n for (let j = 0; j < 9; ++j) {\n this.view.setUint8(base1 + j, SpzWriter.quantizeSh(sh1[j], 5));\n }\n if (sh2) {\n const base2 = base1 + 9;\n for (let j = 0; j < 15; ++j) {\n this.view.setUint8(base2 + j, SpzWriter.quantizeSh(sh2[j], 4));\n }\n if (sh3) {\n const base3 = base2 + 15;\n for (let j = 0; j < 21; ++j) {\n this.view.setUint8(base3 + j, SpzWriter.quantizeSh(sh3[j], 4));\n }\n }\n }\n }\n async finalize() {\n const input = new Uint8Array(this.buffer);\n const stream = new ReadableStream({\n async start(controller) {\n controller.enqueue(input);\n controller.close();\n }\n });\n const compressed = stream.pipeThrough(new CompressionStream("gzip"));\n const response = new Response(compressed);\n const buffer = await response.arrayBuffer();\n console.log(\n "Compressed",\n input.length,\n "bytes to",\n buffer.byteLength,\n "bytes"\n );\n return new Uint8Array(buffer);\n }\n }\n async function transcodeSpz(input) {\n var _a2, _b2, _c;\n const splats = new SplatData();\n const {\n inputs,\n clipXyz,\n maxSh,\n fractionalBits = 12,\n opacityThreshold\n } = input;\n for (const input2 of inputs) {\n let transformPos = function(pos) {\n pos.multiplyScalar(scale);\n pos.applyQuaternion(quaternion);\n pos.add(translate);\n return pos;\n }, transformScales = function(scales) {\n scales.multiplyScalar(scale);\n return scales;\n }, transformQuaternion = function(quat) {\n quat.premultiply(quaternion);\n return quat;\n }, withinClip = function(p) {\n return !clip || clip.containsPoint(p);\n }, withinOpacity = function(opacity) {\n return opacityThreshold !== void 0 ? opacity >= opacityThreshold : true;\n };\n const scale = ((_a2 = input2.transform) == null ? void 0 : _a2.scale) ?? 1;\n const quaternion = new Quaternion().fromArray(\n ((_b2 = input2.transform) == null ? void 0 : _b2.quaternion) ?? [0, 0, 0, 1]\n );\n const translate = new Vector3().fromArray(\n ((_c = input2.transform) == null ? void 0 : _c.translate) ?? [0, 0, 0]\n );\n const clip = clipXyz ? new Box3(\n new Vector3().fromArray(clipXyz.min),\n new Vector3().fromArray(clipXyz.max)\n ) : void 0;\n let fileType = input2.fileType;\n if (!fileType) {\n fileType = getSplatFileType(input2.fileBytes);\n if (!fileType && input2.pathOrUrl) {\n fileType = getSplatFileTypeFromPath(input2.pathOrUrl);\n }\n }\n switch (fileType) {\n case SplatFileType.PLY: {\n const ply = new PlyReader({ fileBytes: input2.fileBytes });\n await ply.parseHeader();\n let lastIndex = null;\n ply.parseSplats(\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n lastIndex = splats.pushSplat();\n splats.setCenter(lastIndex, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(lastIndex, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n lastIndex,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(lastIndex, opacity);\n splats.setColor(lastIndex, r, g, b);\n } else {\n lastIndex = null;\n }\n },\n (index, sh1, sh2, sh3) => {\n if (sh1 && lastIndex !== null) {\n splats.setSh1(lastIndex, sh1);\n }\n if (sh2 && lastIndex !== null) {\n splats.setSh2(lastIndex, sh2);\n }\n if (sh3 && lastIndex !== null) {\n splats.setSh3(lastIndex, sh3);\n }\n }\n );\n break;\n }\n case SplatFileType.SPZ: {\n const spz2 = new SpzReader({ fileBytes: input2.fileBytes });\n await spz2.parseHeader();\n const mapping = new Int32Array(spz2.numSplats);\n mapping.fill(-1);\n const centers = new Float32Array(spz2.numSplats * 3);\n const center = new Vector3();\n spz2.parseSplats(\n (index, x2, y, z) => {\n const center2 = transformPos(new Vector3(x2, y, z));\n centers[index * 3] = center2.x;\n centers[index * 3 + 1] = center2.y;\n centers[index * 3 + 2] = center2.z;\n },\n (index, alpha) => {\n center.fromArray(centers, index * 3);\n if (withinClip(center) && withinOpacity(alpha)) {\n mapping[index] = splats.pushSplat();\n splats.setCenter(mapping[index], center.x, center.y, center.z);\n splats.setOpacity(mapping[index], alpha);\n }\n },\n (index, r, g, b) => {\n if (mapping[index] >= 0) {\n splats.setColor(mapping[index], r, g, b);\n }\n },\n (index, scaleX, scaleY, scaleZ) => {\n if (mapping[index] >= 0) {\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(mapping[index], scales.x, scales.y, scales.z);\n }\n },\n (index, quatX, quatY, quatZ, quatW) => {\n if (mapping[index] >= 0) {\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n mapping[index],\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n }\n },\n (index, sh1, sh2, sh3) => {\n if (mapping[index] >= 0) {\n splats.setSh1(mapping[index], sh1);\n if (sh2) {\n splats.setSh2(mapping[index], sh2);\n }\n if (sh3) {\n splats.setSh3(mapping[index], sh3);\n }\n }\n }\n );\n break;\n }\n case SplatFileType.SPLAT:\n decodeAntiSplat(\n input2.fileBytes,\n (numSplats) => {\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n const index2 = splats.pushSplat();\n splats.setCenter(index2, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(index2, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n index2,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(index2, opacity);\n splats.setColor(index2, r, g, b);\n }\n }\n );\n break;\n case SplatFileType.KSPLAT: {\n let lastIndex = null;\n decodeKsplat(\n input2.fileBytes,\n (numSplats) => {\n },\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n const center = transformPos(new Vector3(x2, y, z));\n if (withinClip(center) && withinOpacity(opacity)) {\n lastIndex = splats.pushSplat();\n splats.setCenter(lastIndex, center.x, center.y, center.z);\n const scales = transformScales(\n new Vector3(scaleX, scaleY, scaleZ)\n );\n splats.setScale(lastIndex, scales.x, scales.y, scales.z);\n const quaternion2 = transformQuaternion(\n new Quaternion(quatX, quatY, quatZ, quatW)\n );\n splats.setQuaternion(\n lastIndex,\n quaternion2.x,\n quaternion2.y,\n quaternion2.z,\n quaternion2.w\n );\n splats.setOpacity(lastIndex, opacity);\n splats.setColor(lastIndex, r, g, b);\n } else {\n lastIndex = null;\n }\n },\n (index, sh1, sh2, sh3) => {\n if (lastIndex !== null) {\n splats.setSh1(lastIndex, sh1);\n if (sh2) {\n splats.setSh2(lastIndex, sh2);\n }\n if (sh3) {\n splats.setSh3(lastIndex, sh3);\n }\n }\n }\n );\n break;\n }\n default:\n throw new Error(`transcodeSpz not implemented for ${fileType}`);\n }\n }\n const shDegree = Math.min(\n maxSh ?? 3,\n splats.sh3 ? 3 : splats.sh2 ? 2 : splats.sh1 ? 1 : 0\n );\n const spz = new SpzWriter({\n numSplats: splats.numSplats,\n shDegree,\n fractionalBits,\n flagAntiAlias: true\n });\n for (let i2 = 0; i2 < splats.numSplats; ++i2) {\n const i3 = i2 * 3;\n const i4 = i2 * 4;\n spz.setCenter(\n i2,\n splats.centers[i3],\n splats.centers[i3 + 1],\n splats.centers[i3 + 2]\n );\n spz.setScale(\n i2,\n splats.scales[i3],\n splats.scales[i3 + 1],\n splats.scales[i3 + 2]\n );\n spz.setQuat(\n i2,\n splats.quaternions[i4],\n splats.quaternions[i4 + 1],\n splats.quaternions[i4 + 2],\n splats.quaternions[i4 + 3]\n );\n spz.setAlpha(i2, splats.opacities[i2]);\n spz.setRgb(\n i2,\n splats.colors[i3],\n splats.colors[i3 + 1],\n splats.colors[i3 + 2]\n );\n if (splats.sh1 && shDegree >= 1) {\n spz.setSh(\n i2,\n splats.sh1.slice(i2 * 9, (i2 + 1) * 9),\n shDegree >= 2 && splats.sh2 ? splats.sh2.slice(i2 * 15, (i2 + 1) * 15) : void 0,\n shDegree >= 3 && splats.sh3 ? splats.sh3.slice(i2 * 21, (i2 + 1) * 21) : void 0\n );\n }\n }\n const spzBytes = await spz.finalize();\n return { fileBytes: spzBytes, clippedCount: spz.clippedCount };\n }\n async function onMessage(event) {\n const { name, args, id } = event.data;\n let result = void 0;\n let error = void 0;\n try {\n switch (name) {\n case "unpackPly": {\n const { packedArray, fileBytes, splatEncoding } = args;\n const decoded = await unpackPly({\n packedArray,\n fileBytes,\n splatEncoding\n });\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodeSpz": {\n const { fileBytes, splatEncoding } = args;\n const decoded = await unpackSpz(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodeAntiSplat": {\n const { fileBytes, splatEncoding } = args;\n const decoded = unpackAntiSplat(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray\n };\n break;\n }\n case "decodeKsplat": {\n const { fileBytes, splatEncoding } = args;\n const decoded = unpackKsplat(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodePcSogs": {\n const { fileBytes, extraFiles, splatEncoding } = args;\n const json = JSON.parse(\n new TextDecoder().decode(fileBytes)\n );\n const decoded = await unpackPcSogs(json, extraFiles, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "decodePcSogsZip": {\n const { fileBytes, splatEncoding } = args;\n const decoded = await unpackPcSogsZip(fileBytes, splatEncoding);\n result = {\n id,\n numSplats: decoded.numSplats,\n packedArray: decoded.packedArray,\n extra: decoded.extra\n };\n break;\n }\n case "sortSplats": {\n const { totalSplats, readback, ordering } = args;\n result = {\n id,\n readback,\n ...sortSplats({ totalSplats, readback, ordering })\n };\n break;\n }\n case "sortDoubleSplats": {\n const { numSplats, readback, ordering } = args;\n {\n result = {\n id,\n readback,\n ordering,\n activeSplats: sort_splats(numSplats, readback, ordering)\n };\n }\n break;\n }\n case "sort32Splats": {\n const { numSplats, readback, ordering } = args;\n {\n result = {\n id,\n readback,\n ordering,\n activeSplats: sort32_splats(numSplats, readback, ordering)\n };\n }\n break;\n }\n case "transcodeSpz": {\n const input = args;\n const spzBytes = await transcodeSpz(input);\n result = {\n id,\n fileBytes: spzBytes,\n input\n };\n break;\n }\n default: {\n throw new Error(`Unknown name: ${name}`);\n }\n }\n } catch (e) {\n error = e;\n console.error(error);\n }\n self.postMessage(\n { id, result, error },\n { transfer: getArrayBuffers(result) }\n );\n }\n async function unpackPly({\n packedArray,\n fileBytes,\n splatEncoding\n }) {\n const ply = new PlyReader({ fileBytes });\n await ply.parseHeader();\n const numSplats = ply.numSplats;\n const extra = {};\n ply.parseSplats(\n (index, x2, y, z, scaleX, scaleY, scaleZ, quatX, quatY, quatZ, quatW, opacity, r, g, b) => {\n setPackedSplat(\n packedArray,\n index,\n x2,\n y,\n z,\n scaleX,\n scaleY,\n scaleZ,\n quatX,\n quatY,\n quatZ,\n quatW,\n opacity,\n r,\n g,\n b,\n splatEncoding\n );\n },\n (index, sh1, sh2, sh3) => {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n encodeSh1Rgb(extra.sh1, index, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n encodeSh2Rgb(extra.sh2, index, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n encodeSh3Rgb(extra.sh3, index, sh3, splatEncoding);\n }\n }\n );\n return { packedArray, numSplats, extra };\n }\n async function unpackSpz(fileBytes, splatEncoding) {\n const spz = new SpzReader({ fileBytes });\n await spz.parseHeader();\n const numSplats = spz.numSplats;\n const maxSplats = computeMaxSplats(numSplats);\n const packedArray = new Uint32Array(maxSplats * 4);\n const extra = {};\n await spz.parseSplats(\n (index, x2, y, z) => {\n setPackedSplatCenter(packedArray, index, x2, y, z);\n },\n (index, alpha) => {\n setPackedSplatOpacity(packedArray, index, alpha);\n },\n (index, r, g, b) => {\n setPackedSplatRgb(packedArray, index, r, g, b, splatEncoding);\n },\n (index, scaleX, scaleY, scaleZ) => {\n setPackedSplatScales(\n packedArray,\n index,\n scaleX,\n scaleY,\n scaleZ,\n splatEncoding\n );\n },\n (index, quatX, quatY, quatZ, quatW) => {\n setPackedSplatQuat(packedArray, index, quatX, quatY, quatZ, quatW);\n },\n (index, sh1, sh2, sh3) => {\n if (sh1) {\n if (!extra.sh1) {\n extra.sh1 = new Uint32Array(numSplats * 2);\n }\n encodeSh1Rgb(extra.sh1, index, sh1, splatEncoding);\n }\n if (sh2) {\n if (!extra.sh2) {\n extra.sh2 = new Uint32Array(numSplats * 4);\n }\n encodeSh2Rgb(extra.sh2, index, sh2, splatEncoding);\n }\n if (sh3) {\n if (!extra.sh3) {\n extra.sh3 = new Uint32Array(numSplats * 4);\n }\n encodeSh3Rgb(extra.sh3, index, sh3, splatEncoding);\n }\n }\n );\n return { packedArray, numSplats, extra };\n }\n const DEPTH_INFINITY_F16 = 31744;\n const DEPTH_SIZE_16 = DEPTH_INFINITY_F16 + 1;\n let depthArray16 = null;\n function sortSplats({\n totalSplats,\n readback,\n ordering\n }) {\n if (!depthArray16) {\n depthArray16 = new Uint32Array(DEPTH_SIZE_16);\n }\n depthArray16.fill(0);\n const readbackUint32 = readback.map((layer) => new Uint32Array(layer.buffer));\n const layerSize = readbackUint32[0].length;\n const numLayers = Math.ceil(totalSplats / layerSize);\n let layerBase = 0;\n for (let layer = 0; layer < numLayers; ++layer) {\n const readbackLayer = readbackUint32[layer];\n const layerSplats = Math.min(readbackLayer.length, totalSplats - layerBase);\n for (let i2 = 0; i2 < layerSplats; ++i2) {\n const pri = readbackLayer[i2] & 32767;\n if (pri < DEPTH_INFINITY_F16) {\n depthArray16[pri] += 1;\n }\n }\n layerBase += layerSplats;\n }\n let activeSplats = 0;\n for (let j = 0; j < DEPTH_SIZE_16; ++j) {\n const nextIndex = activeSplats + depthArray16[j];\n depthArray16[j] = activeSplats;\n activeSplats = nextIndex;\n }\n layerBase = 0;\n for (let layer = 0; layer < numLayers; ++layer) {\n const readbackLayer = readbackUint32[layer];\n const layerSplats = Math.min(readbackLayer.length, totalSplats - layerBase);\n for (let i2 = 0; i2 < layerSplats; ++i2) {\n const pri = readbackLayer[i2] & 32767;\n if (pri < DEPTH_INFINITY_F16) {\n ordering[depthArray16[pri]] = layerBase + i2;\n depthArray16[pri] += 1;\n }\n }\n layerBase += layerSplats;\n }\n if (depthArray16[DEPTH_SIZE_16 - 1] !== activeSplats) {\n throw new Error(\n `Expected ${activeSplats} active splats but got ${depthArray16[DEPTH_SIZE_16 - 1]}`\n );\n }\n return { activeSplats, ordering };\n }\n const messageBuffer = [];\n function bufferMessage(event) {\n messageBuffer.push(event);\n }\n async function initialize() {\n self.addEventListener("message", bufferMessage);\n await __wbg_init();\n self.removeEventListener("message", bufferMessage);\n self.addEventListener("message", onMessage);\n for (const event of messageBuffer) {\n onMessage(event);\n }\n messageBuffer.length = 0;\n }\n initialize().catch(console.error);\n})();\n//# sourceMappingURL=worker-CaMzlx2k.js.map\n';
|
|
8399
8584
|
const blob = typeof self !== "undefined" && self.Blob && new Blob([jsContent], { type: "text/javascript;charset=utf-8" });
|
|
8400
8585
|
function WorkerWrapper(options) {
|
|
8401
8586
|
let objURL;
|
|
@@ -8716,6 +8901,9 @@ function getSplatFileTypeFromPath(pathOrUrl) {
|
|
|
8716
8901
|
if (extension === "ksplat") {
|
|
8717
8902
|
return "ksplat";
|
|
8718
8903
|
}
|
|
8904
|
+
if (extension === "sog") {
|
|
8905
|
+
return "pcsogszip";
|
|
8906
|
+
}
|
|
8719
8907
|
return void 0;
|
|
8720
8908
|
}
|
|
8721
8909
|
function isPcSogs(input) {
|
|
@@ -8737,15 +8925,28 @@ function tryPcSogs(input) {
|
|
|
8737
8925
|
if (!json || typeof json !== "object" || Array.isArray(json)) {
|
|
8738
8926
|
return void 0;
|
|
8739
8927
|
}
|
|
8928
|
+
const isVersion2 = json.version === 2;
|
|
8740
8929
|
for (const key of ["means", "scales", "quats", "sh0"]) {
|
|
8741
8930
|
if (!json[key] || typeof json[key] !== "object" || Array.isArray(json[key])) {
|
|
8742
8931
|
return void 0;
|
|
8743
8932
|
}
|
|
8744
|
-
if (
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8933
|
+
if (isVersion2) {
|
|
8934
|
+
if (!json[key].files) {
|
|
8935
|
+
return void 0;
|
|
8936
|
+
}
|
|
8937
|
+
if ((key === "scales" || key === "sh0") && !json[key].codebook) {
|
|
8938
|
+
return void 0;
|
|
8939
|
+
}
|
|
8940
|
+
if (key === "means" && (!json[key].mins || !json[key].maxs)) {
|
|
8941
|
+
return void 0;
|
|
8942
|
+
}
|
|
8943
|
+
} else {
|
|
8944
|
+
if (!json[key].shape || !json[key].files) {
|
|
8945
|
+
return void 0;
|
|
8946
|
+
}
|
|
8947
|
+
if (key !== "quats" && (!json[key].mins || !json[key].maxs)) {
|
|
8948
|
+
return void 0;
|
|
8949
|
+
}
|
|
8749
8950
|
}
|
|
8750
8951
|
}
|
|
8751
8952
|
return json;
|
|
@@ -9781,7 +9982,7 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9781
9982
|
// The method cannot be private because then SparkRenderer would
|
|
9782
9983
|
// not be able to call it.
|
|
9783
9984
|
autoPoll({ accumulator }) {
|
|
9784
|
-
var _a2, _b2, _c
|
|
9985
|
+
var _a2, _b2, _c;
|
|
9785
9986
|
if (this.camera) {
|
|
9786
9987
|
this.camera.updateMatrixWorld();
|
|
9787
9988
|
this.viewToWorld = this.camera.matrixWorld.clone();
|
|
@@ -9794,9 +9995,14 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9794
9995
|
needsSort = true;
|
|
9795
9996
|
const { mappingVersion } = this.display.accumulator;
|
|
9796
9997
|
if (accumulator.mappingVersion === mappingVersion) {
|
|
9998
|
+
accumulator.refCount += 1;
|
|
9797
9999
|
this.spark.releaseAccumulator(this.display.accumulator);
|
|
9798
10000
|
this.display.accumulator = accumulator;
|
|
10001
|
+
this.display.viewToWorld.copy(this.viewToWorld);
|
|
9799
10002
|
displayed = true;
|
|
10003
|
+
if (this.spark.viewpoint === this) {
|
|
10004
|
+
this.spark.prepareViewpoint(this);
|
|
10005
|
+
}
|
|
9800
10006
|
}
|
|
9801
10007
|
}
|
|
9802
10008
|
const latestView = ((_a2 = this.sorting) == null ? void 0 : _a2.viewToWorld) ?? ((_b2 = this.display) == null ? void 0 : _b2.viewToWorld);
|
|
@@ -9819,7 +10025,7 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9819
10025
|
if (accumulator) {
|
|
9820
10026
|
accumulator.refCount += 1;
|
|
9821
10027
|
}
|
|
9822
|
-
if (
|
|
10028
|
+
if ((_c = this.pending) == null ? void 0 : _c.accumulator) {
|
|
9823
10029
|
this.spark.releaseAccumulator(this.pending.accumulator);
|
|
9824
10030
|
}
|
|
9825
10031
|
this.pending = { accumulator, viewToWorld: this.viewToWorld, displayed };
|
|
@@ -9832,9 +10038,9 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9832
10038
|
return;
|
|
9833
10039
|
}
|
|
9834
10040
|
const { viewToWorld, displayed } = this.pending;
|
|
9835
|
-
let accumulator = this.pending.accumulator
|
|
10041
|
+
let accumulator = this.pending.accumulator;
|
|
9836
10042
|
if (!accumulator) {
|
|
9837
|
-
accumulator = this.spark.active;
|
|
10043
|
+
accumulator = ((_a2 = this.display) == null ? void 0 : _a2.accumulator) ?? this.spark.active;
|
|
9838
10044
|
accumulator.refCount += 1;
|
|
9839
10045
|
}
|
|
9840
10046
|
this.pending = null;
|
|
@@ -9844,6 +10050,7 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9844
10050
|
this.sorting = { viewToWorld };
|
|
9845
10051
|
await this.sortUpdate({ accumulator, viewToWorld, displayed });
|
|
9846
10052
|
this.sorting = null;
|
|
10053
|
+
this.spark.releaseAccumulator(accumulator);
|
|
9847
10054
|
}
|
|
9848
10055
|
}
|
|
9849
10056
|
async sortUpdate({
|
|
@@ -9936,6 +10143,7 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9936
10143
|
displayed = false
|
|
9937
10144
|
}) {
|
|
9938
10145
|
if (!this.display) {
|
|
10146
|
+
accumulator.refCount += 1;
|
|
9939
10147
|
this.display = {
|
|
9940
10148
|
accumulator,
|
|
9941
10149
|
viewToWorld,
|
|
@@ -9943,6 +10151,7 @@ const _SparkViewpoint = class _SparkViewpoint {
|
|
|
9943
10151
|
};
|
|
9944
10152
|
} else {
|
|
9945
10153
|
if (!displayed && accumulator !== this.display.accumulator) {
|
|
10154
|
+
accumulator.refCount += 1;
|
|
9946
10155
|
this.spark.releaseAccumulator(this.display.accumulator);
|
|
9947
10156
|
this.display.accumulator = accumulator;
|
|
9948
10157
|
}
|
|
@@ -10145,7 +10354,7 @@ class SplatAccumulator {
|
|
|
10145
10354
|
numSplats = Math.max(numSplats, base + count);
|
|
10146
10355
|
}
|
|
10147
10356
|
this.splats.numSplats = numSplats;
|
|
10148
|
-
this.toWorld
|
|
10357
|
+
this.toWorld.copy(originToWorld);
|
|
10149
10358
|
this.mapping = generators2;
|
|
10150
10359
|
return updated !== 0;
|
|
10151
10360
|
}
|
|
@@ -10166,8 +10375,8 @@ class SplatAccumulator {
|
|
|
10166
10375
|
}
|
|
10167
10376
|
}
|
|
10168
10377
|
var splatDefines_default = "const float LN_SCALE_MIN = -12.0;\nconst float LN_SCALE_MAX = 9.0;\n\nconst uint SPLAT_TEX_WIDTH_BITS = 11u;\nconst uint SPLAT_TEX_HEIGHT_BITS = 11u;\nconst uint SPLAT_TEX_DEPTH_BITS = 11u;\nconst uint SPLAT_TEX_LAYER_BITS = SPLAT_TEX_WIDTH_BITS + SPLAT_TEX_HEIGHT_BITS;\n\nconst uint SPLAT_TEX_WIDTH = 1u << SPLAT_TEX_WIDTH_BITS;\nconst uint SPLAT_TEX_HEIGHT = 1u << SPLAT_TEX_HEIGHT_BITS;\nconst uint SPLAT_TEX_DEPTH = 1u << SPLAT_TEX_DEPTH_BITS;\n\nconst uint SPLAT_TEX_WIDTH_MASK = SPLAT_TEX_WIDTH - 1u;\nconst uint SPLAT_TEX_HEIGHT_MASK = SPLAT_TEX_HEIGHT - 1u;\nconst uint SPLAT_TEX_DEPTH_MASK = SPLAT_TEX_DEPTH - 1u;\n\nconst uint F16_INF = 0x7c00u;\nconst float PI = 3.1415926535897932384626433832795;\n\nconst float INFINITY = 1.0 / 0.0;\nconst float NEG_INFINITY = -INFINITY;\n\nfloat sqr(float x) {\n return x * x;\n}\n\nfloat pow4(float x) {\n float x2 = x * x;\n return x2 * x2;\n}\n\nfloat pow8(float x) {\n float x4 = pow4(x);\n return x4 * x4;\n}\n\nvec3 srgbToLinear(vec3 rgb) {\n return pow(rgb, vec3(2.2));\n}\n\nvec3 linearToSrgb(vec3 rgb) {\n return pow(rgb, vec3(1.0 / 2.2));\n}\n\nuint encodeQuatOctXy88R8(vec4 q) {\n \n if (q.w < 0.0) {\n q = -q;\n }\n \n float theta = 2.0 * acos(q.w);\n float halfTheta = theta * 0.5;\n float s = sin(halfTheta);\n \n vec3 axis = (abs(s) < 1e-6) ? vec3(1.0, 0.0, 0.0) : q.xyz / s;\n \n \n \n float sum = abs(axis.x) + abs(axis.y) + abs(axis.z);\n vec2 p = vec2(axis.x, axis.y) / sum;\n \n if (axis.z < 0.0) {\n float oldPx = p.x;\n p.x = (1.0 - abs(p.y)) * (p.x >= 0.0 ? 1.0 : -1.0);\n p.y = (1.0 - abs(oldPx)) * (p.y >= 0.0 ? 1.0 : -1.0);\n }\n \n float u_f = p.x * 0.5 + 0.5;\n float v_f = p.y * 0.5 + 0.5;\n \n uint quantU = uint(clamp(round(u_f * 255.0), 0.0, 255.0));\n uint quantV = uint(clamp(round(v_f * 255.0), 0.0, 255.0));\n \n \n \n uint angleInt = uint(clamp(round((theta / 3.14159265359) * 255.0), 0.0, 255.0));\n \n \n return (angleInt << 16u) | (quantV << 8u) | quantU;\n}\n\nvec4 decodeQuatOctXy88R8(uint encoded) {\n \n uint quantU = encoded & uint(0xFFu); \n uint quantV = (encoded >> 8u) & uint(0xFFu); \n uint angleInt = encoded >> 16u; \n\n \n float u_f = float(quantU) / 255.0;\n float v_f = float(quantV) / 255.0;\n vec2 f = vec2(u_f * 2.0 - 1.0, v_f * 2.0 - 1.0);\n\n vec3 axis = vec3(f.xy, 1.0 - abs(f.x) - abs(f.y));\n float t = max(-axis.z, 0.0);\n axis.x += (axis.x >= 0.0) ? -t : t;\n axis.y += (axis.y >= 0.0) ? -t : t;\n axis = normalize(axis);\n \n \n float theta = (float(angleInt) / 255.0) * 3.14159265359;\n float halfTheta = theta * 0.5;\n float s = sin(halfTheta);\n float w = cos(halfTheta);\n \n return vec4(axis * s, w);\n}\n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\nuvec4 packSplatEncoding(\n vec3 center, vec3 scales, vec4 quaternion, vec4 rgba, vec4 rgbMinMaxLnScaleMinMax\n) {\n float rgbMin = rgbMinMaxLnScaleMinMax.x;\n float rgbMax = rgbMinMaxLnScaleMinMax.y;\n vec3 encRgb = (rgba.rgb - vec3(rgbMin)) / (rgbMax - rgbMin);\n uvec4 uRgba = uvec4(round(clamp(vec4(encRgb, rgba.a) * 255.0, 0.0, 255.0)));\n\n uint uQuat = encodeQuatOctXy88R8(quaternion);\n \n \n uvec3 uQuat3 = uvec3(uQuat & 0xffu, (uQuat >> 8u) & 0xffu, (uQuat >> 16u) & 0xffu);\n\n \n float lnScaleMin = rgbMinMaxLnScaleMinMax.z;\n float lnScaleMax = rgbMinMaxLnScaleMinMax.w;\n float lnScaleScale = 254.0 / (lnScaleMax - lnScaleMin);\n uvec3 uScales = uvec3(\n (scales.x == 0.0) ? 0u : uint(round(clamp((log(scales.x) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u,\n (scales.y == 0.0) ? 0u : uint(round(clamp((log(scales.y) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u,\n (scales.z == 0.0) ? 0u : uint(round(clamp((log(scales.z) - lnScaleMin) * lnScaleScale, 0.0, 254.0))) + 1u\n );\n\n \n uint word0 = uRgba.r | (uRgba.g << 8u) | (uRgba.b << 16u) | (uRgba.a << 24u);\n uint word1 = packHalf2x16(center.xy);\n uint word2 = packHalf2x16(vec2(center.z, 0.0)) | (uQuat3.x << 16u) | (uQuat3.y << 24u);\n uint word3 = uScales.x | (uScales.y << 8u) | (uScales.z << 16u) | (uQuat3.z << 24u);\n return uvec4(word0, word1, word2, word3);\n}\n\nuvec4 packSplat(vec3 center, vec3 scales, vec4 quaternion, vec4 rgba) {\n return packSplatEncoding(center, scales, quaternion, rgba, vec4(0.0, 1.0, LN_SCALE_MIN, LN_SCALE_MAX));\n}\n\nvoid unpackSplatEncoding(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quaternion, out vec4 rgba, vec4 rgbMinMaxLnScaleMinMax) {\n uint word0 = packed.x, word1 = packed.y, word2 = packed.z, word3 = packed.w;\n\n uvec4 uRgba = uvec4(word0 & 0xffu, (word0 >> 8u) & 0xffu, (word0 >> 16u) & 0xffu, (word0 >> 24u) & 0xffu);\n float rgbMin = rgbMinMaxLnScaleMinMax.x;\n float rgbMax = rgbMinMaxLnScaleMinMax.y;\n rgba = (vec4(uRgba) / 255.0);\n rgba.rgb = rgba.rgb * (rgbMax - rgbMin) + rgbMin;\n\n center = vec4(\n unpackHalf2x16(word1),\n unpackHalf2x16(word2 & 0xffffu)\n ).xyz;\n\n uvec3 uScales = uvec3(word3 & 0xffu, (word3 >> 8u) & 0xffu, (word3 >> 16u) & 0xffu);\n float lnScaleMin = rgbMinMaxLnScaleMinMax.z;\n float lnScaleMax = rgbMinMaxLnScaleMinMax.w;\n float lnScaleScale = (lnScaleMax - lnScaleMin) / 254.0;\n scales = vec3(\n (uScales.x == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.x - 1u) * lnScaleScale),\n (uScales.y == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.y - 1u) * lnScaleScale),\n (uScales.z == 0u) ? 0.0 : exp(lnScaleMin + float(uScales.z - 1u) * lnScaleScale)\n );\n\n uint uQuat = ((word2 >> 16u) & 0xFFFFu) | ((word3 >> 8u) & 0xFF0000u);\n quaternion = decodeQuatOctXy88R8(uQuat);\n \n \n}\n\nvoid unpackSplat(uvec4 packed, out vec3 center, out vec3 scales, out vec4 quaternion, out vec4 rgba) {\n unpackSplatEncoding(packed, center, scales, quaternion, rgba, vec4(0.0, 1.0, LN_SCALE_MIN, LN_SCALE_MAX));\n}\n\nvec3 quatVec(vec4 q, vec3 v) {\n \n vec3 t = 2.0 * cross(q.xyz, v);\n return v + q.w * t + cross(q.xyz, t);\n}\n\nvec4 quatQuat(vec4 q1, vec4 q2) {\n return vec4(\n q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,\n q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x,\n q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w,\n q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n );\n}\n\nmat3 scaleQuaternionToMatrix(vec3 s, vec4 q) {\n \n return mat3(\n s.x * (1.0 - 2.0 * (q.y * q.y + q.z * q.z)),\n s.x * (2.0 * (q.x * q.y + q.w * q.z)),\n s.x * (2.0 * (q.x * q.z - q.w * q.y)),\n s.y * (2.0 * (q.x * q.y - q.w * q.z)),\n s.y * (1.0 - 2.0 * (q.x * q.x + q.z * q.z)),\n s.y * (2.0 * (q.y * q.z + q.w * q.x)),\n s.z * (2.0 * (q.x * q.z + q.w * q.y)),\n s.z * (2.0 * (q.y * q.z - q.w * q.x)),\n s.z * (1.0 - 2.0 * (q.x * q.x + q.y * q.y))\n );\n}\n\nvec4 slerp(vec4 q1, vec4 q2, float t) {\n \n float cosHalfTheta = dot(q1, q2);\n\n \n if (abs(cosHalfTheta) >= 0.999) {\n return q1;\n }\n \n \n \n if (cosHalfTheta < 0.0) {\n q2 = -q2;\n cosHalfTheta = -cosHalfTheta;\n }\n\n \n float halfTheta = acos(cosHalfTheta);\n float sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta);\n\n \n float ratioA = sin((1.0 - t) * halfTheta) / sinHalfTheta;\n float ratioB = sin(t * halfTheta) / sinHalfTheta;\n\n \n return q1 * ratioA + q2 * ratioB;\n}\n\nivec3 splatTexCoord(int index) {\n uint x = uint(index) & SPLAT_TEX_WIDTH_MASK;\n uint y = (uint(index) >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK;\n uint z = uint(index) >> SPLAT_TEX_LAYER_BITS;\n return ivec3(x, y, z);\n}";
|
|
10169
|
-
var splatFragment_default = "precision highp float;\nprecision highp int;\n\n#include <splatDefines>\n\nuniform float near;\nuniform float far;\nuniform bool encodeLinear;\nuniform float time;\nuniform bool debugFlag;\nuniform float maxStdDev;\nuniform float minAlpha;\nuniform bool stochastic;\nuniform bool disableFalloff;\nuniform float falloff;\n\nuniform bool splatTexEnable;\nuniform sampler3D splatTexture;\nuniform mat2 splatTexMul;\nuniform vec2 splatTexAdd;\nuniform float splatTexNear;\nuniform float splatTexFar;\nuniform float splatTexMid;\n\nout vec4 fragColor;\n\nin vec4 vRgba;\nin vec2 vSplatUv;\nin vec3 vNdc;\nflat in uint vSplatIndex;\n\nvoid main() {\n vec4 rgba = vRgba;\n\n float z = dot(vSplatUv, vSplatUv);\n if (!splatTexEnable) {\n if (z > (maxStdDev * maxStdDev)) {\n discard;\n }\n } else {\n vec2 uv = splatTexMul * vSplatUv + splatTexAdd;\n float ndcZ = vNdc.z;\n float depth = (2.0 * near * far) / (far + near - ndcZ * (far - near));\n float clampedFar = max(splatTexFar, splatTexNear);\n float clampedDepth = clamp(depth, splatTexNear, clampedFar);\n float logDepth = log2(clampedDepth + 1.0);\n float logNear = log2(splatTexNear + 1.0);\n float logFar = log2(clampedFar + 1.0);\n\n float texZ;\n if (splatTexMid > 0.0) {\n float clampedMid = clamp(splatTexMid, splatTexNear, clampedFar);\n float logMid = log2(clampedMid + 1.0);\n texZ = (clampedDepth <= clampedMid) ?\n (0.5 * ((logDepth - logNear) / (logMid - logNear))) :\n (0.5 * ((logDepth - logMid) / (logFar - logMid)) + 0.5);\n } else {\n texZ = (logDepth - logNear) / (logFar - logNear);\n }\n\n vec4 modulate = texture(splatTexture, vec3(uv, 1.0 - texZ));\n rgba *= modulate;\n }\n\n rgba.a *= mix(1.0, exp(-0.5 * z), falloff);\n\n if (rgba.a < minAlpha) {\n discard;\n }\n if (encodeLinear) {\n rgba.rgb = srgbToLinear(rgba.rgb);\n }\n\n if (stochastic) {\n const bool STEADY = false;\n uint uTime = STEADY ? 0u : floatBitsToUint(time);\n uvec2 coord = uvec2(gl_FragCoord.xy);\n uint state = uTime + 0x9e3779b9u * coord.x + 0x85ebca6bu * coord.y + 0xc2b2ae35u * uint(vSplatIndex);\n state = state * 747796405u + 2891336453u;\n uint hash = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;\n hash = (hash >> 22u) ^ hash;\n float rand = float(hash) / 4294967296.0;\n if (rand < rgba.a) {\n fragColor = vec4(rgba.rgb, 1.0);\n } else {\n discard;\n }\n } else {\n #ifdef PREMULTIPLIED_ALPHA\n fragColor = vec4(rgba.rgb * rgba.a, rgba.a);\n #else\n fragColor = rgba;\n #endif\n }\n}";
|
|
10170
|
-
var splatVertex_default = "precision highp float;\nprecision highp int;\nprecision highp usampler2DArray;\n\n#include <splatDefines>\n\nattribute uint splatIndex;\n\nout vec4 vRgba;\nout vec2 vSplatUv;\nout vec3 vNdc;\nflat out uint vSplatIndex;\n\nuniform vec2 renderSize;\nuniform uint numSplats;\nuniform vec4 renderToViewQuat;\nuniform vec3 renderToViewPos;\nuniform float maxStdDev;\nuniform float maxPixelRadius;\nuniform float time;\nuniform float deltaTime;\nuniform bool debugFlag;\nuniform float minAlpha;\nuniform bool stochastic;\nuniform bool enable2DGS;\nuniform float blurAmount;\nuniform float preBlurAmount;\nuniform float focalDistance;\nuniform float apertureAngle;\nuniform float clipXY;\nuniform float focalAdjustment;\n\nuniform usampler2DArray packedSplats;\nuniform vec4 rgbMinMaxLnScaleMinMax;\n\nvoid main() {\n \n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n\n if (uint(gl_InstanceID) >= numSplats) {\n return;\n }\n\n ivec3 texCoord;\n if (stochastic) {\n texCoord = ivec3(\n uint(gl_InstanceID) & SPLAT_TEX_WIDTH_MASK,\n (uint(gl_InstanceID) >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK,\n (uint(gl_InstanceID) >> SPLAT_TEX_LAYER_BITS)\n );\n } else {\n if (splatIndex == 0xffffffffu) {\n \n return;\n }\n texCoord = ivec3(\n splatIndex & SPLAT_TEX_WIDTH_MASK,\n (splatIndex >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK,\n splatIndex >> SPLAT_TEX_LAYER_BITS\n );\n }\n uvec4 packed = texelFetch(packedSplats, texCoord, 0);\n\n vec3 center, scales;\n vec4 quaternion, rgba;\n unpackSplatEncoding(packed, center, scales, quaternion, rgba, rgbMinMaxLnScaleMinMax);\n\n if (rgba.a < minAlpha) {\n return;\n }\n bvec3 zeroScales = equal(scales, vec3(0.0));\n if (all(zeroScales)) {\n return;\n }\n\n \n vec3 viewCenter = quatVec(renderToViewQuat, center) + renderToViewPos;\n\n \n if (viewCenter.z >= 0.0) {\n return;\n }\n\n \n vec4 clipCenter = projectionMatrix * vec4(viewCenter, 1.0);\n\n \n if (abs(clipCenter.z) >= clipCenter.w) {\n return;\n }\n\n \n float clip = clipXY * clipCenter.w;\n if (abs(clipCenter.x) > clip || abs(clipCenter.y) > clip) {\n return;\n }\n\n \n vSplatIndex = splatIndex;\n\n \n vec4 viewQuaternion = quatQuat(renderToViewQuat, quaternion);\n\n if (enable2DGS && any(zeroScales)) {\n vRgba = rgba;\n vSplatUv = position.xy * maxStdDev;\n\n vec3 offset;\n if (zeroScales.z) {\n offset = vec3(vSplatUv.xy * scales.xy, 0.0);\n } else if (zeroScales.y) {\n offset = vec3(vSplatUv.x * scales.x, 0.0, vSplatUv.y * scales.z);\n } else {\n offset = vec3(0.0, vSplatUv.xy * scales.yz);\n }\n\n vec3 viewPos = viewCenter + quatVec(viewQuaternion, offset);\n gl_Position = projectionMatrix * vec4(viewPos, 1.0);\n vNdc = gl_Position.xyz / gl_Position.w;\n return;\n }\n\n \n vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\n\n \n mat3 RS = scaleQuaternionToMatrix(scales, viewQuaternion);\n mat3 cov3D = RS * transpose(RS);\n\n \n vec2 scaledRenderSize = renderSize * focalAdjustment;\n vec2 focal = 0.5 * scaledRenderSize * vec2(projectionMatrix[0][0], projectionMatrix[1][1]);\n float invZ = 1.0 / viewCenter.z;\n
|
|
10378
|
+
var splatFragment_default = "precision highp float;\nprecision highp int;\n\n#include <splatDefines>\n#include <logdepthbuf_pars_fragment>\n\nuniform float near;\nuniform float far;\nuniform bool encodeLinear;\nuniform float time;\nuniform bool debugFlag;\nuniform float maxStdDev;\nuniform float minAlpha;\nuniform bool stochastic;\nuniform bool disableFalloff;\nuniform float falloff;\n\nuniform bool splatTexEnable;\nuniform sampler3D splatTexture;\nuniform mat2 splatTexMul;\nuniform vec2 splatTexAdd;\nuniform float splatTexNear;\nuniform float splatTexFar;\nuniform float splatTexMid;\n\nout vec4 fragColor;\n\nin vec4 vRgba;\nin vec2 vSplatUv;\nin vec3 vNdc;\nflat in uint vSplatIndex;\n\nvoid main() {\n vec4 rgba = vRgba;\n\n float z = dot(vSplatUv, vSplatUv);\n if (!splatTexEnable) {\n if (z > (maxStdDev * maxStdDev)) {\n discard;\n }\n } else {\n vec2 uv = splatTexMul * vSplatUv + splatTexAdd;\n float ndcZ = vNdc.z;\n float depth = (2.0 * near * far) / (far + near - ndcZ * (far - near));\n float clampedFar = max(splatTexFar, splatTexNear);\n float clampedDepth = clamp(depth, splatTexNear, clampedFar);\n float logDepth = log2(clampedDepth + 1.0);\n float logNear = log2(splatTexNear + 1.0);\n float logFar = log2(clampedFar + 1.0);\n\n float texZ;\n if (splatTexMid > 0.0) {\n float clampedMid = clamp(splatTexMid, splatTexNear, clampedFar);\n float logMid = log2(clampedMid + 1.0);\n texZ = (clampedDepth <= clampedMid) ?\n (0.5 * ((logDepth - logNear) / (logMid - logNear))) :\n (0.5 * ((logDepth - logMid) / (logFar - logMid)) + 0.5);\n } else {\n texZ = (logDepth - logNear) / (logFar - logNear);\n }\n\n vec4 modulate = texture(splatTexture, vec3(uv, 1.0 - texZ));\n rgba *= modulate;\n }\n\n rgba.a *= mix(1.0, exp(-0.5 * z), falloff);\n\n if (rgba.a < minAlpha) {\n discard;\n }\n if (encodeLinear) {\n rgba.rgb = srgbToLinear(rgba.rgb);\n }\n\n if (stochastic) {\n const bool STEADY = false;\n uint uTime = STEADY ? 0u : floatBitsToUint(time);\n uvec2 coord = uvec2(gl_FragCoord.xy);\n uint state = uTime + 0x9e3779b9u * coord.x + 0x85ebca6bu * coord.y + 0xc2b2ae35u * uint(vSplatIndex);\n state = state * 747796405u + 2891336453u;\n uint hash = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;\n hash = (hash >> 22u) ^ hash;\n float rand = float(hash) / 4294967296.0;\n if (rand < rgba.a) {\n fragColor = vec4(rgba.rgb, 1.0);\n } else {\n discard;\n }\n } else {\n #ifdef PREMULTIPLIED_ALPHA\n fragColor = vec4(rgba.rgb * rgba.a, rgba.a);\n #else\n fragColor = rgba;\n #endif\n }\n #include <logdepthbuf_fragment>\n}";
|
|
10379
|
+
var splatVertex_default = "precision highp float;\nprecision highp int;\nprecision highp usampler2DArray;\n\n#include <splatDefines>\n#include <logdepthbuf_pars_vertex>\n\nattribute uint splatIndex;\n\nout vec4 vRgba;\nout vec2 vSplatUv;\nout vec3 vNdc;\nflat out uint vSplatIndex;\n\nuniform vec2 renderSize;\nuniform uint numSplats;\nuniform vec4 renderToViewQuat;\nuniform vec3 renderToViewPos;\nuniform float maxStdDev;\nuniform float minPixelRadius;\nuniform float maxPixelRadius;\nuniform float time;\nuniform float deltaTime;\nuniform bool debugFlag;\nuniform float minAlpha;\nuniform bool stochastic;\nuniform bool enable2DGS;\nuniform float blurAmount;\nuniform float preBlurAmount;\nuniform float focalDistance;\nuniform float apertureAngle;\nuniform float clipXY;\nuniform float focalAdjustment;\n\nuniform usampler2DArray packedSplats;\nuniform vec4 rgbMinMaxLnScaleMinMax;\n\n#ifdef USE_LOGDEPTHBUF\n bool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n }\n#endif\n\nvoid main() {\n \n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n\n if (uint(gl_InstanceID) >= numSplats) {\n return;\n }\n\n ivec3 texCoord;\n if (stochastic) {\n texCoord = ivec3(\n uint(gl_InstanceID) & SPLAT_TEX_WIDTH_MASK,\n (uint(gl_InstanceID) >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK,\n (uint(gl_InstanceID) >> SPLAT_TEX_LAYER_BITS)\n );\n } else {\n if (splatIndex == 0xffffffffu) {\n \n return;\n }\n texCoord = ivec3(\n splatIndex & SPLAT_TEX_WIDTH_MASK,\n (splatIndex >> SPLAT_TEX_WIDTH_BITS) & SPLAT_TEX_HEIGHT_MASK,\n splatIndex >> SPLAT_TEX_LAYER_BITS\n );\n }\n uvec4 packed = texelFetch(packedSplats, texCoord, 0);\n\n vec3 center, scales;\n vec4 quaternion, rgba;\n unpackSplatEncoding(packed, center, scales, quaternion, rgba, rgbMinMaxLnScaleMinMax);\n\n if (rgba.a < minAlpha) {\n return;\n }\n bvec3 zeroScales = equal(scales, vec3(0.0));\n if (all(zeroScales)) {\n return;\n }\n\n \n vec3 viewCenter = quatVec(renderToViewQuat, center) + renderToViewPos;\n\n \n if (viewCenter.z >= 0.0) {\n return;\n }\n\n \n vec4 clipCenter = projectionMatrix * vec4(viewCenter, 1.0);\n\n \n if (abs(clipCenter.z) >= clipCenter.w) {\n return;\n }\n\n \n float clip = clipXY * clipCenter.w;\n if (abs(clipCenter.x) > clip || abs(clipCenter.y) > clip) {\n return;\n }\n\n \n vSplatIndex = splatIndex;\n\n \n vec4 viewQuaternion = quatQuat(renderToViewQuat, quaternion);\n\n if (enable2DGS && any(zeroScales)) {\n vRgba = rgba;\n vSplatUv = position.xy * maxStdDev;\n\n vec3 offset;\n if (zeroScales.z) {\n offset = vec3(vSplatUv.xy * scales.xy, 0.0);\n } else if (zeroScales.y) {\n offset = vec3(vSplatUv.x * scales.x, 0.0, vSplatUv.y * scales.z);\n } else {\n offset = vec3(0.0, vSplatUv.xy * scales.yz);\n }\n\n vec3 viewPos = viewCenter + quatVec(viewQuaternion, offset);\n gl_Position = projectionMatrix * vec4(viewPos, 1.0);\n vNdc = gl_Position.xyz / gl_Position.w;\n return;\n }\n\n \n vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\n\n \n mat3 RS = scaleQuaternionToMatrix(scales, viewQuaternion);\n mat3 cov3D = RS * transpose(RS);\n\n \n vec2 scaledRenderSize = renderSize * focalAdjustment;\n vec2 focal = 0.5 * scaledRenderSize * vec2(projectionMatrix[0][0], projectionMatrix[1][1]);\n\n mat3 J;\n if(isOrthographic) {\n J = mat3(\n focal.x, 0.0, 0.0,\n 0.0, focal.y, 0.0,\n 0.0, 0.0, 0.0\n );\n } else {\n float invZ = 1.0 / viewCenter.z;\n vec2 J1 = focal * invZ;\n vec2 J2 = -(J1 * viewCenter.xy) * invZ;\n J = mat3(\n J1.x, 0.0, J2.x,\n 0.0, J1.y, J2.y,\n 0.0, 0.0, 0.0\n );\n }\n\n \n \n \n \n \n \n \n mat3 cov2D = transpose(J) * cov3D * J;\n float a = cov2D[0][0];\n float d = cov2D[1][1];\n float b = cov2D[0][1];\n\n \n a += preBlurAmount;\n d += preBlurAmount;\n\n float fullBlurAmount = blurAmount;\n if ((focalDistance > 0.0) && (apertureAngle > 0.0)) {\n float focusRadius = maxPixelRadius;\n if (viewCenter.z < 0.0) {\n float focusBlur = abs((-viewCenter.z - focalDistance) / viewCenter.z);\n float apertureRadius = focal.x * tan(0.5 * apertureAngle);\n focusRadius = focusBlur * apertureRadius;\n }\n fullBlurAmount = clamp(sqr(focusRadius), blurAmount, sqr(maxPixelRadius));\n }\n\n \n float detOrig = a * d - b * b;\n a += fullBlurAmount;\n d += fullBlurAmount;\n float det = a * d - b * b;\n\n \n float blurAdjust = sqrt(max(0.0, detOrig / det));\n rgba.a *= blurAdjust;\n if (rgba.a < minAlpha) {\n return;\n }\n\n \n float eigenAvg = 0.5 * (a + d);\n float eigenDelta = sqrt(max(0.0, eigenAvg * eigenAvg - det));\n float eigen1 = eigenAvg + eigenDelta;\n float eigen2 = eigenAvg - eigenDelta;\n\n vec2 eigenVec1 = normalize(vec2((abs(b) < 0.001) ? 1.0 : b, eigen1 - a));\n vec2 eigenVec2 = vec2(eigenVec1.y, -eigenVec1.x);\n\n float scale1 = min(maxPixelRadius, maxStdDev * sqrt(eigen1));\n float scale2 = min(maxPixelRadius, maxStdDev * sqrt(eigen2));\n if (scale1 < minPixelRadius && scale2 < minPixelRadius) {\n return;\n }\n\n \n vec2 pixelOffset = position.x * eigenVec1 * scale1 + position.y * eigenVec2 * scale2;\n vec2 ndcOffset = (2.0 / scaledRenderSize) * pixelOffset;\n vec3 ndc = vec3(ndcCenter.xy + ndcOffset, ndcCenter.z);\n\n vRgba = rgba;\n vSplatUv = position.xy * maxStdDev;\n vNdc = ndc;\n gl_Position = vec4(ndc.xy * clipCenter.w, clipCenter.zw);\n #include <logdepthbuf_vertex>\n}";
|
|
10171
10380
|
let shaders = null;
|
|
10172
10381
|
function getShaders() {
|
|
10173
10382
|
if (!shaders) {
|
|
@@ -10180,38 +10389,6 @@ function getShaders() {
|
|
|
10180
10389
|
return shaders;
|
|
10181
10390
|
}
|
|
10182
10391
|
const MAX_ACCUMULATORS = 5;
|
|
10183
|
-
let hasSplatMesh = false;
|
|
10184
|
-
let hasSparkRenderer = false;
|
|
10185
|
-
let sparkRendererInstance;
|
|
10186
|
-
function containsSplatMesh(object3D) {
|
|
10187
|
-
let hasSplatMesh2 = false;
|
|
10188
|
-
if (object3D instanceof SplatMesh) {
|
|
10189
|
-
return true;
|
|
10190
|
-
}
|
|
10191
|
-
object3D.traverse((child) => {
|
|
10192
|
-
hasSplatMesh2 = hasSplatMesh2 || child instanceof SplatMesh;
|
|
10193
|
-
});
|
|
10194
|
-
return hasSplatMesh2;
|
|
10195
|
-
}
|
|
10196
|
-
const sceneAdd = THREE__namespace.Scene.prototype.add;
|
|
10197
|
-
THREE__namespace.Scene.prototype.add = function(object) {
|
|
10198
|
-
hasSplatMesh = hasSplatMesh || containsSplatMesh(object);
|
|
10199
|
-
hasSparkRenderer = hasSparkRenderer || object instanceof SparkRenderer;
|
|
10200
|
-
sceneAdd.call(this, object);
|
|
10201
|
-
return this;
|
|
10202
|
-
};
|
|
10203
|
-
const sceneOnBeforeRender = THREE__namespace.Scene.prototype.onBeforeRender;
|
|
10204
|
-
THREE__namespace.Scene.prototype.onBeforeRender = function(renderer) {
|
|
10205
|
-
if (!hasSplatMesh) {
|
|
10206
|
-
return;
|
|
10207
|
-
}
|
|
10208
|
-
if (!hasSparkRenderer) {
|
|
10209
|
-
const spark = sparkRendererInstance || new SparkRenderer({ renderer });
|
|
10210
|
-
this.add(spark);
|
|
10211
|
-
}
|
|
10212
|
-
THREE__namespace.Scene.prototype.onBeforeRender = sceneOnBeforeRender;
|
|
10213
|
-
THREE__namespace.Scene.prototype.add = sceneAdd;
|
|
10214
|
-
};
|
|
10215
10392
|
const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
10216
10393
|
constructor(options) {
|
|
10217
10394
|
const uniforms = _SparkRenderer.makeUniforms();
|
|
@@ -10237,7 +10414,11 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10237
10414
|
this.lastUpdateTime = null;
|
|
10238
10415
|
this.defaultCameras = [];
|
|
10239
10416
|
this.lastStochastic = null;
|
|
10240
|
-
this.pendingUpdate =
|
|
10417
|
+
this.pendingUpdate = {
|
|
10418
|
+
scene: null,
|
|
10419
|
+
originToWorld: new THREE__namespace.Matrix4(),
|
|
10420
|
+
timeoutId: -1
|
|
10421
|
+
};
|
|
10241
10422
|
this.envViewpoint = null;
|
|
10242
10423
|
this.frustumCulled = false;
|
|
10243
10424
|
this.renderer = options.renderer;
|
|
@@ -10264,6 +10445,7 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10264
10445
|
this.needsUpdate = false;
|
|
10265
10446
|
this.originDistance = options.originDistance ?? 1;
|
|
10266
10447
|
this.maxStdDev = options.maxStdDev ?? Math.sqrt(8);
|
|
10448
|
+
this.minPixelRadius = options.minPixelRadius ?? 0;
|
|
10267
10449
|
this.maxPixelRadius = options.maxPixelRadius ?? 512;
|
|
10268
10450
|
this.minAlpha = options.minAlpha ?? 0.5 * (1 / 255);
|
|
10269
10451
|
this.enable2DGS = options.enable2DGS ?? false;
|
|
@@ -10276,6 +10458,7 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10276
10458
|
this.focalAdjustment = options.focalAdjustment ?? 1;
|
|
10277
10459
|
this.splatEncoding = options.splatEncoding ?? { ...DEFAULT_SPLAT_ENCODING };
|
|
10278
10460
|
this.active = new SplatAccumulator();
|
|
10461
|
+
this.active.refCount = 1;
|
|
10279
10462
|
this.accumulatorCount = 1;
|
|
10280
10463
|
this.freeAccumulators = [];
|
|
10281
10464
|
for (let count = 0; count < 1; ++count) {
|
|
@@ -10290,7 +10473,6 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10290
10473
|
this.viewpoint = this.defaultView;
|
|
10291
10474
|
this.prepareViewpoint(this.viewpoint);
|
|
10292
10475
|
this.clock = options.clock ? cloneClock(options.clock) : new THREE__namespace.Clock();
|
|
10293
|
-
sparkRendererInstance = this;
|
|
10294
10476
|
}
|
|
10295
10477
|
static makeUniforms() {
|
|
10296
10478
|
const uniforms = {
|
|
@@ -10307,6 +10489,8 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10307
10489
|
renderToViewPos: { value: new THREE__namespace.Vector3() },
|
|
10308
10490
|
// Maximum distance (in stddevs) from Gsplat center to render
|
|
10309
10491
|
maxStdDev: { value: 1 },
|
|
10492
|
+
// Minimum pixel radius for splat rendering
|
|
10493
|
+
minPixelRadius: { value: 0 },
|
|
10310
10494
|
// Maximum pixel radius for splat rendering
|
|
10311
10495
|
maxPixelRadius: { value: 512 },
|
|
10312
10496
|
// Minimum alpha value for splat rendering
|
|
@@ -10441,6 +10625,7 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10441
10625
|
this.uniforms.far.value = typedCamera.far;
|
|
10442
10626
|
this.uniforms.encodeLinear.value = viewpoint.encodeLinear;
|
|
10443
10627
|
this.uniforms.maxStdDev.value = this.maxStdDev;
|
|
10628
|
+
this.uniforms.minPixelRadius.value = this.minPixelRadius;
|
|
10444
10629
|
this.uniforms.maxPixelRadius.value = this.maxPixelRadius;
|
|
10445
10630
|
this.uniforms.minAlpha.value = this.minAlpha;
|
|
10446
10631
|
this.uniforms.stochastic.value = viewpoint.stochastic;
|
|
@@ -10527,21 +10712,32 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10527
10712
|
scene,
|
|
10528
10713
|
viewToWorld
|
|
10529
10714
|
}) {
|
|
10530
|
-
const originToWorld = this.matrixWorld
|
|
10715
|
+
const originToWorld = this.matrixWorld;
|
|
10531
10716
|
if (this.preUpdate) {
|
|
10532
|
-
this.updateInternal({
|
|
10533
|
-
} else {
|
|
10534
|
-
this.pendingUpdate = {
|
|
10717
|
+
this.updateInternal({
|
|
10535
10718
|
scene,
|
|
10536
|
-
originToWorld
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10719
|
+
originToWorld: originToWorld.clone(),
|
|
10720
|
+
viewToWorld
|
|
10721
|
+
});
|
|
10722
|
+
} else {
|
|
10723
|
+
this.pendingUpdate.scene = scene;
|
|
10724
|
+
this.pendingUpdate.originToWorld.copy(originToWorld);
|
|
10725
|
+
if (this.pendingUpdate.timeoutId === -1) {
|
|
10726
|
+
this.pendingUpdate.timeoutId = setTimeout(() => {
|
|
10540
10727
|
const { scene: scene2, originToWorld: originToWorld2 } = this.pendingUpdate;
|
|
10541
|
-
this.pendingUpdate = null;
|
|
10542
|
-
this.
|
|
10543
|
-
|
|
10544
|
-
|
|
10728
|
+
this.pendingUpdate.scene = null;
|
|
10729
|
+
this.pendingUpdate.timeoutId = -1;
|
|
10730
|
+
const updated = this.updateInternal({
|
|
10731
|
+
scene: scene2,
|
|
10732
|
+
originToWorld: originToWorld2,
|
|
10733
|
+
viewToWorld
|
|
10734
|
+
});
|
|
10735
|
+
if (updated) {
|
|
10736
|
+
const gl = this.renderer.getContext();
|
|
10737
|
+
gl.flush();
|
|
10738
|
+
}
|
|
10739
|
+
}, 1);
|
|
10740
|
+
}
|
|
10545
10741
|
}
|
|
10546
10742
|
}
|
|
10547
10743
|
updateInternal({
|
|
@@ -10601,7 +10797,7 @@ const _SparkRenderer = class _SparkRenderer extends THREE__namespace.Mesh {
|
|
|
10601
10797
|
}
|
|
10602
10798
|
const originChanged = !withinCoorientDist({
|
|
10603
10799
|
matrix1: originToWorld,
|
|
10604
|
-
matrix2:
|
|
10800
|
+
matrix2: accumulator.toWorld,
|
|
10605
10801
|
maxDistance: 1e-5,
|
|
10606
10802
|
minCoorient: 0.99999
|
|
10607
10803
|
});
|
|
@@ -11126,14 +11322,28 @@ function decodeKsplat(fileBytes, initNumSplats, splatCallback, shCallback) {
|
|
|
11126
11322
|
}
|
|
11127
11323
|
class SpzReader {
|
|
11128
11324
|
constructor({ fileBytes }) {
|
|
11325
|
+
this.version = -1;
|
|
11326
|
+
this.numSplats = 0;
|
|
11327
|
+
this.shDegree = 0;
|
|
11328
|
+
this.fractionalBits = 0;
|
|
11329
|
+
this.flags = 0;
|
|
11330
|
+
this.flagAntiAlias = false;
|
|
11331
|
+
this.reserved = 0;
|
|
11332
|
+
this.headerParsed = false;
|
|
11333
|
+
this.parsed = false;
|
|
11129
11334
|
this.fileBytes = fileBytes instanceof ArrayBuffer ? new Uint8Array(fileBytes) : fileBytes;
|
|
11130
11335
|
this.reader = new GunzipReader({ fileBytes: this.fileBytes });
|
|
11131
|
-
|
|
11336
|
+
}
|
|
11337
|
+
async parseHeader() {
|
|
11338
|
+
if (this.headerParsed) {
|
|
11339
|
+
throw new Error("SPZ file header already parsed");
|
|
11340
|
+
}
|
|
11341
|
+
const header = new DataView((await this.reader.read(16)).buffer);
|
|
11132
11342
|
if (header.getUint32(0, true) !== 1347635022) {
|
|
11133
11343
|
throw new Error("Invalid SPZ file");
|
|
11134
11344
|
}
|
|
11135
11345
|
this.version = header.getUint32(4, true);
|
|
11136
|
-
if (this.version < 1 || this.version >
|
|
11346
|
+
if (this.version < 1 || this.version > 3) {
|
|
11137
11347
|
throw new Error(`Unsupported SPZ version: ${this.version}`);
|
|
11138
11348
|
}
|
|
11139
11349
|
this.numSplats = header.getUint32(8, true);
|
|
@@ -11142,15 +11352,19 @@ class SpzReader {
|
|
|
11142
11352
|
this.flags = header.getUint8(14);
|
|
11143
11353
|
this.flagAntiAlias = (this.flags & 1) !== 0;
|
|
11144
11354
|
this.reserved = header.getUint8(15);
|
|
11355
|
+
this.headerParsed = true;
|
|
11145
11356
|
this.parsed = false;
|
|
11146
11357
|
}
|
|
11147
|
-
parseSplats(centerCallback, alphaCallback, rgbCallback, scalesCallback, quatCallback, shCallback) {
|
|
11358
|
+
async parseSplats(centerCallback, alphaCallback, rgbCallback, scalesCallback, quatCallback, shCallback) {
|
|
11359
|
+
if (!this.headerParsed) {
|
|
11360
|
+
throw new Error("SPZ file header must be parsed first");
|
|
11361
|
+
}
|
|
11148
11362
|
if (this.parsed) {
|
|
11149
11363
|
throw new Error("SPZ file already parsed");
|
|
11150
11364
|
}
|
|
11151
11365
|
this.parsed = true;
|
|
11152
11366
|
if (this.version === 1) {
|
|
11153
|
-
const centerBytes = this.reader.read(this.numSplats * 3 * 2);
|
|
11367
|
+
const centerBytes = await this.reader.read(this.numSplats * 3 * 2);
|
|
11154
11368
|
const centerUint16 = new Uint16Array(centerBytes.buffer);
|
|
11155
11369
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11156
11370
|
const i3 = i * 3;
|
|
@@ -11159,9 +11373,9 @@ class SpzReader {
|
|
|
11159
11373
|
const z = fromHalf(centerUint16[i3 + 2]);
|
|
11160
11374
|
centerCallback == null ? void 0 : centerCallback(i, x, y, z);
|
|
11161
11375
|
}
|
|
11162
|
-
} else if (this.version === 2) {
|
|
11376
|
+
} else if (this.version === 2 || this.version === 3) {
|
|
11163
11377
|
const fixed = 1 << this.fractionalBits;
|
|
11164
|
-
const centerBytes = this.reader.read(this.numSplats * 3 * 3);
|
|
11378
|
+
const centerBytes = await this.reader.read(this.numSplats * 3 * 3);
|
|
11165
11379
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11166
11380
|
const i9 = i * 9;
|
|
11167
11381
|
const x = ((centerBytes[i9 + 2] << 24 | centerBytes[i9 + 1] << 16 | centerBytes[i9] << 8) >> 8) / fixed;
|
|
@@ -11173,13 +11387,13 @@ class SpzReader {
|
|
|
11173
11387
|
throw new Error("Unreachable");
|
|
11174
11388
|
}
|
|
11175
11389
|
{
|
|
11176
|
-
const bytes = this.reader.read(this.numSplats);
|
|
11390
|
+
const bytes = await this.reader.read(this.numSplats);
|
|
11177
11391
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11178
11392
|
alphaCallback == null ? void 0 : alphaCallback(i, bytes[i] / 255);
|
|
11179
11393
|
}
|
|
11180
11394
|
}
|
|
11181
11395
|
{
|
|
11182
|
-
const rgbBytes = this.reader.read(this.numSplats * 3);
|
|
11396
|
+
const rgbBytes = await this.reader.read(this.numSplats * 3);
|
|
11183
11397
|
const scale = SH_C0 / 0.15;
|
|
11184
11398
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11185
11399
|
const i3 = i * 3;
|
|
@@ -11190,7 +11404,7 @@ class SpzReader {
|
|
|
11190
11404
|
}
|
|
11191
11405
|
}
|
|
11192
11406
|
{
|
|
11193
|
-
const scalesBytes = this.reader.read(this.numSplats * 3);
|
|
11407
|
+
const scalesBytes = await this.reader.read(this.numSplats * 3);
|
|
11194
11408
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11195
11409
|
const i3 = i * 3;
|
|
11196
11410
|
const scaleX = Math.exp(scalesBytes[i3] / 16 - 10);
|
|
@@ -11199,8 +11413,45 @@ class SpzReader {
|
|
|
11199
11413
|
scalesCallback == null ? void 0 : scalesCallback(i, scaleX, scaleY, scaleZ);
|
|
11200
11414
|
}
|
|
11201
11415
|
}
|
|
11202
|
-
{
|
|
11203
|
-
const
|
|
11416
|
+
if (this.version === 3) {
|
|
11417
|
+
const maxValue = 1 / Math.sqrt(2);
|
|
11418
|
+
const quatBytes = await this.reader.read(this.numSplats * 4);
|
|
11419
|
+
for (let i = 0; i < this.numSplats; i++) {
|
|
11420
|
+
const i3 = i * 4;
|
|
11421
|
+
const quaternion = [0, 0, 0, 0];
|
|
11422
|
+
const values = [
|
|
11423
|
+
quatBytes[i3],
|
|
11424
|
+
quatBytes[i3 + 1],
|
|
11425
|
+
quatBytes[i3 + 2],
|
|
11426
|
+
quatBytes[i3 + 3]
|
|
11427
|
+
];
|
|
11428
|
+
const combinedValues = values[0] + (values[1] << 8) + (values[2] << 16) + (values[3] << 24);
|
|
11429
|
+
const valueMask = (1 << 9) - 1;
|
|
11430
|
+
const largestIndex = combinedValues >>> 30;
|
|
11431
|
+
let remainingValues = combinedValues;
|
|
11432
|
+
let sumSquares = 0;
|
|
11433
|
+
for (let i2 = 3; i2 >= 0; --i2) {
|
|
11434
|
+
if (i2 !== largestIndex) {
|
|
11435
|
+
const value = remainingValues & valueMask;
|
|
11436
|
+
const sign2 = remainingValues >>> 9 & 1;
|
|
11437
|
+
remainingValues = remainingValues >>> 10;
|
|
11438
|
+
quaternion[i2] = maxValue * (value / valueMask);
|
|
11439
|
+
quaternion[i2] = sign2 === 0 ? quaternion[i2] : -quaternion[i2];
|
|
11440
|
+
sumSquares += quaternion[i2] * quaternion[i2];
|
|
11441
|
+
}
|
|
11442
|
+
}
|
|
11443
|
+
const square = 1 - sumSquares;
|
|
11444
|
+
quaternion[largestIndex] = Math.sqrt(Math.max(square, 0));
|
|
11445
|
+
quatCallback == null ? void 0 : quatCallback(
|
|
11446
|
+
i,
|
|
11447
|
+
quaternion[0],
|
|
11448
|
+
quaternion[1],
|
|
11449
|
+
quaternion[2],
|
|
11450
|
+
quaternion[3]
|
|
11451
|
+
);
|
|
11452
|
+
}
|
|
11453
|
+
} else {
|
|
11454
|
+
const quatBytes = await this.reader.read(this.numSplats * 3);
|
|
11204
11455
|
for (let i = 0; i < this.numSplats; i++) {
|
|
11205
11456
|
const i3 = i * 3;
|
|
11206
11457
|
const quatX = quatBytes[i3] / 127.5 - 1;
|
|
@@ -11216,7 +11467,7 @@ class SpzReader {
|
|
|
11216
11467
|
const sh1 = new Float32Array(3 * 3);
|
|
11217
11468
|
const sh2 = this.shDegree >= 2 ? new Float32Array(5 * 3) : void 0;
|
|
11218
11469
|
const sh3 = this.shDegree >= 3 ? new Float32Array(7 * 3) : void 0;
|
|
11219
|
-
const shBytes = this.reader.read(
|
|
11470
|
+
const shBytes = await this.reader.read(
|
|
11220
11471
|
this.numSplats * SH_DEGREE_TO_VECS[this.shDegree] * 3
|
|
11221
11472
|
);
|
|
11222
11473
|
let offset = 0;
|
|
@@ -11245,7 +11496,7 @@ class SpzReader {
|
|
|
11245
11496
|
const SH_DEGREE_TO_VECS = { 1: 3, 2: 8, 3: 15 };
|
|
11246
11497
|
const SH_C0 = 0.28209479177387814;
|
|
11247
11498
|
const SPZ_MAGIC = 1347635022;
|
|
11248
|
-
const SPZ_VERSION =
|
|
11499
|
+
const SPZ_VERSION = 3;
|
|
11249
11500
|
const FLAG_ANTIALIASED = 1;
|
|
11250
11501
|
class SpzWriter {
|
|
11251
11502
|
constructor({
|
|
@@ -11255,7 +11506,12 @@ class SpzWriter {
|
|
|
11255
11506
|
flagAntiAlias = true
|
|
11256
11507
|
}) {
|
|
11257
11508
|
this.clippedCount = 0;
|
|
11258
|
-
const splatSize = 9 +
|
|
11509
|
+
const splatSize = 9 + // Position
|
|
11510
|
+
1 + // Opacity
|
|
11511
|
+
3 + // Scale
|
|
11512
|
+
3 + // DC-rgb
|
|
11513
|
+
4 + // Rotation
|
|
11514
|
+
(shDegree >= 1 ? 9 : 0) + (shDegree >= 2 ? 15 : 0) + (shDegree >= 3 ? 21 : 0);
|
|
11259
11515
|
const bufferSize = 16 + numSplats * splatSize;
|
|
11260
11516
|
this.buffer = new ArrayBuffer(bufferSize);
|
|
11261
11517
|
this.view = new DataView(this.buffer);
|
|
@@ -11327,30 +11583,30 @@ class SpzWriter {
|
|
|
11327
11583
|
Math.max(0, Math.min(255, Math.round((Math.log(scaleZ) + 10) * 16)))
|
|
11328
11584
|
);
|
|
11329
11585
|
}
|
|
11330
|
-
setQuat(index,
|
|
11331
|
-
const base = 16 + this.numSplats * 16 + index *
|
|
11332
|
-
const
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
Math.
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
0
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
);
|
|
11586
|
+
setQuat(index, ...q) {
|
|
11587
|
+
const base = 16 + this.numSplats * 16 + index * 4;
|
|
11588
|
+
const quat = normalize$1(q);
|
|
11589
|
+
let iLargest = 0;
|
|
11590
|
+
for (let i = 1; i < 4; ++i) {
|
|
11591
|
+
if (Math.abs(quat[i]) > Math.abs(quat[iLargest])) {
|
|
11592
|
+
iLargest = i;
|
|
11593
|
+
}
|
|
11594
|
+
}
|
|
11595
|
+
const negate = quat[iLargest] < 0 ? 1 : 0;
|
|
11596
|
+
let comp = iLargest;
|
|
11597
|
+
for (let i = 0; i < 4; ++i) {
|
|
11598
|
+
if (i !== iLargest) {
|
|
11599
|
+
const negbit = (quat[i] < 0 ? 1 : 0) ^ negate;
|
|
11600
|
+
const mag = Math.floor(
|
|
11601
|
+
((1 << 9) - 1) * (Math.abs(quat[i]) / Math.SQRT1_2) + 0.5
|
|
11602
|
+
);
|
|
11603
|
+
comp = comp << 10 | negbit << 9 | mag;
|
|
11604
|
+
}
|
|
11605
|
+
}
|
|
11606
|
+
this.view.setUint8(base, comp & 255);
|
|
11607
|
+
this.view.setUint8(base + 1, comp >> 8 & 255);
|
|
11608
|
+
this.view.setUint8(base + 2, comp >> 16 & 255);
|
|
11609
|
+
this.view.setUint8(base + 3, comp >>> 24 & 255);
|
|
11354
11610
|
}
|
|
11355
11611
|
static quantizeSh(sh, bits2) {
|
|
11356
11612
|
const value = Math.round(sh * 128) + 128;
|
|
@@ -11360,7 +11616,7 @@ class SpzWriter {
|
|
|
11360
11616
|
}
|
|
11361
11617
|
setSh(index, sh1, sh2, sh3) {
|
|
11362
11618
|
const shVecs = SH_DEGREE_TO_VECS[this.shDegree] || 0;
|
|
11363
|
-
const base1 = 16 + this.numSplats *
|
|
11619
|
+
const base1 = 16 + this.numSplats * 20 + index * shVecs * 3;
|
|
11364
11620
|
for (let j = 0; j < 9; ++j) {
|
|
11365
11621
|
this.view.setUint8(base1 + j, SpzWriter.quantizeSh(sh1[j], 5));
|
|
11366
11622
|
}
|
|
@@ -11490,6 +11746,7 @@ async function transcodeSpz(input) {
|
|
|
11490
11746
|
}
|
|
11491
11747
|
case SplatFileType.SPZ: {
|
|
11492
11748
|
const spz2 = new SpzReader({ fileBytes: input2.fileBytes });
|
|
11749
|
+
await spz2.parseHeader();
|
|
11493
11750
|
const mapping = new Int32Array(spz2.numSplats);
|
|
11494
11751
|
mapping.fill(-1);
|
|
11495
11752
|
const centers = new Float32Array(spz2.numSplats * 3);
|
|
@@ -13533,6 +13790,7 @@ exports.PackedSplats = PackedSplats;
|
|
|
13533
13790
|
exports.PlyReader = PlyReader;
|
|
13534
13791
|
exports.PointerControls = PointerControls;
|
|
13535
13792
|
exports.Readback = Readback;
|
|
13793
|
+
exports.RgbaArray = RgbaArray;
|
|
13536
13794
|
exports.Sint8ToFloat = Sint8ToFloat;
|
|
13537
13795
|
exports.SparkControls = SparkControls;
|
|
13538
13796
|
exports.SparkRenderer = SparkRenderer;
|