@needle-tools/gltf-progressive 1.2.3-alpha.2 → 1.2.3-alpha.3

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,6 +4,9 @@ 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
+ ## [1.2.3-alpha.3] - 2023-07-01
8
+ - Add: prevent loading highres textures when user has enabled data-save mode
9
+
7
10
  ## [1.2.3-alpha.2] - 2023-06-27
8
11
  - Fix: error caused by parser associations containing `undefined` value
9
12
 
@@ -4,12 +4,12 @@ var d = (a, t, e) => (Ve(a, typeof t != "symbol" ? t + "" : t, e), e), Se = (a,
4
4
  if (!t.has(a))
5
5
  throw TypeError("Cannot " + e);
6
6
  };
7
- var m = (a, t, e) => (Se(a, t, "read from private field"), e ? e.call(a) : t.get(a)), q = (a, t, e) => {
7
+ var m = (a, t, e) => (Se(a, t, "read from private field"), e ? e.call(a) : t.get(a)), X = (a, t, e) => {
8
8
  if (t.has(a))
9
9
  throw TypeError("Cannot add the same private member more than once");
10
10
  t instanceof WeakSet ? t.add(a) : t.set(a, e);
11
- }, $ = (a, t, e, r) => (Se(a, t, "write to private field"), r ? r.call(a, e) : t.set(a, e), e);
12
- import { BufferGeometry as de, Mesh as J, Material as Ne, Texture as ee, TextureLoader as Ue, Matrix4 as be, Frustum as We, Clock as Ke, MeshStandardMaterial as qe, Sphere as Xe, Box3 as Te, Vector3 as V } from "three";
11
+ }, F = (a, t, e, r) => (Se(a, t, "write to private field"), r ? r.call(a, e) : t.set(a, e), e);
12
+ import { BufferGeometry as de, Mesh as J, Material as Ne, Texture as ee, TextureLoader as Ue, Matrix4 as be, Frustum as We, Clock as Ke, MeshStandardMaterial as qe, Sphere as Xe, Box3 as Te, Vector3 as N } from "three";
13
13
  import { GLTFLoader as Ye } from "three/examples/jsm/loaders/GLTFLoader.js";
14
14
  import { MeshoptDecoder as He } from "three/examples/jsm/libs/meshopt_decoder.module.js";
15
15
  import { DRACOLoader as Je } from "three/examples/jsm/loaders/DRACOLoader.js";
@@ -88,7 +88,7 @@ function tt(a) {
88
88
  t.setAttribute(e, a.getAttribute(e));
89
89
  return t.setIndex(a.getIndex()), t;
90
90
  }
91
- const X = new Array(), N = "NEEDLE_progressive", L = ae("debugprogressive"), xe = Symbol("needle-progressive-texture"), ne = /* @__PURE__ */ new Map(), ve = /* @__PURE__ */ new Set();
91
+ const Y = new Array(), U = "NEEDLE_progressive", L = ae("debugprogressive"), xe = Symbol("needle-progressive-texture"), ne = /* @__PURE__ */ new Map(), ve = /* @__PURE__ */ new Set();
92
92
  if (L) {
93
93
  let a = function() {
94
94
  t += 1, console.log("Toggle LOD level", t, ne), ne.forEach((o, i) => {
@@ -96,10 +96,10 @@ if (L) {
96
96
  const n = i[s];
97
97
  if (n != null) {
98
98
  if (n.isBufferGeometry === !0) {
99
- const l = S.getMeshLODInformation(n), f = l ? Math.min(t, l.lods.length) : 0;
100
- i["DEBUG:LOD"] = t, S.assignMeshLOD(i, f), l && (e = Math.max(e, l.lods.length - 1));
99
+ const l = b.getMeshLODInformation(n), f = l ? Math.min(t, l.lods.length) : 0;
100
+ i["DEBUG:LOD"] = t, b.assignMeshLOD(i, f), l && (e = Math.max(e, l.lods.length - 1));
101
101
  } else if (i.isMaterial === !0) {
102
- i["DEBUG:LOD"] = t, S.assignTextureLOD(i, t);
102
+ i["DEBUG:LOD"] = t, b.assignTextureLOD(i, t);
103
103
  break;
104
104
  }
105
105
  }
@@ -120,7 +120,7 @@ function Ae(a, t, e) {
120
120
  const r = ne.get(a);
121
121
  ((o = r == null ? void 0 : r.keys) == null ? void 0 : o.includes(t)) == !1 && r.keys.push(t);
122
122
  }
123
- const O = class {
123
+ const _ = class {
124
124
  constructor(t, e) {
125
125
  d(this, "parser");
126
126
  d(this, "url");
@@ -129,17 +129,17 @@ const O = class {
129
129
  var r, o;
130
130
  if (this._isLoadingMesh)
131
131
  return null;
132
- const e = (o = (r = this.parser.json.meshes[t]) == null ? void 0 : r.extensions) == null ? void 0 : o[N];
132
+ const e = (o = (r = this.parser.json.meshes[t]) == null ? void 0 : r.extensions) == null ? void 0 : o[U];
133
133
  return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((i) => {
134
134
  var s;
135
- return this._isLoadingMesh = !1, i && O.registerMesh(this.url, e.guid, i, (s = e.lods) == null ? void 0 : s.length, void 0, e), i;
135
+ return this._isLoadingMesh = !1, i && _.registerMesh(this.url, e.guid, i, (s = e.lods) == null ? void 0 : s.length, void 0, e), i;
136
136
  })) : null;
137
137
  });
138
138
  L && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
139
139
  }
140
140
  /** The name of the extension */
141
141
  get name() {
142
- return N;
142
+ return U;
143
143
  }
144
144
  static getMeshLODInformation(t) {
145
145
  const e = this.getAssignedLODInformation(t);
@@ -241,9 +241,9 @@ const O = class {
241
241
  const o = t.geometry, i = this.getAssignedLODInformation(o);
242
242
  if (!i)
243
243
  return Promise.resolve(null);
244
- for (const s of X)
244
+ for (const s of Y)
245
245
  (r = s.onBeforeGetLODMesh) == null || r.call(s, t, e);
246
- return t["LOD:requested level"] = e, O.getOrLoadLOD(o, e).then((s) => {
246
+ return t["LOD:requested level"] = e, _.getOrLoadLOD(o, e).then((s) => {
247
247
  if (t["LOD:requested level"] === e) {
248
248
  if (delete t["LOD:requested level"], Array.isArray(s)) {
249
249
  const n = i.index || 0;
@@ -302,7 +302,7 @@ const O = class {
302
302
  return Promise.resolve(null);
303
303
  }
304
304
  static assignTextureLODForSlot(t, e, r, o) {
305
- return (t == null ? void 0 : t.isTexture) !== !0 ? Promise.resolve(null) : o === "glyphMap" ? Promise.resolve(t) : O.getOrLoadLOD(t, e).then((i) => {
305
+ return (t == null ? void 0 : t.isTexture) !== !0 ? Promise.resolve(null) : o === "glyphMap" ? Promise.resolve(t) : _.getOrLoadLOD(t, e).then((i) => {
306
306
  if (Array.isArray(i))
307
307
  return null;
308
308
  if ((i == null ? void 0 : i.isTexture) === !0) {
@@ -332,7 +332,7 @@ const O = class {
332
332
  return L && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((o, i) => {
333
333
  var s;
334
334
  if (o != null && o.extensions) {
335
- const n = o == null ? void 0 : o.extensions[N];
335
+ const n = o == null ? void 0 : o.extensions[U];
336
336
  if (n) {
337
337
  if (!n.lods) {
338
338
  L && console.warn("Texture has no LODs", n);
@@ -342,22 +342,22 @@ const O = class {
342
342
  for (const f of this.parser.associations.keys())
343
343
  if (f.isTexture === !0) {
344
344
  const c = this.parser.associations.get(f);
345
- (c == null ? void 0 : c.textures) === i && (l = !0, O.registerTexture(this.url, f, (s = n.lods) == null ? void 0 : s.length, i, n));
345
+ (c == null ? void 0 : c.textures) === i && (l = !0, _.registerTexture(this.url, f, (s = n.lods) == null ? void 0 : s.length, i, n));
346
346
  }
347
347
  l || this.parser.getDependency("texture", i).then((f) => {
348
348
  var c;
349
- f && O.registerTexture(this.url, f, (c = n.lods) == null ? void 0 : c.length, i, n);
349
+ f && _.registerTexture(this.url, f, (c = n.lods) == null ? void 0 : c.length, i, n);
350
350
  });
351
351
  }
352
352
  }
353
353
  }), (r = this.parser.json.meshes) == null || r.forEach((o, i) => {
354
354
  if (o != null && o.extensions) {
355
- const s = o == null ? void 0 : o.extensions[N];
355
+ const s = o == null ? void 0 : o.extensions[U];
356
356
  if (s && s.lods) {
357
357
  for (const n of this.parser.associations.keys())
358
358
  if (n.isMesh) {
359
359
  const l = this.parser.associations.get(n);
360
- (l == null ? void 0 : l.meshes) === i && O.registerMesh(this.url, s.guid, n, s.lods.length, l.primitives, s);
360
+ (l == null ? void 0 : l.meshes) === i && _.registerMesh(this.url, s.guid, n, s.lods.length, l.primitives, s);
361
361
  }
362
362
  }
363
363
  }
@@ -374,7 +374,7 @@ const O = class {
374
374
  const M = t;
375
375
  M.source && M.source[xe] && (s = M.source[xe]);
376
376
  }
377
- if (s || (s = O.lodInfos.get(i)), s) {
377
+ if (s || (s = _.lodInfos.get(i)), s) {
378
378
  if (e > 0) {
379
379
  let y = !1;
380
380
  const v = Array.isArray(s.lods);
@@ -391,78 +391,78 @@ const O = class {
391
391
  const y = u + "_" + s.guid, v = this.previouslyLoaded.get(y);
392
392
  if (v !== void 0) {
393
393
  r && console.log(`LOD ${e} was already loading/loaded: ${y}`);
394
- let p = await v.catch((Y) => (console.error(`Error loading LOD ${e} from ${u}
395
- `, Y), null)), D = !1;
394
+ let p = await v.catch((z) => (console.error(`Error loading LOD ${e} from ${u}
395
+ `, z), null)), D = !1;
396
396
  if (p == null || (p instanceof ee && t instanceof ee ? (l = p.image) != null && l.data || (f = p.source) != null && f.data ? p = this.copySettings(t, p) : (D = !0, this.previouslyLoaded.delete(y)) : p instanceof de && t instanceof de && ((c = p.attributes.position) != null && c.array || (D = !0, this.previouslyLoaded.delete(y)))), !D)
397
397
  return p;
398
398
  }
399
- const x = s, R = new Promise(async (p, D) => {
400
- const Y = new Ye();
401
- Ie(Y), L && (await new Promise((b) => setTimeout(b, 1e3)), r && console.warn("Start loading (delayed) " + u, x.guid));
402
- let G = u;
399
+ const x = s, G = new Promise(async (p, D) => {
400
+ const z = new Ye();
401
+ Ie(z), L && (await new Promise((O) => setTimeout(O, 1e3)), r && console.warn("Start loading (delayed) " + u, x.guid));
402
+ let q = u;
403
403
  if (x && Array.isArray(x.lods)) {
404
- const b = x.lods[e];
405
- b.hash && (G += "?v=" + b.hash);
404
+ const O = x.lods[e];
405
+ O.hash && (q += "?v=" + O.hash);
406
406
  }
407
- const _ = await Y.loadAsync(G).catch((b) => (console.error(`Error loading LOD ${e} from ${u}
408
- `, b), null));
409
- if (!_)
407
+ const S = await z.loadAsync(q).catch((O) => (console.error(`Error loading LOD ${e} from ${u}
408
+ `, O), null));
409
+ if (!S)
410
410
  return null;
411
- const K = _.parser;
411
+ const V = S.parser;
412
412
  r && console.log("Loading finished " + u, x.guid);
413
- let F = 0;
414
- if (_.parser.json.textures) {
415
- let b = !1;
416
- for (const g of _.parser.json.textures) {
413
+ let A = 0;
414
+ if (S.parser.json.textures) {
415
+ let O = !1;
416
+ for (const g of S.parser.json.textures) {
417
417
  if (g != null && g.extensions) {
418
- const h = g == null ? void 0 : g.extensions[N];
418
+ const h = g == null ? void 0 : g.extensions[U];
419
419
  if (h != null && h.guid && h.guid === x.guid) {
420
- b = !0;
420
+ O = !0;
421
421
  break;
422
422
  }
423
423
  }
424
- F++;
424
+ A++;
425
425
  }
426
- if (b) {
427
- let g = await K.getDependency("texture", F);
428
- return g && O.assignLODInformation(o.url, g, i, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + g.name + '"', u, F, g, y), t instanceof ee && (g = this.copySettings(t, g)), g && (g.guid = x.guid), p(g);
426
+ if (O) {
427
+ let g = await V.getDependency("texture", A);
428
+ return g && _.assignLODInformation(o.url, g, i, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + g.name + '"', u, A, g, y), t instanceof ee && (g = this.copySettings(t, g)), g && (g.guid = x.guid), p(g);
429
429
  } else
430
- L && console.warn("Could not find texture with guid", x.guid, _.parser.json);
430
+ L && console.warn("Could not find texture with guid", x.guid, S.parser.json);
431
431
  }
432
- if (F = 0, _.parser.json.meshes) {
433
- let b = !1;
434
- for (const g of _.parser.json.meshes) {
432
+ if (A = 0, S.parser.json.meshes) {
433
+ let O = !1;
434
+ for (const g of S.parser.json.meshes) {
435
435
  if (g != null && g.extensions) {
436
- const h = g == null ? void 0 : g.extensions[N];
436
+ const h = g == null ? void 0 : g.extensions[U];
437
437
  if (h != null && h.guid && h.guid === x.guid) {
438
- b = !0;
438
+ O = !0;
439
439
  break;
440
440
  }
441
441
  }
442
- F++;
442
+ A++;
443
443
  }
444
- if (b) {
445
- const g = await K.getDependency("mesh", F), h = x;
446
- if (r && console.log(`Loaded Mesh "${g.name}"`, u, F, g, y), g.isMesh === !0) {
444
+ if (O) {
445
+ const g = await V.getDependency("mesh", A), h = x;
446
+ if (r && console.log(`Loaded Mesh "${g.name}"`, u, A, g, y), g.isMesh === !0) {
447
447
  const w = g.geometry;
448
- return O.assignLODInformation(o.url, w, i, e, void 0, h.density), p(w);
448
+ return _.assignLODInformation(o.url, w, i, e, void 0, h.density), p(w);
449
449
  } else {
450
450
  const w = new Array();
451
451
  for (let T = 0; T < g.children.length; T++) {
452
- const A = g.children[T];
453
- if (A.isMesh === !0) {
454
- const P = A.geometry;
455
- O.assignLODInformation(o.url, P, i, e, T, h.density), w.push(P);
452
+ const P = g.children[T];
453
+ if (P.isMesh === !0) {
454
+ const E = P.geometry;
455
+ _.assignLODInformation(o.url, E, i, e, T, h.density), w.push(E);
456
456
  }
457
457
  }
458
458
  return p(w);
459
459
  }
460
460
  } else
461
- L && console.warn("Could not find mesh with guid", x.guid, _.parser.json);
461
+ L && console.warn("Could not find mesh with guid", x.guid, S.parser.json);
462
462
  }
463
463
  return p(null);
464
464
  });
465
- return this.previouslyLoaded.set(y, R), await R;
465
+ return this.previouslyLoaded.set(y, G), await G;
466
466
  } else if (t instanceof ee) {
467
467
  r && console.log("Load texture from uri: " + u);
468
468
  const v = await new Ue().loadAsync(u);
@@ -490,22 +490,22 @@ const O = class {
490
490
  `, 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;
491
491
  }
492
492
  };
493
- let S = O;
493
+ let b = _;
494
494
  /**
495
495
  * Register a texture with LOD information
496
496
  */
497
- d(S, "registerTexture", (t, e, r, o, i) => {
497
+ d(b, "registerTexture", (t, e, r, o, i) => {
498
498
  if (L && console.log("> Progressive: register texture", o, e.name, e.uuid, e, i), !e) {
499
499
  L && console.error("gltf-progressive: Register texture without texture");
500
500
  return;
501
501
  }
502
502
  e.source && (e.source[xe] = i);
503
503
  const s = i.guid;
504
- O.assignLODInformation(t, e, s, r, o, void 0), O.lodInfos.set(s, i), O.lowresCache.set(s, e);
504
+ _.assignLODInformation(t, e, s, r, o, void 0), _.lodInfos.set(s, i), _.lowresCache.set(s, e);
505
505
  }), /**
506
506
  * Register a mesh with LOD information
507
507
  */
508
- d(S, "registerMesh", (t, e, r, o, i, s) => {
508
+ d(b, "registerMesh", (t, e, r, o, i, s) => {
509
509
  var f;
510
510
  L && console.log("> Progressive: register mesh", i, r.name, s, r.uuid, r);
511
511
  const n = r.geometry;
@@ -513,15 +513,15 @@ d(S, "registerMesh", (t, e, r, o, i, s) => {
513
513
  L && console.warn("gltf-progressive: Register mesh without geometry");
514
514
  return;
515
515
  }
516
- n.userData || (n.userData = {}), O.assignLODInformation(t, n, e, o, i, s.density), O.lodInfos.set(e, s);
517
- let l = O.lowresCache.get(e);
518
- l ? l.push(r.geometry) : l = [r.geometry], O.lowresCache.set(e, l), o > 0 && !Oe(r) && et(r, n);
519
- for (const c of X)
516
+ n.userData || (n.userData = {}), _.assignLODInformation(t, n, e, o, i, s.density), _.lodInfos.set(e, s);
517
+ let l = _.lowresCache.get(e);
518
+ l ? l.push(r.geometry) : l = [r.geometry], _.lowresCache.set(e, l), o > 0 && !Oe(r) && et(r, n);
519
+ for (const c of Y)
520
520
  (f = c.onRegisteredNewMesh) == null || f.call(c, r, s);
521
521
  }), /** A map of key = asset uuid and value = LOD information */
522
- d(S, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
523
- d(S, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
524
- d(S, "lowresCache", /* @__PURE__ */ new Map());
522
+ d(b, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
523
+ d(b, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
524
+ d(b, "lowresCache", /* @__PURE__ */ new Map());
525
525
  class rt {
526
526
  constructor(t, e, r, o, i) {
527
527
  d(this, "url");
@@ -535,9 +535,9 @@ class rt {
535
535
  this.url = t, this.key = e, this.level = r, o != null && (this.index = o), i != null && (this.density = i);
536
536
  }
537
537
  }
538
- const B = ae("debugprogressive"), st = ae("noprogressive"), Le = Symbol("Needle:LODSManager"), Me = Symbol("Needle:LODState"), H = Symbol("Needle:CurrentLOD"), k = { mesh_lod: -1, texture_lod: -1 };
539
- var C, U, ge, Q, Z, pe, W;
540
- const E = class {
538
+ const k = ae("debugprogressive"), st = ae("noprogressive"), Le = Symbol("Needle:LODSManager"), Me = Symbol("Needle:LODState"), H = Symbol("Needle:CurrentLOD"), I = { mesh_lod: -1, texture_lod: -1 };
539
+ var B, W, ge, Q, Z, pe, K;
540
+ const C = class {
541
541
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
542
542
  constructor(t, e) {
543
543
  d(this, "context");
@@ -553,27 +553,27 @@ const E = class {
553
553
  * The update interval in frames. If set to 0, the LODs will be updated every frame. If set to 2, the LODs will be updated every second frame, etc.
554
554
  */
555
555
  d(this, "updateInterval", "auto");
556
- q(this, C, 1);
556
+ X(this, B, 1);
557
557
  /**
558
558
  * If set to true, the LODsManager will not update the LODs.
559
559
  */
560
560
  d(this, "pause", !1);
561
561
  d(this, "_lodchangedlisteners", []);
562
- q(this, U, void 0);
563
- q(this, ge, new Ke());
564
- q(this, Q, 0);
565
- q(this, Z, 0);
566
- q(this, pe, 0);
567
- q(this, W, 0);
562
+ X(this, W, void 0);
563
+ X(this, ge, new Ke());
564
+ X(this, Q, 0);
565
+ X(this, Z, 0);
566
+ X(this, pe, 0);
567
+ X(this, K, 0);
568
568
  d(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
569
569
  // private testIfLODLevelsAreAvailable() {
570
570
  d(this, "_sphere", new Xe());
571
571
  d(this, "_tempBox", new Te());
572
572
  d(this, "_tempBox2", new Te());
573
573
  d(this, "tempMatrix", new be());
574
- d(this, "_tempWorldPosition", new V());
575
- d(this, "_tempBoxSize", new V());
576
- d(this, "_tempBox2Size", new V());
574
+ d(this, "_tempWorldPosition", new N());
575
+ d(this, "_tempBoxSize", new N());
576
+ d(this, "_tempBox2Size", new N());
577
577
  this.renderer = t, this.context = { ...e };
578
578
  }
579
579
  /** @internal */
@@ -581,11 +581,11 @@ const E = class {
581
581
  return t[Me];
582
582
  }
583
583
  static addPlugin(t) {
584
- X.push(t);
584
+ Y.push(t);
585
585
  }
586
586
  static removePlugin(t) {
587
- const e = X.indexOf(t);
588
- e >= 0 && X.splice(e, 1);
587
+ const e = Y.indexOf(t);
588
+ e >= 0 && Y.splice(e, 1);
589
589
  }
590
590
  /**
591
591
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -595,7 +595,7 @@ const E = class {
595
595
  static get(t, e) {
596
596
  if (t[Le])
597
597
  return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[Le];
598
- const r = new E(t, {
598
+ const r = new C(t, {
599
599
  engine: "unknown",
600
600
  ...e
601
601
  });
@@ -603,7 +603,7 @@ const E = class {
603
603
  }
604
604
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
605
605
  get plugins() {
606
- return X;
606
+ return Y;
607
607
  }
608
608
  addEventListener(t, e) {
609
609
  t === "changed" && this._lodchangedlisteners.push(e);
@@ -612,20 +612,20 @@ const E = class {
612
612
  * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
613
613
  */
614
614
  enable() {
615
- if (m(this, U))
615
+ if (m(this, W))
616
616
  return;
617
617
  console.debug("[gltf-progressive] Enabling LODsManager for renderer");
618
618
  let t = 0;
619
- $(this, U, this.renderer.render);
619
+ F(this, W, this.renderer.render);
620
620
  const e = this;
621
621
  ke(this.renderer), this.renderer.render = function(r, o) {
622
- e.renderer.getRenderTarget() == null && (t = 0, $(e, Q, m(e, Q) + 1), $(e, Z, m(e, ge).getDelta()), $(e, pe, m(e, pe) + m(e, Z)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, Z)), $(e, W, e._fpsBuffer.reduce((l, f) => l + f) / e._fpsBuffer.length), B && m(e, Q) % 30 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
622
+ e.renderer.getRenderTarget() == null && (t = 0, F(e, Q, m(e, Q) + 1), F(e, Z, m(e, ge).getDelta()), F(e, pe, m(e, pe) + m(e, Z)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, Z)), F(e, K, e._fpsBuffer.reduce((l, f) => l + f) / e._fpsBuffer.length), k && m(e, Q) % 30 === 0 && console.log("FPS", Math.round(m(e, K)), "Interval:", m(e, B)));
623
623
  const s = m(e, Q), n = t++;
624
- e.onBeforeRender(r, o, n, s), m(e, U).call(this, r, o), e.onAfterRender(r, o, n, s);
624
+ e.onBeforeRender(r, o, n, s), m(e, W).call(this, r, o), e.onAfterRender(r, o, n, s);
625
625
  };
626
626
  }
627
627
  disable() {
628
- m(this, U) && (this.renderer.render = m(this, U), $(this, U, void 0));
628
+ m(this, W) && (this.renderer.render = m(this, W), F(this, W, void 0));
629
629
  }
630
630
  onBeforeRender(t, e, r, o) {
631
631
  }
@@ -640,13 +640,13 @@ const E = class {
640
640
  (c.name === "EffectMaterial" || c.name === "CopyShader") && (n = !1);
641
641
  }
642
642
  if ((e.parent && e.parent.type === "CubeCamera" || r >= 1 && e.type === "OrthographicCamera") && (n = !1), n) {
643
- if (st || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? ($(this, C, m(this, C) + 1), B && console.warn("↓ Reducing LOD updates", m(this, C), m(this, W).toFixed(0))) : m(this, W) >= 80 && m(this, C) > 1 && ($(this, C, m(this, C) - 1), B && console.warn("↑ Increasing LOD updates", m(this, C), m(this, W).toFixed(0))) : $(this, C, this.updateInterval), m(this, C) > 0 && o % m(this, C) != 0))
643
+ if (st || (this.updateInterval === "auto" ? m(this, K) < 40 && m(this, B) < 10 ? (F(this, B, m(this, B) + 1), k && console.warn("↓ Reducing LOD updates", m(this, B), m(this, K).toFixed(0))) : m(this, K) >= 60 && m(this, B) > 1 && (F(this, B, m(this, B) - 1), k && console.warn("↑ Increasing LOD updates", m(this, B), m(this, K).toFixed(0))) : F(this, B, this.updateInterval), m(this, B) > 0 && o % m(this, B) != 0))
644
644
  return;
645
645
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
646
646
  const c = this.targetTriangleDensity;
647
647
  for (const u of s) {
648
648
  if (u.material && (((l = u.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((f = u.geometry) == null ? void 0 : f.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
649
- B && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
649
+ k && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
650
650
  continue;
651
651
  }
652
652
  switch (u.material.type) {
@@ -658,7 +658,7 @@ const E = class {
658
658
  case "MeshDepthMaterial":
659
659
  continue;
660
660
  }
661
- if (B === "color" && u.material && !u.object.progressive_debug_color) {
661
+ if (k === "color" && u.material && !u.object.progressive_debug_color) {
662
662
  u.object.progressive_debug_color = !0;
663
663
  const v = Math.random() * 16777215, x = new qe({ color: v });
664
664
  u.object.material = x;
@@ -680,17 +680,17 @@ const E = class {
680
680
  let s = r[Me];
681
681
  if (s || (s = new it(), r[Me] = s), s.frames++ < 2)
682
682
  return;
683
- for (const c of X)
683
+ for (const c of Y)
684
684
  (l = c.onBeforeUpdateLOD) == null || l.call(c, this.renderer, t, e, r);
685
- this.calculateLodLevel(e, r, s, 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);
686
- let n = k.texture_lod;
685
+ this.calculateLodLevel(e, r, s, o, I), I.mesh_lod = Math.round(I.mesh_lod), I.texture_lod = Math.round(I.texture_lod), I.mesh_lod >= 0 && this.loadProgressiveMeshes(r, I.mesh_lod);
686
+ let n = I.texture_lod;
687
687
  if (r.material && n >= 0) {
688
688
  const c = r["DEBUG:LOD"];
689
689
  c != null && (n = c), this.loadProgressiveTextures(r.material, n);
690
690
  }
691
- for (const c of X)
692
- (f = c.onAfterUpdatedLOD) == null || f.call(c, this.renderer, t, e, r, k);
693
- s.lastLodLevel_Mesh = k.mesh_lod, s.lastLodLevel_Texture = k.texture_lod;
691
+ for (const c of Y)
692
+ (f = c.onAfterUpdatedLOD) == null || f.call(c, this.renderer, t, e, r, I);
693
+ s.lastLodLevel_Mesh = I.mesh_lod, s.lastLodLevel_Texture = I.texture_lod;
694
694
  }
695
695
  /** Load progressive textures for the given material
696
696
  * @param material the material to load the textures for
@@ -706,7 +706,7 @@ const E = class {
706
706
  return;
707
707
  }
708
708
  let r = !1;
709
- (t[H] === void 0 || e < t[H]) && (r = !0), r && (t[H] = e, S.assignTextureLOD(t, e).then((o) => {
709
+ (t[H] === void 0 || e < t[H]) && (r = !0), r && (t[H] = e, b.assignTextureLOD(t, e).then((o) => {
710
710
  this._lodchangedlisteners.forEach((i) => i({ type: "texture", level: e, object: t }));
711
711
  }));
712
712
  }
@@ -722,7 +722,7 @@ const E = class {
722
722
  if (t[H] !== e) {
723
723
  t[H] = e;
724
724
  const r = t.geometry;
725
- return S.assignMeshLOD(t, e).then((o) => (o && t[H] == e && r != t.geometry && this._lodchangedlisteners.forEach((i) => i({ type: "mesh", level: e, object: t })), o));
725
+ return b.assignMeshLOD(t, e).then((o) => (o && t[H] == e && r != t.geometry && this._lodchangedlisteners.forEach((i) => i({ type: "mesh", level: e, object: t })), o));
726
726
  }
727
727
  return Promise.resolve(null);
728
728
  }
@@ -731,7 +731,7 @@ const E = class {
731
731
  return this._tempPtInside.set(i, s, r.z).applyMatrix4(e).z < 0;
732
732
  }
733
733
  calculateLodLevel(t, e, r, o, i) {
734
- var R, z;
734
+ var G, $;
735
735
  if (!e) {
736
736
  i.mesh_lod = -1, i.texture_lod = -1;
737
737
  return;
@@ -741,14 +741,14 @@ const E = class {
741
741
  return;
742
742
  }
743
743
  let n = 10 + 1, l = !1;
744
- if (B && e["DEBUG:LOD"] != null)
744
+ if (k && e["DEBUG:LOD"] != null)
745
745
  return e["DEBUG:LOD"];
746
- const f = S.getMeshLODInformation(e.geometry), c = f == null ? void 0 : f.lods, M = c && c.length > 0, u = S.getMaterialMinMaxLODsCount(e.material), y = (u == null ? void 0 : u.min_count) != 1 / 0 && u.min_count > 0 && u.max_count > 0;
746
+ const f = b.getMeshLODInformation(e.geometry), c = f == null ? void 0 : f.lods, M = c && c.length > 0, u = b.getMaterialMinMaxLODsCount(e.material), y = (u == null ? void 0 : u.min_count) != 1 / 0 && u.min_count > 0 && u.max_count > 0;
747
747
  if (!M && !y) {
748
748
  i.mesh_lod = 0, i.texture_lod = 0;
749
749
  return;
750
750
  }
751
- if (M || (l = !0, n = 0), !((R = this.cameraFrustrum) != null && R.intersectsObject(e))) {
751
+ if (M || (l = !0, n = 0), !((G = this.cameraFrustrum) != null && G.intersectsObject(e))) {
752
752
  i.mesh_lod = 99, i.texture_lod = 99;
753
753
  return;
754
754
  }
@@ -768,85 +768,86 @@ const E = class {
768
768
  return;
769
769
  }
770
770
  }
771
- if (this._tempBox.copy(x), this._tempBox.applyMatrix4(e.matrixWorld), E.isInside(this._tempBox, this.projectionScreenMatrix)) {
771
+ if (this._tempBox.copy(x), this._tempBox.applyMatrix4(e.matrixWorld), C.isInside(this._tempBox, this.projectionScreenMatrix)) {
772
772
  i.mesh_lod = 0, i.texture_lod = 0;
773
773
  return;
774
774
  }
775
775
  if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
776
776
  const h = this._tempBox.min, w = this._tempBox.max;
777
- let T = h.x, A = h.y, P = w.x, j = w.y;
777
+ let T = h.x, P = h.y, E = w.x, j = w.y;
778
778
  const le = 2, ye = 1.5, ce = (h.x + w.x) * 0.5, ue = (h.y + w.y) * 0.5;
779
- T = (T - ce) * le + ce, A = (A - ue) * le + ue, P = (P - ce) * le + ce, j = (j - ue) * le + ue;
780
- const Fe = T < 0 && P > 0 ? 0 : Math.min(Math.abs(h.x), Math.abs(w.x)), $e = A < 0 && j > 0 ? 0 : Math.min(Math.abs(h.y), Math.abs(w.y)), me = Math.max(Fe, $e);
779
+ T = (T - ce) * le + ce, P = (P - ue) * le + ue, E = (E - ce) * le + ce, j = (j - ue) * le + ue;
780
+ const Fe = T < 0 && E > 0 ? 0 : Math.min(Math.abs(h.x), Math.abs(w.x)), $e = P < 0 && j > 0 ? 0 : Math.min(Math.abs(h.y), Math.abs(w.y)), me = Math.max(Fe, $e);
781
781
  r.lastCentrality = (ye - me) * (ye - me) * (ye - me);
782
782
  } else
783
783
  r.lastCentrality = 1;
784
784
  const D = this._tempBox.getSize(this._tempBoxSize);
785
785
  D.multiplyScalar(0.5), screen.availHeight > 0 && v > 0 && D.multiplyScalar(v / screen.availHeight), D.x *= p.aspect;
786
- const Y = t.matrixWorldInverse, G = this._tempBox2;
787
- G.copy(x), G.applyMatrix4(e.matrixWorld), G.applyMatrix4(Y);
788
- const _ = G.getSize(this._tempBox2Size), K = Math.max(_.x, _.y);
789
- if (Math.max(D.x, D.y) != 0 && K != 0 && (D.z = _.z / Math.max(_.x, _.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, B && E.debugDrawLine) {
786
+ const z = t.matrixWorldInverse, q = this._tempBox2;
787
+ q.copy(x), q.applyMatrix4(e.matrixWorld), q.applyMatrix4(z);
788
+ const S = q.getSize(this._tempBox2Size), V = Math.max(S.x, S.y);
789
+ if (Math.max(D.x, D.y) != 0 && V != 0 && (D.z = S.z / Math.max(S.x, S.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, k && C.debugDrawLine) {
790
790
  const h = this.tempMatrix.copy(this.projectionScreenMatrix);
791
791
  h.invert();
792
- const w = E.corner0, T = E.corner1, A = E.corner2, P = E.corner3;
793
- w.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = w.x, A.copy(this._tempBox.max), A.y = w.y, P.copy(this._tempBox.max);
794
- const j = (w.z + P.z) * 0.5;
795
- w.z = T.z = A.z = P.z = j, w.applyMatrix4(h), T.applyMatrix4(h), A.applyMatrix4(h), P.applyMatrix4(h), E.debugDrawLine(w, T, 255), E.debugDrawLine(w, A, 255), E.debugDrawLine(T, P, 255), E.debugDrawLine(A, P, 255);
792
+ const w = C.corner0, T = C.corner1, P = C.corner2, E = C.corner3;
793
+ w.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = w.x, P.copy(this._tempBox.max), P.y = w.y, E.copy(this._tempBox.max);
794
+ const j = (w.z + E.z) * 0.5;
795
+ w.z = T.z = P.z = E.z = j, w.applyMatrix4(h), T.applyMatrix4(h), P.applyMatrix4(h), E.applyMatrix4(h), C.debugDrawLine(w, T, 255), C.debugDrawLine(w, P, 255), C.debugDrawLine(T, E, 255), C.debugDrawLine(P, E, 255);
796
796
  }
797
- let b = 999;
797
+ let O = 999;
798
798
  if (c && r.lastScreenCoverage > 0) {
799
799
  for (let h = 0; h < c.length; h++)
800
800
  if (c[h].density / r.lastScreenCoverage < o) {
801
- b = h;
801
+ O = h;
802
802
  break;
803
803
  }
804
804
  }
805
- b < n && (n = b, l = !0);
805
+ O < n && (n = O, l = !0);
806
806
  }
807
- if (l ? i.mesh_lod = n : i.mesh_lod = r.lastLodLevel_Mesh, B && i.mesh_lod != r.lastLodLevel_Mesh) {
807
+ if (l ? i.mesh_lod = n : i.mesh_lod = r.lastLodLevel_Mesh, k && i.mesh_lod != r.lastLodLevel_Mesh) {
808
808
  const D = c == null ? void 0 : c[i.mesh_lod];
809
809
  D && console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${i.mesh_lod} (${D.density.toFixed(0)}) - ${e.name}`);
810
810
  }
811
- if (y)
811
+ if (y) {
812
+ const p = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
812
813
  if (r.lastLodLevel_Texture < 0) {
813
- if (i.texture_lod = u.max_count - 1, B) {
814
- const p = u.lods[u.max_count - 1];
815
- B && console.log(`First Texture LOD ${i.texture_lod} (${p.max_height}px) - ${e.name}`);
814
+ if (i.texture_lod = u.max_count - 1, k) {
815
+ const D = u.lods[u.max_count - 1];
816
+ k && console.log(`First Texture LOD ${i.texture_lod} (${D.max_height}px) - ${e.name}`);
816
817
  }
817
818
  } else {
818
- const p = r.lastScreenspaceVolume.x + r.lastScreenspaceVolume.y + r.lastScreenspaceVolume.z;
819
- let D = r.lastScreenCoverage * 2;
820
- ((z = this.context) == null ? void 0 : z.engine) === "model-viewer" && (D *= 2);
821
- const G = v / window.devicePixelRatio * D;
822
- for (let _ = u.lods.length - 1; _ >= 0; _--) {
823
- let K = u.lods[_];
824
- if (!(je() && K.max_height > 4096) && K.max_height > G) {
825
- if (i.texture_lod = _, i.texture_lod < r.lastLodLevel_Texture) {
826
- const F = K.max_height;
827
- B && console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${i.texture_lod} = ${F}px
828
- Screensize: ${G.toFixed(0)}px, Coverage: ${(100 * r.lastScreenCoverage).toFixed(2)}%, Volume ${p.toFixed(1)}
819
+ const D = r.lastScreenspaceVolume.x + r.lastScreenspaceVolume.y + r.lastScreenspaceVolume.z;
820
+ let z = r.lastScreenCoverage * 2;
821
+ (($ = this.context) == null ? void 0 : $.engine) === "model-viewer" && (z *= 2);
822
+ const S = v / window.devicePixelRatio * z;
823
+ for (let V = u.lods.length - 1; V >= 0; V--) {
824
+ let A = u.lods[V];
825
+ if (!(p && A.max_height >= 2048) && !(je() && A.max_height > 4096) && A.max_height > S) {
826
+ if (i.texture_lod = V, i.texture_lod < r.lastLodLevel_Texture) {
827
+ const O = A.max_height;
828
+ k && console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${i.texture_lod} = ${O}px
829
+ Screensize: ${S.toFixed(0)}px, Coverage: ${(100 * r.lastScreenCoverage).toFixed(2)}%, Volume ${D.toFixed(1)}
829
830
  ${e.name}`);
830
831
  }
831
832
  break;
832
833
  }
833
834
  }
834
835
  }
835
- else
836
+ } else
836
837
  i.texture_lod = 0;
837
838
  }
838
839
  };
839
- let I = E;
840
- C = new WeakMap(), U = new WeakMap(), ge = new WeakMap(), Q = new WeakMap(), Z = new WeakMap(), pe = new WeakMap(), W = new WeakMap(), /** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
840
+ let R = C;
841
+ B = new WeakMap(), W = new WeakMap(), ge = new WeakMap(), Q = new WeakMap(), Z = new WeakMap(), pe = new WeakMap(), K = new WeakMap(), /** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
841
842
  */
842
- d(I, "debugDrawLine"), d(I, "corner0", new V()), d(I, "corner1", new V()), d(I, "corner2", new V()), d(I, "corner3", new V()), d(I, "_tempPtInside", new V());
843
+ d(R, "debugDrawLine"), d(R, "corner0", new N()), d(R, "corner1", new N()), d(R, "corner2", new N()), d(R, "corner3", new N()), d(R, "_tempPtInside", new N());
843
844
  class it {
844
845
  constructor() {
845
846
  d(this, "frames", 0);
846
847
  d(this, "lastLodLevel_Mesh", -1);
847
848
  d(this, "lastLodLevel_Texture", -1);
848
849
  d(this, "lastScreenCoverage", 0);
849
- d(this, "lastScreenspaceVolume", new V());
850
+ d(this, "lastScreenspaceVolume", new N());
850
851
  d(this, "lastCentrality", 0);
851
852
  }
852
853
  }
@@ -900,8 +901,8 @@ function Ge(a) {
900
901
  }
901
902
  };
902
903
  console.debug("[gltf-progressive] setup model-viewer");
903
- const i = I.get(t, { engine: "model-viewer" });
904
- return I.addPlugin(new at()), i.enable(), i.addEventListener("changed", () => {
904
+ const i = R.get(t, { engine: "model-viewer" });
905
+ return R.addPlugin(new at()), i.enable(), i.addEventListener("changed", () => {
905
906
  r == null || r.call(a);
906
907
  }), a.addEventListener("model-visibility", (s) => {
907
908
  s.detail.visible && (r == null || r.call(a));
@@ -947,17 +948,17 @@ class at {
947
948
  for (let y = 0; y < f.length; y++) {
948
949
  const v = f[y], x = l[v];
949
950
  if ((x == null ? void 0 : x.isTexture) === !0) {
950
- const R = (M = (c = x.userData) == null ? void 0 : c.associations) == null ? void 0 : M.textures;
951
- if (R == null)
951
+ const G = (M = (c = x.userData) == null ? void 0 : c.associations) == null ? void 0 : M.textures;
952
+ if (G == null)
952
953
  continue;
953
- const z = r.parser.json.textures[R];
954
- if (!z) {
955
- console.warn("Texture data not found for texture index " + R);
954
+ const $ = r.parser.json.textures[G];
955
+ if (!$) {
956
+ console.warn("Texture data not found for texture index " + G);
956
957
  continue;
957
958
  }
958
- if ((u = z == null ? void 0 : z.extensions) != null && u[N]) {
959
- const p = z.extensions[N];
960
- p && i && S.registerTexture(i, x, p.lods.length, R, p);
959
+ if ((u = $ == null ? void 0 : $.extensions) != null && u[U]) {
960
+ const p = $.extensions[U];
961
+ p && i && b.registerTexture(i, x, p.lods.length, G, p);
961
962
  }
962
963
  }
963
964
  }
@@ -978,23 +979,23 @@ class at {
978
979
  const r = this.tryGetCurrentModelViewer(t), o = this.getUrl(r);
979
980
  if (!o)
980
981
  return;
981
- const i = (n = (s = e.userData) == null ? void 0 : s.gltfExtensions) == null ? void 0 : n[N];
982
+ const i = (n = (s = e.userData) == null ? void 0 : s.gltfExtensions) == null ? void 0 : n[U];
982
983
  if (i && o) {
983
984
  const l = e.uuid;
984
- S.registerMesh(o, l, e, 0, i.lods.length, i);
985
+ b.registerMesh(o, l, e, 0, i.lods.length, i);
985
986
  }
986
987
  }
987
988
  }
988
989
  function mt(a, t, e, r) {
989
- ke(t), Ie(e), e.register((i) => new S(i, a));
990
- const o = I.get(t);
990
+ ke(t), Ie(e), e.register((i) => new b(i, a));
991
+ const o = R.get(t);
991
992
  return (r == null ? void 0 : r.enableLODsManager) !== !1 && o.enable(), o;
992
993
  }
993
994
  Re();
994
995
  export {
995
- N as EXTENSION_NAME,
996
- I as LODsManager,
997
- S as NEEDLE_progressive,
996
+ U as EXTENSION_NAME,
997
+ R as LODsManager,
998
+ b as NEEDLE_progressive,
998
999
  Be as VERSION,
999
1000
  Ie as addDracoAndKTX2Loaders,
1000
1001
  ke as createLoaders,
@@ -1,8 +1,8 @@
1
- var Re=Object.defineProperty,Ge=(t,e,s)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,d=(t,e,s)=>(Ge(t,typeof e!="symbol"?e+"":e,s),s),Oe=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},v=(t,e,s)=>(Oe(t,e,"read from private field"),s?s.call(t):e.get(t)),V=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},G=(t,e,s,o)=>(Oe(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as oe,Mesh as K,Material as Fe,Texture as Y,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as ze,Sphere as Ue,Box3 as Te,Vector3 as F}from"three";import{GLTFLoader as Ve}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ke}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Xe}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let ie="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ie+"draco_decoder.js",{method:"head"}).catch(t=>{ie="./include/draco/",me="./include/ktx2/"});function He(t){ie=t}function Ye(t){me=t}let J,pe,Q;function xe(t){J||(J=new Ke,J.setDecoderPath(ie),J.setDecoderConfig({type:"js"})),Q||(Q=new Xe,Q.setTranscoderPath(me)),pe||(pe=qe),t?Q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ve(t){t.dracoLoader||t.setDRACOLoader(J),t.ktx2Loader||t.setKTX2Loader(Q),t.meshoptDecoder||t.setMeshoptDecoder(pe)}Z("debugprogressive");function Z(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let le;function Qe(){return le!==void 0||(le=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",le)),le}const ye=Symbol("needle:raycast-mesh");function ae(t){return t?.[ye]instanceof oe?t[ye]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ae(t)){const s=et(e);s.userData={isRaycastMesh:!0},t[ye]=s}}function Ze(t=!0){if(t){if(ee)return;const e=ee=K.prototype.raycast;K.prototype.raycast=function(s,o){const r=this,n=ae(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),e.call(this,s,o),i&&(r.geometry=i)}}else{if(!ee)return;K.prototype.raycast=ee,ee=null}}let ee=null;function et(t){const e=new oe;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const N=new Array,j="NEEDLE_progressive",y=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),te=new Map,Me=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,te),te.forEach((r,n)=>{for(const i of r.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=b.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,b.assignMeshLOD(n,a),u&&(s=Math.max(s,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,b.assignTextureLOD(n,e);break}}}}),e>=s&&(e=-1)},e=-1,s=2,o=!1;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(o=!o,Me&&Me.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Ae(t,e,s){var o;if(!y)return;te.has(t)||te.set(t,{keys:[],sourceId:s});const r=te.get(t);((o=r?.keys)==null?void 0:o.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const n=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[j];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).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}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}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 i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(y==="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=s.getAssignedLODInformation(i);if(u){const a=s.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 p=0;p<a.lods.length;p++){const c=a.lods[p];c.width&&(l.lods[p]=l.lods[p]||{min_height:1/0,max_height:0},l.lods[p].min_height=Math.min(l.lods[p].min_height,c.height),l.lods[p].max_height=Math.max(l.lods[p].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var s;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,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const n=o.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof K||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const n of N)(s=n.onBeforeGetLODMesh)==null||s.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=r.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,y&&Ae(t,"geometry",r.url)):y&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else y&&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 instanceof Fe||t.isMaterial===!0){const s=t,o=[],r=new Array;if(y&&Me.add(s),s.uniforms&&s.isRawShaderMaterial||s.isShaderMaterial===!0){const n=s;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i);o.push(u),r.push(i)}}}else for(const n of Object.keys(s)){const i=s[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,n);o.push(l),r.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=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof Y||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?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t){if(s&&o){const n=s[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,n,r),null}s[o]=r}if(y&&o&&s){const n=this.getAssignedLODInformation(t);n&&Ae(s,o,n.url)}}return r}else y=="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 y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[j];if(i){if(!i.lods){y&&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===r&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,r,i))}l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const n=o?.extensions[j];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,n;const i=y=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const p=t;p.source&&p.source[Le]&&(a=p.source[Le])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let f=!1;const S=Array.isArray(a.lods);if(S&&e>=a.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(u)}const p=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!p)return y&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=Je(l.url,p);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let g=await S.catch(E=>(console.error(`Error loading LOD ${e} from ${c}
2
- `,E),null)),x=!1;if(g==null||(g instanceof Y&&t instanceof Y?(o=g.image)!=null&&o.data||(r=g.source)!=null&&r.data?g=this.copySettings(t,g):(x=!0,this.previouslyLoaded.delete(f)):g instanceof oe&&t instanceof oe&&((n=g.attributes.position)!=null&&n.array||(x=!0,this.previouslyLoaded.delete(f)))),!x)return g}const M=a,A=new Promise(async(g,x)=>{const E=new Ve;ve(E),y&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+c,M.guid));let I=c;if(M&&Array.isArray(M.lods)){const m=M.lods[e];m.hash&&(I+="?v="+m.hash)}const D=await E.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${c}
3
- `,m),null));if(!D)return null;const q=D.parser;i&&console.log("Loading finished "+c,M.guid);let B=0;if(D.parser.json.textures){let m=!1;for(const h of D.parser.json.textures){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){m=!0;break}}B++}if(m){let h=await q.getDependency("texture",B);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,B,h,f),t instanceof Y&&(h=this.copySettings(t,h)),h&&(h.guid=M.guid),g(h)}else y&&console.warn("Could not find texture with guid",M.guid,D.parser.json)}if(B=0,D.parser.json.meshes){let m=!1;for(const h of D.parser.json.meshes){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){m=!0;break}}B++}if(m){const h=await q.getDependency("mesh",B),L=M;if(i&&console.log(`Loaded Mesh "${h.name}"`,c,B,h,f),h.isMesh===!0){const _=h.geometry;return w.assignLODInformation(l.url,_,u,e,void 0,L.density),g(_)}else{const _=new Array;for(let O=0;O<h.children.length;O++){const W=h.children[O];if(W.isMesh===!0){const U=W.geometry;w.assignLODInformation(l.url,U,u,e,O,L.density),_.push(U)}}return g(_)}}else y&&console.warn("Could not find mesh with guid",M.guid,D.parser.json)}return g(null)});return this.previouslyLoaded.set(f,A),await A}else if(t instanceof Y){i&&console.log("Load texture from uri: "+c);const f=await new We().loadAsync(c);return f?(f.guid=a.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(a,f)):y&&console.warn("failed loading",c),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,n){if(!e)return;e.userData||(e.userData={});const i=new tt(t,s,o,r,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(),y&&console.warn(`Copying texture settings
1
+ var Re=Object.defineProperty,Ge=(t,e,s)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,d=(t,e,s)=>(Ge(t,typeof e!="symbol"?e+"":e,s),s),be=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},v=(t,e,s)=>(be(t,e,"read from private field"),s?s.call(t):e.get(t)),q=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},F=(t,e,s,o)=>(be(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as oe,Mesh as X,Material as Fe,Texture as Y,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as ze,Sphere as Ve,Box3 as Te,Vector3 as W}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Xe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let ie="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ie+"draco_decoder.js",{method:"head"}).catch(t=>{ie="./include/draco/",me="./include/ktx2/"});function He(t){ie=t}function Ye(t){me=t}let J,pe,Q;function xe(t){J||(J=new Xe,J.setDecoderPath(ie),J.setDecoderConfig({type:"js"})),Q||(Q=new Ke,Q.setTranscoderPath(me)),pe||(pe=qe),t?Q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ve(t){t.dracoLoader||t.setDRACOLoader(J),t.ktx2Loader||t.setKTX2Loader(Q),t.meshoptDecoder||t.setMeshoptDecoder(pe)}Z("debugprogressive");function Z(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let le;function Qe(){return le!==void 0||(le=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",le)),le}const ye=Symbol("needle:raycast-mesh");function ae(t){return t?.[ye]instanceof oe?t[ye]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ae(t)){const s=et(e);s.userData={isRaycastMesh:!0},t[ye]=s}}function Ze(t=!0){if(t){if(ee)return;const e=ee=X.prototype.raycast;X.prototype.raycast=function(s,o){const r=this,n=ae(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),e.call(this,s,o),i&&(r.geometry=i)}}else{if(!ee)return;X.prototype.raycast=ee,ee=null}}let ee=null;function et(t){const e=new oe;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const $=new Array,j="NEEDLE_progressive",y=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),te=new Map,Me=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,te),te.forEach((r,n)=>{for(const i of r.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=O.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,O.assignMeshLOD(n,a),u&&(s=Math.max(s,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,O.assignTextureLOD(n,e);break}}}}),e>=s&&(e=-1)},e=-1,s=2,o=!1;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(o=!o,Me&&Me.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Ae(t,e,s){var o;if(!y)return;te.has(t)||te.set(t,{keys:[],sourceId:s});const r=te.get(t);((o=r?.keys)==null?void 0:o.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const n=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[j];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).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}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}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 i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(y==="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=s.getAssignedLODInformation(i);if(u){const a=s.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 p=0;p<a.lods.length;p++){const c=a.lods[p];c.width&&(l.lods[p]=l.lods[p]||{min_height:1/0,max_height:0},l.lods[p].min_height=Math.min(l.lods[p].min_height,c.height),l.lods[p].max_height=Math.max(l.lods[p].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var s;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,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const n=o.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof X||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const n of $)(s=n.onBeforeGetLODMesh)==null||s.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=r.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,y&&Ae(t,"geometry",r.url)):y&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else y&&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 instanceof Fe||t.isMaterial===!0){const s=t,o=[],r=new Array;if(y&&Me.add(s),s.uniforms&&s.isRawShaderMaterial||s.isShaderMaterial===!0){const n=s;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i);o.push(u),r.push(i)}}}else for(const n of Object.keys(s)){const i=s[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,n);o.push(l),r.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=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof Y||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?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t){if(s&&o){const n=s[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,n,r),null}s[o]=r}if(y&&o&&s){const n=this.getAssignedLODInformation(t);n&&Ae(s,o,n.url)}}return r}else y=="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 y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[j];if(i){if(!i.lods){y&&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===r&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,r,i))}l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const n=o?.extensions[j];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,n;const i=y=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const p=t;p.source&&p.source[Le]&&(a=p.source[Le])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let f=!1;const S=Array.isArray(a.lods);if(S&&e>=a.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(u)}const p=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!p)return y&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=Je(l.url,p);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let m=await S.catch(E=>(console.error(`Error loading LOD ${e} from ${c}
2
+ `,E),null)),x=!1;if(m==null||(m instanceof Y&&t instanceof Y?(o=m.image)!=null&&o.data||(r=m.source)!=null&&r.data?m=this.copySettings(t,m):(x=!0,this.previouslyLoaded.delete(f)):m instanceof oe&&t instanceof oe&&((n=m.attributes.position)!=null&&n.array||(x=!0,this.previouslyLoaded.delete(f)))),!x)return m}const M=a,I=new Promise(async(m,x)=>{const E=new Ue;ve(E),y&&(await new Promise(g=>setTimeout(g,1e3)),i&&console.warn("Start loading (delayed) "+c,M.guid));let k=c;if(M&&Array.isArray(M.lods)){const g=M.lods[e];g.hash&&(k+="?v="+g.hash)}const D=await E.loadAsync(k).catch(g=>(console.error(`Error loading LOD ${e} from ${c}
3
+ `,g),null));if(!D)return null;const G=D.parser;i&&console.log("Loading finished "+c,M.guid);let A=0;if(D.parser.json.textures){let g=!1;for(const h of D.parser.json.textures){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){g=!0;break}}A++}if(g){let h=await G.getDependency("texture",A);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,A,h,f),t instanceof Y&&(h=this.copySettings(t,h)),h&&(h.guid=M.guid),m(h)}else y&&console.warn("Could not find texture with guid",M.guid,D.parser.json)}if(A=0,D.parser.json.meshes){let g=!1;for(const h of D.parser.json.meshes){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){g=!0;break}}A++}if(g){const h=await G.getDependency("mesh",A),L=M;if(i&&console.log(`Loaded Mesh "${h.name}"`,c,A,h,f),h.isMesh===!0){const _=h.geometry;return w.assignLODInformation(l.url,_,u,e,void 0,L.density),m(_)}else{const _=new Array;for(let b=0;b<h.children.length;b++){const N=h.children[b];if(N.isMesh===!0){const U=N.geometry;w.assignLODInformation(l.url,U,u,e,b,L.density),_.push(U)}}return m(_)}}else y&&console.warn("Could not find mesh with guid",M.guid,D.parser.json)}return m(null)});return this.previouslyLoaded.set(f,I),await I}else if(t instanceof Y){i&&console.log("Load texture from uri: "+c);const f=await new We().loadAsync(c);return f?(f.guid=a.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(a,f)):y&&console.warn("failed loading",c),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,n){if(!e)return;e.userData||(e.userData={});const i=new tt(t,s,o,r,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(),y&&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 b=w;d(b,"registerTexture",(t,e,s,o,r)=>{if(y&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const n=r.guid;w.assignLODInformation(t,e,n,s,o,void 0),w.lodInfos.set(n,r),w.lowresCache.set(n,e)}),d(b,"registerMesh",(t,e,s,o,r,n)=>{var i;y&&console.log("> Progressive: register mesh",r,s.name,n,s.uuid,s);const l=s.geometry;if(!l){y&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,r,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),o>0&&!ae(s)&&Ee(s,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,s,n)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class tt{constructor(e,s,o,r,n){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r),n!=null&&(this.density=n)}}const C=Z("debugprogressive"),st=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),X=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var T,$,_e,H,se,ue,z;const P=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new Se),d(this,"cameraFrustrum",new Ne),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval","auto"),V(this,T,1),d(this,"pause",!1),d(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,_e,new $e),V(this,H,0),V(this,se,0),V(this,ue,0),V(this,z,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new Ue),d(this,"_tempBox",new Te),d(this,"_tempBox2",new Te),d(this,"tempMatrix",new Se),d(this,"_tempWorldPosition",new F),d(this,"_tempBoxSize",new F),d(this,"_tempBox2Size",new F),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}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[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const s=new P(t,{engine:"unknown",...e});return t[De]=s,s}get plugins(){return N}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(v(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;xe(this.renderer),this.renderer.render=function(s,o){e.renderer.getRenderTarget()==null&&(t=0,G(e,H,v(e,H)+1),G(e,se,v(e,_e).getDelta()),G(e,ue,v(e,ue)+v(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,se)),G(e,z,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),C&&v(e,H)%30===0&&console.log("FPS",Math.round(v(e,z)),"Interval:",v(e,T)));const r=v(e,H),n=t++;e.onBeforeRender(s,o,n,r),v(e,$).call(this,s,o),e.onAfterRender(s,o,n,r)}}disable(){v(this,$)&&(this.renderer.render=v(this,$),G(this,$,void 0))}onBeforeRender(t,e,s,o){}onAfterRender(t,e,s,o){var r,n;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),l=i.opaque;let u=!0;if(l.length===1){const a=l[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(u=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(u=!1),u){if(st||(this.updateInterval==="auto"?v(this,z)<40&&v(this,T)<10?(G(this,T,v(this,T)+1),C&&console.warn("\u2193 Reducing LOD updates",v(this,T),v(this,z).toFixed(0))):v(this,z)>=80&&v(this,T)>1&&(G(this,T,v(this,T)-1),C&&console.warn("\u2191 Increasing LOD updates",v(this,T),v(this,z).toFixed(0))):G(this,T,this.updateInterval),v(this,T)>0&&o%v(this,T)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const a=this.targetTriangleDensity;for(const c of l){if(c.material&&(((r=c.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=c.geometry)==null?void 0:n.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){C&&(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(C==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const S=Math.random()*16777215,M=new ze({color:S});c.object.material=M}const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}const p=i.transparent;for(const c of p){const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}}}updateLODs(t,e,s,o,r){var n,i;s.userData||(s.userData={});let l=s[we];if(l||(l=new rt,s[we]=l),l.frames++<2)return;for(const a of N)(n=a.onBeforeUpdateLOD)==null||n.call(a,this.renderer,t,e,s);this.calculateLodLevel(e,s,l,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(s,k.mesh_lod);let u=k.texture_lod;if(s.material&&u>=0){const a=s["DEBUG:LOD"];a!=null&&(u=a),this.loadProgressiveTextures(s.material,u)}for(const a of N)(i=a.onAfterUpdatedLOD)==null||i.call(a,this.renderer,t,e,s,k);l.lastLodLevel_Mesh=k.mesh_lod,l.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 s=!1;(t[X]===void 0||e<t[X])&&(s=!0),s&&(t[X]=e,b.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[X]!==e){t[X]=e;const s=t.geometry;return b.assignMeshLOD(t,e).then(o=>(o&&t[X]==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,n=(s.y+o.y)*.5;return this._tempPtInside.set(r,n,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var n,i;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let l=10+1,u=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=b.getMeshLODInformation(e.geometry),p=a?.lods,c=p&&p.length>0,f=b.getMaterialMinMaxLODsCount(e.material),S=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!c&&!S){r.mesh_lod=0,r.texture_lod=0;return}if(c||(u=!0,l=0),!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e))){r.mesh_lod=99,r.texture_lod=99;return}const M=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let A=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const g=e;g.boundingBox||g.computeBoundingBox(),A=g.boundingBox}if(A&&t.isPerspectiveCamera){const g=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 m=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(A),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&g.fov>70){const m=this._tempBox.min,h=this._tempBox.max;let L=m.x,_=m.y,O=h.x,W=h.y;const U=2,he=1.5,re=(m.x+h.x)*.5,ne=(m.y+h.y)*.5;L=(L-re)*U+re,_=(_-ne)*U+ne,O=(O-re)*U+re,W=(W-ne)*U+ne;const ke=L<0&&O>0?0:Math.min(Math.abs(m.x),Math.abs(h.x)),je=_<0&&W>0?0:Math.min(Math.abs(m.y),Math.abs(h.y)),fe=Math.max(ke,je);s.lastCentrality=(he-fe)*(he-fe)*(he-fe)}else s.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&M>0&&x.multiplyScalar(M/screen.availHeight),x.x*=g.aspect;const E=t.matrixWorldInverse,I=this._tempBox2;I.copy(A),I.applyMatrix4(e.matrixWorld),I.applyMatrix4(E);const D=I.getSize(this._tempBox2Size),q=Math.max(D.x,D.y);if(Math.max(x.x,x.y)!=0&&q!=0&&(x.z=D.z/Math.max(D.x,D.y)*Math.max(x.x,x.y)),s.lastScreenCoverage=Math.max(x.x,x.y,x.z),s.lastScreenspaceVolume.copy(x),s.lastScreenCoverage*=s.lastCentrality,C&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const h=P.corner0,L=P.corner1,_=P.corner2,O=P.corner3;h.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=h.x,_.copy(this._tempBox.max),_.y=h.y,O.copy(this._tempBox.max);const W=(h.z+O.z)*.5;h.z=L.z=_.z=O.z=W,h.applyMatrix4(m),L.applyMatrix4(m),_.applyMatrix4(m),O.applyMatrix4(m),P.debugDrawLine(h,L,255),P.debugDrawLine(h,_,255),P.debugDrawLine(L,O,255),P.debugDrawLine(_,O,255)}let B=999;if(p&&s.lastScreenCoverage>0){for(let m=0;m<p.length;m++)if(p[m].density/s.lastScreenCoverage<o){B=m;break}}B<l&&(l=B,u=!0)}if(u?r.mesh_lod=l:r.mesh_lod=s.lastLodLevel_Mesh,C&&r.mesh_lod!=s.lastLodLevel_Mesh){const g=p?.[r.mesh_lod];g&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${g.density.toFixed(0)}) - ${e.name}`)}if(S)if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,C){const g=f.lods[f.max_count-1];C&&console.log(`First Texture LOD ${r.texture_lod} (${g.max_height}px) - ${e.name}`)}}else{const g=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let x=s.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(x*=2);const E=M/window.devicePixelRatio*x;for(let I=f.lods.length-1;I>=0;I--){let D=f.lods[I];if(!(Qe()&&D.max_height>4096)&&D.max_height>E){if(r.texture_lod=I,r.texture_lod<s.lastLodLevel_Texture){const q=D.max_height;C&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${q}px
6
- Screensize: ${E.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
7
- ${e.name}`)}break}}}else r.texture_lod=0}};let R=P;T=new WeakMap,$=new WeakMap,_e=new WeakMap,H=new WeakMap,se=new WeakMap,ue=new WeakMap,z=new WeakMap,d(R,"debugDrawLine"),d(R,"corner0",new F),d(R,"corner1",new F),d(R,"corner2",new F),d(R,"corner3",new F),d(R,"_tempPtInside",new F);class rt{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new F),d(this,"lastCentrality",0)}}const Ie=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let de=null;function be(){const t=nt();t&&(t.mapURLs(function(e){return Pe(),e}),Pe(),de?.disconnect(),de=new MutationObserver(e=>{e.forEach(s=>{s.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&Ce(o)})})}),de.observe(document,{childList:!0,subtree:!0}))}function nt(){return customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),be()}),null)}function Pe(){document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Be=new WeakSet;let ot=0;function Ce(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ot+`
8
- `,t.getAttribute("src"));let e=null,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),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),!s&&l!=null&&(s=t[l]),!o&&u!=null&&(o=t[u])}if(e&&s){let r=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=R.get(e,{engine:"model-viewer"});return R.addPlugin(new it),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class it{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[ce]==!0)return;s[ce]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),n=this.getUrl(r);if(n&&o&&s.material){let i=function(u){var a,p,c;if(u[ce]==!0)return;u[ce]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let S=0;S<f.length;S++){const M=f[S],A=u[M];if(A?.isTexture===!0){const g=(p=(a=A.userData)==null?void 0:a.associations)==null?void 0:p.textures;if(g==null)continue;const x=o.parser.json.textures[g];if(!x){console.warn("Texture data not found for texture index "+g);continue}if((c=x?.extensions)!=null&&c[j]){const E=x.extensions[j];E&&n&&b.registerTexture(n,A,E.lods.length,g,E)}}}};const l=s.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Ie]==!0)return;s[Ie]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[j];if(l&&i){const u=s.uuid;b.registerMesh(i,u,s,0,l.lods.length,l)}}}function lt(t,e,s,o){xe(e),ve(s),s.register(n=>new b(n,t));const r=R.get(e);return o?.enableLODsManager!==!1&&r.enable(),r}be();export{j as EXTENSION_NAME,R as LODsManager,b as NEEDLE_progressive,ge as VERSION,ve as addDracoAndKTX2Loaders,xe as createLoaders,ae as getRaycastMesh,be as patchModelViewer,Ee as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
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=w;d(O,"registerTexture",(t,e,s,o,r)=>{if(y&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const n=r.guid;w.assignLODInformation(t,e,n,s,o,void 0),w.lodInfos.set(n,r),w.lowresCache.set(n,e)}),d(O,"registerMesh",(t,e,s,o,r,n)=>{var i;y&&console.log("> Progressive: register mesh",r,s.name,n,s.uuid,s);const l=s.geometry;if(!l){y&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,r,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),o>0&&!ae(s)&&Ee(s,l);for(const a of $)(i=a.onRegisteredNewMesh)==null||i.call(a,s,n)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class tt{constructor(e,s,o,r,n){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r),n!=null&&(this.density=n)}}const B=Z("debugprogressive"),st=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),K=Symbol("Needle:CurrentLOD"),C={mesh_lod:-1,texture_lod:-1};var T,z,_e,H,se,ue,V;const P=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new Se),d(this,"cameraFrustrum",new Ne),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval","auto"),q(this,T,1),d(this,"pause",!1),d(this,"_lodchangedlisteners",[]),q(this,z,void 0),q(this,_e,new $e),q(this,H,0),q(this,se,0),q(this,ue,0),q(this,V,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new Ve),d(this,"_tempBox",new Te),d(this,"_tempBox2",new Te),d(this,"tempMatrix",new Se),d(this,"_tempWorldPosition",new W),d(this,"_tempBoxSize",new W),d(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){$.push(t)}static removePlugin(t){const e=$.indexOf(t);e>=0&&$.splice(e,1)}static get(t,e){if(t[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const s=new P(t,{engine:"unknown",...e});return t[De]=s,s}get plugins(){return $}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(v(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;F(this,z,this.renderer.render);const e=this;xe(this.renderer),this.renderer.render=function(s,o){e.renderer.getRenderTarget()==null&&(t=0,F(e,H,v(e,H)+1),F(e,se,v(e,_e).getDelta()),F(e,ue,v(e,ue)+v(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,se)),F(e,V,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),B&&v(e,H)%30===0&&console.log("FPS",Math.round(v(e,V)),"Interval:",v(e,T)));const r=v(e,H),n=t++;e.onBeforeRender(s,o,n,r),v(e,z).call(this,s,o),e.onAfterRender(s,o,n,r)}}disable(){v(this,z)&&(this.renderer.render=v(this,z),F(this,z,void 0))}onBeforeRender(t,e,s,o){}onAfterRender(t,e,s,o){var r,n;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),l=i.opaque;let u=!0;if(l.length===1){const a=l[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(u=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(u=!1),u){if(st||(this.updateInterval==="auto"?v(this,V)<40&&v(this,T)<10?(F(this,T,v(this,T)+1),B&&console.warn("\u2193 Reducing LOD updates",v(this,T),v(this,V).toFixed(0))):v(this,V)>=60&&v(this,T)>1&&(F(this,T,v(this,T)-1),B&&console.warn("\u2191 Increasing LOD updates",v(this,T),v(this,V).toFixed(0))):F(this,T,this.updateInterval),v(this,T)>0&&o%v(this,T)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const a=this.targetTriangleDensity;for(const c of l){if(c.material&&(((r=c.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=c.geometry)==null?void 0:n.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){B&&(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(B==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const S=Math.random()*16777215,M=new ze({color:S});c.object.material=M}const f=c.object;(f instanceof X||f.isMesh)&&this.updateLODs(t,e,f,a,o)}const p=i.transparent;for(const c of p){const f=c.object;(f instanceof X||f.isMesh)&&this.updateLODs(t,e,f,a,o)}}}updateLODs(t,e,s,o,r){var n,i;s.userData||(s.userData={});let l=s[we];if(l||(l=new rt,s[we]=l),l.frames++<2)return;for(const a of $)(n=a.onBeforeUpdateLOD)==null||n.call(a,this.renderer,t,e,s);this.calculateLodLevel(e,s,l,o,C),C.mesh_lod=Math.round(C.mesh_lod),C.texture_lod=Math.round(C.texture_lod),C.mesh_lod>=0&&this.loadProgressiveMeshes(s,C.mesh_lod);let u=C.texture_lod;if(s.material&&u>=0){const a=s["DEBUG:LOD"];a!=null&&(u=a),this.loadProgressiveTextures(s.material,u)}for(const a of $)(i=a.onAfterUpdatedLOD)==null||i.call(a,this.renderer,t,e,s,C);l.lastLodLevel_Mesh=C.mesh_lod,l.lastLodLevel_Texture=C.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[K]===void 0||e<t[K])&&(s=!0),s&&(t[K]=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[K]!==e){t[K]=e;const s=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[K]==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,n=(s.y+o.y)*.5;return this._tempPtInside.set(r,n,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var n,i;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let l=10+1,u=!1;if(B&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),p=a?.lods,c=p&&p.length>0,f=O.getMaterialMinMaxLODsCount(e.material),S=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!c&&!S){r.mesh_lod=0,r.texture_lod=0;return}if(c||(u=!0,l=0),!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e))){r.mesh_lod=99,r.texture_lod=99;return}const M=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let I=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),I=m.boundingBox}if(I&&t.isPerspectiveCamera){const m=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 g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(I),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.fov>70){const g=this._tempBox.min,h=this._tempBox.max;let L=g.x,_=g.y,b=h.x,N=h.y;const U=2,he=1.5,re=(g.x+h.x)*.5,ne=(g.y+h.y)*.5;L=(L-re)*U+re,_=(_-ne)*U+ne,b=(b-re)*U+re,N=(N-ne)*U+ne;const ke=L<0&&b>0?0:Math.min(Math.abs(g.x),Math.abs(h.x)),je=_<0&&N>0?0:Math.min(Math.abs(g.y),Math.abs(h.y)),fe=Math.max(ke,je);s.lastCentrality=(he-fe)*(he-fe)*(he-fe)}else s.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&M>0&&x.multiplyScalar(M/screen.availHeight),x.x*=m.aspect;const E=t.matrixWorldInverse,k=this._tempBox2;k.copy(I),k.applyMatrix4(e.matrixWorld),k.applyMatrix4(E);const D=k.getSize(this._tempBox2Size),G=Math.max(D.x,D.y);if(Math.max(x.x,x.y)!=0&&G!=0&&(x.z=D.z/Math.max(D.x,D.y)*Math.max(x.x,x.y)),s.lastScreenCoverage=Math.max(x.x,x.y,x.z),s.lastScreenspaceVolume.copy(x),s.lastScreenCoverage*=s.lastCentrality,B&&P.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const h=P.corner0,L=P.corner1,_=P.corner2,b=P.corner3;h.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=h.x,_.copy(this._tempBox.max),_.y=h.y,b.copy(this._tempBox.max);const N=(h.z+b.z)*.5;h.z=L.z=_.z=b.z=N,h.applyMatrix4(g),L.applyMatrix4(g),_.applyMatrix4(g),b.applyMatrix4(g),P.debugDrawLine(h,L,255),P.debugDrawLine(h,_,255),P.debugDrawLine(L,b,255),P.debugDrawLine(_,b,255)}let A=999;if(p&&s.lastScreenCoverage>0){for(let g=0;g<p.length;g++)if(p[g].density/s.lastScreenCoverage<o){A=g;break}}A<l&&(l=A,u=!0)}if(u?r.mesh_lod=l:r.mesh_lod=s.lastLodLevel_Mesh,B&&r.mesh_lod!=s.lastLodLevel_Mesh){const m=p?.[r.mesh_lod];m&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`)}if(S){const m="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,B){const x=f.lods[f.max_count-1];B&&console.log(`First Texture LOD ${r.texture_lod} (${x.max_height}px) - ${e.name}`)}}else{const x=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let E=s.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(E*=2);const k=M/window.devicePixelRatio*E;for(let D=f.lods.length-1;D>=0;D--){let G=f.lods[D];if(!(m&&G.max_height>=2048)&&!(Qe()&&G.max_height>4096)&&G.max_height>k){if(r.texture_lod=D,r.texture_lod<s.lastLodLevel_Texture){const A=G.max_height;B&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${A}px
6
+ Screensize: ${k.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${x.toFixed(1)}
7
+ ${e.name}`)}break}}}}else r.texture_lod=0}};let R=P;T=new WeakMap,z=new WeakMap,_e=new WeakMap,H=new WeakMap,se=new WeakMap,ue=new WeakMap,V=new WeakMap,d(R,"debugDrawLine"),d(R,"corner0",new W),d(R,"corner1",new W),d(R,"corner2",new W),d(R,"corner3",new W),d(R,"_tempPtInside",new W);class rt{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new W),d(this,"lastCentrality",0)}}const Ie=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let de=null;function Oe(){const t=nt();t&&(t.mapURLs(function(e){return Pe(),e}),Pe(),de?.disconnect(),de=new MutationObserver(e=>{e.forEach(s=>{s.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&Ce(o)})})}),de.observe(document,{childList:!0,subtree:!0}))}function nt(){return customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Pe(){document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Be=new WeakSet;let ot=0;function Ce(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ot+`
8
+ `,t.getAttribute("src"));let e=null,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),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),!s&&l!=null&&(s=t[l]),!o&&u!=null&&(o=t[u])}if(e&&s){let r=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=R.get(e,{engine:"model-viewer"});return R.addPlugin(new it),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class it{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[ce]==!0)return;s[ce]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),n=this.getUrl(r);if(n&&o&&s.material){let i=function(u){var a,p,c;if(u[ce]==!0)return;u[ce]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let S=0;S<f.length;S++){const M=f[S],I=u[M];if(I?.isTexture===!0){const m=(p=(a=I.userData)==null?void 0:a.associations)==null?void 0:p.textures;if(m==null)continue;const x=o.parser.json.textures[m];if(!x){console.warn("Texture data not found for texture index "+m);continue}if((c=x?.extensions)!=null&&c[j]){const E=x.extensions[j];E&&n&&O.registerTexture(n,I,E.lods.length,m,E)}}}};const l=s.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Ie]==!0)return;s[Ie]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[j];if(l&&i){const u=s.uuid;O.registerMesh(i,u,s,0,l.lods.length,l)}}}function lt(t,e,s,o){xe(e),ve(s),s.register(n=>new O(n,t));const r=R.get(e);return o?.enableLODsManager!==!1&&r.enable(),r}Oe();export{j as EXTENSION_NAME,R as LODsManager,O as NEEDLE_progressive,ge as VERSION,ve as addDracoAndKTX2Loaders,xe as createLoaders,ae as getRaycastMesh,Oe as patchModelViewer,Ee as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
@@ -1,8 +1,8 @@
1
- "use strict";var Re=Object.defineProperty;var Ge=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var x=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},$=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let ue="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",_e="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ue+"draco_decoder.js",{method:"head"}).catch(a=>{ue="./include/draco/",_e="./include/ktx2/"});function ze(a){ue=a}function Ue(a){_e=a}let re,Le,se;function ve(a){re||(re=new $e.DRACOLoader,re.setDecoderPath(ue),re.setDecoderConfig({type:"js"})),se||(se=new Ne.KTX2Loader,se.setTranscoderPath(_e)),Le||(Le=Ve.MeshoptDecoder),a?se.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Oe(a){a.dracoLoader||a.setDRACOLoader(re),a.ktx2Loader||a.setKTX2Loader(se),a.meshoptDecoder||a.setMeshoptDecoder(Le)}ie("debugprogressive");function ie(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let Z;function qe(){return Z!==void 0||(Z=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ie("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Z)),Z}const Me=Symbol("needle:raycast-mesh");function he(a){return(a==null?void 0:a[Me])instanceof h.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!he(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(ee)return;const t=ee=h.Mesh.prototype.raycast;h.Mesh.prototype.raycast=function(e,r){const i=this,o=he(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),t.call(this,e,r),s&&(i.geometry=s)}}else{if(!ee)return;h.Mesh.prototype.raycast=ee,ee=null}}let ee=null;function Xe(a){const t=new h.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const X=new Array,N="NEEDLE_progressive",M=ie("debugprogressive"),ye=Symbol("needle-progressive-texture"),oe=new Map,De=new Set;if(M){let a=function(){t+=1,console.log("Toggle LOD level",t,oe),oe.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const l=b.getMeshLODInformation(n),f=l?Math.min(t,l.lods.length):0;o["DEBUG:LOD"]=t,b.assignMeshLOD(o,f),l&&(e=Math.max(e,l.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=t,b.assignTextureLOD(o,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,De&&De.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function Te(a,t,e){var i;if(!M)return;oe.has(a)||oe.set(a,{keys:[],sourceId:e});const r=oe.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(t))==!1&&r.keys.push(t)}const S=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,i;if(this._isLoadingMesh)return null;const e=(i=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:i[N];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(o=>{var s;return this._isLoadingMesh=!1,o&&S.registerMesh(this.url,e.guid,o,(s=e.lods)==null?void 0:s.length,void 0,e),o})):null});M&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}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,i="LODS:minmax",o=t[i];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[i]=e,e}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const f=n.uniforms[l].value;(f==null?void 0:f.isTexture)===!0&&s(f,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[i]=e,e;function s(n,l){const f=r.getAssignedLODInformation(n);if(f){const c=r.lodInfos.get(f.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 D=0;D<c.lods.length;D++){const u=c.lods[D];u.width&&(l.lods[D]=l.lods[D]||{min_height:1/0,max_height:0},l.lods[D].min_height=Math.min(l.lods[D].min_height,u.height),l.lods[D].max_height=Math.max(l.lods[D].max_height,u.height))}}}}}static hasLODLevelAvailable(t,e){var o;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,i;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),e===void 0)return i!=null;if(i)return Array.isArray(i.lods)?e<i.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof h.Mesh||t.isMesh===!0){const i=t.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of X)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?(t.geometry=s,M&&Te(t,"geometry",o.url)):M&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else M&&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 instanceof h.Material||t.isMaterial===!0){const r=t,i=[],o=new Array;if(M&&De.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const l=s.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const f=this.assignTextureLODForSlot(l,e,r,n);i.push(f),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,s);i.push(l),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let l=0;l<s.length;l++){const f=s[l],c=o[l];f&&f.isTexture===!0?n.push({material:r,slot:c,texture:f,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof h.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=t){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<e)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,s,o),null}r[i]=o}if(M&&i&&r){const s=this.getAssignedLODInformation(t);s&&Te(r,i,s.url)}}return o}else M=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return M&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const n=i==null?void 0:i.extensions[N];if(n){if(!n.lods){M&&console.warn("Texture has no LODs",n);return}let l=!1;for(const f of this.parser.associations.keys())if(f.isTexture===!0){const c=this.parser.associations.get(f);(c==null?void 0:c.textures)===o&&(l=!0,S.registerTexture(this.url,f,(s=n.lods)==null?void 0:s.length,o,n))}l||this.parser.getDependency("texture",o).then(f=>{var c;f&&S.registerTexture(this.url,f,(c=n.lods)==null?void 0:c.length,o,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[N];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);(l==null?void 0:l.meshes)===o&&S.registerMesh(this.url,s.guid,n,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var n,l,f,c;const r=M=="verbose",i=t.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(t.isTexture===!0){const D=t;D.source&&D.source[ye]&&(s=D.source[ye])}if(s||(s=S.lodInfos.get(o)),s){if(e>0){let m=!1;const v=Array.isArray(s.lods);if(v&&e>=s.lods.length?m=!0:v||(m=!0),m)return this.lowresCache.get(o)}const D=Array.isArray(s.lods)?(n=s.lods[e])==null?void 0:n.path:s.lods;if(!D)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const u=We(i.url,D);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const m=u+"_"+s.guid,v=this.previouslyLoaded.get(m);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let y=await v.catch(Y=>(console.error(`Error loading LOD ${e} from ${u}
2
- `,Y),null)),w=!1;if(y==null||(y instanceof h.Texture&&t instanceof h.Texture?(l=y.image)!=null&&l.data||(f=y.source)!=null&&f.data?y=this.copySettings(t,y):(w=!0,this.previouslyLoaded.delete(m)):y instanceof h.BufferGeometry&&t instanceof h.BufferGeometry&&((c=y.attributes.position)!=null&&c.array||(w=!0,this.previouslyLoaded.delete(m)))),!w)return y}const L=s,G=new Promise(async(y,w)=>{const Y=new Fe.GLTFLoader;Oe(Y),M&&(await new Promise(T=>setTimeout(T,1e3)),r&&console.warn("Start loading (delayed) "+u,L.guid));let F=u;if(L&&Array.isArray(L.lods)){const T=L.lods[e];T.hash&&(F+="?v="+T.hash)}const O=await Y.loadAsync(F).catch(T=>(console.error(`Error loading LOD ${e} from ${u}
3
- `,T),null));if(!O)return null;const q=O.parser;r&&console.log("Loading finished "+u,L.guid);let V=0;if(O.parser.json.textures){let T=!1;for(const p of O.parser.json.textures){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[N];if(g!=null&&g.guid&&g.guid===L.guid){T=!0;break}}V++}if(T){let p=await q.getDependency("texture",V);return p&&S.assignLODInformation(i.url,p,o,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+p.name+'"',u,V,p,m),t instanceof h.Texture&&(p=this.copySettings(t,p)),p&&(p.guid=L.guid),y(p)}else M&&console.warn("Could not find texture with guid",L.guid,O.parser.json)}if(V=0,O.parser.json.meshes){let T=!1;for(const p of O.parser.json.meshes){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[N];if(g!=null&&g.guid&&g.guid===L.guid){T=!0;break}}V++}if(T){const p=await q.getDependency("mesh",V),g=L;if(r&&console.log(`Loaded Mesh "${p.name}"`,u,V,p,m),p.isMesh===!0){const _=p.geometry;return S.assignLODInformation(i.url,_,o,e,void 0,g.density),y(_)}else{const _=new Array;for(let A=0;A<p.children.length;A++){const E=p.children[A];if(E.isMesh===!0){const P=E.geometry;S.assignLODInformation(i.url,P,o,e,A,g.density),_.push(P)}}return y(_)}}else M&&console.warn("Could not find mesh with guid",L.guid,O.parser.json)}return y(null)});return this.previouslyLoaded.set(m,G),await G}else if(t instanceof h.Texture){r&&console.log("Load texture from uri: "+u);const v=await new h.TextureLoader().loadAsync(u);return v?(v.guid=s.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(s,v)):M&&console.warn("failed loading",u),v}}else M&&console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,i,o,s){if(!e)return;e.userData||(e.userData={});const n=new Ye(t,r,i,o,s);e.userData.LODS=n}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(),M&&console.warn(`Copying texture settings
1
+ "use strict";var Re=Object.defineProperty;var Ge=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var x=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),X=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},V=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let ue="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ve="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ue+"draco_decoder.js",{method:"head"}).catch(a=>{ue="./include/draco/",ve="./include/ktx2/"});function ze(a){ue=a}function Ue(a){ve=a}let re,Le,se;function _e(a){re||(re=new $e.DRACOLoader,re.setDecoderPath(ue),re.setDecoderConfig({type:"js"})),se||(se=new Ne.KTX2Loader,se.setTranscoderPath(ve)),Le||(Le=Ve.MeshoptDecoder),a?se.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Oe(a){a.dracoLoader||a.setDRACOLoader(re),a.ktx2Loader||a.setKTX2Loader(se),a.meshoptDecoder||a.setMeshoptDecoder(Le)}oe("debugprogressive");function oe(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let Z;function qe(){return Z!==void 0||(Z=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),oe("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Z)),Z}const Me=Symbol("needle:raycast-mesh");function he(a){return(a==null?void 0:a[Me])instanceof h.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!he(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(ee)return;const t=ee=h.Mesh.prototype.raycast;h.Mesh.prototype.raycast=function(e,r){const o=this,i=he(o);let s;i&&o.isMesh&&(s=o.geometry,o.geometry=i),t.call(this,e,r),s&&(o.geometry=s)}}else{if(!ee)return;h.Mesh.prototype.raycast=ee,ee=null}}let ee=null;function Xe(a){const t=new h.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,$="NEEDLE_progressive",M=oe("debugprogressive"),ye=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(M){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,i)=>{for(const s of o.keys){const n=i[s];if(n!=null){if(n.isBufferGeometry===!0){const l=b.getMeshLODInformation(n),f=l?Math.min(t,l.lods.length):0;i["DEBUG:LOD"]=t,b.assignMeshLOD(i,f),l&&(e=Math.max(e,l.lods.length-1))}else if(i.isMaterial===!0){i["DEBUG:LOD"]=t,b.assignTextureLOD(i,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",o=>{o.key==="p"&&a(),o.key==="w"&&(r=!r,De&&De.forEach(i=>{i.name!="BackgroundCubeMaterial"&&i.glyphMap==null&&"wireframe"in i&&(i.wireframe=r)}))})}function Te(a,t,e){var o;if(!M)return;ie.has(a)||ie.set(a,{keys:[],sourceId:e});const r=ie.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const O=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(i=>{var s;return this._isLoadingMesh=!1,i&&O.registerMesh(this.url,e.guid,i,(s=e.lods)==null?void 0:s.length,void 0,e),i})):null});M&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return $}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",i=t[o];if(i!=null)return i;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const f=n.uniforms[l].value;(f==null?void 0:f.isTexture)===!0&&s(f,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[o]=e,e;function s(n,l){const f=r.getAssignedLODInformation(n);if(f){const c=r.lodInfos.get(f.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 D=0;D<c.lods.length;D++){const u=c.lods[D];u.width&&(l.lods[D]=l.lods[D]||{min_height:1/0,max_height:0},l.lods[D].min_height=Math.min(l.lods[D].min_height,u.height),l.lods[D].max_height=Math.max(l.lods[D].max_height,u.height))}}}}}static hasLODLevelAvailable(t,e){var i;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(i=r==null?void 0:r.userData)!=null&&i.LODS){const s=r.userData.LODS;if(o=this.lodInfos.get(s.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 r;if(!t)return Promise.resolve(null);if(t instanceof h.Mesh||t.isMesh===!0){const o=t.geometry,i=this.getAssignedLODInformation(o);if(!i)return Promise.resolve(null);for(const s of Y)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,O.getOrLoadLOD(o,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const n=i.index||0;s=s[n]}s&&o!=s&&((s==null?void 0:s.isBufferGeometry)?(t.geometry=s,M&&Te(t,"geometry",i.url)):M&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else M&&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 instanceof h.Material||t.isMaterial===!0){const r=t,o=[],i=new Array;if(M&&De.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const l=s.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const f=this.assignTextureLODForSlot(l,e,r,n);o.push(f),i.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,s);o.push(l),i.push(s)}}return Promise.all(o).then(s=>{const n=new Array;for(let l=0;l<s.length;l++){const f=s[l],c=i[l];f&&f.isTexture===!0?n.push({material:r,slot:c,texture:f,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof h.Texture||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==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(i=>{if(Array.isArray(i))return null;if((i==null?void 0:i.isTexture)===!0){if(i!=t){if(r&&o){const s=r[o];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<e)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,s,i),null}r[o]=i}if(M&&o&&r){const s=this.getAssignedLODInformation(t);s&&Te(r,o,s.url)}}return i}else M=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(i=>(console.error("Error loading LOD",t,i),null))}afterRoot(t){var e,r;return M&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,i)=>{var s;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[$];if(n){if(!n.lods){M&&console.warn("Texture has no LODs",n);return}let l=!1;for(const f of this.parser.associations.keys())if(f.isTexture===!0){const c=this.parser.associations.get(f);(c==null?void 0:c.textures)===i&&(l=!0,O.registerTexture(this.url,f,(s=n.lods)==null?void 0:s.length,i,n))}l||this.parser.getDependency("texture",i).then(f=>{var c;f&&O.registerTexture(this.url,f,(c=n.lods)==null?void 0:c.length,i,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,i)=>{if(o!=null&&o.extensions){const s=o==null?void 0:o.extensions[$];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);(l==null?void 0:l.meshes)===i&&O.registerMesh(this.url,s.guid,n,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var n,l,f,c;const r=M=="verbose",o=t.userData.LODS;if(!o)return null;const i=o==null?void 0:o.key;let s;if(t.isTexture===!0){const D=t;D.source&&D.source[ye]&&(s=D.source[ye])}if(s||(s=O.lodInfos.get(i)),s){if(e>0){let m=!1;const _=Array.isArray(s.lods);if(_&&e>=s.lods.length?m=!0:_||(m=!0),m)return this.lowresCache.get(i)}const D=Array.isArray(s.lods)?(n=s.lods[e])==null?void 0:n.path:s.lods;if(!D)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const u=We(o.url,D);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const m=u+"_"+s.guid,_=this.previouslyLoaded.get(m);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let y=await _.catch(z=>(console.error(`Error loading LOD ${e} from ${u}
2
+ `,z),null)),w=!1;if(y==null||(y instanceof h.Texture&&t instanceof h.Texture?(l=y.image)!=null&&l.data||(f=y.source)!=null&&f.data?y=this.copySettings(t,y):(w=!0,this.previouslyLoaded.delete(m)):y instanceof h.BufferGeometry&&t instanceof h.BufferGeometry&&((c=y.attributes.position)!=null&&c.array||(w=!0,this.previouslyLoaded.delete(m)))),!w)return y}const L=s,F=new Promise(async(y,w)=>{const z=new Fe.GLTFLoader;Oe(z),M&&(await new Promise(S=>setTimeout(S,1e3)),r&&console.warn("Start loading (delayed) "+u,L.guid));let K=u;if(L&&Array.isArray(L.lods)){const S=L.lods[e];S.hash&&(K+="?v="+S.hash)}const T=await z.loadAsync(K).catch(S=>(console.error(`Error loading LOD ${e} from ${u}
3
+ `,S),null));if(!T)return null;const U=T.parser;r&&console.log("Loading finished "+u,L.guid);let E=0;if(T.parser.json.textures){let S=!1;for(const p of T.parser.json.textures){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[$];if(g!=null&&g.guid&&g.guid===L.guid){S=!0;break}}E++}if(S){let p=await U.getDependency("texture",E);return p&&O.assignLODInformation(o.url,p,i,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+p.name+'"',u,E,p,m),t instanceof h.Texture&&(p=this.copySettings(t,p)),p&&(p.guid=L.guid),y(p)}else M&&console.warn("Could not find texture with guid",L.guid,T.parser.json)}if(E=0,T.parser.json.meshes){let S=!1;for(const p of T.parser.json.meshes){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[$];if(g!=null&&g.guid&&g.guid===L.guid){S=!0;break}}E++}if(S){const p=await U.getDependency("mesh",E),g=L;if(r&&console.log(`Loaded Mesh "${p.name}"`,u,E,p,m),p.isMesh===!0){const v=p.geometry;return O.assignLODInformation(o.url,v,i,e,void 0,g.density),y(v)}else{const v=new Array;for(let A=0;A<p.children.length;A++){const P=p.children[A];if(P.isMesh===!0){const C=P.geometry;O.assignLODInformation(o.url,C,i,e,A,g.density),v.push(C)}}return y(v)}}else M&&console.warn("Could not find mesh with guid",L.guid,T.parser.json)}return y(null)});return this.previouslyLoaded.set(m,F),await F}else if(t instanceof h.Texture){r&&console.log("Load texture from uri: "+u);const _=await new h.TextureLoader().loadAsync(u);return _?(_.guid=s.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=t.colorSpace,r&&console.log(s,_)):M&&console.warn("failed loading",u),_}}else M&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,i,s){if(!e)return;e.userData||(e.userData={});const n=new Ye(t,r,o,i,s);e.userData.LODS=n}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(),M&&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 b=S;d(b,"registerTexture",(t,e,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,o),!e){M&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=o);const s=o.guid;S.assignLODInformation(t,e,s,r,i,void 0),S.lodInfos.set(s,o),S.lowresCache.set(s,e)}),d(b,"registerMesh",(t,e,r,i,o,s)=>{var f;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),S.assignLODInformation(t,n,e,i,o,s.density),S.lodInfos.set(e,s);let l=S.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(e,l),i>0&&!he(r)&&Ce(r,n);for(const c of X)(f=c.onRegisteredNewMesh)==null||f.call(c,r,s)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class Ye{constructor(t,e,r,i,o){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const k=ie("debugprogressive"),He=ie("noprogressive"),me=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1};var B,U,fe,j,J,de,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new h.Matrix4);d(this,"cameraFrustrum",new h.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"_lodchangedlisteners",[]);K(this,U,void 0);K(this,fe,new h.Clock);K(this,j,0);K(this,J,0);K(this,de,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new h.Sphere);d(this,"_tempBox",new h.Box3);d(this,"_tempBox2",new h.Box3);d(this,"tempMatrix",new h.Matrix4);d(this,"_tempWorldPosition",new h.Vector3);d(this,"_tempBoxSize",new h.Vector3);d(this,"_tempBox2Size",new h.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[xe]}static addPlugin(t){X.push(t)}static removePlugin(t){const e=X.indexOf(t);e>=0&&X.splice(e,1)}static get(t,e){if(t[me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[me];const r=new C(t,{engine:"unknown",...e});return t[me]=r,r}get plugins(){return X}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(x(this,U))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;$(this,U,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,i){e.renderer.getRenderTarget()==null&&(t=0,$(e,j,x(e,j)+1),$(e,J,x(e,fe).getDelta()),$(e,de,x(e,de)+x(e,J)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,J)),$(e,W,e._fpsBuffer.reduce((l,f)=>l+f)/e._fpsBuffer.length),k&&x(e,j)%30===0&&console.log("FPS",Math.round(x(e,W)),"Interval:",x(e,B)));const s=x(e,j),n=t++;e.onBeforeRender(r,i,n,s),x(e,U).call(this,r,i),e.onAfterRender(r,i,n,s)}}disable(){x(this,U)&&(this.renderer.render=x(this,U),$(this,U,void 0))}onBeforeRender(t,e,r,i){}onAfterRender(t,e,r,i){var l,f;if(this.pause)return;const o=this.renderer.renderLists.get(t,0),s=o.opaque;let n=!0;if(s.length===1){const c=s[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(n=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(n=!1),n){if(He||(this.updateInterval==="auto"?x(this,W)<40&&x(this,B)<10?($(this,B,x(this,B)+1),k&&console.warn("↓ Reducing LOD updates",x(this,B),x(this,W).toFixed(0))):x(this,W)>=80&&x(this,B)>1&&($(this,B,x(this,B)-1),k&&console.warn("↑ Increasing LOD updates",x(this,B),x(this,W).toFixed(0))):$(this,B,this.updateInterval),x(this,B)>0&&i%x(this,B)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of s){if(u.material&&(((l=u.geometry)==null?void 0:l.type)==="BoxGeometry"||((f=u.geometry)==null?void 0:f.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){k&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&u.material&&!u.object.progressive_debug_color){u.object.progressive_debug_color=!0;const v=Math.random()*16777215,L=new h.MeshStandardMaterial({color:v});u.object.material=L}const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,i)}const D=o.transparent;for(const u of D){const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,i)}}}updateLODs(t,e,r,i,o){var l,f;r.userData||(r.userData={});let s=r[xe];if(s||(s=new je,r[xe]=s),s.frames++<2)return;for(const c of X)(l=c.onBeforeUpdateLOD)==null||l.call(c,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,i,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let n=R.texture_lod;if(r.material&&n>=0){const c=r["DEBUG:LOD"];c!=null&&(n=c),this.loadProgressiveTextures(r.material,n)}for(const c of X)(f=c.onAfterUpdatedLOD)==null||f.call(c,this.renderer,t,e,r,R);s.lastLodLevel_Mesh=R.mesh_lod,s.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return b.assignMeshLOD(t,e).then(i=>(i&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(o=>o({type:"mesh",level:e,object:t})),i))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,i=t.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,i,o){var G,z;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const f=b.getMeshLODInformation(e.geometry),c=f==null?void 0:f.lods,D=c&&c.length>0,u=b.getMaterialMinMaxLODsCount(e.material),m=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!D&&!m){o.mesh_lod=0,o.texture_lod=0;return}if(D||(l=!0,n=0),!((G=this.cameraFrustrum)!=null&&G.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let L=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;y.boundingBox||y.computeBoundingBox(),L=y.boundingBox}if(L&&t.isPerspectiveCamera){const y=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 g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(L),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const g=this._tempBox.min,_=this._tempBox.max;let A=g.x,E=g.y,P=_.x,Q=_.y;const ne=2,ge=1.5,ae=(g.x+_.x)*.5,le=(g.y+_.y)*.5;A=(A-ae)*ne+ae,E=(E-le)*ne+le,P=(P-ae)*ne+ae,Q=(Q-le)*ne+le;const Ie=A<0&&P>0?0:Math.min(Math.abs(g.x),Math.abs(_.x)),ke=E<0&&Q>0?0:Math.min(Math.abs(g.y),Math.abs(_.y)),pe=Math.max(Ie,ke);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&v>0&&w.multiplyScalar(v/screen.availHeight),w.x*=y.aspect;const Y=t.matrixWorldInverse,F=this._tempBox2;F.copy(L),F.applyMatrix4(e.matrixWorld),F.applyMatrix4(Y);const O=F.getSize(this._tempBox2Size),q=Math.max(O.x,O.y);if(Math.max(w.x,w.y)!=0&&q!=0&&(w.z=O.z/Math.max(O.x,O.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,k&&C.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const _=C.corner0,A=C.corner1,E=C.corner2,P=C.corner3;_.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=_.x,E.copy(this._tempBox.max),E.y=_.y,P.copy(this._tempBox.max);const Q=(_.z+P.z)*.5;_.z=A.z=E.z=P.z=Q,_.applyMatrix4(g),A.applyMatrix4(g),E.applyMatrix4(g),P.applyMatrix4(g),C.debugDrawLine(_,A,255),C.debugDrawLine(_,E,255),C.debugDrawLine(A,P,255),C.debugDrawLine(E,P,255)}let T=999;if(c&&r.lastScreenCoverage>0){for(let g=0;g<c.length;g++)if(c[g].density/r.lastScreenCoverage<i){T=g;break}}T<n&&(n=T,l=!0)}if(l?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,k&&o.mesh_lod!=r.lastLodLevel_Mesh){const w=c==null?void 0:c[o.mesh_lod];w&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${w.density.toFixed(0)}) - ${e.name}`)}if(m)if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,k){const y=u.lods[u.max_count-1];k&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let w=r.lastScreenCoverage*2;((z=this.context)==null?void 0:z.engine)==="model-viewer"&&(w*=2);const F=v/window.devicePixelRatio*w;for(let O=u.lods.length-1;O>=0;O--){let q=u.lods[O];if(!(qe()&&q.max_height>4096)&&q.max_height>F){if(o.texture_lod=O,o.texture_lod<r.lastLodLevel_Texture){const V=q.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${V}px
6
- Screensize: ${F.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
7
- ${e.name}`)}break}}}else o.texture_lod=0}};let I=C;B=new WeakMap,U=new WeakMap,fe=new WeakMap,j=new WeakMap,J=new WeakMap,de=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new h.Vector3),d(I,"corner1",new h.Vector3),d(I,"corner2",new h.Vector3),d(I,"corner3",new h.Vector3),d(I,"_tempPtInside",new h.Vector3);class je{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new h.Vector3);d(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let te=null;function Se(){const a=Je();a&&(a.mapURLs(function(t){return Ee(),t}),Ee(),te==null||te.disconnect(),te=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),te.observe(document,{childList:!0,subtree:!0}))}function Je(){const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function Ee(){document.querySelectorAll("model-viewer").forEach(t=>{Be(t)})}const Pe=new WeakSet;let Qe=0;function Be(a){if(!a||Pe.has(a))return null;Pe.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++Qe+`
8
- `,a.getAttribute("src"));let t=null,e=null,r=null;for(let i=a;i!=null;i=Object.getPrototypeOf(i)){const o=Object.getOwnPropertySymbols(i),s=o.find(f=>f.toString()=="Symbol(renderer)"),n=o.find(f=>f.toString()=="Symbol(scene)"),l=o.find(f=>f.toString()=="Symbol(needsRender)");!t&&s!=null&&(t=a[s].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let i=function(){if(r){let s=0,n=setInterval(()=>{if(s++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=I.get(t,{engine:"model-viewer"});return I.addPlugin(new Ze),o.enable(),o.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",s=>{s.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{i()}),()=>{o.disable()}}return null}class Ze{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,r,i){this.tryParseMeshLOD(e,i),this.tryParseTextureLOD(e,i)}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[ce]==!0)return;e[ce]=!0;const r=this.tryGetCurrentGLTF(t),i=this.tryGetCurrentModelViewer(t),o=this.getUrl(i);if(o&&r&&e.material){let s=function(l){var c,D,u;if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const f=Object.keys(l);for(let m=0;m<f.length;m++){const v=f[m],L=l[v];if((L==null?void 0:L.isTexture)===!0){const G=(D=(c=L.userData)==null?void 0:c.associations)==null?void 0:D.textures;if(G==null)continue;const z=r.parser.json.textures[G];if(!z){console.warn("Texture data not found for texture index "+G);continue}if((u=z==null?void 0:z.extensions)!=null&&u[N]){const y=z.extensions[N];y&&o&&b.registerTexture(o,L,y.lods.length,G,y)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)s(l);else s(n)}}tryParseMeshLOD(t,e){var s,n;if(e[Ae]==!0)return;e[Ae]=!0;const r=this.tryGetCurrentModelViewer(t),i=this.getUrl(r);if(!i)return;const o=(n=(s=e.userData)==null?void 0:s.gltfExtensions)==null?void 0:n[N];if(o&&i){const l=e.uuid;b.registerMesh(i,l,e,0,o.lods.length,o)}}}function et(a,t,e,r){ve(t),Oe(e),e.register(o=>new b(o,a));const i=I.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}Se();exports.EXTENSION_NAME=N;exports.LODsManager=I;exports.NEEDLE_progressive=b;exports.VERSION=we;exports.addDracoAndKTX2Loaders=Oe;exports.createLoaders=ve;exports.getRaycastMesh=he;exports.patchModelViewer=Se;exports.registerRaycastMesh=Ce;exports.setDracoDecoderLocation=ze;exports.setKTX2TranscoderLocation=Ue;exports.useNeedleProgressive=et;exports.useRaycastMeshes=Ke;
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 b=O;d(b,"registerTexture",(t,e,r,o,i)=>{if(M&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,i),!e){M&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=i);const s=i.guid;O.assignLODInformation(t,e,s,r,o,void 0),O.lodInfos.set(s,i),O.lowresCache.set(s,e)}),d(b,"registerMesh",(t,e,r,o,i,s)=>{var f;M&&console.log("> Progressive: register mesh",i,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),O.assignLODInformation(t,n,e,o,i,s.density),O.lodInfos.set(e,s);let l=O.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(e,l),o>0&&!he(r)&&Ce(r,n);for(const c of Y)(f=c.onRegisteredNewMesh)==null||f.call(c,r,s)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class Ye{constructor(t,e,r,o,i){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o),i!=null&&(this.density=i)}}const R=oe("debugprogressive"),He=oe("noprogressive"),me=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),G={mesh_lod:-1,texture_lod:-1};var I,W,fe,j,J,de,q;const B=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new h.Matrix4);d(this,"cameraFrustrum",new h.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");X(this,I,1);d(this,"pause",!1);d(this,"_lodchangedlisteners",[]);X(this,W,void 0);X(this,fe,new h.Clock);X(this,j,0);X(this,J,0);X(this,de,0);X(this,q,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new h.Sphere);d(this,"_tempBox",new h.Box3);d(this,"_tempBox2",new h.Box3);d(this,"tempMatrix",new h.Matrix4);d(this,"_tempWorldPosition",new h.Vector3);d(this,"_tempBoxSize",new h.Vector3);d(this,"_tempBox2Size",new h.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[xe]}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[me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[me];const r=new B(t,{engine:"unknown",...e});return t[me]=r,r}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(x(this,W))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;V(this,W,this.renderer.render);const e=this;_e(this.renderer),this.renderer.render=function(r,o){e.renderer.getRenderTarget()==null&&(t=0,V(e,j,x(e,j)+1),V(e,J,x(e,fe).getDelta()),V(e,de,x(e,de)+x(e,J)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,J)),V(e,q,e._fpsBuffer.reduce((l,f)=>l+f)/e._fpsBuffer.length),R&&x(e,j)%30===0&&console.log("FPS",Math.round(x(e,q)),"Interval:",x(e,I)));const s=x(e,j),n=t++;e.onBeforeRender(r,o,n,s),x(e,W).call(this,r,o),e.onAfterRender(r,o,n,s)}}disable(){x(this,W)&&(this.renderer.render=x(this,W),V(this,W,void 0))}onBeforeRender(t,e,r,o){}onAfterRender(t,e,r,o){var l,f;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),s=i.opaque;let n=!0;if(s.length===1){const c=s[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(n=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(n=!1),n){if(He||(this.updateInterval==="auto"?x(this,q)<40&&x(this,I)<10?(V(this,I,x(this,I)+1),R&&console.warn("↓ Reducing LOD updates",x(this,I),x(this,q).toFixed(0))):x(this,q)>=60&&x(this,I)>1&&(V(this,I,x(this,I)-1),R&&console.warn("↑ Increasing LOD updates",x(this,I),x(this,q).toFixed(0))):V(this,I,this.updateInterval),x(this,I)>0&&o%x(this,I)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of s){if(u.material&&(((l=u.geometry)==null?void 0:l.type)==="BoxGeometry"||((f=u.geometry)==null?void 0:f.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){R&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(R==="color"&&u.material&&!u.object.progressive_debug_color){u.object.progressive_debug_color=!0;const _=Math.random()*16777215,L=new h.MeshStandardMaterial({color:_});u.object.material=L}const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,o)}const D=i.transparent;for(const u of D){const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,o)}}}updateLODs(t,e,r,o,i){var l,f;r.userData||(r.userData={});let s=r[xe];if(s||(s=new je,r[xe]=s),s.frames++<2)return;for(const c of Y)(l=c.onBeforeUpdateLOD)==null||l.call(c,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,o,G),G.mesh_lod=Math.round(G.mesh_lod),G.texture_lod=Math.round(G.texture_lod),G.mesh_lod>=0&&this.loadProgressiveMeshes(r,G.mesh_lod);let n=G.texture_lod;if(r.material&&n>=0){const c=r["DEBUG:LOD"];c!=null&&(n=c),this.loadProgressiveTextures(r.material,n)}for(const c of Y)(f=c.onAfterUpdatedLOD)==null||f.call(c,this.renderer,t,e,r,G);s.lastLodLevel_Mesh=G.mesh_lod,s.lastLodLevel_Texture=G.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[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(i=>i({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return b.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,i=(r.x+o.x)*.5,s=(r.y+o.y)*.5;return this._tempPtInside.set(i,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,i){var F,N;if(!e){i.mesh_lod=-1,i.texture_lod=-1;return}if(!t){i.mesh_lod=-1,i.texture_lod=-1;return}let n=10+1,l=!1;if(R&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const f=b.getMeshLODInformation(e.geometry),c=f==null?void 0:f.lods,D=c&&c.length>0,u=b.getMaterialMinMaxLODsCount(e.material),m=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!D&&!m){i.mesh_lod=0,i.texture_lod=0;return}if(D||(l=!0,n=0),!((F=this.cameraFrustrum)!=null&&F.intersectsObject(e))){i.mesh_lod=99,i.texture_lod=99;return}const _=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let L=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;y.boundingBox||y.computeBoundingBox(),L=y.boundingBox}if(L&&t.isPerspectiveCamera){const y=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 g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){i.mesh_lod=0,i.texture_lod=0;return}}if(this._tempBox.copy(L),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){i.mesh_lod=0,i.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const g=this._tempBox.min,v=this._tempBox.max;let A=g.x,P=g.y,C=v.x,Q=v.y;const ne=2,ge=1.5,ae=(g.x+v.x)*.5,le=(g.y+v.y)*.5;A=(A-ae)*ne+ae,P=(P-le)*ne+le,C=(C-ae)*ne+ae,Q=(Q-le)*ne+le;const Ie=A<0&&C>0?0:Math.min(Math.abs(g.x),Math.abs(v.x)),ke=P<0&&Q>0?0:Math.min(Math.abs(g.y),Math.abs(v.y)),pe=Math.max(Ie,ke);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&_>0&&w.multiplyScalar(_/screen.availHeight),w.x*=y.aspect;const z=t.matrixWorldInverse,K=this._tempBox2;K.copy(L),K.applyMatrix4(e.matrixWorld),K.applyMatrix4(z);const T=K.getSize(this._tempBox2Size),U=Math.max(T.x,T.y);if(Math.max(w.x,w.y)!=0&&U!=0&&(w.z=T.z/Math.max(T.x,T.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,R&&B.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const v=B.corner0,A=B.corner1,P=B.corner2,C=B.corner3;v.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=v.x,P.copy(this._tempBox.max),P.y=v.y,C.copy(this._tempBox.max);const Q=(v.z+C.z)*.5;v.z=A.z=P.z=C.z=Q,v.applyMatrix4(g),A.applyMatrix4(g),P.applyMatrix4(g),C.applyMatrix4(g),B.debugDrawLine(v,A,255),B.debugDrawLine(v,P,255),B.debugDrawLine(A,C,255),B.debugDrawLine(P,C,255)}let S=999;if(c&&r.lastScreenCoverage>0){for(let g=0;g<c.length;g++)if(c[g].density/r.lastScreenCoverage<o){S=g;break}}S<n&&(n=S,l=!0)}if(l?i.mesh_lod=n:i.mesh_lod=r.lastLodLevel_Mesh,R&&i.mesh_lod!=r.lastLodLevel_Mesh){const w=c==null?void 0:c[i.mesh_lod];w&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${i.mesh_lod} (${w.density.toFixed(0)}) - ${e.name}`)}if(m){const y="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(i.texture_lod=u.max_count-1,R){const w=u.lods[u.max_count-1];R&&console.log(`First Texture LOD ${i.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let z=r.lastScreenCoverage*2;((N=this.context)==null?void 0:N.engine)==="model-viewer"&&(z*=2);const T=_/window.devicePixelRatio*z;for(let U=u.lods.length-1;U>=0;U--){let E=u.lods[U];if(!(y&&E.max_height>=2048)&&!(qe()&&E.max_height>4096)&&E.max_height>T){if(i.texture_lod=U,i.texture_lod<r.lastLodLevel_Texture){const S=E.max_height;R&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${i.texture_lod} = ${S}px
6
+ Screensize: ${T.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
7
+ ${e.name}`)}break}}}}else i.texture_lod=0}};let k=B;I=new WeakMap,W=new WeakMap,fe=new WeakMap,j=new WeakMap,J=new WeakMap,de=new WeakMap,q=new WeakMap,d(k,"debugDrawLine"),d(k,"corner0",new h.Vector3),d(k,"corner1",new h.Vector3),d(k,"corner2",new h.Vector3),d(k,"corner3",new h.Vector3),d(k,"_tempPtInside",new h.Vector3);class je{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new h.Vector3);d(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let te=null;function Se(){const a=Je();a&&(a.mapURLs(function(t){return Ee(),t}),Ee(),te==null||te.disconnect(),te=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),te.observe(document,{childList:!0,subtree:!0}))}function Je(){const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function Ee(){document.querySelectorAll("model-viewer").forEach(t=>{Be(t)})}const Pe=new WeakSet;let Qe=0;function Be(a){if(!a||Pe.has(a))return null;Pe.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++Qe+`
8
+ `,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const i=Object.getOwnPropertySymbols(o),s=i.find(f=>f.toString()=="Symbol(renderer)"),n=i.find(f=>f.toString()=="Symbol(scene)"),l=i.find(f=>f.toString()=="Symbol(needsRender)");!t&&s!=null&&(t=a[s].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let o=function(){if(r){let s=0,n=setInterval(()=>{if(s++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const i=k.get(t,{engine:"model-viewer"});return k.addPlugin(new Ze),i.enable(),i.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",s=>{s.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{o()}),()=>{i.disable()}}return null}class Ze{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,r,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[ce]==!0)return;e[ce]=!0;const r=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),i=this.getUrl(o);if(i&&r&&e.material){let s=function(l){var c,D,u;if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const f=Object.keys(l);for(let m=0;m<f.length;m++){const _=f[m],L=l[_];if((L==null?void 0:L.isTexture)===!0){const F=(D=(c=L.userData)==null?void 0:c.associations)==null?void 0:D.textures;if(F==null)continue;const N=r.parser.json.textures[F];if(!N){console.warn("Texture data not found for texture index "+F);continue}if((u=N==null?void 0:N.extensions)!=null&&u[$]){const y=N.extensions[$];y&&i&&b.registerTexture(i,L,y.lods.length,F,y)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)s(l);else s(n)}}tryParseMeshLOD(t,e){var s,n;if(e[Ae]==!0)return;e[Ae]=!0;const r=this.tryGetCurrentModelViewer(t),o=this.getUrl(r);if(!o)return;const i=(n=(s=e.userData)==null?void 0:s.gltfExtensions)==null?void 0:n[$];if(i&&o){const l=e.uuid;b.registerMesh(o,l,e,0,i.lods.length,i)}}}function et(a,t,e,r){_e(t),Oe(e),e.register(i=>new b(i,a));const o=k.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Se();exports.EXTENSION_NAME=$;exports.LODsManager=k;exports.NEEDLE_progressive=b;exports.VERSION=we;exports.addDracoAndKTX2Loaders=Oe;exports.createLoaders=_e;exports.getRaycastMesh=he;exports.patchModelViewer=Se;exports.registerRaycastMesh=Ce;exports.setDracoDecoderLocation=ze;exports.setKTX2TranscoderLocation=Ue;exports.useNeedleProgressive=et;exports.useRaycastMeshes=Ke;
@@ -191,7 +191,7 @@ export class LODsManager {
191
191
  if (debugProgressiveLoading)
192
192
  console.warn("↓ Reducing LOD updates", this.#updateInterval, this.#fps.toFixed(0));
193
193
  }
194
- else if (this.#fps >= 80 && this.#updateInterval > 1) {
194
+ else if (this.#fps >= 60 && this.#updateInterval > 1) {
195
195
  this.#updateInterval -= 1;
196
196
  if (debugProgressiveLoading)
197
197
  console.warn("↑ Increasing LOD updates", this.#updateInterval, this.#fps.toFixed(0));
@@ -575,6 +575,7 @@ export class LODsManager {
575
575
  }
576
576
  }
577
577
  if (has_texture_lods) {
578
+ const saveDataEnabled = "saveData" in globalThis.navigator && globalThis.navigator.saveData === true;
578
579
  // If this is the first time a texture LOD is requested we want to get the highest LOD to not display the minimal resolution that the root glTF contains as long while we wait for loading of e.g. the 8k LOD 0 texture
579
580
  if (state.lastLodLevel_Texture < 0) {
580
581
  result.texture_lod = texture_lods_minmax.max_count - 1;
@@ -594,6 +595,9 @@ export class LODsManager {
594
595
  const pixelSizeOnScreen = screenSize * factor;
595
596
  for (let i = texture_lods_minmax.lods.length - 1; i >= 0; i--) {
596
597
  let lod = texture_lods_minmax.lods[i];
598
+ if (saveDataEnabled && lod.max_height >= 2048) {
599
+ continue; // skip 2k textures when saveData is enabled
600
+ }
597
601
  if (isMobileDevice() && lod.max_height > 4096)
598
602
  continue; // skip 8k textures on mobile devices (for now)
599
603
  if (lod.max_height > pixelSizeOnScreen) {
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "1.2.3-alpha.2";
2
+ export const version = "1.2.3-alpha.3";
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": "1.2.3-alpha.2",
3
+ "version": "1.2.3-alpha.3",
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": {