@needle-tools/gltf-progressive 1.2.10 → 1.2.12

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,13 @@ 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.12] - 2024-09-23
8
+ - Add: `assignTextureLOD` now also accepts mesh as parameter
9
+ - Change: improved `assignTextureLOD` typing
10
+
11
+ ## [1.2.11] - 2024-09-11
12
+ - Fix: draco and KTX decoder path handling when gstatic can not be reached and user set path
13
+
7
14
  ## [1.2.10] - 2024-09-10
8
15
  - Fix: loading and assigning texture LOD for ShaderMaterial and RawShaderMaterial
9
16
 
@@ -9,37 +9,38 @@ var m = (a, t, e) => (_e(a, t, "read from private field"), e ? e.call(a) : t.get
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
11
  }, U = (a, t, e, s) => (_e(a, t, "write to private field"), s ? s.call(a, e) : t.set(a, e), e);
12
- import { BufferGeometry as de, Mesh as H, Material as ze, Texture as te, TextureLoader as Ve, Matrix4 as Se, Clock as Ne, MeshStandardMaterial as We, Sphere as qe, Box3 as be, Vector3 as z } from "three";
13
- import { GLTFLoader as Xe } from "three/examples/jsm/loaders/GLTFLoader.js";
12
+ import { BufferGeometry as ge, Mesh as H, Material as ze, Texture as se, TextureLoader as Ve, Matrix4 as Se, Clock as Ne, MeshStandardMaterial as We, Sphere as Xe, Box3 as be, Vector3 as z } from "three";
13
+ import { GLTFLoader as qe } from "three/examples/jsm/loaders/GLTFLoader.js";
14
14
  import { MeshoptDecoder as Ke } from "three/examples/jsm/libs/meshopt_decoder.module.js";
15
15
  import { DRACOLoader as Ye } from "three/examples/jsm/loaders/DRACOLoader.js";
16
16
  import { KTX2Loader as He } from "three/examples/jsm/loaders/KTX2Loader.js";
17
17
  const Ce = "";
18
18
  globalThis.GLTF_PROGRESSIVE_VERSION = Ce;
19
19
  console.debug(`[gltf-progressive] version ${Ce}`);
20
- let he = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", Oe = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
21
- fetch(he + "draco_decoder.js", { method: "head" }).catch((a) => {
22
- he = "./include/draco/", Oe = "./include/ktx2/";
20
+ let j = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", ae = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
21
+ const Je = j, Qe = ae;
22
+ fetch(j + "draco_decoder.js", { method: "head" }).catch((a) => {
23
+ j === Je && (j = "./include/draco/"), ae === Qe && (ae = "./include/ktx2/");
23
24
  });
24
- function dt(a) {
25
- he = a;
25
+ function gt(a) {
26
+ j = a;
26
27
  }
27
- function ht(a) {
28
- Oe = a;
28
+ function pt(a) {
29
+ ae = a;
29
30
  }
30
- let Q, fe, Z;
31
+ let Q, he, Z;
31
32
  function Be(a) {
32
- return Q || (Q = new Ye(), Q.setDecoderPath(he), Q.setDecoderConfig({ type: "js" })), Z || (Z = new He(), Z.setTranscoderPath(Oe)), fe || (fe = Ke), a ? Z.detectSupport(a) : a !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: Q, ktx2Loader: Z, meshoptDecoder: fe };
33
+ return Q || (Q = new Ye(), Q.setDecoderPath(j), Q.setDecoderConfig({ type: "js" })), Z || (Z = new He(), Z.setTranscoderPath(ae)), he || (he = Ke), a ? Z.detectSupport(a) : a !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: Q, ktx2Loader: Z, meshoptDecoder: he };
33
34
  }
34
35
  function Ie(a) {
35
- a.dracoLoader || a.setDRACOLoader(Q), a.ktx2Loader || a.setKTX2Loader(Z), a.meshoptDecoder || a.setMeshoptDecoder(fe);
36
+ a.dracoLoader || a.setDRACOLoader(Q), a.ktx2Loader || a.setKTX2Loader(Z), a.meshoptDecoder || a.setMeshoptDecoder(he);
36
37
  }
37
- oe("debugprogressive");
38
- function oe(a) {
38
+ le("debugprogressive");
39
+ function le(a) {
39
40
  const e = new URL(window.location.href).searchParams.get(a);
40
41
  return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
41
42
  }
42
- function Je(a, t) {
43
+ function Ze(a, t) {
43
44
  if (t === void 0 || t.startsWith("./") || t.startsWith("http") || a === void 0)
44
45
  return t;
45
46
  const e = a.lastIndexOf("/");
@@ -51,47 +52,47 @@ function Je(a, t) {
51
52
  }
52
53
  return t;
53
54
  }
54
- let se;
55
- function Qe() {
56
- return se !== void 0 || (se = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), oe("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", se)), se;
55
+ let re;
56
+ function je() {
57
+ return re !== void 0 || (re = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), le("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", re)), re;
57
58
  }
58
- const we = Symbol("needle:raycast-mesh");
59
- function ye(a) {
60
- return (a == null ? void 0 : a[we]) instanceof de ? a[we] : null;
59
+ const ve = Symbol("needle:raycast-mesh");
60
+ function me(a) {
61
+ return (a == null ? void 0 : a[ve]) instanceof ge ? a[ve] : null;
61
62
  }
62
- function Ze(a, t) {
63
- if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !ye(a)) {
64
- const s = je(t);
65
- s.userData = { isRaycastMesh: !0 }, a[we] = s;
63
+ function et(a, t) {
64
+ if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !me(a)) {
65
+ const s = tt(t);
66
+ s.userData = { isRaycastMesh: !0 }, a[ve] = s;
66
67
  }
67
68
  }
68
- function gt(a = !0) {
69
+ function yt(a = !0) {
69
70
  if (a) {
70
- if (re)
71
+ if (ie)
71
72
  return;
72
- const t = re = H.prototype.raycast;
73
+ const t = ie = H.prototype.raycast;
73
74
  H.prototype.raycast = function(e, s) {
74
- const n = this, r = ye(n);
75
+ const n = this, r = me(n);
75
76
  let i;
76
77
  r && n.isMesh && (i = n.geometry, n.geometry = r), t.call(this, e, s), i && (n.geometry = i);
77
78
  };
78
79
  } else {
79
- if (!re)
80
+ if (!ie)
80
81
  return;
81
- H.prototype.raycast = re, re = null;
82
+ H.prototype.raycast = ie, ie = null;
82
83
  }
83
84
  }
84
- let re = null;
85
- function je(a) {
86
- const t = new de();
85
+ let ie = null;
86
+ function tt(a) {
87
+ const t = new ge();
87
88
  for (const e in a.attributes)
88
89
  t.setAttribute(e, a.getAttribute(e));
89
90
  return t.setIndex(a.getIndex()), t;
90
91
  }
91
- const Y = new Array(), V = "NEEDLE_progressive", x = oe("debugprogressive"), Le = Symbol("needle-progressive-texture"), ne = /* @__PURE__ */ new Map(), ve = /* @__PURE__ */ new Set();
92
+ const Y = new Array(), V = "NEEDLE_progressive", x = le("debugprogressive"), Me = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), Oe = /* @__PURE__ */ new Set();
92
93
  if (x) {
93
94
  let a = function() {
94
- t += 1, console.log("Toggle LOD level", t, ne), ne.forEach((n, r) => {
95
+ t += 1, console.log("Toggle LOD level", t, oe), oe.forEach((n, r) => {
95
96
  for (const i of n.keys) {
96
97
  const o = r[i];
97
98
  if (o != null) {
@@ -107,7 +108,7 @@ if (x) {
107
108
  }), t >= e && (t = -1);
108
109
  }, t = -1, e = 2, s = !1;
109
110
  window.addEventListener("keyup", (n) => {
110
- n.key === "p" && a(), n.key === "w" && (s = !s, ve && ve.forEach((r) => {
111
+ n.key === "p" && a(), n.key === "w" && (s = !s, Oe && Oe.forEach((r) => {
111
112
  r.name != "BackgroundCubeMaterial" && r.glyphMap == null && "wireframe" in r && (r.wireframe = s);
112
113
  }));
113
114
  });
@@ -116,8 +117,8 @@ function Te(a, t, e) {
116
117
  var n;
117
118
  if (!x)
118
119
  return;
119
- ne.has(a) || ne.set(a, { keys: [], sourceId: e });
120
- const s = ne.get(a);
120
+ oe.has(a) || oe.set(a, { keys: [], sourceId: e });
121
+ const s = oe.get(a);
121
122
  ((n = s == null ? void 0 : s.keys) == null ? void 0 : n.includes(t)) == !1 && s.keys.push(t);
122
123
  }
123
124
  const v = class {
@@ -257,19 +258,29 @@ const v = class {
257
258
  x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
258
259
  return Promise.resolve(null);
259
260
  }
260
- /** Load a different resolution of a texture (if available)
261
- * @param context the context
262
- * @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
263
- * @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
264
- * @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
265
- * @returns a promise that resolves to the material or texture with the requested LOD level
266
- */
267
261
  static assignTextureLOD(t, e = 0) {
268
262
  if (!t)
269
263
  return Promise.resolve(null);
264
+ if (t.isMesh === !0) {
265
+ const s = t;
266
+ if (Array.isArray(s.material)) {
267
+ const n = new Array();
268
+ for (const r of s.material) {
269
+ const i = this.assignTextureLOD(r, e);
270
+ n.push(i);
271
+ }
272
+ return Promise.all(n).then((r) => {
273
+ const i = new Array();
274
+ for (const o of r)
275
+ Array.isArray(o) && i.push(...o);
276
+ return i;
277
+ });
278
+ } else
279
+ return this.assignTextureLOD(s.material, e);
280
+ }
270
281
  if (t instanceof ze || t.isMaterial === !0) {
271
282
  const s = t, n = [], r = new Array();
272
- if (x && ve.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
283
+ if (x && Oe.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
273
284
  const i = s;
274
285
  for (const o of Object.keys(i.uniforms)) {
275
286
  const l = i.uniforms[o].value;
@@ -295,7 +306,7 @@ const v = class {
295
306
  return o;
296
307
  });
297
308
  }
298
- if (t instanceof te || t.isTexture === !0) {
309
+ if (t instanceof se || t.isTexture === !0) {
299
310
  const s = t;
300
311
  return this.assignTextureLODForSlot(s, e, null, null);
301
312
  }
@@ -372,7 +383,7 @@ const v = class {
372
383
  let i;
373
384
  if (t.isTexture === !0) {
374
385
  const g = t;
375
- g.source && g.source[Le] && (i = g.source[Le]);
386
+ g.source && g.source[Me] && (i = g.source[Me]);
376
387
  }
377
388
  if (i || (i = v.lodInfos.get(r)), i) {
378
389
  if (e > 0) {
@@ -384,7 +395,7 @@ const v = class {
384
395
  const g = Array.isArray(i.lods) ? (o = i.lods[e]) == null ? void 0 : o.path : i.lods;
385
396
  if (!g)
386
397
  return x && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
387
- const p = Je(n.url, g);
398
+ const p = Ze(n.url, g);
388
399
  if (p.endsWith(".glb") || p.endsWith(".gltf")) {
389
400
  if (!i.guid)
390
401
  return console.warn("missing pointer for glb/gltf texture", i), null;
@@ -393,11 +404,11 @@ const v = class {
393
404
  s && console.log(`LOD ${e} was already loading/loaded: ${M}`);
394
405
  let h = await w.catch(($) => (console.error(`Error loading LOD ${e} from ${p}
395
406
  `, $), null)), B = !1;
396
- if (h == null || (h instanceof te && t instanceof te ? (l = h.image) != null && l.data || (u = h.source) != null && u.data ? h = this.copySettings(t, h) : (B = !0, this.previouslyLoaded.delete(M)) : h instanceof de && t instanceof de && ((c = h.attributes.position) != null && c.array || (B = !0, this.previouslyLoaded.delete(M)))), !B)
407
+ if (h == null || (h instanceof se && t instanceof se ? (l = h.image) != null && l.data || (u = h.source) != null && u.data ? h = this.copySettings(t, h) : (B = !0, this.previouslyLoaded.delete(M)) : h instanceof ge && t instanceof ge && ((c = h.attributes.position) != null && c.array || (B = !0, this.previouslyLoaded.delete(M)))), !B)
397
408
  return h;
398
409
  }
399
410
  const L = i, F = new Promise(async (h, B) => {
400
- const $ = new Xe();
411
+ const $ = new qe();
401
412
  Ie($), x && (await new Promise((A) => setTimeout(A, 1e3)), s && console.warn("Start loading (delayed) " + p, L.guid));
402
413
  let I = p;
403
414
  if (L && Array.isArray(L.lods)) {
@@ -408,7 +419,7 @@ const v = class {
408
419
  `, A), null));
409
420
  if (!S)
410
421
  return null;
411
- const q = S.parser;
422
+ const X = S.parser;
412
423
  s && console.log("Loading finished " + p, L.guid);
413
424
  let T = 0;
414
425
  if (S.parser.json.textures) {
@@ -424,8 +435,8 @@ const v = class {
424
435
  T++;
425
436
  }
426
437
  if (A) {
427
- let f = await q.getDependency("texture", T);
428
- return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof te && (f = this.copySettings(t, f)), f && (f.guid = L.guid), h(f);
438
+ let f = await X.getDependency("texture", T);
439
+ return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof se && (f = this.copySettings(t, f)), f && (f.guid = L.guid), h(f);
429
440
  } else
430
441
  x && console.warn("Could not find texture with guid", L.guid, S.parser.json);
431
442
  }
@@ -442,7 +453,7 @@ const v = class {
442
453
  T++;
443
454
  }
444
455
  if (A) {
445
- const f = await q.getDependency("mesh", T), y = L;
456
+ const f = await X.getDependency("mesh", T), y = L;
446
457
  if (s && console.log(`Loaded Mesh "${f.name}"`, p, T, f, M), f.isMesh === !0) {
447
458
  const O = f.geometry;
448
459
  return v.assignLODInformation(n.url, O, r, e, void 0, y.density), h(O);
@@ -451,8 +462,8 @@ const v = class {
451
462
  for (let b = 0; b < f.children.length; b++) {
452
463
  const E = f.children[b];
453
464
  if (E.isMesh === !0) {
454
- const X = E.geometry;
455
- v.assignLODInformation(n.url, X, r, e, b, y.density), O.push(X);
465
+ const q = E.geometry;
466
+ v.assignLODInformation(n.url, q, r, e, b, y.density), O.push(q);
456
467
  }
457
468
  }
458
469
  return h(O);
@@ -463,7 +474,7 @@ const v = class {
463
474
  return h(null);
464
475
  });
465
476
  return this.previouslyLoaded.set(M, F), await F;
466
- } else if (t instanceof te) {
477
+ } else if (t instanceof se) {
467
478
  s && console.log("Load texture from uri: " + p);
468
479
  const w = await new Ve().loadAsync(p);
469
480
  return w ? (w.guid = i.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = t.colorSpace, s && console.log(i, w)) : x && console.warn("failed loading", p), w;
@@ -476,7 +487,7 @@ const v = class {
476
487
  if (!e)
477
488
  return;
478
489
  e.userData || (e.userData = {});
479
- const o = new et(t, s, n, r, i);
490
+ const o = new st(t, s, n, r, i);
480
491
  e.userData.LODS = o;
481
492
  }
482
493
  static getAssignedLODInformation(t) {
@@ -499,7 +510,7 @@ d(_, "registerTexture", (t, e, s, n, r) => {
499
510
  x && console.error("gltf-progressive: Register texture without texture");
500
511
  return;
501
512
  }
502
- e.source && (e.source[Le] = r);
513
+ e.source && (e.source[Me] = r);
503
514
  const i = r.guid;
504
515
  v.assignLODInformation(t, e, i, s, n, void 0), v.lodInfos.set(i, r), v.lowresCache.set(i, e);
505
516
  }), /**
@@ -515,14 +526,14 @@ d(_, "registerMesh", (t, e, s, n, r, i) => {
515
526
  }
516
527
  o.userData || (o.userData = {}), v.assignLODInformation(t, o, e, n, r, i.density), v.lodInfos.set(e, i);
517
528
  let l = v.lowresCache.get(e);
518
- l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !ye(s) && Ze(s, o);
529
+ l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !me(s) && et(s, o);
519
530
  for (const c of Y)
520
531
  (u = c.onRegisteredNewMesh) == null || u.call(c, s, i);
521
532
  }), /** A map of key = asset uuid and value = LOD information */
522
533
  d(_, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
523
534
  d(_, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
524
535
  d(_, "lowresCache", /* @__PURE__ */ new Map());
525
- class et {
536
+ class st {
526
537
  constructor(t, e, s, n, r) {
527
538
  d(this, "url");
528
539
  /** the key to lookup the LOD information */
@@ -535,8 +546,8 @@ class et {
535
546
  this.url = t, this.key = e, this.level = s, n != null && (this.index = n), r != null && (this.density = r);
536
547
  }
537
548
  }
538
- const k = oe("debugprogressive"), tt = oe("noprogressive"), Me = Symbol("Needle:LODSManager"), De = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), R = { mesh_lod: -1, texture_lod: -1 };
539
- var C, N, ge, j, ee, pe, W;
549
+ const k = le("debugprogressive"), rt = le("noprogressive"), De = Symbol("Needle:LODSManager"), we = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), R = { mesh_lod: -1, texture_lod: -1 };
550
+ var C, N, pe, ee, te, ye, W;
540
551
  const P = class {
541
552
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
542
553
  constructor(t, e) {
@@ -567,14 +578,14 @@ const P = class {
567
578
  d(this, "manual", !1);
568
579
  d(this, "_lodchangedlisteners", []);
569
580
  K(this, N, void 0);
570
- K(this, ge, new Ne());
571
- K(this, j, 0);
581
+ K(this, pe, new Ne());
572
582
  K(this, ee, 0);
573
- K(this, pe, 0);
583
+ K(this, te, 0);
584
+ K(this, ye, 0);
574
585
  K(this, W, 0);
575
586
  d(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
576
587
  // private testIfLODLevelsAreAvailable() {
577
- d(this, "_sphere", new qe());
588
+ d(this, "_sphere", new Xe());
578
589
  d(this, "_tempBox", new be());
579
590
  d(this, "_tempBox2", new be());
580
591
  d(this, "tempMatrix", new Se());
@@ -585,7 +596,7 @@ const P = class {
585
596
  }
586
597
  /** @internal */
587
598
  static getObjectLODState(t) {
588
- return t[De];
599
+ return t[we];
589
600
  }
590
601
  static addPlugin(t) {
591
602
  Y.push(t);
@@ -600,13 +611,13 @@ const P = class {
600
611
  * @returns The LODsManager instance.
601
612
  */
602
613
  static get(t, e) {
603
- if (t[Me])
604
- return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[Me];
614
+ if (t[De])
615
+ return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[De];
605
616
  const s = new P(t, {
606
617
  engine: "unknown",
607
618
  ...e
608
619
  });
609
- return t[Me] = s, s;
620
+ return t[De] = s, s;
610
621
  }
611
622
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
612
623
  get plugins() {
@@ -633,7 +644,7 @@ const P = class {
633
644
  const e = this;
634
645
  Be(this.renderer), this.renderer.render = function(s, n) {
635
646
  const r = e.renderer.getRenderTarget();
636
- (r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e, j, m(e, j) + 1), U(e, ee, m(e, ge).getDelta()), U(e, pe, m(e, pe) + m(e, ee)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, ee)), U(e, W, e._fpsBuffer.reduce((o, l) => o + l) / e._fpsBuffer.length), k && m(e, j) % 200 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
647
+ (r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e, ee, m(e, ee) + 1), U(e, te, m(e, pe).getDelta()), U(e, ye, m(e, ye) + m(e, te)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, te)), U(e, W, e._fpsBuffer.reduce((o, l) => o + l) / e._fpsBuffer.length), k && m(e, ee) % 200 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
637
648
  const i = t++;
638
649
  m(e, N).call(this, s, n), e.onAfterRender(s, n, i);
639
650
  };
@@ -654,7 +665,7 @@ const P = class {
654
665
  (o.name === "EffectMaterial" || o.name === "CopyShader") && (i = !1);
655
666
  }
656
667
  if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
657
- if (tt || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? (U(this, C, m(this, C) + 1), k && console.warn("↓ Reducing LOD updates", m(this, C), m(this, W).toFixed(0))) : m(this, W) >= 60 && m(this, C) > 1 && (U(this, C, m(this, C) - 1), k && console.warn("↑ Increasing LOD updates", m(this, C), m(this, W).toFixed(0))) : U(this, C, this.updateInterval), m(this, C) > 0 && m(this, j) % m(this, C) != 0))
668
+ if (rt || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? (U(this, C, m(this, C) + 1), k && console.warn("↓ Reducing LOD updates", m(this, C), m(this, W).toFixed(0))) : m(this, W) >= 60 && m(this, C) > 1 && (U(this, C, m(this, C) - 1), k && console.warn("↑ Increasing LOD updates", m(this, C), m(this, W).toFixed(0))) : U(this, C, this.updateInterval), m(this, C) > 0 && m(this, ee) % m(this, C) != 0))
658
669
  return;
659
670
  this.internalUpdate(t, e);
660
671
  }
@@ -704,8 +715,8 @@ const P = class {
704
715
  updateLODs(t, e, s, n) {
705
716
  var o, l;
706
717
  s.userData || (s.userData = {});
707
- let r = s[De];
708
- if (r || (r = new st(), s[De] = r), r.frames++ < 2)
718
+ let r = s[we];
719
+ if (r || (r = new it(), s[we] = r), r.frames++ < 2)
709
720
  return;
710
721
  for (const u of Y)
711
722
  (o = u.onBeforeUpdateLOD) == null || o.call(u, this.renderer, t, e, s);
@@ -783,7 +794,7 @@ const P = class {
783
794
  if (!D.boundingBox)
784
795
  D.computeBoundingBox();
785
796
  else if (s.frames % 30 === 0) {
786
- const h = ye(D), B = D.geometry;
797
+ const h = me(D), B = D.geometry;
787
798
  h && (D.geometry = h), D.computeBoundingBox(), D.geometry = B;
788
799
  }
789
800
  L = D.boundingBox;
@@ -804,11 +815,11 @@ const P = class {
804
815
  }
805
816
  if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && D.fov > 70) {
806
817
  const f = this._tempBox.min, y = this._tempBox.max;
807
- let O = f.x, b = f.y, E = y.x, X = y.y;
808
- const ae = 2, me = 1.5, le = (f.x + y.x) * 0.5, ce = (f.y + y.y) * 0.5;
809
- O = (O - le) * ae + le, b = (b - ce) * ae + ce, E = (E - le) * ae + le, X = (X - ce) * ae + ce;
810
- const Ge = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), Fe = b < 0 && X > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), xe = Math.max(Ge, Fe);
811
- s.lastCentrality = (me - xe) * (me - xe) * (me - xe);
818
+ let O = f.x, b = f.y, E = y.x, q = y.y;
819
+ const ce = 2, xe = 1.5, ue = (f.x + y.x) * 0.5, fe = (f.y + y.y) * 0.5;
820
+ O = (O - ue) * ce + ue, b = (b - fe) * ce + fe, E = (E - ue) * ce + ue, q = (q - fe) * ce + fe;
821
+ const Ge = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), Fe = b < 0 && q > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), Le = Math.max(Ge, Fe);
822
+ s.lastCentrality = (xe - Le) * (xe - Le) * (xe - Le);
812
823
  } else
813
824
  s.lastCentrality = 1;
814
825
  const h = this._tempBox.getSize(this._tempBoxSize);
@@ -821,8 +832,8 @@ const P = class {
821
832
  f.invert();
822
833
  const y = P.corner0, O = P.corner1, b = P.corner2, E = P.corner3;
823
834
  y.copy(this._tempBox.min), O.copy(this._tempBox.max), O.x = y.x, b.copy(this._tempBox.max), b.y = y.y, E.copy(this._tempBox.max);
824
- const X = (y.z + E.z) * 0.5;
825
- y.z = O.z = b.z = E.z = X, y.applyMatrix4(f), O.applyMatrix4(f), b.applyMatrix4(f), E.applyMatrix4(f), P.debugDrawLine(y, O, 255), P.debugDrawLine(y, b, 255), P.debugDrawLine(O, E, 255), P.debugDrawLine(b, E, 255);
835
+ const q = (y.z + E.z) * 0.5;
836
+ y.z = O.z = b.z = E.z = q, y.applyMatrix4(f), O.applyMatrix4(f), b.applyMatrix4(f), E.applyMatrix4(f), P.debugDrawLine(y, O, 255), P.debugDrawLine(y, b, 255), P.debugDrawLine(O, E, 255), P.debugDrawLine(b, E, 255);
826
837
  }
827
838
  let T = 999;
828
839
  if (c && s.lastScreenCoverage > 0) {
@@ -851,10 +862,10 @@ const P = class {
851
862
  ((F = this.context) == null ? void 0 : F.engine) === "model-viewer" && (B *= 2);
852
863
  const I = w / window.devicePixelRatio * B;
853
864
  for (let S = p.lods.length - 1; S >= 0; S--) {
854
- let q = p.lods[S];
855
- if (!(D && q.max_height >= 2048) && !(Qe() && q.max_height > 4096) && q.max_height > I) {
865
+ let X = p.lods[S];
866
+ if (!(D && X.max_height >= 2048) && !(je() && X.max_height > 4096) && X.max_height > I) {
856
867
  if (r.texture_lod = S, r.texture_lod < s.lastLodLevel_Texture) {
857
- const T = q.max_height;
868
+ const T = X.max_height;
858
869
  k && console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${T}px
859
870
  Screensize: ${I.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
860
871
  ${e.name}`);
@@ -868,10 +879,10 @@ ${e.name}`);
868
879
  }
869
880
  };
870
881
  let G = P;
871
- C = new WeakMap(), N = new WeakMap(), ge = new WeakMap(), j = new WeakMap(), ee = 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.
882
+ C = new WeakMap(), N = new WeakMap(), pe = new WeakMap(), ee = new WeakMap(), te = new WeakMap(), ye = 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.
872
883
  */
873
884
  d(G, "debugDrawLine"), d(G, "corner0", new z()), d(G, "corner1", new z()), d(G, "corner2", new z()), d(G, "corner3", new z()), d(G, "_tempPtInside", new z());
874
- class st {
885
+ class it {
875
886
  constructor() {
876
887
  d(this, "frames", 0);
877
888
  d(this, "lastLodLevel_Mesh", -1);
@@ -881,21 +892,21 @@ class st {
881
892
  d(this, "lastCentrality", 0);
882
893
  }
883
894
  }
884
- const Ae = Symbol("NEEDLE_mesh_lod"), ue = Symbol("NEEDLE_texture_lod");
885
- let ie = null;
895
+ const Ae = Symbol("NEEDLE_mesh_lod"), de = Symbol("NEEDLE_texture_lod");
896
+ let ne = null;
886
897
  function ke() {
887
- const a = rt();
898
+ const a = nt();
888
899
  a && (a.mapURLs(function(t) {
889
900
  return Ee(), t;
890
- }), Ee(), ie == null || ie.disconnect(), ie = new MutationObserver((t) => {
901
+ }), Ee(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
891
902
  t.forEach((e) => {
892
903
  e.addedNodes.forEach((s) => {
893
904
  s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Re(s);
894
905
  });
895
906
  });
896
- }), ie.observe(document, { childList: !0, subtree: !0 }));
907
+ }), ne.observe(document, { childList: !0, subtree: !0 }));
897
908
  }
898
- function rt() {
909
+ function nt() {
899
910
  if (typeof customElements > "u")
900
911
  return null;
901
912
  const a = customElements.get("model-viewer");
@@ -911,11 +922,11 @@ function Ee() {
911
922
  });
912
923
  }
913
924
  const Pe = /* @__PURE__ */ new WeakSet();
914
- let it = 0;
925
+ let ot = 0;
915
926
  function Re(a) {
916
927
  if (!a || Pe.has(a))
917
928
  return null;
918
- Pe.add(a), console.debug("[gltf-progressive] found new model-viewer..." + ++it + `
929
+ Pe.add(a), console.debug("[gltf-progressive] found new model-viewer..." + ++ot + `
919
930
  `, a.getAttribute("src"));
920
931
  let t = null, e = null, s = null;
921
932
  for (let n = a; n != null; n = Object.getPrototypeOf(n)) {
@@ -936,7 +947,7 @@ function Re(a) {
936
947
  };
937
948
  console.debug("[gltf-progressive] setup model-viewer");
938
949
  const r = G.get(t, { engine: "model-viewer" });
939
- return G.addPlugin(new nt()), r.enable(), r.addEventListener("changed", () => {
950
+ return G.addPlugin(new at()), r.enable(), r.addEventListener("changed", () => {
940
951
  s == null || s.call(a);
941
952
  }), a.addEventListener("model-visibility", (i) => {
942
953
  i.detail.visible && (s == null || s.call(a));
@@ -948,7 +959,7 @@ function Re(a) {
948
959
  }
949
960
  return null;
950
961
  }
951
- class nt {
962
+ class at {
952
963
  constructor() {
953
964
  d(this, "_didWarnAboutMissingUrl", !1);
954
965
  }
@@ -968,16 +979,16 @@ class nt {
968
979
  return t.element;
969
980
  }
970
981
  tryParseTextureLOD(t, e) {
971
- if (e[ue] == !0)
982
+ if (e[de] == !0)
972
983
  return;
973
- e[ue] = !0;
984
+ e[de] = !0;
974
985
  const s = this.tryGetCurrentGLTF(t), n = this.tryGetCurrentModelViewer(t), r = this.getUrl(n);
975
986
  if (r && s && e.material) {
976
987
  let i = function(l) {
977
988
  var c, g, p;
978
- if (l[ue] == !0)
989
+ if (l[de] == !0)
979
990
  return;
980
- l[ue] = !0, l.userData && (l.userData.LOD = -1);
991
+ l[de] = !0, l.userData && (l.userData.LOD = -1);
981
992
  const u = Object.keys(l);
982
993
  for (let M = 0; M < u.length; M++) {
983
994
  const w = u[M], L = l[w];
@@ -1020,7 +1031,7 @@ class nt {
1020
1031
  }
1021
1032
  }
1022
1033
  }
1023
- function pt(a, t, e, s) {
1034
+ function mt(a, t, e, s) {
1024
1035
  Be(t), Ie(e), e.register((r) => new _(r, a));
1025
1036
  const n = G.get(t);
1026
1037
  return (s == null ? void 0 : s.enableLODsManager) !== !1 && n.enable(), n;
@@ -1033,11 +1044,11 @@ export {
1033
1044
  Ce as VERSION,
1034
1045
  Ie as addDracoAndKTX2Loaders,
1035
1046
  Be as createLoaders,
1036
- ye as getRaycastMesh,
1047
+ me as getRaycastMesh,
1037
1048
  ke as patchModelViewer,
1038
- Ze as registerRaycastMesh,
1039
- dt as setDracoDecoderLocation,
1040
- ht as setKTX2TranscoderLocation,
1041
- pt as useNeedleProgressive,
1042
- gt as useRaycastMeshes
1049
+ et as registerRaycastMesh,
1050
+ gt as setDracoDecoderLocation,
1051
+ pt as setKTX2TranscoderLocation,
1052
+ mt as useNeedleProgressive,
1053
+ yt as useRaycastMeshes
1043
1054
  };
@@ -1,8 +1,8 @@
1
- var Re=Object.defineProperty,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ie,Mesh as q,Material as Ge,Texture as Q,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let le="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(le+"draco_decoder.js",{method:"head"}).catch(t=>{le="./include/draco/",me="./include/ktx2/"});function Xe(t){le=t}function Ke(t){me=t}let K,ae,H;function pe(t){return K||(K=new Ve,K.setDecoderPath(le),K.setDecoderConfig({type:"js"})),H||(H=new qe,H.setTranscoderPath(me)),ae||(ae=ze),t?H.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:H,meshoptDecoder:ae}}function ve(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(H),t.meshoptDecoder||t.setMeshoptDecoder(ae)}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 He(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function Ye(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const xe=Symbol("needle:raycast-mesh");function ee(t){return t?.[xe]instanceof ie?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=Qe(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Je(t=!0){if(t){if(te)return;const e=te=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=ee(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!te)return;q.prototype.raycast=te,te=null}}let te=null;function Qe(t){const e=new ie;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,R="NEEDLE_progressive",y=Z("debugprogressive"),ye=Symbol("needle-progressive-texture"),re=new Map,Le=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,re),re.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null){if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!y)return;re.has(t)||re.set(t,{keys:[],sourceId:r});const s=re.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[R];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,y&&Ee(t,"geometry",s.url)):y&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),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 Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(y&&Le.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof Q||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(y&&n&&r){const o=this.getAssignedLODInformation(t);o&&Ee(r,n,o.url)}}return s}else y=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[R];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[R];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=y=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const f=t;f.source&&f.source[ye]&&(l=f.source[ye])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return y&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=He(a.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
2
- `,O),null)),_=!1;if(d==null||(d instanceof Q&&t instanceof Q?(n=d.image)!=null&&n.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(_=!0,this.previouslyLoaded.delete(p)):d instanceof ie&&t instanceof ie&&((o=d.attributes.position)!=null&&o.array||(_=!0,this.previouslyLoaded.delete(p)))),!_)return d}const D=l,L=new Promise(async(d,_)=>{const O=new Ue;ve(O),y&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let I=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(I+="?v="+m.hash)}const T=await O.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
3
- `,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let v=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){let h=await W.getDependency("texture",v);return h&&w.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,v,h,p),t instanceof Q&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else y&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(v=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){const h=await W.getDependency("mesh",v),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,v,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(a.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(a.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else y&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Q){i&&console.log("Load texture from uri: "+g);const p=await new Ne().loadAsync(g);return p?(p.guid=l.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(l,p)):y&&console.warn("failed loading",g),p}}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,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new Ze(t,r,n,s,o);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,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ae,Mesh as q,Material as Ge,Texture as Z,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let K="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Xe=K,Ke=ee;fetch(K+"draco_decoder.js",{method:"head"}).catch(t=>{K===Xe&&(K="./include/draco/"),ee===Ke&&(ee="./include/ktx2/")});function He(t){K=t}function Ye(t){ee=t}let H,ue,Y;function pe(t){return H||(H=new Ve,H.setDecoderPath(K),H.setDecoderConfig({type:"js"})),Y||(Y=new qe,Y.setTranscoderPath(ee)),ue||(ue=ze),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:H,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(H),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}te("debugprogressive");function te(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 r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ce;function Qe(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const xe=Symbol("needle:raycast-mesh");function re(t){return t?.[xe]instanceof ae?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Ze(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=re(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function et(t){const e=new ae;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,R="NEEDLE_progressive",v=te("debugprogressive"),ve=Symbol("needle-progressive-texture"),oe=new Map,Le=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,oe),oe.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null){if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!v)return;oe.has(t)||oe.set(t,{keys:[],sourceId:r});const s=oe.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[R];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null}),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ee(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t instanceof Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&Le.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o&&Ee(r,n,o.url)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[R];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[R];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const f=t;f.source&&f.source[ve]&&(l=f.source[ve])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Je(a.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
2
+ `,O),null)),_=!1;if(d==null||(d instanceof Z&&t instanceof Z?(n=d.image)!=null&&n.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(_=!0,this.previouslyLoaded.delete(p)):d instanceof ae&&t instanceof ae&&((o=d.attributes.position)!=null&&o.array||(_=!0,this.previouslyLoaded.delete(p)))),!_)return d}const D=l,L=new Promise(async(d,_)=>{const O=new Ue;ye(O),v&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let I=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(I+="?v="+m.hash)}const T=await O.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
3
+ `,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let y=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){let h=await W.getDependency("texture",y);return h&&w.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,y,h,p),t instanceof Z&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else v&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(y=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){const h=await W.getDependency("mesh",y),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,y,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(a.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(a.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else v&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Z){i&&console.log("Load texture from uri: "+g);const p=await new Ne().loadAsync(g);return p?(p.guid=l.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(l,p)):v&&console.warn("failed loading",g),p}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new tt(t,r,n,s,o);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(),v&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,n,s)=>{if(y&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(S,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){y&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!ee(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Ze{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=Z("debugprogressive"),et=Z("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),Y=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,J,se,ce,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,J,0),V(this,se,0),V(this,ce,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.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 F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(x(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,J,x(e,J)+1),G(e,se,x(e,we).getDelta()),G(e,ce,x(e,ce)+x(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,se)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,J)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(et||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,J)%x(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){P&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new tt,r[De]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[Y]===void 0||e<t[Y])&&(r=!0),r&&(t[Y]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[Y]!==e){t[Y]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[Y]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=ee(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const v=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(v)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const v=this._tempBox.min,m=this._tempBox.max;let h=v.x,M=v.y,b=m.x,C=m.y;const z=2,X=1.5,oe=(v.x+m.x)*.5,ne=(v.y+m.y)*.5;h=(h-oe)*z+oe,M=(M-ne)*z+ne,b=(b-oe)*z+oe,C=(C-ne)*z+ne;const ke=h<0&&b>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),fe=Math.max(ke,Ce);r.lastCentrality=(X-fe)*(X-fe)*(X-fe)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(v),h.applyMatrix4(v),M.applyMatrix4(v),b.applyMatrix4(v),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let v=0;v<l.length;v++)if(l[v].density/r.lastScreenCoverage<n){W=v;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Ye()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}px
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ve]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(S,"registerMesh",(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){v&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!re(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class tt{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=te("debugprogressive"),rt=te("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,Q,ne,de,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,Q,0),V(this,ne,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.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 F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(x(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,Q,x(e,Q)+1),G(e,ne,x(e,we).getDelta()),G(e,de,x(e,de)+x(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,ne)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,Q)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(rt||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,Q)%x(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){P&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new st,r[De]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const y=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const y=this._tempBox.min,m=this._tempBox.max;let h=y.x,M=y.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(y.x+m.x)*.5,le=(y.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-le)*z+le,b=(b-ie)*z+ie,C=(C-le)*z+le;const ke=h<0&&b>0?0:Math.min(Math.abs(y.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(m.y)),ge=Math.max(ke,Ce);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(y),h.applyMatrix4(y),M.applyMatrix4(y),b.applyMatrix4(y),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let y=0;y<l.length;y++)if(l[y].density/r.lastScreenCoverage<n){W=y;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Qe()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}px
6
6
  Screensize: ${O.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${d.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};let j=B;E=new WeakMap,$=new WeakMap,we=new WeakMap,J=new WeakMap,se=new WeakMap,ce=new WeakMap,U=new WeakMap,c(j,"debugDrawLine"),c(j,"corner0",new N),c(j,"corner1",new N),c(j,"corner2",new N),c(j,"corner3",new N),c(j,"_tempPtInside",new N);class tt{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new N),c(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let he=null;function _e(){const t=rt();t&&(t.mapURLs(function(e){return Ie(),e}),Ie(),he?.disconnect(),he=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&Pe(n)})})}),he.observe(document,{childList:!0,subtree:!0}))}function rt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),_e()}),null)}function Ie(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Pe(t)})}const Be=new WeakSet;let st=0;function Pe(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++st+`
8
- `,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new ot),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class ot{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[de]==!0)return;r[de]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var l,f,g;if(u[de]==!0)return;u[de]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(l=L.userData)==null?void 0:l.associations)==null?void 0:f.textures;if(d==null)continue;const _=n.parser.json.textures[d];if(!_){console.warn("Texture data not found for texture index "+d);continue}if((g=_?.extensions)!=null&&g[R]){const O=_.extensions[R];O&&o&&S.registerTexture(o,L,O.lods.length,d,O)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[Ae]==!0)return;r[Ae]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(a&&i){const u=r.uuid;S.registerMesh(i,u,r,0,a.lods.length,a)}}}function nt(t,e,r,n){pe(e),ve(r),r.register(o=>new S(o,t));const s=j.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}_e();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,ge as VERSION,ve as addDracoAndKTX2Loaders,pe as createLoaders,ee as getRaycastMesh,_e as patchModelViewer,Te as registerRaycastMesh,Xe as setDracoDecoderLocation,Ke as setKTX2TranscoderLocation,nt as useNeedleProgressive,Je as useRaycastMeshes};
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}};let j=B;E=new WeakMap,$=new WeakMap,we=new WeakMap,Q=new WeakMap,ne=new WeakMap,de=new WeakMap,U=new WeakMap,c(j,"debugDrawLine"),c(j,"corner0",new N),c(j,"corner1",new N),c(j,"corner2",new N),c(j,"corner3",new N),c(j,"_tempPtInside",new N);class st{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new N),c(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let fe=null;function _e(){const t=ot();t&&(t.mapURLs(function(e){return Ie(),e}),Ie(),fe?.disconnect(),fe=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&Pe(n)})})}),fe.observe(document,{childList:!0,subtree:!0}))}function ot(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),_e()}),null)}function Ie(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Pe(t)})}const Be=new WeakSet;let nt=0;function Pe(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++nt+`
8
+ `,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new it),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class it{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[he]==!0)return;r[he]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var l,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(l=L.userData)==null?void 0:l.associations)==null?void 0:f.textures;if(d==null)continue;const _=n.parser.json.textures[d];if(!_){console.warn("Texture data not found for texture index "+d);continue}if((g=_?.extensions)!=null&&g[R]){const O=_.extensions[R];O&&o&&S.registerTexture(o,L,O.lods.length,d,O)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[Ae]==!0)return;r[Ae]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(a&&i){const u=r.uuid;S.registerMesh(i,u,r,0,a.lods.length,a)}}}function lt(t,e,r,n){pe(e),ye(r),r.register(o=>new S(o,t));const s=j.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}_e();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,me as VERSION,ye as addDracoAndKTX2Loaders,pe as createLoaders,re as getRaycastMesh,_e as patchModelViewer,Te 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 ke=(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)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(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)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),De="";globalThis.GLTF_PROGRESSIVE_VERSION=De;console.debug(`[gltf-progressive] version ${De}`);let fe="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",we="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(fe+"draco_decoder.js",{method:"head"}).catch(a=>{fe="./include/draco/",we="./include/ktx2/"});function Ne(a){fe=a}function Ue(a){we=a}let J,ue,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(fe),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(we)),ue||(ue=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:ue}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(ue)}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 ze(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 ee;function We(){return ee!==void 0||(ee=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ie("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ee)),ee}const xe=Symbol("needle:raycast-mesh");function oe(a){return(a==null?void 0:a[xe])instanceof p.BufferGeometry?a[xe]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!oe(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[xe]=r}}function qe(a=!0){if(a){if(te)return;const t=te=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=oe(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!te)return;p.Mesh.prototype.raycast=te,te=null}}let te=null;function Xe(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ie("debugprogressive"),ye=Symbol("needle-progressive-texture"),se=new Map,Me=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,se),se.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,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,Me&&Me.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)return;se.has(a)||se.set(a,{keys:[],sourceId:e});const r=se.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const _=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[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const u=n.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&Me.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.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):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.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)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[ye]&&(i=g.source[ye])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=ze(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
1
+ "use strict";var Re=Object.defineProperty;var ke=(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)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(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)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let Z="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ne=Z,Ue=oe;fetch(Z+"draco_decoder.js",{method:"head"}).catch(a=>{Z===Ne&&(Z="./include/draco/"),oe===Ue&&(oe="./include/ktx2/")});function ze(a){Z=a}function We(a){oe=a}let J,de,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(Z),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(oe)),de||(de=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:de}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(de)}ne("debugprogressive");function ne(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function qe(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 te;function Xe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ae(a){return(a==null?void 0:a[Me])instanceof p.BufferGeometry?a[Me]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ae(a)){const r=Ye(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(re)return;const t=re=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=ae(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!re)return;p.Mesh.prototype.raycast=re,re=null}}let re=null;function Ye(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),me=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,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(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)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 _=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[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const u=n.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const i=this.assignTextureLOD(s,e);o.push(i)}return Promise.all(o).then(s=>{const i=new Array;for(const n of s)Array.isArray(n)&&i.push(...n);return i})}else return this.assignTextureLOD(r.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.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):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.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)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[me]&&(i=g.source[me])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=qe(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
2
2
  `,$),null)),R=!1;if(h==null||(h instanceof p.Texture&&t instanceof p.Texture?(l=h.image)!=null&&l.data||(u=h.source)!=null&&u.data?h=this.copySettings(t,h):(R=!0,this.previouslyLoaded.delete(D)):h instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=h.attributes.position)!=null&&c.array||(R=!0,this.previouslyLoaded.delete(D)))),!R)return h}const M=i,F=new Promise(async(h,R)=>{const $=new Ge.GLTFLoader;_e($),x&&(await new Promise(E=>setTimeout(E,1e3)),r&&console.warn("Start loading (delayed) "+y,M.guid));let k=y;if(M&&Array.isArray(M.lods)){const E=M.lods[e];E.hash&&(k+="?v="+E.hash)}const b=await $.loadAsync(k).catch(E=>(console.error(`Error loading LOD ${e} from ${y}
3
- `,E),null));if(!b)return null;const q=b.parser;r&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(r&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,s,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,s,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,F),await F}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,i){if(!e)return;e.userData||(e.userData={});const n=new Ke(t,r,o,s,i);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(),x&&console.warn(`Copying texture settings
3
+ `,E),null));if(!b)return null;const q=b.parser;r&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(r&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,s,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,s,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,F),await F}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,i){if(!e)return;e.userData||(e.userData={});const n=new He(t,r,o,s,i);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(),x&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=_;d(O,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=s);const i=s.guid;_.assignLODInformation(t,e,i,r,o,void 0),_.lodInfos.set(i,s),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,r,o,s,i)=>{var u;x&&console.log("> Progressive: register mesh",s,r.name,i,r.uuid,r);const n=r.geometry;if(!n){x&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),_.assignLODInformation(t,n,e,o,s,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],_.lowresCache.set(e,l),o>0&&!oe(r)&&Pe(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Ke{constructor(t,e,r,o,s){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),s!=null&&(this.density=s)}}const G=ie("debugprogressive"),Ye=ie("noprogressive"),me=Symbol("Needle:LODSManager"),Le=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),V={mesh_lod:-1,texture_lod:-1};var B,z,de,Z,j,he,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,de,new p.Clock);K(this,Z,0);K(this,j,0);K(this,he,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Le]}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 C(t,{engine:"unknown",...e});return t[me]=r,r}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+1),N(e,j,L(e,de).getDelta()),N(e,he,L(e,he)+L(e,j)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,j)),N(e,W,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),G&&L(e,Z)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,z)&&(this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(s.length===1){const n=s[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Ye||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,Z)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const c of o){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){G&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const i=r.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const n=r.transmissive;for(const c of n){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[Le];if(s||(s=new He,r[Le]=s),s.frames++<2)return;for(const u of Y)(n=u.onBeforeUpdateLOD)==null||n.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,o,V),V.mesh_lod=Math.round(V.mesh_lod),V.texture_lod=Math.round(V.texture_lod),V.mesh_lod>=0&&this.loadProgressiveMeshes(r,V.mesh_lod);let i=V.texture_lod;if(r.material&&i>=0){const u=r["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(r.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,V);s.lastLodLevel_Mesh=V.mesh_lod,s.lastLodLevel_Texture=V.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,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,i=(r.y+o.y)*.5;return this._tempPtInside.set(s,i,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var F;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let n=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){s.mesh_lod=0,s.texture_lod=0;return}g||(l=!0,n=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(r.frames%30===0){const h=oe(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const ne=2,ge=1.5,ae=(f.x+m.x)*.5,le=(f.y+m.y)*.5;S=(S-ae)*ne+ae,T=(T-le)*ne+le,P=(P-ae)*ne+ae,X=(X-le)*ne+le;const Be=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ie=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),pe=Math.max(Be,Ie);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&r.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/r.lastScreenCoverage<o){A=f;break}}A<n&&(n=A,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const h=c==null?void 0:c[s.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let R=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(We()&&q.max_height>4096)&&q.max_height>k){if(s.texture_lod=b,s.texture_lod<r.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${A}px
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=_;d(O,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[me]=s);const i=s.guid;_.assignLODInformation(t,e,i,r,o,void 0),_.lodInfos.set(i,s),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,r,o,s,i)=>{var u;x&&console.log("> Progressive: register mesh",s,r.name,i,r.uuid,r);const n=r.geometry;if(!n){x&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),_.assignLODInformation(t,n,e,o,s,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],_.lowresCache.set(e,l),o>0&&!ae(r)&&Pe(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class He{constructor(t,e,r,o,s){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),s!=null&&(this.density=s)}}const G=ne("debugprogressive"),Je=ne("noprogressive"),Le=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),V={mesh_lod:-1,texture_lod:-1};var B,z,he,j,ee,ge,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,he,new p.Clock);K(this,j,0);K(this,ee,0);K(this,ge,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[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[Le])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Le];const r=new C(t,{engine:"unknown",...e});return t[Le]=r,r}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,N(e,j,L(e,j)+1),N(e,ee,L(e,he).getDelta()),N(e,ge,L(e,ge)+L(e,ee)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,ee)),N(e,W,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),G&&L(e,j)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,z)&&(this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(s.length===1){const n=s[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Je||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,j)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const c of o){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){G&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const i=r.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const n=r.transmissive;for(const c of n){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[xe];if(s||(s=new Qe,r[xe]=s),s.frames++<2)return;for(const u of Y)(n=u.onBeforeUpdateLOD)==null||n.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,o,V),V.mesh_lod=Math.round(V.mesh_lod),V.texture_lod=Math.round(V.texture_lod),V.mesh_lod>=0&&this.loadProgressiveMeshes(r,V.mesh_lod);let i=V.texture_lod;if(r.material&&i>=0){const u=r["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(r.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,V);s.lastLodLevel_Mesh=V.mesh_lod,s.lastLodLevel_Texture=V.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,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,i=(r.y+o.y)*.5;return this._tempPtInside.set(s,i,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var F;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let n=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){s.mesh_lod=0,s.texture_lod=0;return}g||(l=!0,n=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(r.frames%30===0){const h=ae(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const le=2,pe=1.5,ce=(f.x+m.x)*.5,ue=(f.y+m.y)*.5;S=(S-ce)*le+ce,T=(T-ue)*le+ue,P=(P-ce)*le+ce,X=(X-ue)*le+ue;const Be=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ie=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max(Be,Ie);r.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&r.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/r.lastScreenCoverage<o){A=f;break}}A<n&&(n=A,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const h=c==null?void 0:c[s.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let R=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(Xe()&&q.max_height>4096)&&q.max_height>k){if(s.texture_lod=b,s.texture_lod<r.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${A}px
6
6
  Screensize: ${k.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};let I=C;B=new WeakMap,z=new WeakMap,de=new WeakMap,Z=new WeakMap,j=new WeakMap,he=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new p.Vector3),d(I,"corner1",new p.Vector3),d(I,"corner2",new p.Vector3),d(I,"corner3",new p.Vector3),d(I,"_tempPtInside",new p.Vector3);class He{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const Te=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let re=null;function Oe(){const a=Je();a&&(a.mapURLs(function(t){return Ae(),t}),Ae(),re==null||re.disconnect(),re=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ce(r)})})}),re.observe(document,{childList:!0,subtree:!0}))}function Je(){if(typeof customElements>"u")return null;const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Ae(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Ee=new WeakSet;let Qe=0;function Ce(a){if(!a||Ee.has(a))return null;Ee.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 s=Object.getOwnPropertySymbols(o),i=s.find(u=>u.toString()=="Symbol(renderer)"),n=s.find(u=>u.toString()=="Symbol(scene)"),l=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=a[i].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let o=function(){if(r){let i=0,n=setInterval(()=>{if(i++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=I.get(t,{engine:"model-viewer"});return I.addPlugin(new Ze),s.enable(),s.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",i=>{i.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{o()}),()=>{s.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),s=this.getUrl(o);if(s&&r&&e.material){let i=function(l){var c,g,y;if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let D=0;D<u.length;D++){const v=u[D],M=l[v];if((M==null?void 0:M.isTexture)===!0){const F=(g=(c=M.userData)==null?void 0:c.associations)==null?void 0:g.textures;if(F==null)continue;const w=r.parser.json.textures[F];if(!w){console.warn("Texture data not found for texture index "+F);continue}if((y=w==null?void 0:w.extensions)!=null&&y[U]){const h=w.extensions[U];h&&s&&O.registerTexture(s,M,h.lods.length,F,h)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)i(l);else i(n)}}tryParseMeshLOD(t,e){var i,n;if(e[Te]==!0)return;e[Te]=!0;const r=this.tryGetCurrentModelViewer(t),o=this.getUrl(r);if(!o)return;const s=(n=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:n[U];if(s&&o){const l=e.uuid;O.registerMesh(o,l,e,0,s.lods.length,s)}}}function je(a,t,e,r){ve(t),_e(e),e.register(s=>new O(s,a));const o=I.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Oe();exports.EXTENSION_NAME=U;exports.LODsManager=I;exports.NEEDLE_progressive=O;exports.VERSION=De;exports.addDracoAndKTX2Loaders=_e;exports.createLoaders=ve;exports.getRaycastMesh=oe;exports.patchModelViewer=Oe;exports.registerRaycastMesh=Pe;exports.setDracoDecoderLocation=Ne;exports.setKTX2TranscoderLocation=Ue;exports.useNeedleProgressive=je;exports.useRaycastMeshes=qe;
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}};let I=C;B=new WeakMap,z=new WeakMap,he=new WeakMap,j=new WeakMap,ee=new WeakMap,ge=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new p.Vector3),d(I,"corner1",new p.Vector3),d(I,"corner2",new p.Vector3),d(I,"corner3",new p.Vector3),d(I,"_tempPtInside",new p.Vector3);class Qe{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const Te=Symbol("NEEDLE_mesh_lod"),fe=Symbol("NEEDLE_texture_lod");let se=null;function Oe(){const a=Ze();a&&(a.mapURLs(function(t){return Ae(),t}),Ae(),se==null||se.disconnect(),se=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ce(r)})})}),se.observe(document,{childList:!0,subtree:!0}))}function Ze(){if(typeof customElements>"u")return null;const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Ae(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Ee=new WeakSet;let je=0;function Ce(a){if(!a||Ee.has(a))return null;Ee.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++je+`
8
+ `,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),i=s.find(u=>u.toString()=="Symbol(renderer)"),n=s.find(u=>u.toString()=="Symbol(scene)"),l=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=a[i].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let o=function(){if(r){let i=0,n=setInterval(()=>{if(i++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=I.get(t,{engine:"model-viewer"});return I.addPlugin(new et),s.enable(),s.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",i=>{i.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{o()}),()=>{s.disable()}}return null}class et{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[fe]==!0)return;e[fe]=!0;const r=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),s=this.getUrl(o);if(s&&r&&e.material){let i=function(l){var c,g,y;if(l[fe]==!0)return;l[fe]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let D=0;D<u.length;D++){const v=u[D],M=l[v];if((M==null?void 0:M.isTexture)===!0){const F=(g=(c=M.userData)==null?void 0:c.associations)==null?void 0:g.textures;if(F==null)continue;const w=r.parser.json.textures[F];if(!w){console.warn("Texture data not found for texture index "+F);continue}if((y=w==null?void 0:w.extensions)!=null&&y[U]){const h=w.extensions[U];h&&s&&O.registerTexture(s,M,h.lods.length,F,h)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)i(l);else i(n)}}tryParseMeshLOD(t,e){var i,n;if(e[Te]==!0)return;e[Te]=!0;const r=this.tryGetCurrentModelViewer(t),o=this.getUrl(r);if(!o)return;const s=(n=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:n[U];if(s&&o){const l=e.uuid;O.registerMesh(o,l,e,0,s.lods.length,s)}}}function tt(a,t,e,r){ve(t),_e(e),e.register(s=>new O(s,a));const o=I.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Oe();exports.EXTENSION_NAME=U;exports.LODsManager=I;exports.NEEDLE_progressive=O;exports.VERSION=we;exports.addDracoAndKTX2Loaders=_e;exports.createLoaders=ve;exports.getRaycastMesh=ae;exports.patchModelViewer=Oe;exports.registerRaycastMesh=Pe;exports.setDracoDecoderLocation=ze;exports.setKTX2TranscoderLocation=We;exports.useNeedleProgressive=tt;exports.useRaycastMeshes=Ke;
@@ -94,7 +94,9 @@ export declare class NEEDLE_progressive implements GLTFLoaderPlugin {
94
94
  * @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
95
95
  * @returns a promise that resolves to the material or texture with the requested LOD level
96
96
  */
97
- static assignTextureLOD(materialOrTexture: Material | Texture, level?: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | Texture | null>;
97
+ static assignTextureLOD(materialOrTexture: Material, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
98
+ static assignTextureLOD(materialOrTexture: Mesh, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
99
+ static assignTextureLOD(materialOrTexture: Texture, level: number): Promise<Texture | null>;
98
100
  private static assignTextureLODForSlot;
99
101
  private readonly parser;
100
102
  private readonly url;
package/lib/extension.js CHANGED
@@ -283,16 +283,31 @@ export class NEEDLE_progressive {
283
283
  }
284
284
  return Promise.resolve(null);
285
285
  }
286
- /** Load a different resolution of a texture (if available)
287
- * @param context the context
288
- * @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
289
- * @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
290
- * @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
291
- * @returns a promise that resolves to the material or texture with the requested LOD level
292
- */
293
286
  static assignTextureLOD(materialOrTexture, level = 0) {
294
287
  if (!materialOrTexture)
295
288
  return Promise.resolve(null);
289
+ if (materialOrTexture.isMesh === true) {
290
+ const mesh = materialOrTexture;
291
+ if (Array.isArray(mesh.material)) {
292
+ const arr = new Array();
293
+ for (const mat of mesh.material) {
294
+ const promise = this.assignTextureLOD(mat, level);
295
+ arr.push(promise);
296
+ }
297
+ return Promise.all(arr).then(res => {
298
+ const textures = new Array();
299
+ for (const tex of res) {
300
+ if (Array.isArray(tex)) {
301
+ textures.push(...tex);
302
+ }
303
+ }
304
+ return textures;
305
+ });
306
+ }
307
+ else {
308
+ return this.assignTextureLOD(mesh.material, level);
309
+ }
310
+ }
296
311
  if (materialOrTexture instanceof Material || materialOrTexture.isMaterial === true) {
297
312
  const material = materialOrTexture;
298
313
  const promises = [];
package/lib/loaders.js CHANGED
@@ -1,12 +1,18 @@
1
1
  import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
2
2
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
3
3
  import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
4
- let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/';
4
+ let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';
5
5
  let DEFAULT_KTX2_TRANSCODER_LOCATION = 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/';
6
+ const defaultDraco = DEFAULT_DRACO_DECODER_LOCATION;
7
+ const defaultKTX2 = DEFAULT_KTX2_TRANSCODER_LOCATION;
6
8
  fetch(DEFAULT_DRACO_DECODER_LOCATION + "draco_decoder.js", { method: "head" })
7
9
  .catch(_ => {
8
- DEFAULT_DRACO_DECODER_LOCATION = "./include/draco/";
9
- DEFAULT_KTX2_TRANSCODER_LOCATION = "./include/ktx2/";
10
+ // check if the default values have been changed by the user.
11
+ // If they didnt change / the default paths are not reachable, fall back to local versions
12
+ if (DEFAULT_DRACO_DECODER_LOCATION === defaultDraco)
13
+ DEFAULT_DRACO_DECODER_LOCATION = "./include/draco/";
14
+ if (DEFAULT_KTX2_TRANSCODER_LOCATION === defaultKTX2)
15
+ DEFAULT_KTX2_TRANSCODER_LOCATION = "./include/ktx2/";
10
16
  });
11
17
  /**
12
18
  * Set the location of the Draco decoder.
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "1.2.10";
2
+ export const version = "1.2.12";
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.10",
3
+ "version": "1.2.12",
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": {