@needle-tools/gltf-progressive 2.0.0-alpha → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,7 +4,7 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [2.0.0-alpha] - 2024-12-09
7
+ ## [2.0.0-alpha.1] - 2024-12-09
8
8
  - Add: `Accept` header options for Needle Cloud requests
9
9
 
10
10
  ## [1.2.15] - 2024-10-21
@@ -22,10 +22,10 @@ const Ze = j, je = ae;
22
22
  fetch(j + "draco_decoder.js", { method: "head" }).catch((o) => {
23
23
  j === Ze && (j = "./include/draco/"), ae === je && (ae = "./include/ktx2/");
24
24
  });
25
- function xt(o) {
25
+ function Lt(o) {
26
26
  j = o;
27
27
  }
28
- function Lt(o) {
28
+ function xt(o) {
29
29
  ae = o;
30
30
  }
31
31
  let Q, he, Z;
@@ -46,7 +46,7 @@ function tt(...o) {
46
46
  let e = o[0];
47
47
  const s = new URL(e, window.location.href);
48
48
  if (s.hostname.endsWith("needle.tools")) {
49
- const r = t ? t.progressive : !0, i = t ? t.usecase : "default";
49
+ const r = (t == null ? void 0 : t.progressive) !== void 0 ? t.progressive : !0, i = t != null && t.usecase ? t.usecase : "default";
50
50
  r ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${i}` : this.requestHeader.Accept = `*/*;usecase=${i}`, e = s.toString();
51
51
  }
52
52
  return o[0] = e, Me == null ? void 0 : Me.call(this, ...o);
@@ -108,8 +108,8 @@ function nt(o) {
108
108
  t.setAttribute(e, o.getAttribute(e));
109
109
  return t.setIndex(o.getIndex()), t;
110
110
  }
111
- const Y = new Array(), V = "NEEDLE_progressive", x = le("debugprogressive"), De = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), Se = /* @__PURE__ */ new Set();
112
- if (x) {
111
+ const Y = new Array(), V = "NEEDLE_progressive", L = le("debugprogressive"), De = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), Se = /* @__PURE__ */ new Set();
112
+ if (L) {
113
113
  let o = function() {
114
114
  t += 1, console.log("Toggle LOD level", t, oe), oe.forEach((n, r) => {
115
115
  for (const i of n.keys) {
@@ -134,7 +134,7 @@ if (x) {
134
134
  }
135
135
  function Pe(o, t, e) {
136
136
  var n;
137
- if (!x)
137
+ if (!L)
138
138
  return;
139
139
  oe.has(o) || oe.set(o, { keys: [], sourceId: e });
140
140
  const s = oe.get(o);
@@ -155,7 +155,7 @@ const v = class {
155
155
  return this._isLoadingMesh = !1, r && v.registerMesh(this.url, e.guid, r, (i = e.lods) == null ? void 0 : i.length, void 0, e), r;
156
156
  })) : null;
157
157
  });
158
- x && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
158
+ L && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
159
159
  }
160
160
  /** The name of the extension */
161
161
  get name() {
@@ -178,7 +178,7 @@ const v = class {
178
178
  this.getMaterialMinMaxLODsCount(a, e);
179
179
  return t[n] = e, e;
180
180
  }
181
- if (x === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
181
+ if (L === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
182
182
  const a = t;
183
183
  for (const l of Object.keys(a.uniforms)) {
184
184
  const u = a.uniforms[l].value;
@@ -269,12 +269,12 @@ const v = class {
269
269
  const a = r.index || 0;
270
270
  i = i[a];
271
271
  }
272
- i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, x && Pe(t, "geometry", r.url)) : x && console.error("Invalid LOD geometry", i));
272
+ i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, L && Pe(t, "geometry", r.url)) : L && console.error("Invalid LOD geometry", i));
273
273
  }
274
274
  return i;
275
275
  }).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
276
276
  } else
277
- x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
277
+ L && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
278
278
  return Promise.resolve(null);
279
279
  }
280
280
  static assignTextureLOD(t, e = 0) {
@@ -299,7 +299,7 @@ const v = class {
299
299
  }
300
300
  if (t instanceof We || t.isMaterial === !0) {
301
301
  const s = t, n = [], r = new Array();
302
- if (x && Se.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
302
+ if (L && Se.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
303
303
  const i = s;
304
304
  for (const a of Object.keys(i.uniforms)) {
305
305
  const l = i.uniforms[a].value;
@@ -342,30 +342,30 @@ const v = class {
342
342
  if (i) {
343
343
  const a = this.getAssignedLODInformation(i);
344
344
  if (a && (a == null ? void 0 : a.level) < e)
345
- return x === "verbose" && console.warn("Assigned texture level is already higher: ", a.level, e, s, i, r), null;
345
+ return L === "verbose" && console.warn("Assigned texture level is already higher: ", a.level, e, s, i, r), null;
346
346
  }
347
347
  s[n] = r;
348
348
  }
349
- if (x && n && s) {
349
+ if (L && n && s) {
350
350
  const i = this.getAssignedLODInformation(t);
351
351
  i && Pe(s, n, i.url);
352
352
  }
353
353
  }
354
354
  return r;
355
355
  } else
356
- x == "verbose" && console.warn("No LOD found for", t, e);
356
+ L == "verbose" && console.warn("No LOD found for", t, e);
357
357
  return null;
358
358
  }).catch((r) => (console.error("Error loading LOD", t, r), null));
359
359
  }
360
360
  afterRoot(t) {
361
361
  var e, s;
362
- return x && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, r) => {
362
+ return L && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, r) => {
363
363
  var i;
364
364
  if (n != null && n.extensions) {
365
365
  const a = n == null ? void 0 : n.extensions[V];
366
366
  if (a) {
367
367
  if (!a.lods) {
368
- x && console.warn("Texture has no LODs", a);
368
+ L && console.warn("Texture has no LODs", a);
369
369
  return;
370
370
  }
371
371
  let l = !1;
@@ -395,7 +395,7 @@ const v = class {
395
395
  }
396
396
  static async getOrLoadLOD(t, e) {
397
397
  var a, l, u, c;
398
- const s = x == "verbose", n = t.userData.LODS;
398
+ const s = L == "verbose", n = t.userData.LODS;
399
399
  if (!n)
400
400
  return null;
401
401
  const r = n == null ? void 0 : n.key;
@@ -413,7 +413,7 @@ const v = class {
413
413
  }
414
414
  const g = Array.isArray(i.lods) ? (a = i.lods[e]) == null ? void 0 : a.path : i.lods;
415
415
  if (!g)
416
- return x && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
416
+ return L && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
417
417
  const p = st(n.url, g);
418
418
  if (p.endsWith(".glb") || p.endsWith(".gltf")) {
419
419
  if (!i.guid)
@@ -426,12 +426,12 @@ const v = class {
426
426
  if (h == null || (h instanceof se && t instanceof se ? (l = h.image) != null && l.data || (u = h.source) != null && u.data ? h = this.copySettings(t, h) : (B = !0, this.previouslyLoaded.delete(M)) : h instanceof ge && t instanceof ge && ((c = h.attributes.position) != null && c.array || (B = !0, this.previouslyLoaded.delete(M)))), !B)
427
427
  return h;
428
428
  }
429
- const L = i, $ = new Promise(async (h, B) => {
429
+ const x = i, $ = new Promise(async (h, B) => {
430
430
  const F = new be();
431
- Ge(F), x && (await new Promise((A) => setTimeout(A, 1e3)), s && console.warn("Start loading (delayed) " + p, L.guid));
431
+ Ge(F), L && (await new Promise((A) => setTimeout(A, 1e3)), s && console.warn("Start loading (delayed) " + p, x.guid));
432
432
  let k = p;
433
- if (L && Array.isArray(L.lods)) {
434
- const A = L.lods[e];
433
+ if (x && Array.isArray(x.lods)) {
434
+ const A = x.lods[e];
435
435
  A.hash && (k += "?v=" + A.hash);
436
436
  }
437
437
  const S = await F.loadAsync(k).catch((A) => (console.error(`Error loading LOD ${e} from ${p}
@@ -439,14 +439,14 @@ const v = class {
439
439
  if (!S)
440
440
  return null;
441
441
  const q = S.parser;
442
- s && console.log("Loading finished " + p, L.guid);
442
+ s && console.log("Loading finished " + p, x.guid);
443
443
  let T = 0;
444
444
  if (S.parser.json.textures) {
445
445
  let A = !1;
446
446
  for (const f of S.parser.json.textures) {
447
447
  if (f != null && f.extensions) {
448
448
  const y = f == null ? void 0 : f.extensions[V];
449
- if (y != null && y.guid && y.guid === L.guid) {
449
+ if (y != null && y.guid && y.guid === x.guid) {
450
450
  A = !0;
451
451
  break;
452
452
  }
@@ -455,16 +455,16 @@ const v = class {
455
455
  }
456
456
  if (A) {
457
457
  let f = await q.getDependency("texture", T);
458
- return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof se && (f = this.copySettings(t, f)), f && (f.guid = L.guid), h(f);
458
+ return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof se && (f = this.copySettings(t, f)), f && (f.guid = x.guid), h(f);
459
459
  } else
460
- x && console.warn("Could not find texture with guid", L.guid, S.parser.json);
460
+ L && console.warn("Could not find texture with guid", x.guid, S.parser.json);
461
461
  }
462
462
  if (T = 0, S.parser.json.meshes) {
463
463
  let A = !1;
464
464
  for (const f of S.parser.json.meshes) {
465
465
  if (f != null && f.extensions) {
466
466
  const y = f == null ? void 0 : f.extensions[V];
467
- if (y != null && y.guid && y.guid === L.guid) {
467
+ if (y != null && y.guid && y.guid === x.guid) {
468
468
  A = !0;
469
469
  break;
470
470
  }
@@ -472,7 +472,7 @@ const v = class {
472
472
  T++;
473
473
  }
474
474
  if (A) {
475
- const f = await q.getDependency("mesh", T), y = L;
475
+ const f = await q.getDependency("mesh", T), y = x;
476
476
  if (s && console.log(`Loaded Mesh "${f.name}"`, p, T, f, M), f.isMesh === !0) {
477
477
  const O = f.geometry;
478
478
  return v.assignLODInformation(n.url, O, r, e, void 0, y.density), h(O);
@@ -488,7 +488,7 @@ const v = class {
488
488
  return h(O);
489
489
  }
490
490
  } else
491
- x && console.warn("Could not find mesh with guid", L.guid, S.parser.json);
491
+ L && console.warn("Could not find mesh with guid", x.guid, S.parser.json);
492
492
  }
493
493
  return h(null);
494
494
  });
@@ -496,10 +496,10 @@ const v = class {
496
496
  } else if (t instanceof se) {
497
497
  s && console.log("Load texture from uri: " + p);
498
498
  const w = await new qe().loadAsync(p);
499
- return w ? (w.guid = i.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = t.colorSpace, s && console.log(i, w)) : x && console.warn("failed loading", p), w;
499
+ return w ? (w.guid = i.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = t.colorSpace, s && console.log(i, w)) : L && console.warn("failed loading", p), w;
500
500
  }
501
501
  } else
502
- x && console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`, t.type);
502
+ L && console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`, t.type);
503
503
  return null;
504
504
  }
505
505
  static assignLODInformation(t, e, s, n, r, i) {
@@ -515,7 +515,7 @@ const v = class {
515
515
  }
516
516
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
517
517
  static copySettings(t, e) {
518
- return e = e.clone(), x && console.warn(`Copying texture settings
518
+ return e = e.clone(), L && console.warn(`Copying texture settings
519
519
  `, t.uuid, `
520
520
  `, e.uuid), e.offset = t.offset, e.repeat = t.repeat, e.colorSpace = t.colorSpace, e.magFilter = t.magFilter, e.minFilter = t.minFilter, e.wrapS = t.wrapS, e.wrapT = t.wrapT, e.flipY = t.flipY, e.anisotropy = t.anisotropy, e.mipmaps || (e.generateMipmaps = t.generateMipmaps), e;
521
521
  }
@@ -525,8 +525,8 @@ let _ = v;
525
525
  * Register a texture with LOD information
526
526
  */
527
527
  d(_, "registerTexture", (t, e, s, n, r) => {
528
- if (x && console.log("> Progressive: register texture", n, e.name, e.uuid, e, r), !e) {
529
- x && console.error("gltf-progressive: Register texture without texture");
528
+ if (L && console.log("> Progressive: register texture", n, e.name, e.uuid, e, r), !e) {
529
+ L && console.error("gltf-progressive: Register texture without texture");
530
530
  return;
531
531
  }
532
532
  e.source && (e.source[De] = r);
@@ -537,10 +537,10 @@ d(_, "registerTexture", (t, e, s, n, r) => {
537
537
  */
538
538
  d(_, "registerMesh", (t, e, s, n, r, i) => {
539
539
  var u;
540
- x && console.log("> Progressive: register mesh", r, s.name, i, s.uuid, s);
540
+ L && console.log("> Progressive: register mesh", r, s.name, i, s.uuid, s);
541
541
  const a = s.geometry;
542
542
  if (!a) {
543
- x && console.warn("gltf-progressive: Register mesh without geometry");
543
+ L && console.warn("gltf-progressive: Register mesh without geometry");
544
544
  return;
545
545
  }
546
546
  a.userData || (a.userData = {}), v.assignLODInformation(t, a, e, n, r, i.density), v.lodInfos.set(e, i);
@@ -669,7 +669,7 @@ const P = class {
669
669
  };
670
670
  }
671
671
  disable() {
672
- m(this, N) && (this.renderer.render = m(this, N), U(this, N, void 0));
672
+ m(this, N) && (console.debug("[gltf-progressive] Disabling LODsManager for renderer"), this.renderer.render = m(this, N), U(this, N, void 0));
673
673
  }
674
674
  update(t, e) {
675
675
  this.internalUpdate(t, e);
@@ -807,7 +807,7 @@ const P = class {
807
807
  }
808
808
  g || (l = !0, a = 0);
809
809
  const w = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
810
- let L = e.geometry.boundingBox;
810
+ let x = e.geometry.boundingBox;
811
811
  if (e.type === "SkinnedMesh") {
812
812
  const D = e;
813
813
  if (!D.boundingBox)
@@ -816,9 +816,9 @@ const P = class {
816
816
  const h = me(D), B = D.geometry;
817
817
  h && (D.geometry = h), D.computeBoundingBox(), D.geometry = B;
818
818
  }
819
- L = D.boundingBox;
819
+ x = D.boundingBox;
820
820
  }
821
- if (L && t.isPerspectiveCamera) {
821
+ if (x && t.isPerspectiveCamera) {
822
822
  const D = t;
823
823
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
824
824
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
@@ -828,23 +828,23 @@ const P = class {
828
828
  return;
829
829
  }
830
830
  }
831
- if (this._tempBox.copy(L), this._tempBox.applyMatrix4(e.matrixWorld), P.isInside(this._tempBox, this.projectionScreenMatrix)) {
831
+ if (this._tempBox.copy(x), this._tempBox.applyMatrix4(e.matrixWorld), P.isInside(this._tempBox, this.projectionScreenMatrix)) {
832
832
  r.mesh_lod = 0, r.texture_lod = 0;
833
833
  return;
834
834
  }
835
835
  if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && D.fov > 70) {
836
836
  const f = this._tempBox.min, y = this._tempBox.max;
837
837
  let O = f.x, b = f.y, E = y.x, X = y.y;
838
- const ce = 2, xe = 1.5, ue = (f.x + y.x) * 0.5, fe = (f.y + y.y) * 0.5;
838
+ const ce = 2, Le = 1.5, ue = (f.x + y.x) * 0.5, fe = (f.y + y.y) * 0.5;
839
839
  O = (O - ue) * ce + ue, b = (b - fe) * ce + fe, E = (E - ue) * ce + ue, X = (X - fe) * ce + fe;
840
- const Ue = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), ze = b < 0 && X > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), Le = Math.max(Ue, ze);
841
- s.lastCentrality = (xe - Le) * (xe - Le) * (xe - Le);
840
+ const Ue = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), ze = b < 0 && X > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), xe = Math.max(Ue, ze);
841
+ s.lastCentrality = (Le - xe) * (Le - xe) * (Le - xe);
842
842
  } else
843
843
  s.lastCentrality = 1;
844
844
  const h = this._tempBox.getSize(this._tempBoxSize);
845
845
  h.multiplyScalar(0.5), screen.availHeight > 0 && w > 0 && h.multiplyScalar(w / screen.availHeight), h.x *= D.aspect;
846
846
  const B = t.matrixWorldInverse, F = this._tempBox2;
847
- F.copy(L), F.applyMatrix4(e.matrixWorld), F.applyMatrix4(B);
847
+ F.copy(x), F.applyMatrix4(e.matrixWorld), F.applyMatrix4(B);
848
848
  const k = F.getSize(this._tempBox2Size), S = Math.max(k.x, k.y);
849
849
  if (Math.max(h.x, h.y) != 0 && S != 0 && (h.z = k.z / Math.max(k.x, k.y) * Math.max(h.x, h.y)), s.lastScreenCoverage = Math.max(h.x, h.y, h.z), s.lastScreenspaceVolume.copy(h), s.lastScreenCoverage *= s.lastCentrality, I && P.debugDrawLine) {
850
850
  const f = this.tempMatrix.copy(this.projectionScreenMatrix);
@@ -1010,9 +1010,9 @@ class ft {
1010
1010
  l[de] = !0, l.userData && (l.userData.LOD = -1);
1011
1011
  const u = Object.keys(l);
1012
1012
  for (let M = 0; M < u.length; M++) {
1013
- const w = u[M], L = l[w];
1014
- if ((L == null ? void 0 : L.isTexture) === !0) {
1015
- const $ = (g = (c = L.userData) == null ? void 0 : c.associations) == null ? void 0 : g.textures;
1013
+ const w = u[M], x = l[w];
1014
+ if ((x == null ? void 0 : x.isTexture) === !0) {
1015
+ const $ = (g = (c = x.userData) == null ? void 0 : c.associations) == null ? void 0 : g.textures;
1016
1016
  if ($ == null)
1017
1017
  continue;
1018
1018
  const D = s.parser.json.textures[$];
@@ -1022,7 +1022,7 @@ class ft {
1022
1022
  }
1023
1023
  if ((p = D == null ? void 0 : D.extensions) != null && p[V]) {
1024
1024
  const h = D.extensions[V];
1025
- h && r && _.registerTexture(r, L, h.lods.length, $, h);
1025
+ h && r && _.registerTexture(r, x, h.lods.length, $, h);
1026
1026
  }
1027
1027
  }
1028
1028
  }
@@ -1070,8 +1070,8 @@ export {
1070
1070
  me as getRaycastMesh,
1071
1071
  $e as patchModelViewer,
1072
1072
  it as registerRaycastMesh,
1073
- xt as setDracoDecoderLocation,
1074
- Lt as setKTX2TranscoderLocation,
1073
+ Lt as setDracoDecoderLocation,
1074
+ xt as setKTX2TranscoderLocation,
1075
1075
  Dt as useNeedleProgressive,
1076
1076
  Mt as useRaycastMeshes
1077
1077
  };
@@ -1,8 +1,8 @@
1
- var $e=Object.defineProperty,Ne=(t,e,r)=>e in t?$e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Ne(t,typeof e!="symbol"?e+"":e,r),r),Se=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},v=(t,e,r)=>(Se(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,o)=>(Se(t,e,"write to private field"),o?o.call(t,r):e.set(t,r),r);import{BufferGeometry as le,Mesh as q,Material as Fe,Texture as Z,TextureLoader as Ue,Matrix4 as Te,Clock as ze,MeshStandardMaterial as Ve,Sphere as qe,Box3 as Ee,Vector3 as W}from"three";import{GLTFLoader as me}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as He}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const pe="";globalThis.GLTF_PROGRESSIVE_VERSION=pe,console.debug(`[gltf-progressive] version ${pe}`);let H="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=H,Je=ee;fetch(H+"draco_decoder.js",{method:"head"}).catch(t=>{H===Ye&&(H="./include/draco/"),ee===Je&&(ee="./include/ktx2/")});function Qe(t){H=t}function Ze(t){ee=t}let K,ue,Y;function ye(t){return K||(K=new He,K.setDecoderPath(H),K.setDecoderConfig({type:"js"})),Y||(Y=new Ke,Y.setTranscoderPath(ee)),ue||(ue=Xe),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:Y,meshoptDecoder:ue}}function ve(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}const xe=new WeakMap;function Ae(t,e){let r=xe.get(t);r?r=Object.assign(r,e):r=e,xe.set(t,r)}const Be=me.prototype.load;function et(...t){const e=xe.get(this);let r=t[0];const o=new URL(r,window.location.href);if(o.hostname.endsWith("needle.tools")){const s=e?e.progressive:!0,n=e?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${n}`:this.requestHeader.Accept=`*/*;usecase=${n}`,r=o.toString()}return t[0]=r,Be?.call(this,...t)}me.prototype.load=et,te("debugprogressive");function te(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function tt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const o=t.substring(0,r+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let ce;function rt(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const Le=Symbol("needle:raycast-mesh");function re(t){return t?.[Le]instanceof le?t[Le]:null}function Ie(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=nt(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,o){const s=this,n=re(s);let i;n&&s.isMesh&&(i=s.geometry,s.geometry=n),e.call(this,r,o),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function nt(t){const e=new le;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const N=new Array,R="NEEDLE_progressive",x=te("debugprogressive"),Me=Symbol("needle-progressive-texture"),ne=new Map,De=new Set;if(x){let t=function(){e+=1,console.log("Toggle LOD level",e,ne),ne.forEach((s,n)=>{for(const i of s.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,S.assignMeshLOD(n,a),u&&(r=Math.max(r,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,S.assignTextureLOD(n,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,o=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(o=!o,De&&De.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Pe(t,e,r){var o;if(!x)return;ne.has(t)||ne.set(t,{keys:[],sourceId:r});const s=ne.get(t);((o=s?.keys)==null?void 0:o.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var o,s;if(this._isLoadingMesh)return null;const n=(s=(o=this.parser.json.meshes[r])==null?void 0:o.extensions)==null?void 0:s[R];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let f=0;f<a.lods.length;f++){const g=a.lods[f];g.width&&(l.lods[f]=l.lods[f]||{min_height:1/0,max_height:0},l.lods[f].min_height=Math.min(l.lods[f].min_height,g.height),l.lods[f].max_height=Math.max(l.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,s;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(r=o?.userData)!=null&&r.LODS){const n=o.userData.LODS;if(s=this.lodInfos.get(n.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const n of N)(r=n.onBeforeGetLODMesh)==null||r.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=s.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,x&&Pe(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const i of s)Array.isArray(i)&&n.push(...i);return n})}else return this.assignTextureLOD(r.material,e)}if(t instanceof Fe||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&n.uniforms[i].value!=a&&(n.uniforms[i].value=a,n.uniformsNeedUpdate=!0),a));o.push(u),s.push(i)}}}else for(const n of Object.keys(r)){const i=r[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,n);o.push(l),s.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&o){const n=r[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,n,s),null}r[o]=s}if(x&&o&&r){const n=this.getAssignedLODInformation(t);n&&Pe(r,o,n.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[R];if(i){if(!i.lods){x&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const n=o?.extensions[R];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var r,o,s,n;const i=x=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const f=t;f.source&&f.source[Me]&&(a=f.source[Me])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let p=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!f)return x&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const g=tt(l.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=g+"_"+a.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(_=>(console.error(`Error loading LOD ${e} from ${g}
2
- `,_),null)),O=!1;if(d==null||(d instanceof Z&&t instanceof Z?(o=d.image)!=null&&o.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(O=!0,this.previouslyLoaded.delete(p)):d instanceof le&&t instanceof le&&((n=d.attributes.position)!=null&&n.array||(O=!0,this.previouslyLoaded.delete(p)))),!O)return d}const D=a,L=new Promise(async(d,O)=>{const _=new me;ve(_),x&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let B=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(B+="?v="+m.hash)}const T=await _.loadAsync(B).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
3
- `,m),null));if(!T)return null;const $=T.parser;i&&console.log("Loading finished "+g,D.guid);let y=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){let h=await $.getDependency("texture",y);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,y,h,p),t instanceof Z&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else x&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(y=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){const h=await $.getDependency("mesh",y),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,y,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(l.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(l.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else x&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Z){i&&console.log("Load texture from uri: "+g);const p=await new Ue().loadAsync(g);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):x&&console.warn("failed loading",g),p}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,n){if(!e)return;e.userData||(e.userData={});const i=new ot(t,r,o,s,n);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),x&&console.warn(`Copying texture settings
1
+ var $e=Object.defineProperty,Ne=(t,e,r)=>e in t?$e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Ne(t,typeof e!="symbol"?e+"":e,r),r),Se=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},y=(t,e,r)=>(Se(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,o)=>(Se(t,e,"write to private field"),o?o.call(t,r):e.set(t,r),r);import{BufferGeometry as le,Mesh as q,Material as Fe,Texture as Z,TextureLoader as Ue,Matrix4 as Te,Clock as ze,MeshStandardMaterial as Ve,Sphere as qe,Box3 as Ee,Vector3 as W}from"three";import{GLTFLoader as me}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as He}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const pe="";globalThis.GLTF_PROGRESSIVE_VERSION=pe,console.debug(`[gltf-progressive] version ${pe}`);let H="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=H,Je=ee;fetch(H+"draco_decoder.js",{method:"head"}).catch(t=>{H===Ye&&(H="./include/draco/"),ee===Je&&(ee="./include/ktx2/")});function Qe(t){H=t}function Ze(t){ee=t}let K,ue,Y;function ve(t){return K||(K=new He,K.setDecoderPath(H),K.setDecoderConfig({type:"js"})),Y||(Y=new Ke,Y.setTranscoderPath(ee)),ue||(ue=Xe),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}const xe=new WeakMap;function Ae(t,e){let r=xe.get(t);r?r=Object.assign(r,e):r=e,xe.set(t,r)}const Be=me.prototype.load;function et(...t){const e=xe.get(this);let r=t[0];const o=new URL(r,window.location.href);if(o.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,n=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${n}`:this.requestHeader.Accept=`*/*;usecase=${n}`,r=o.toString()}return t[0]=r,Be?.call(this,...t)}me.prototype.load=et,te("debugprogressive");function te(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function tt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const o=t.substring(0,r+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let ce;function rt(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const Le=Symbol("needle:raycast-mesh");function re(t){return t?.[Le]instanceof le?t[Le]:null}function Ie(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=nt(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,o){const s=this,n=re(s);let i;n&&s.isMesh&&(i=s.geometry,s.geometry=n),e.call(this,r,o),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function nt(t){const e=new le;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const N=new Array,R="NEEDLE_progressive",x=te("debugprogressive"),Me=Symbol("needle-progressive-texture"),ne=new Map,De=new Set;if(x){let t=function(){e+=1,console.log("Toggle LOD level",e,ne),ne.forEach((s,n)=>{for(const i of s.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,S.assignMeshLOD(n,a),u&&(r=Math.max(r,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,S.assignTextureLOD(n,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,o=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(o=!o,De&&De.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Pe(t,e,r){var o;if(!x)return;ne.has(t)||ne.set(t,{keys:[],sourceId:r});const s=ne.get(t);((o=s?.keys)==null?void 0:o.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var o,s;if(this._isLoadingMesh)return null;const n=(s=(o=this.parser.json.meshes[r])==null?void 0:o.extensions)==null?void 0:s[R];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let f=0;f<a.lods.length;f++){const g=a.lods[f];g.width&&(l.lods[f]=l.lods[f]||{min_height:1/0,max_height:0},l.lods[f].min_height=Math.min(l.lods[f].min_height,g.height),l.lods[f].max_height=Math.max(l.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,s;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(r=o?.userData)!=null&&r.LODS){const n=o.userData.LODS;if(s=this.lodInfos.get(n.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const n of N)(r=n.onBeforeGetLODMesh)==null||r.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=s.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,x&&Pe(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const i of s)Array.isArray(i)&&n.push(...i);return n})}else return this.assignTextureLOD(r.material,e)}if(t instanceof Fe||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&n.uniforms[i].value!=a&&(n.uniforms[i].value=a,n.uniformsNeedUpdate=!0),a));o.push(u),s.push(i)}}}else for(const n of Object.keys(r)){const i=r[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,n);o.push(l),s.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&o){const n=r[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,n,s),null}r[o]=s}if(x&&o&&r){const n=this.getAssignedLODInformation(t);n&&Pe(r,o,n.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[R];if(i){if(!i.lods){x&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const n=o?.extensions[R];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var r,o,s,n;const i=x=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const f=t;f.source&&f.source[Me]&&(a=f.source[Me])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let p=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!f)return x&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const g=tt(l.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=g+"_"+a.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(_=>(console.error(`Error loading LOD ${e} from ${g}
2
+ `,_),null)),O=!1;if(d==null||(d instanceof Z&&t instanceof Z?(o=d.image)!=null&&o.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(O=!0,this.previouslyLoaded.delete(p)):d instanceof le&&t instanceof le&&((n=d.attributes.position)!=null&&n.array||(O=!0,this.previouslyLoaded.delete(p)))),!O)return d}const D=a,L=new Promise(async(d,O)=>{const _=new me;ye(_),x&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let B=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(B+="?v="+m.hash)}const T=await _.loadAsync(B).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
3
+ `,m),null));if(!T)return null;const $=T.parser;i&&console.log("Loading finished "+g,D.guid);let v=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){let h=await $.getDependency("texture",v);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,v,h,p),t instanceof Z&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else x&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(v=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){const h=await $.getDependency("mesh",v),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,v,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(l.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(l.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else x&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Z){i&&console.log("Load texture from uri: "+g);const p=await new Ue().loadAsync(g);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):x&&console.warn("failed loading",g),p}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,n){if(!e)return;e.userData||(e.userData={});const i=new ot(t,r,o,s,n);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),x&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Me]=s);const n=s.guid;w.assignLODInformation(t,e,n,r,o,void 0),w.lodInfos.set(n,s),w.lowresCache.set(n,e)}),c(S,"registerMesh",(t,e,r,o,s,n)=>{var i;x&&console.log("> Progressive: register mesh",s,r.name,n,r.uuid,r);const l=r.geometry;if(!l){x&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,s,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),o>0&&!re(r)&&Ie(r,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,r,n)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class ot{constructor(e,r,o,s,n){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=o,s!=null&&(this.index=s),n!=null&&(this.density=n)}}const P=te("debugprogressive"),it=te("noprogressive"),we=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,F,_e,Q,oe,de,U;const I=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Te),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,F,void 0),V(this,_e,new ze),V(this,Q,0),V(this,oe,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new qe),c(this,"_tempBox",new Ee),c(this,"_tempBox2",new Ee),c(this,"tempMatrix",new Te),c(this,"_tempWorldPosition",new W),c(this,"_tempBoxSize",new W),c(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Oe]}static addPlugin(t){N.push(t)}static removePlugin(t){const e=N.indexOf(t);e>=0&&N.splice(e,1)}static get(t,e){if(t[we])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[we];const r=new I(t,{engine:"unknown",...e});return t[we]=r,r}get plugins(){return N}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(v(this,F))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,F,this.renderer.render);const e=this;ye(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,Q,v(e,Q)+1),G(e,oe,v(e,_e).getDelta()),G(e,de,v(e,de)+v(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,oe)),G(e,U,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),P&&v(e,Q)%200===0&&console.log("FPS",Math.round(v(e,U)),"Interval:",v(e,E)));const n=t++;v(e,F).call(this,r,o),e.onAfterRender(r,o,n)}}disable(){v(this,F)&&(this.renderer.render=v(this,F),G(this,F,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?v(this,U)<40&&v(this,E)<10?(G(this,E,v(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",v(this,E),v(this,U).toFixed(0))):v(this,U)>=60&&v(this,E)>1&&(G(this,E,v(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",v(this,E),v(this,U).toFixed(0))):G(this,E,this.updateInterval),v(this,E)>0&&v(this,Q)%v(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,o;const s=this.renderer.renderLists.get(t,0),n=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of n){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((o=a.geometry)==null?void 0:o.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){P&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Ve({color:g});a.object.material=p}const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const l=s.transparent;for(const a of l){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const a of u){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,o){var s,n;r.userData||(r.userData={});let i=r[Oe];if(i||(i=new at,r[Oe]=i),i.frames++<2)return;for(const u of N)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let l=k.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of N)(n=u.onAfterUpdatedLOD)==null||n.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,n=(r.y+o.y)*.5;return this._tempPtInside.set(s,n,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var n;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,l=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,f=a&&a.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(l=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),O=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=O}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const y=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),I.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const y=this._tempBox.min,m=this._tempBox.max;let h=y.x,M=y.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(y.x+m.x)*.5,ae=(y.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-ae)*z+ae,b=(b-ie)*z+ie,C=(C-ae)*z+ae;const Ge=h<0&&b>0?0:Math.min(Math.abs(y.x),Math.abs(m.x)),We=M<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(m.y)),ge=Math.max(Ge,We);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const O=t.matrixWorldInverse,_=this._tempBox2;_.copy(D),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(O);const B=_.getSize(this._tempBox2Size),T=Math.max(B.x,B.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=B.z/Math.max(B.x,B.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&I.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const m=I.corner0,h=I.corner1,M=I.corner2,b=I.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(y),h.applyMatrix4(y),M.applyMatrix4(y),b.applyMatrix4(y),I.debugDrawLine(m,h,255),I.debugDrawLine(m,M,255),I.debugDrawLine(h,b,255),I.debugDrawLine(M,b,255)}let $=999;if(a&&r.lastScreenCoverage>0){for(let y=0;y<a.length;y++)if(a[y].density/r.lastScreenCoverage<o){$=y;break}}$<i&&(i=$,l=!0)}if(l?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=a?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let O=r.lastScreenCoverage*2;((n=this.context)==null?void 0:n.engine)==="model-viewer"&&(O*=2);const _=A/window.devicePixelRatio*O;for(let B=g.lods.length-1;B>=0;B--){let T=g.lods[B];if(!(L&&T.max_height>=2048)&&!(rt()&&T.max_height>4096)&&T.max_height>_){if(s.texture_lod=B,s.texture_lod<r.lastLodLevel_Texture){const $=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${$}px
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Me]=s);const n=s.guid;w.assignLODInformation(t,e,n,r,o,void 0),w.lodInfos.set(n,s),w.lowresCache.set(n,e)}),c(S,"registerMesh",(t,e,r,o,s,n)=>{var i;x&&console.log("> Progressive: register mesh",s,r.name,n,r.uuid,r);const l=r.geometry;if(!l){x&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,s,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),o>0&&!re(r)&&Ie(r,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,r,n)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class ot{constructor(e,r,o,s,n){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=o,s!=null&&(this.index=s),n!=null&&(this.density=n)}}const P=te("debugprogressive"),it=te("noprogressive"),we=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,F,_e,Q,oe,de,U;const I=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Te),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,F,void 0),V(this,_e,new ze),V(this,Q,0),V(this,oe,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new qe),c(this,"_tempBox",new Ee),c(this,"_tempBox2",new Ee),c(this,"tempMatrix",new Te),c(this,"_tempWorldPosition",new W),c(this,"_tempBoxSize",new W),c(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Oe]}static addPlugin(t){N.push(t)}static removePlugin(t){const e=N.indexOf(t);e>=0&&N.splice(e,1)}static get(t,e){if(t[we])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[we];const r=new I(t,{engine:"unknown",...e});return t[we]=r,r}get plugins(){return N}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(y(this,F))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,F,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,Q,y(e,Q)+1),G(e,oe,y(e,_e).getDelta()),G(e,de,y(e,de)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),G(e,U,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),P&&y(e,Q)%200===0&&console.log("FPS",Math.round(y(e,U)),"Interval:",y(e,E)));const n=t++;y(e,F).call(this,r,o),e.onAfterRender(r,o,n)}}disable(){y(this,F)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,F),G(this,F,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?y(this,U)<40&&y(this,E)<10?(G(this,E,y(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",y(this,E),y(this,U).toFixed(0))):y(this,U)>=60&&y(this,E)>1&&(G(this,E,y(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",y(this,E),y(this,U).toFixed(0))):G(this,E,this.updateInterval),y(this,E)>0&&y(this,Q)%y(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,o;const s=this.renderer.renderLists.get(t,0),n=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of n){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((o=a.geometry)==null?void 0:o.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){P&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Ve({color:g});a.object.material=p}const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const l=s.transparent;for(const a of l){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const a of u){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,o){var s,n;r.userData||(r.userData={});let i=r[Oe];if(i||(i=new at,r[Oe]=i),i.frames++<2)return;for(const u of N)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let l=k.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of N)(n=u.onAfterUpdatedLOD)==null||n.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,n=(r.y+o.y)*.5;return this._tempPtInside.set(s,n,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var n;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,l=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,f=a&&a.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(l=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),O=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=O}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const v=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(v)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),I.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const v=this._tempBox.min,m=this._tempBox.max;let h=v.x,M=v.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(v.x+m.x)*.5,ae=(v.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-ae)*z+ae,b=(b-ie)*z+ie,C=(C-ae)*z+ae;const Ge=h<0&&b>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),We=M<0&&C>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),ge=Math.max(Ge,We);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const O=t.matrixWorldInverse,_=this._tempBox2;_.copy(D),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(O);const B=_.getSize(this._tempBox2Size),T=Math.max(B.x,B.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=B.z/Math.max(B.x,B.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&I.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=I.corner0,h=I.corner1,M=I.corner2,b=I.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(v),h.applyMatrix4(v),M.applyMatrix4(v),b.applyMatrix4(v),I.debugDrawLine(m,h,255),I.debugDrawLine(m,M,255),I.debugDrawLine(h,b,255),I.debugDrawLine(M,b,255)}let $=999;if(a&&r.lastScreenCoverage>0){for(let v=0;v<a.length;v++)if(a[v].density/r.lastScreenCoverage<o){$=v;break}}$<i&&(i=$,l=!0)}if(l?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=a?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let O=r.lastScreenCoverage*2;((n=this.context)==null?void 0:n.engine)==="model-viewer"&&(O*=2);const _=A/window.devicePixelRatio*O;for(let B=g.lods.length-1;B>=0;B--){let T=g.lods[B];if(!(L&&T.max_height>=2048)&&!(rt()&&T.max_height>4096)&&T.max_height>_){if(s.texture_lod=B,s.texture_lod<r.lastLodLevel_Texture){const $=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${$}px
6
6
  Screensize: ${_.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${d.toFixed(1)}
7
7
  ${e.name}`)}break}}}}else s.texture_lod=0}};let j=I;E=new WeakMap,F=new WeakMap,_e=new WeakMap,Q=new WeakMap,oe=new WeakMap,de=new WeakMap,U=new WeakMap,c(j,"debugDrawLine"),c(j,"corner0",new W),c(j,"corner1",new W),c(j,"corner2",new W),c(j,"corner3",new W),c(j,"_tempPtInside",new W);class at{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new W),c(this,"lastCentrality",0)}}const ke=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let fe=null;function be(){const t=lt();t&&(t.mapURLs(function(e){return Ce(),e}),Ce(),fe?.disconnect(),fe=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&je(o)})})}),fe.observe(document,{childList:!0,subtree:!0}))}function lt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),be()}),null)}function Ce(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{je(t)})}const Re=new WeakSet;let ut=0;function je(t){if(!t||Re.has(t))return null;Re.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ut+`
8
- `,t.getAttribute("src"));let e=null,r=null,o=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const n=Object.getOwnPropertySymbols(s),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!o&&u!=null&&(o=t[u])}if(e&&r){let s=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=j.get(e,{engine:"model-viewer"});return j.addPlugin(new ct),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class ct{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,o,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[he]==!0)return;r[he]=!0;const o=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),n=this.getUrl(s);if(n&&o&&r.material){let i=function(u){var a,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(a=L.userData)==null?void 0:a.associations)==null?void 0:f.textures;if(d==null)continue;const O=o.parser.json.textures[d];if(!O){console.warn("Texture data not found for texture index "+d);continue}if((g=O?.extensions)!=null&&g[R]){const _=O.extensions[R];_&&n&&S.registerTexture(n,L,_.lods.length,d,_)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var o,s;if(r[ke]==!0)return;r[ke]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(s=(o=r.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(l&&i){const u=r.uuid;S.registerMesh(i,u,r,0,l.lods.length,l)}}}function dt(t,e,r,o){ye(e),ve(r),Ae(r,{progressive:!0,...o?.hints}),r.register(n=>new S(n,t));const s=j.get(e);return o?.enableLODsManager!==!1&&s.enable(),s}be();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,pe as VERSION,ve as addDracoAndKTX2Loaders,Ae as configureLoader,ye as createLoaders,re as getRaycastMesh,be as patchModelViewer,Ie as registerRaycastMesh,Qe as setDracoDecoderLocation,Ze as setKTX2TranscoderLocation,dt as useNeedleProgressive,st as useRaycastMeshes};
8
+ `,t.getAttribute("src"));let e=null,r=null,o=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const n=Object.getOwnPropertySymbols(s),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!o&&u!=null&&(o=t[u])}if(e&&r){let s=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=j.get(e,{engine:"model-viewer"});return j.addPlugin(new ct),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class ct{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,o,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[he]==!0)return;r[he]=!0;const o=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),n=this.getUrl(s);if(n&&o&&r.material){let i=function(u){var a,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(a=L.userData)==null?void 0:a.associations)==null?void 0:f.textures;if(d==null)continue;const O=o.parser.json.textures[d];if(!O){console.warn("Texture data not found for texture index "+d);continue}if((g=O?.extensions)!=null&&g[R]){const _=O.extensions[R];_&&n&&S.registerTexture(n,L,_.lods.length,d,_)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var o,s;if(r[ke]==!0)return;r[ke]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(s=(o=r.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(l&&i){const u=r.uuid;S.registerMesh(i,u,r,0,l.lods.length,l)}}}function dt(t,e,r,o){ve(e),ye(r),Ae(r,{progressive:!0,...o?.hints}),r.register(n=>new S(n,t));const s=j.get(e);return o?.enableLODsManager!==!1&&s.enable(),s}be();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,pe as VERSION,ye as addDracoAndKTX2Loaders,Ae as configureLoader,ve as createLoaders,re as getRaycastMesh,be as patchModelViewer,Ie as registerRaycastMesh,Qe as setDracoDecoderLocation,Ze as setKTX2TranscoderLocation,dt as useNeedleProgressive,st as useRaycastMeshes};
@@ -1,8 +1,8 @@
1
- "use strict";var Ve=Object.defineProperty;var $e=(n,t,e)=>t in n?Ve(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>($e(n,typeof t!="symbol"?t+"":t,e),e),Ae=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var L=(n,t,e)=>(Ae(n,t,"read from private field"),e?e.call(n):t.get(n)),K=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},N=(n,t,e,s)=>(Ae(n,t,"write to private field"),s?s.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),_e=require("three/examples/jsm/loaders/GLTFLoader.js"),Ne=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Ue=require("three/examples/jsm/loaders/DRACOLoader.js"),ze=require("three/examples/jsm/loaders/KTX2Loader.js"),Oe="";globalThis.GLTF_PROGRESSIVE_VERSION=Oe;console.debug(`[gltf-progressive] version ${Oe}`);let Q="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const We=Q,qe=oe;fetch(Q+"draco_decoder.js",{method:"head"}).catch(n=>{Q===We&&(Q="./include/draco/"),oe===qe&&(oe="./include/ktx2/")});function Xe(n){Q=n}function Ke(n){oe=n}let j,de,J;function Se(n){return j||(j=new Ue.DRACOLoader,j.setDecoderPath(Q),j.setDecoderConfig({type:"js"})),J||(J=new ze.KTX2Loader,J.setTranscoderPath(oe)),de||(de=Ne.MeshoptDecoder),n?J.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:de}}function be(n){n.dracoLoader||n.setDRACOLoader(j),n.ktx2Loader||n.setKTX2Loader(J),n.meshoptDecoder||n.setMeshoptDecoder(de)}const De=new WeakMap;function Ie(n,t){let e=De.get(n);e?e=Object.assign(e,t):e=t,De.set(n,e)}const me=_e.GLTFLoader.prototype.load;function Ye(...n){const t=De.get(this);let e=n[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=t?t.progressive:!0,i=t?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return n[0]=e,me==null?void 0:me.call(this,...n)}_e.GLTFLoader.prototype.load=Ye;ne("debugprogressive");function ne(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function He(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const s=n.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}let te;function je(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const we=Symbol("needle:raycast-mesh");function ae(n){return(n==null?void 0:n[we])instanceof p.BufferGeometry?n[we]:null}function Re(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!ae(n)){const s=Qe(t);s.userData={isRaycastMesh:!0},n[we]=s}}function Je(n=!0){if(n){if(se)return;const t=se=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,s){const o=this,r=ae(o);let i;r&&o.isMesh&&(i=o.geometry,o.geometry=r),t.call(this,e,s),i&&(o.geometry=i)}}else{if(!se)return;p.Mesh.prototype.raycast=se,se=null}}let se=null;function Qe(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),Le=Symbol("needle-progressive-texture"),ie=new Map,ve=new Set;if(x){let n=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,r)=>{for(const i of o.keys){const a=r[i];if(a!=null){if(a.isBufferGeometry===!0){const l=O.getMeshLODInformation(a),u=l?Math.min(t,l.lods.length):0;r["DEBUG:LOD"]=t,O.assignMeshLOD(r,u),l&&(e=Math.max(e,l.lods.length-1))}else if(r.isMaterial===!0){r["DEBUG:LOD"]=t,O.assignTextureLOD(r,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,s=!1;window.addEventListener("keyup",o=>{o.key==="p"&&n(),o.key==="w"&&(s=!s,ve&&ve.forEach(r=>{r.name!="BackgroundCubeMaterial"&&r.glyphMap==null&&"wireframe"in r&&(r.wireframe=s)}))})}function Ee(n,t,e){var o;if(!x)return;ie.has(n)||ie.set(n,{keys:[],sourceId:e});const s=ie.get(n);((o=s==null?void 0:s.keys)==null?void 0:o.includes(t))==!1&&s.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var s,o;if(this._isLoadingMesh)return null;const e=(o=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var i;return this._isLoadingMesh=!1,r&&_.registerMesh(this.url,e.guid,r,(i=e.lods)==null?void 0:i.length,void 0,e),r})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(a,l){const u=s.getAssignedLODInformation(a);if(u){const c=s.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const a=t[i];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let s,o;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const i=s.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const i of Y)(s=i.onBeforeGetLODMesh)==null||s.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const a=r.index||0;i=i[a]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&Ee(t,"geometry",r.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);o.push(i)}return Promise.all(o).then(r=>{const i=new Array;for(const a of r)Array.isArray(a)&&i.push(...a);return i})}else return this.assignTextureLOD(s.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const s=t,o=[],r=new Array;if(x&&ve.add(s),s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,s,a).then(c=>(c&&i.uniforms[a].value!=c&&(i.uniforms[a].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),r.push(a)}}}else for(const i of Object.keys(s)){const a=s[i];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,i);o.push(l),r.push(i)}}return Promise.all(o).then(i=>{const a=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=r[l];u&&u.isTexture===!0?a.push({material:s,slot:c,texture:u,level:e}):a.push({material:s,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t){if(s&&o){const i=s[o];if(i){const a=this.getAssignedLODInformation(i);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,i,r),null}s[o]=r}if(x&&o&&s){const i=this.getAssignedLODInformation(t);i&&Ee(s,o,i.url)}}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var i;if(o!=null&&o.extensions){const a=o==null?void 0:o.extensions[U];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===r&&(l=!0,_.registerTexture(this.url,u,(i=a.lods)==null?void 0:i.length,r,a))}l||this.parser.getDependency("texture",r).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&_.registerMesh(this.url,i.guid,a,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const s=x=="verbose",o=t.userData.LODS;if(!o)return null;const r=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[Le]&&(i=g.source[Le])}if(i||(i=_.lodInfos.get(r)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(r)}const g=Array.isArray(i.lods)?(a=i.lods[e])==null?void 0:a.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=He(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
1
+ "use strict";var Ve=Object.defineProperty;var $e=(n,t,e)=>t in n?Ve(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>($e(n,typeof t!="symbol"?t+"":t,e),e),Ae=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var L=(n,t,e)=>(Ae(n,t,"read from private field"),e?e.call(n):t.get(n)),K=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},N=(n,t,e,s)=>(Ae(n,t,"write to private field"),s?s.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),_e=require("three/examples/jsm/loaders/GLTFLoader.js"),Ne=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Ue=require("three/examples/jsm/loaders/DRACOLoader.js"),ze=require("three/examples/jsm/loaders/KTX2Loader.js"),Oe="";globalThis.GLTF_PROGRESSIVE_VERSION=Oe;console.debug(`[gltf-progressive] version ${Oe}`);let Q="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const We=Q,qe=oe;fetch(Q+"draco_decoder.js",{method:"head"}).catch(n=>{Q===We&&(Q="./include/draco/"),oe===qe&&(oe="./include/ktx2/")});function Xe(n){Q=n}function Ke(n){oe=n}let j,de,J;function Se(n){return j||(j=new Ue.DRACOLoader,j.setDecoderPath(Q),j.setDecoderConfig({type:"js"})),J||(J=new ze.KTX2Loader,J.setTranscoderPath(oe)),de||(de=Ne.MeshoptDecoder),n?J.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:de}}function be(n){n.dracoLoader||n.setDRACOLoader(j),n.ktx2Loader||n.setKTX2Loader(J),n.meshoptDecoder||n.setMeshoptDecoder(de)}const De=new WeakMap;function Ie(n,t){let e=De.get(n);e?e=Object.assign(e,t):e=t,De.set(n,e)}const me=_e.GLTFLoader.prototype.load;function Ye(...n){const t=De.get(this);let e=n[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,i=t!=null&&t.usecase?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return n[0]=e,me==null?void 0:me.call(this,...n)}_e.GLTFLoader.prototype.load=Ye;ne("debugprogressive");function ne(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function He(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const s=n.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}let te;function je(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const we=Symbol("needle:raycast-mesh");function ae(n){return(n==null?void 0:n[we])instanceof p.BufferGeometry?n[we]:null}function Re(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!ae(n)){const s=Qe(t);s.userData={isRaycastMesh:!0},n[we]=s}}function Je(n=!0){if(n){if(se)return;const t=se=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,s){const o=this,r=ae(o);let i;r&&o.isMesh&&(i=o.geometry,o.geometry=r),t.call(this,e,s),i&&(o.geometry=i)}}else{if(!se)return;p.Mesh.prototype.raycast=se,se=null}}let se=null;function Qe(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),Le=Symbol("needle-progressive-texture"),ie=new Map,ve=new Set;if(x){let n=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,r)=>{for(const i of o.keys){const a=r[i];if(a!=null){if(a.isBufferGeometry===!0){const l=O.getMeshLODInformation(a),u=l?Math.min(t,l.lods.length):0;r["DEBUG:LOD"]=t,O.assignMeshLOD(r,u),l&&(e=Math.max(e,l.lods.length-1))}else if(r.isMaterial===!0){r["DEBUG:LOD"]=t,O.assignTextureLOD(r,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,s=!1;window.addEventListener("keyup",o=>{o.key==="p"&&n(),o.key==="w"&&(s=!s,ve&&ve.forEach(r=>{r.name!="BackgroundCubeMaterial"&&r.glyphMap==null&&"wireframe"in r&&(r.wireframe=s)}))})}function Ee(n,t,e){var o;if(!x)return;ie.has(n)||ie.set(n,{keys:[],sourceId:e});const s=ie.get(n);((o=s==null?void 0:s.keys)==null?void 0:o.includes(t))==!1&&s.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var s,o;if(this._isLoadingMesh)return null;const e=(o=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var i;return this._isLoadingMesh=!1,r&&_.registerMesh(this.url,e.guid,r,(i=e.lods)==null?void 0:i.length,void 0,e),r})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(a,l){const u=s.getAssignedLODInformation(a);if(u){const c=s.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const a=t[i];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let s,o;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const i=s.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const i of Y)(s=i.onBeforeGetLODMesh)==null||s.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const a=r.index||0;i=i[a]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&Ee(t,"geometry",r.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);o.push(i)}return Promise.all(o).then(r=>{const i=new Array;for(const a of r)Array.isArray(a)&&i.push(...a);return i})}else return this.assignTextureLOD(s.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const s=t,o=[],r=new Array;if(x&&ve.add(s),s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,s,a).then(c=>(c&&i.uniforms[a].value!=c&&(i.uniforms[a].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),r.push(a)}}}else for(const i of Object.keys(s)){const a=s[i];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,i);o.push(l),r.push(i)}}return Promise.all(o).then(i=>{const a=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=r[l];u&&u.isTexture===!0?a.push({material:s,slot:c,texture:u,level:e}):a.push({material:s,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t){if(s&&o){const i=s[o];if(i){const a=this.getAssignedLODInformation(i);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,i,r),null}s[o]=r}if(x&&o&&s){const i=this.getAssignedLODInformation(t);i&&Ee(s,o,i.url)}}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var i;if(o!=null&&o.extensions){const a=o==null?void 0:o.extensions[U];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===r&&(l=!0,_.registerTexture(this.url,u,(i=a.lods)==null?void 0:i.length,r,a))}l||this.parser.getDependency("texture",r).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&_.registerMesh(this.url,i.guid,a,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const s=x=="verbose",o=t.userData.LODS;if(!o)return null;const r=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[Le]&&(i=g.source[Le])}if(i||(i=_.lodInfos.get(r)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(r)}const g=Array.isArray(i.lods)?(a=i.lods[e])==null?void 0:a.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=He(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
2
2
  `,$),null)),R=!1;if(h==null||(h instanceof p.Texture&&t instanceof p.Texture?(l=h.image)!=null&&l.data||(u=h.source)!=null&&u.data?h=this.copySettings(t,h):(R=!0,this.previouslyLoaded.delete(D)):h instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=h.attributes.position)!=null&&c.array||(R=!0,this.previouslyLoaded.delete(D)))),!R)return h}const M=i,V=new Promise(async(h,R)=>{const $=new _e.GLTFLoader;be($),x&&(await new Promise(E=>setTimeout(E,1e3)),s&&console.warn("Start loading (delayed) "+y,M.guid));let k=y;if(M&&Array.isArray(M.lods)){const E=M.lods[e];E.hash&&(k+="?v="+E.hash)}const b=await $.loadAsync(k).catch(E=>(console.error(`Error loading LOD ${e} from ${y}
3
3
  `,E),null));if(!b)return null;const q=b.parser;s&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,r,e,void 0,void 0),s&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(s&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,r,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,r,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,V),await V}else if(t instanceof p.Texture){s&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,s&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,i){if(!e)return;e.userData||(e.userData={});const a=new Ze(t,s,o,r,i);e.userData.LODS=a}static getAssignedLODInformation(t){var e;return((e=t==null?void 0:t.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),x&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=_;d(O,"registerTexture",(t,e,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const i=r.guid;_.assignLODInformation(t,e,i,s,o,void 0),_.lodInfos.set(i,r),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,s,o,r,i)=>{var u;x&&console.log("> Progressive: register mesh",r,s.name,i,s.uuid,s);const a=s.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),_.assignLODInformation(t,a,e,o,r,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],_.lowresCache.set(e,l),o>0&&!ae(s)&&Re(s,a);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,s,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Ze{constructor(t,e,s,o,r){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=s,o!=null&&(this.index=o),r!=null&&(this.density=r)}}const G=ne("debugprogressive"),et=ne("noprogressive"),xe=Symbol("Needle:LODSManager"),Me=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),F={mesh_lod:-1,texture_lod:-1};var B,z,he,Z,ee,ge,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,he,new p.Clock);K(this,Z,0);K(this,ee,0);K(this,ge,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Me]}static addPlugin(t){Y.push(t)}static removePlugin(t){const e=Y.indexOf(t);e>=0&&Y.splice(e,1)}static get(t,e){if(t[xe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[xe];const s=new C(t,{engine:"unknown",...e});return t[xe]=s,s}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;Se(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+1),N(e,ee,L(e,he).getDelta()),N(e,ge,L(e,ge)+L(e,ee)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,ee)),N(e,W,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),G&&L(e,Z)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,s,o),e.onAfterRender(s,o,i)}}disable(){L(this,z)&&(this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(et||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,Z)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=this.targetTriangleDensity;for(const c of o){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){G&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const i=s.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const a=s.transmissive;for(const c of a){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}}updateLODs(t,e,s,o){var a,l;s.userData||(s.userData={});let r=s[Me];if(r||(r=new tt,s[Me]=r),r.frames++<2)return;for(const u of Y)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,s);this.calculateLodLevel(e,s,r,o,F),F.mesh_lod=Math.round(F.mesh_lod),F.texture_lod=Math.round(F.texture_lod),F.mesh_lod>=0&&this.loadProgressiveMeshes(s,F.mesh_lod);let i=F.texture_lod;if(s.material&&i>=0){const u=s["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(s.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,s,F);r.lastLodLevel_Mesh=F.mesh_lod,r.lastLodLevel_Texture=F.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[H]===void 0||e<t[H])&&(s=!0),s&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const s=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,i=(s.y+o.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var V;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){r.mesh_lod=0,r.texture_lod=0;return}g||(l=!0,a=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(s.frames%30===0){const h=ae(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const le=2,pe=1.5,ce=(f.x+m.x)*.5,ue=(f.y+m.y)*.5;S=(S-ce)*le+ce,T=(T-ue)*le+ue,P=(P-ce)*le+ce,X=(X-ue)*le+ue;const Ge=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Fe=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max(Ge,Fe);s.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else s.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),s.lastScreenCoverage=Math.max(h.x,h.y,h.z),s.lastScreenspaceVolume.copy(h),s.lastScreenCoverage*=s.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&s.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/s.lastScreenCoverage<o){A=f;break}}A<a&&(a=A,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,G&&r.mesh_lod!=s.lastLodLevel_Mesh){const h=c==null?void 0:c[r.mesh_lod];h&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let R=s.lastScreenCoverage*2;((V=this.context)==null?void 0:V.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(je()&&q.max_height>4096)&&q.max_height>k){if(r.texture_lod=b,r.texture_lod<s.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${A}px
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=_;d(O,"registerTexture",(t,e,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const i=r.guid;_.assignLODInformation(t,e,i,s,o,void 0),_.lodInfos.set(i,r),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,s,o,r,i)=>{var u;x&&console.log("> Progressive: register mesh",r,s.name,i,s.uuid,s);const a=s.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),_.assignLODInformation(t,a,e,o,r,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],_.lowresCache.set(e,l),o>0&&!ae(s)&&Re(s,a);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,s,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Ze{constructor(t,e,s,o,r){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=s,o!=null&&(this.index=o),r!=null&&(this.density=r)}}const G=ne("debugprogressive"),et=ne("noprogressive"),xe=Symbol("Needle:LODSManager"),Me=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),F={mesh_lod:-1,texture_lod:-1};var B,z,he,Z,ee,ge,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,he,new p.Clock);K(this,Z,0);K(this,ee,0);K(this,ge,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Me]}static addPlugin(t){Y.push(t)}static removePlugin(t){const e=Y.indexOf(t);e>=0&&Y.splice(e,1)}static get(t,e){if(t[xe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[xe];const s=new C(t,{engine:"unknown",...e});return t[xe]=s,s}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;Se(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+1),N(e,ee,L(e,he).getDelta()),N(e,ge,L(e,ge)+L(e,ee)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,ee)),N(e,W,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),G&&L(e,Z)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,s,o),e.onAfterRender(s,o,i)}}disable(){L(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(et||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,Z)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=this.targetTriangleDensity;for(const c of o){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){G&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const i=s.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const a=s.transmissive;for(const c of a){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}}updateLODs(t,e,s,o){var a,l;s.userData||(s.userData={});let r=s[Me];if(r||(r=new tt,s[Me]=r),r.frames++<2)return;for(const u of Y)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,s);this.calculateLodLevel(e,s,r,o,F),F.mesh_lod=Math.round(F.mesh_lod),F.texture_lod=Math.round(F.texture_lod),F.mesh_lod>=0&&this.loadProgressiveMeshes(s,F.mesh_lod);let i=F.texture_lod;if(s.material&&i>=0){const u=s["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(s.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,s,F);r.lastLodLevel_Mesh=F.mesh_lod,r.lastLodLevel_Texture=F.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[H]===void 0||e<t[H])&&(s=!0),s&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const s=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,i=(s.y+o.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var V;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){r.mesh_lod=0,r.texture_lod=0;return}g||(l=!0,a=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(s.frames%30===0){const h=ae(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const le=2,pe=1.5,ce=(f.x+m.x)*.5,ue=(f.y+m.y)*.5;S=(S-ce)*le+ce,T=(T-ue)*le+ue,P=(P-ce)*le+ce,X=(X-ue)*le+ue;const Ge=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Fe=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max(Ge,Fe);s.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else s.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),s.lastScreenCoverage=Math.max(h.x,h.y,h.z),s.lastScreenspaceVolume.copy(h),s.lastScreenCoverage*=s.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&s.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/s.lastScreenCoverage<o){A=f;break}}A<a&&(a=A,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,G&&r.mesh_lod!=s.lastLodLevel_Mesh){const h=c==null?void 0:c[r.mesh_lod];h&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let R=s.lastScreenCoverage*2;((V=this.context)==null?void 0:V.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(je()&&q.max_height>4096)&&q.max_height>k){if(r.texture_lod=b,r.texture_lod<s.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${A}px
6
6
  Screensize: ${k.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
7
7
  ${e.name}`)}break}}}}else r.texture_lod=0}};let I=C;B=new WeakMap,z=new WeakMap,he=new WeakMap,Z=new WeakMap,ee=new WeakMap,ge=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new p.Vector3),d(I,"corner1",new p.Vector3),d(I,"corner2",new p.Vector3),d(I,"corner3",new p.Vector3),d(I,"_tempPtInside",new p.Vector3);class tt{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const Pe=Symbol("NEEDLE_mesh_lod"),fe=Symbol("NEEDLE_texture_lod");let re=null;function Te(){const n=st();n&&(n.mapURLs(function(t){return Ce(),t}),Ce(),re==null||re.disconnect(),re=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&ke(s)})})}),re.observe(document,{childList:!0,subtree:!0}))}function st(){if(typeof customElements>"u")return null;const n=customElements.get("model-viewer");return n||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Te()}),null)}function Ce(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{ke(t)})}const Be=new WeakSet;let rt=0;function ke(n){if(!n||Be.has(n))return null;Be.add(n),console.debug("[gltf-progressive] found new model-viewer..."+ ++rt+`
8
8
  `,n.getAttribute("src"));let t=null,e=null,s=null;for(let o=n;o!=null;o=Object.getPrototypeOf(o)){const r=Object.getOwnPropertySymbols(o),i=r.find(u=>u.toString()=="Symbol(renderer)"),a=r.find(u=>u.toString()=="Symbol(scene)"),l=r.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=n[i].threeRenderer),!e&&a!=null&&(e=n[a]),!s&&l!=null&&(s=n[l])}if(t&&e){let o=function(){if(s){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}s==null||s.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const r=I.get(t,{engine:"model-viewer"});return I.addPlugin(new it),r.enable(),r.addEventListener("changed",()=>{s==null||s.call(n)}),n.addEventListener("model-visibility",i=>{i.detail.visible&&(s==null||s.call(n))}),n.addEventListener("load",()=>{o()}),()=>{r.disable()}}return null}class it{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,s,o){this.tryParseMeshLOD(e,o),this.tryParseTextureLOD(e,o)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[fe]==!0)return;e[fe]=!0;const s=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),r=this.getUrl(o);if(r&&s&&e.material){let i=function(l){var c,g,y;if(l[fe]==!0)return;l[fe]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let D=0;D<u.length;D++){const v=u[D],M=l[v];if((M==null?void 0:M.isTexture)===!0){const V=(g=(c=M.userData)==null?void 0:c.associations)==null?void 0:g.textures;if(V==null)continue;const w=s.parser.json.textures[V];if(!w){console.warn("Texture data not found for texture index "+V);continue}if((y=w==null?void 0:w.extensions)!=null&&y[U]){const h=w.extensions[U];h&&r&&O.registerTexture(r,M,h.lods.length,V,h)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(t,e){var i,a;if(e[Pe]==!0)return;e[Pe]=!0;const s=this.tryGetCurrentModelViewer(t),o=this.getUrl(s);if(!o)return;const r=(a=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:a[U];if(r&&o){const l=e.uuid;O.registerMesh(o,l,e,0,r.lods.length,r)}}}function ot(n,t,e,s){Se(t),be(e),Ie(e,{progressive:!0,...s==null?void 0:s.hints}),e.register(r=>new O(r,n));const o=I.get(t);return(s==null?void 0:s.enableLODsManager)!==!1&&o.enable(),o}Te();exports.EXTENSION_NAME=U;exports.LODsManager=I;exports.NEEDLE_progressive=O;exports.VERSION=Oe;exports.addDracoAndKTX2Loaders=be;exports.configureLoader=Ie;exports.createLoaders=Se;exports.getRaycastMesh=ae;exports.patchModelViewer=Te;exports.registerRaycastMesh=Re;exports.setDracoDecoderLocation=Xe;exports.setKTX2TranscoderLocation=Ke;exports.useNeedleProgressive=ot;exports.useRaycastMeshes=Je;
package/lib/loaders.js CHANGED
@@ -82,8 +82,8 @@ function onLoad(...args) {
82
82
  let url_str = args[0];
83
83
  const url = new URL(url_str, window.location.href);
84
84
  if (url.hostname.endsWith("needle.tools")) {
85
- const progressive = config ? config.progressive : true;
86
- const usecase = config ? config.usecase : "default";
85
+ const progressive = config?.progressive !== undefined ? config.progressive : true;
86
+ const usecase = config?.usecase ? config.usecase : "default";
87
87
  if (progressive) {
88
88
  this.requestHeader["Accept"] = `*/*;progressive=allowed;usecase=${usecase}`;
89
89
  }
@@ -160,6 +160,7 @@ export class LODsManager {
160
160
  disable() {
161
161
  if (!this.#originalRender)
162
162
  return;
163
+ console.debug("[gltf-progressive] Disabling LODsManager for renderer");
163
164
  this.renderer.render = this.#originalRender;
164
165
  this.#originalRender = undefined;
165
166
  }
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "2.0.0-alpha";
2
+ export const version = "2.0.0-alpha.2";
3
3
  globalThis["GLTF_PROGRESSIVE_VERSION"] = version;
4
4
  console.debug(`[gltf-progressive] version ${version}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "2.0.0-alpha",
3
+ "version": "2.0.0-alpha.2",
4
4
  "description": "three.js support for loading glTF or GLB files that contain progressive loading data",
5
5
  "homepage": "https://needle.tools",
6
6
  "author": {