@needle-tools/gltf-progressive 1.2.4-beta.1 → 1.2.5-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,9 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.2.5-beta] - 2023-07-09
8
+ - Change: Update skinned mesh bounding box every 30 frames using the lowres mesh version
9
+
7
10
  ## [1.2.4-beta.1] - 2023-07-09
8
11
  - Add: LODsManager `manual` property which can be used to manually update the LODs in the scene by calling `LODsManager.update(scene, camera)`
9
12
  - Fix: updating LODs in WebXR
package/README.md CHANGED
@@ -17,6 +17,7 @@ Examples are in the `/examples` directory. Live versions can be found in the lin
17
17
  - \<model-viewer\>
18
18
  - [single \<model-viewer> element](https://engine.needle.tools/demos/gltf-progressive/modelviewer)
19
19
  - [multiple \<model-viewer> elements](https://engine.needle.tools/demos/gltf-progressive/modelviewer-multiple)
20
+ - [Needle Engine](https://stackblitz.com/edit/needle-engine-gltf-progressive?file=src%2Fmain.ts)
20
21
 
21
22
  **Interactive Examples**:
22
23
  - [Stackblitz](https://stackblitz.com/@marwie/collections/gltf-progressive)
@@ -4,11 +4,11 @@ var f = (a, t, e) => (ze(a, typeof t != "symbol" ? t + "" : t, e), e), Se = (a,
4
4
  if (!t.has(a))
5
5
  throw TypeError("Cannot " + e);
6
6
  };
7
- var m = (a, t, e) => (Se(a, t, "read from private field"), e ? e.call(a) : t.get(a)), K = (a, t, e) => {
7
+ var x = (a, t, e) => (Se(a, t, "read from private field"), e ? e.call(a) : t.get(a)), K = (a, t, e) => {
8
8
  if (t.has(a))
9
9
  throw TypeError("Cannot add the same private member more than once");
10
10
  t instanceof WeakSet ? t.add(a) : t.set(a, e);
11
- }, F = (a, t, e, r) => (Se(a, t, "write to private field"), r ? r.call(a, e) : t.set(a, e), e);
11
+ }, $ = (a, t, e, r) => (Se(a, t, "write to private field"), r ? r.call(a, e) : t.set(a, e), e);
12
12
  import { BufferGeometry as he, Mesh as H, Material as Ve, Texture as re, TextureLoader as Ne, Matrix4 as be, Frustum as We, Clock as qe, MeshStandardMaterial as Xe, Sphere as Ke, Box3 as Te, Vector3 as V } from "three";
13
13
  import { GLTFLoader as Ye } from "three/examples/jsm/loaders/GLTFLoader.js";
14
14
  import { MeshoptDecoder as He } from "three/examples/jsm/libs/meshopt_decoder.module.js";
@@ -17,19 +17,19 @@ import { KTX2Loader as Qe } from "three/examples/jsm/loaders/KTX2Loader.js";
17
17
  const Be = "";
18
18
  globalThis.GLTF_PROGRESSIVE_VERSION = Be;
19
19
  console.debug(`[gltf-progressive] version ${Be}`);
20
- let ge = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", Oe = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
20
+ let ge = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", _e = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
21
21
  fetch(ge + "draco_decoder.js", { method: "head" }).catch((a) => {
22
- ge = "./include/draco/", Oe = "./include/ktx2/";
22
+ ge = "./include/draco/", _e = "./include/ktx2/";
23
23
  });
24
24
  function gt(a) {
25
25
  ge = a;
26
26
  }
27
27
  function pt(a) {
28
- Oe = a;
28
+ _e = a;
29
29
  }
30
30
  let Q, de, Z;
31
31
  function Ie(a) {
32
- return Q || (Q = new Je(), Q.setDecoderPath(ge), Q.setDecoderConfig({ type: "js" })), Z || (Z = new Qe(), Z.setTranscoderPath(Oe)), de || (de = He), 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: de };
32
+ return Q || (Q = new Je(), Q.setDecoderPath(ge), Q.setDecoderConfig({ type: "js" })), Z || (Z = new Qe(), Z.setTranscoderPath(_e)), de || (de = He), 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: de };
33
33
  }
34
34
  function ke(a) {
35
35
  a.dracoLoader || a.setDRACOLoader(Q), a.ktx2Loader || a.setKTX2Loader(Z), a.meshoptDecoder || a.setMeshoptDecoder(de);
@@ -55,14 +55,14 @@ let se;
55
55
  function je() {
56
56
  return se !== void 0 || (se = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), ae("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", se)), se;
57
57
  }
58
- const we = Symbol("needle:raycast-mesh");
59
- function _e(a) {
60
- return (a == null ? void 0 : a[we]) instanceof he ? a[we] : null;
58
+ const ve = Symbol("needle:raycast-mesh");
59
+ function me(a) {
60
+ return (a == null ? void 0 : a[ve]) instanceof he ? a[ve] : null;
61
61
  }
62
62
  function et(a, t) {
63
- if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !_e(a)) {
63
+ if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !me(a)) {
64
64
  const r = tt(t);
65
- r.userData = { isRaycastMesh: !0 }, a[we] = r;
65
+ r.userData = { isRaycastMesh: !0 }, a[ve] = r;
66
66
  }
67
67
  }
68
68
  function yt(a = !0) {
@@ -71,7 +71,7 @@ function yt(a = !0) {
71
71
  return;
72
72
  const t = ie = H.prototype.raycast;
73
73
  H.prototype.raycast = function(e, r) {
74
- const n = this, s = _e(n);
74
+ const n = this, s = me(n);
75
75
  let i;
76
76
  s && n.isMesh && (i = n.geometry, n.geometry = s), t.call(this, e, r), i && (n.geometry = i);
77
77
  };
@@ -88,8 +88,8 @@ function tt(a) {
88
88
  t.setAttribute(e, a.getAttribute(e));
89
89
  return t.setIndex(a.getIndex()), t;
90
90
  }
91
- const Y = new Array(), N = "NEEDLE_progressive", x = ae("debugprogressive"), Le = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), ve = /* @__PURE__ */ new Set();
92
- if (x) {
91
+ const Y = new Array(), N = "NEEDLE_progressive", L = ae("debugprogressive"), Me = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), Oe = /* @__PURE__ */ new Set();
92
+ if (L) {
93
93
  let a = function() {
94
94
  t += 1, console.log("Toggle LOD level", t, oe), oe.forEach((n, s) => {
95
95
  for (const i of n.keys) {
@@ -107,14 +107,14 @@ if (x) {
107
107
  }), t >= e && (t = -1);
108
108
  }, t = -1, e = 2, r = !1;
109
109
  window.addEventListener("keyup", (n) => {
110
- n.key === "p" && a(), n.key === "w" && (r = !r, ve && ve.forEach((s) => {
110
+ n.key === "p" && a(), n.key === "w" && (r = !r, Oe && Oe.forEach((s) => {
111
111
  s.name != "BackgroundCubeMaterial" && s.glyphMap == null && "wireframe" in s && (s.wireframe = r);
112
112
  }));
113
113
  });
114
114
  }
115
115
  function Ae(a, t, e) {
116
116
  var n;
117
- if (!x)
117
+ if (!L)
118
118
  return;
119
119
  oe.has(a) || oe.set(a, { keys: [], sourceId: e });
120
120
  const r = oe.get(a);
@@ -135,7 +135,7 @@ const O = class {
135
135
  return this._isLoadingMesh = !1, s && O.registerMesh(this.url, e.guid, s, (i = e.lods) == null ? void 0 : i.length, void 0, e), s;
136
136
  })) : null;
137
137
  });
138
- x && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
138
+ L && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
139
139
  }
140
140
  /** The name of the extension */
141
141
  get name() {
@@ -158,7 +158,7 @@ const O = class {
158
158
  this.getMaterialMinMaxLODsCount(o, e);
159
159
  return t[n] = e, e;
160
160
  }
161
- if (x === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
161
+ if (L === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
162
162
  const o = t;
163
163
  for (const l of Object.keys(o.uniforms)) {
164
164
  const u = o.uniforms[l].value;
@@ -249,12 +249,12 @@ const O = class {
249
249
  const o = s.index || 0;
250
250
  i = i[o];
251
251
  }
252
- i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, x && Ae(t, "geometry", s.url)) : x && console.error("Invalid LOD geometry", i));
252
+ i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, L && Ae(t, "geometry", s.url)) : L && console.error("Invalid LOD geometry", i));
253
253
  }
254
254
  return i;
255
255
  }).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
256
256
  } else
257
- x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
257
+ L && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
258
258
  return Promise.resolve(null);
259
259
  }
260
260
  /** Load a different resolution of a texture (if available)
@@ -269,7 +269,7 @@ const O = class {
269
269
  return Promise.resolve(null);
270
270
  if (t instanceof Ve || t.isMaterial === !0) {
271
271
  const r = t, n = [], s = new Array();
272
- if (x && ve.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
272
+ if (L && Oe.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
273
273
  const i = r;
274
274
  for (const o of Object.keys(i.uniforms)) {
275
275
  const l = i.uniforms[o].value;
@@ -312,30 +312,30 @@ const O = class {
312
312
  if (i) {
313
313
  const o = this.getAssignedLODInformation(i);
314
314
  if (o && (o == null ? void 0 : o.level) < e)
315
- return x === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, e, r, i, s), null;
315
+ return L === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, e, r, i, s), null;
316
316
  }
317
317
  r[n] = s;
318
318
  }
319
- if (x && n && r) {
319
+ if (L && n && r) {
320
320
  const i = this.getAssignedLODInformation(t);
321
321
  i && Ae(r, n, i.url);
322
322
  }
323
323
  }
324
324
  return s;
325
325
  } else
326
- x == "verbose" && console.warn("No LOD found for", t, e);
326
+ L == "verbose" && console.warn("No LOD found for", t, e);
327
327
  return null;
328
328
  }).catch((s) => (console.error("Error loading LOD", t, s), null));
329
329
  }
330
330
  afterRoot(t) {
331
331
  var e, r;
332
- return x && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, s) => {
332
+ return L && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, s) => {
333
333
  var i;
334
334
  if (n != null && n.extensions) {
335
335
  const o = n == null ? void 0 : n.extensions[N];
336
336
  if (o) {
337
337
  if (!o.lods) {
338
- x && console.warn("Texture has no LODs", o);
338
+ L && console.warn("Texture has no LODs", o);
339
339
  return;
340
340
  }
341
341
  let l = !1;
@@ -365,14 +365,14 @@ const O = class {
365
365
  }
366
366
  static async getOrLoadLOD(t, e) {
367
367
  var o, l, u, c;
368
- const r = x == "verbose", n = t.userData.LODS;
368
+ const r = L == "verbose", n = t.userData.LODS;
369
369
  if (!n)
370
370
  return null;
371
371
  const s = n == null ? void 0 : n.key;
372
372
  let i;
373
373
  if (t.isTexture === !0) {
374
374
  const d = t;
375
- d.source && d.source[Le] && (i = d.source[Le]);
375
+ d.source && d.source[Me] && (i = d.source[Me]);
376
376
  }
377
377
  if (i || (i = O.lodInfos.get(s)), i) {
378
378
  if (e > 0) {
@@ -383,7 +383,7 @@ const O = class {
383
383
  }
384
384
  const d = Array.isArray(i.lods) ? (o = i.lods[e]) == null ? void 0 : o.path : i.lods;
385
385
  if (!d)
386
- return x && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
386
+ return L && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
387
387
  const h = Ze(n.url, d);
388
388
  if (h.endsWith(".glb") || h.endsWith(".gltf")) {
389
389
  if (!i.guid)
@@ -391,20 +391,20 @@ const O = class {
391
391
  const w = h + "_" + i.guid, v = this.previouslyLoaded.get(w);
392
392
  if (v !== void 0) {
393
393
  r && console.log(`LOD ${e} was already loading/loaded: ${w}`);
394
- let y = await v.catch((U) => (console.error(`Error loading LOD ${e} from ${h}
395
- `, U), null)), L = !1;
396
- if (y == null || (y instanceof re && t instanceof re ? (l = y.image) != null && l.data || (u = y.source) != null && u.data ? y = this.copySettings(t, y) : (L = !0, this.previouslyLoaded.delete(w)) : y instanceof he && t instanceof he && ((c = y.attributes.position) != null && c.array || (L = !0, this.previouslyLoaded.delete(w)))), !L)
397
- return y;
394
+ let g = await v.catch((I) => (console.error(`Error loading LOD ${e} from ${h}
395
+ `, I), null)), m = !1;
396
+ if (g == null || (g instanceof re && t instanceof re ? (l = g.image) != null && l.data || (u = g.source) != null && u.data ? g = this.copySettings(t, g) : (m = !0, this.previouslyLoaded.delete(w)) : g instanceof he && t instanceof he && ((c = g.attributes.position) != null && c.array || (m = !0, this.previouslyLoaded.delete(w)))), !m)
397
+ return g;
398
398
  }
399
- const M = i, G = new Promise(async (y, L) => {
400
- const U = new Ye();
401
- ke(U), x && (await new Promise((_) => setTimeout(_, 1e3)), r && console.warn("Start loading (delayed) " + h, M.guid));
399
+ const M = i, F = new Promise(async (g, m) => {
400
+ const I = new Ye();
401
+ ke(I), L && (await new Promise((_) => setTimeout(_, 1e3)), r && console.warn("Start loading (delayed) " + h, M.guid));
402
402
  let X = h;
403
403
  if (M && Array.isArray(M.lods)) {
404
404
  const _ = M.lods[e];
405
405
  _.hash && (X += "?v=" + _.hash);
406
406
  }
407
- const S = await U.loadAsync(X).catch((_) => (console.error(`Error loading LOD ${e} from ${h}
407
+ const S = await I.loadAsync(X).catch((_) => (console.error(`Error loading LOD ${e} from ${h}
408
408
  `, _), null));
409
409
  if (!S)
410
410
  return null;
@@ -413,10 +413,10 @@ const O = class {
413
413
  let A = 0;
414
414
  if (S.parser.json.textures) {
415
415
  let _ = !1;
416
- for (const p of S.parser.json.textures) {
417
- if (p != null && p.extensions) {
418
- const g = p == null ? void 0 : p.extensions[N];
419
- if (g != null && g.guid && g.guid === M.guid) {
416
+ for (const y of S.parser.json.textures) {
417
+ if (y != null && y.extensions) {
418
+ const p = y == null ? void 0 : y.extensions[N];
419
+ if (p != null && p.guid && p.guid === M.guid) {
420
420
  _ = !0;
421
421
  break;
422
422
  }
@@ -424,17 +424,17 @@ const O = class {
424
424
  A++;
425
425
  }
426
426
  if (_) {
427
- let p = await z.getDependency("texture", A);
428
- return p && O.assignLODInformation(n.url, p, s, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + p.name + '"', h, A, p, w), t instanceof re && (p = this.copySettings(t, p)), p && (p.guid = M.guid), y(p);
427
+ let y = await z.getDependency("texture", A);
428
+ return y && O.assignLODInformation(n.url, y, s, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + y.name + '"', h, A, y, w), t instanceof re && (y = this.copySettings(t, y)), y && (y.guid = M.guid), g(y);
429
429
  } else
430
- x && console.warn("Could not find texture with guid", M.guid, S.parser.json);
430
+ L && console.warn("Could not find texture with guid", M.guid, S.parser.json);
431
431
  }
432
432
  if (A = 0, S.parser.json.meshes) {
433
433
  let _ = !1;
434
- for (const p of S.parser.json.meshes) {
435
- if (p != null && p.extensions) {
436
- const g = p == null ? void 0 : p.extensions[N];
437
- if (g != null && g.guid && g.guid === M.guid) {
434
+ for (const y of S.parser.json.meshes) {
435
+ if (y != null && y.extensions) {
436
+ const p = y == null ? void 0 : y.extensions[N];
437
+ if (p != null && p.guid && p.guid === M.guid) {
438
438
  _ = !0;
439
439
  break;
440
440
  }
@@ -442,34 +442,34 @@ const O = class {
442
442
  A++;
443
443
  }
444
444
  if (_) {
445
- const p = await z.getDependency("mesh", A), g = M;
446
- if (r && console.log(`Loaded Mesh "${p.name}"`, h, A, p, w), p.isMesh === !0) {
447
- const D = p.geometry;
448
- return O.assignLODInformation(n.url, D, s, e, void 0, g.density), y(D);
445
+ const y = await z.getDependency("mesh", A), p = M;
446
+ if (r && console.log(`Loaded Mesh "${y.name}"`, h, A, y, w), y.isMesh === !0) {
447
+ const D = y.geometry;
448
+ return O.assignLODInformation(n.url, D, s, e, void 0, p.density), g(D);
449
449
  } else {
450
450
  const D = new Array();
451
- for (let T = 0; T < p.children.length; T++) {
452
- const P = p.children[T];
453
- if (P.isMesh === !0) {
454
- const E = P.geometry;
455
- O.assignLODInformation(n.url, E, s, e, T, g.density), D.push(E);
451
+ for (let T = 0; T < y.children.length; T++) {
452
+ const E = y.children[T];
453
+ if (E.isMesh === !0) {
454
+ const P = E.geometry;
455
+ O.assignLODInformation(n.url, P, s, e, T, p.density), D.push(P);
456
456
  }
457
457
  }
458
- return y(D);
458
+ return g(D);
459
459
  }
460
460
  } else
461
- x && console.warn("Could not find mesh with guid", M.guid, S.parser.json);
461
+ L && console.warn("Could not find mesh with guid", M.guid, S.parser.json);
462
462
  }
463
- return y(null);
463
+ return g(null);
464
464
  });
465
- return this.previouslyLoaded.set(w, G), await G;
465
+ return this.previouslyLoaded.set(w, F), await F;
466
466
  } else if (t instanceof re) {
467
467
  r && console.log("Load texture from uri: " + h);
468
468
  const v = await new Ne().loadAsync(h);
469
- 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", h), v;
469
+ return v ? (v.guid = i.guid, v.flipY = !1, v.needsUpdate = !0, v.colorSpace = t.colorSpace, r && console.log(i, v)) : L && console.warn("failed loading", h), v;
470
470
  }
471
471
  } else
472
- x && console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`, t.type);
472
+ L && console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`, t.type);
473
473
  return null;
474
474
  }
475
475
  static assignLODInformation(t, e, r, n, s, i) {
@@ -485,7 +485,7 @@ const O = class {
485
485
  }
486
486
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
487
487
  static copySettings(t, e) {
488
- return e = e.clone(), x && console.warn(`Copying texture settings
488
+ return e = e.clone(), L && console.warn(`Copying texture settings
489
489
  `, t.uuid, `
490
490
  `, e.uuid), e.offset = t.offset, e.repeat = t.repeat, e.colorSpace = t.colorSpace, e.magFilter = t.magFilter, e.minFilter = t.minFilter, e.wrapS = t.wrapS, e.wrapT = t.wrapT, e.flipY = t.flipY, e.anisotropy = t.anisotropy, e.mipmaps || (e.generateMipmaps = t.generateMipmaps), e;
491
491
  }
@@ -495,11 +495,11 @@ let b = O;
495
495
  * Register a texture with LOD information
496
496
  */
497
497
  f(b, "registerTexture", (t, e, r, n, s) => {
498
- if (x && console.log("> Progressive: register texture", n, e.name, e.uuid, e, s), !e) {
499
- x && console.error("gltf-progressive: Register texture without texture");
498
+ if (L && console.log("> Progressive: register texture", n, e.name, e.uuid, e, s), !e) {
499
+ L && console.error("gltf-progressive: Register texture without texture");
500
500
  return;
501
501
  }
502
- e.source && (e.source[Le] = s);
502
+ e.source && (e.source[Me] = s);
503
503
  const i = s.guid;
504
504
  O.assignLODInformation(t, e, i, r, n, void 0), O.lodInfos.set(i, s), O.lowresCache.set(i, e);
505
505
  }), /**
@@ -507,15 +507,15 @@ f(b, "registerTexture", (t, e, r, n, s) => {
507
507
  */
508
508
  f(b, "registerMesh", (t, e, r, n, s, i) => {
509
509
  var u;
510
- x && console.log("> Progressive: register mesh", s, r.name, i, r.uuid, r);
510
+ L && console.log("> Progressive: register mesh", s, r.name, i, r.uuid, r);
511
511
  const o = r.geometry;
512
512
  if (!o) {
513
- x && console.warn("gltf-progressive: Register mesh without geometry");
513
+ L && console.warn("gltf-progressive: Register mesh without geometry");
514
514
  return;
515
515
  }
516
516
  o.userData || (o.userData = {}), O.assignLODInformation(t, o, e, n, s, i.density), O.lodInfos.set(e, i);
517
517
  let l = O.lowresCache.get(e);
518
- l ? l.push(r.geometry) : l = [r.geometry], O.lowresCache.set(e, l), n > 0 && !_e(r) && et(r, o);
518
+ l ? l.push(r.geometry) : l = [r.geometry], O.lowresCache.set(e, l), n > 0 && !me(r) && et(r, o);
519
519
  for (const c of Y)
520
520
  (u = c.onRegisteredNewMesh) == null || u.call(c, r, i);
521
521
  }), /** A map of key = asset uuid and value = LOD information */
@@ -535,7 +535,7 @@ class rt {
535
535
  this.url = t, this.key = e, this.level = r, n != null && (this.index = n), s != null && (this.density = s);
536
536
  }
537
537
  }
538
- const I = ae("debugprogressive"), st = ae("noprogressive"), Me = Symbol("Needle:LODSManager"), De = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), k = { mesh_lod: -1, texture_lod: -1 };
538
+ const k = ae("debugprogressive"), st = ae("noprogressive"), De = Symbol("Needle:LODSManager"), we = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), R = { mesh_lod: -1, texture_lod: -1 };
539
539
  var B, W, pe, j, ee, ye, q;
540
540
  const C = class {
541
541
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
@@ -586,7 +586,7 @@ const C = class {
586
586
  }
587
587
  /** @internal */
588
588
  static getObjectLODState(t) {
589
- return t[De];
589
+ return t[we];
590
590
  }
591
591
  static addPlugin(t) {
592
592
  Y.push(t);
@@ -601,13 +601,13 @@ const C = class {
601
601
  * @returns The LODsManager instance.
602
602
  */
603
603
  static get(t, e) {
604
- if (t[Me])
605
- return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[Me];
604
+ if (t[De])
605
+ return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[De];
606
606
  const r = new C(t, {
607
607
  engine: "unknown",
608
608
  ...e
609
609
  });
610
- return t[Me] = r, r;
610
+ return t[De] = r, r;
611
611
  }
612
612
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
613
613
  get plugins() {
@@ -616,25 +616,31 @@ const C = class {
616
616
  addEventListener(t, e) {
617
617
  t === "changed" && this._lodchangedlisteners.push(e);
618
618
  }
619
+ removeEventListener(t, e) {
620
+ if (t === "changed") {
621
+ const r = this._lodchangedlisteners.indexOf(e);
622
+ r >= 0 && this._lodchangedlisteners.splice(r, 1);
623
+ }
624
+ }
619
625
  /**
620
626
  * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
621
627
  */
622
628
  enable() {
623
- if (m(this, W))
629
+ if (x(this, W))
624
630
  return;
625
631
  console.debug("[gltf-progressive] Enabling LODsManager for renderer");
626
632
  let t = 0;
627
- F(this, W, this.renderer.render);
633
+ $(this, W, this.renderer.render);
628
634
  const e = this;
629
635
  Ie(this.renderer), this.renderer.render = function(r, n) {
630
636
  const s = e.renderer.getRenderTarget();
631
- (s == null || "isXRRenderTarget" in s && s.isXRRenderTarget) && (t = 0, F(e, j, m(e, j) + 1), F(e, ee, m(e, pe).getDelta()), F(e, ye, m(e, ye) + m(e, ee)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, ee)), F(e, q, e._fpsBuffer.reduce((o, l) => o + l) / e._fpsBuffer.length), I && m(e, j) % 30 === 0 && console.log("FPS", Math.round(m(e, q)), "Interval:", m(e, B)));
637
+ (s == null || "isXRRenderTarget" in s && s.isXRRenderTarget) && (t = 0, $(e, j, x(e, j) + 1), $(e, ee, x(e, pe).getDelta()), $(e, ye, x(e, ye) + x(e, ee)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / x(e, ee)), $(e, q, e._fpsBuffer.reduce((o, l) => o + l) / e._fpsBuffer.length), k && x(e, j) % 30 === 0 && console.log("FPS", Math.round(x(e, q)), "Interval:", x(e, B)));
632
638
  const i = t++;
633
- m(e, W).call(this, r, n), e.onAfterRender(r, n, i);
639
+ x(e, W).call(this, r, n), e.onAfterRender(r, n, i);
634
640
  };
635
641
  }
636
642
  disable() {
637
- m(this, W) && (this.renderer.render = m(this, W), F(this, W, void 0));
643
+ x(this, W) && (this.renderer.render = x(this, W), $(this, W, void 0));
638
644
  }
639
645
  update(t, e) {
640
646
  this.internalUpdate(t, e);
@@ -649,7 +655,7 @@ const C = class {
649
655
  (o.name === "EffectMaterial" || o.name === "CopyShader") && (i = !1);
650
656
  }
651
657
  if ((e.parent && e.parent.type === "CubeCamera" || r >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
652
- if (st || (this.updateInterval === "auto" ? m(this, q) < 40 && m(this, B) < 10 ? (F(this, B, m(this, B) + 1), I && console.warn("↓ Reducing LOD updates", m(this, B), m(this, q).toFixed(0))) : m(this, q) >= 60 && m(this, B) > 1 && (F(this, B, m(this, B) - 1), I && console.warn("↑ Increasing LOD updates", m(this, B), m(this, q).toFixed(0))) : F(this, B, this.updateInterval), m(this, B) > 0 && m(this, j) % m(this, B) != 0))
658
+ if (st || (this.updateInterval === "auto" ? x(this, q) < 40 && x(this, B) < 10 ? ($(this, B, x(this, B) + 1), k && console.warn("↓ Reducing LOD updates", x(this, B), x(this, q).toFixed(0))) : x(this, q) >= 60 && x(this, B) > 1 && ($(this, B, x(this, B) - 1), k && console.warn("↑ Increasing LOD updates", x(this, B), x(this, q).toFixed(0))) : $(this, B, this.updateInterval), x(this, B) > 0 && x(this, j) % x(this, B) != 0))
653
659
  return;
654
660
  this.internalUpdate(t, e);
655
661
  }
@@ -664,7 +670,7 @@ const C = class {
664
670
  const s = this.targetTriangleDensity;
665
671
  for (const c of n) {
666
672
  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")) {
667
- I && (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)));
673
+ k && (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)));
668
674
  continue;
669
675
  }
670
676
  switch (c.material.type) {
@@ -676,7 +682,7 @@ const C = class {
676
682
  case "MeshDepthMaterial":
677
683
  continue;
678
684
  }
679
- if (I === "color" && c.material && !c.object.progressive_debug_color) {
685
+ if (k === "color" && c.material && !c.object.progressive_debug_color) {
680
686
  c.object.progressive_debug_color = !0;
681
687
  const h = Math.random() * 16777215, w = new Xe({ color: h });
682
688
  c.object.material = w;
@@ -699,20 +705,20 @@ const C = class {
699
705
  updateLODs(t, e, r, n) {
700
706
  var o, l;
701
707
  r.userData || (r.userData = {});
702
- let s = r[De];
703
- if (s || (s = new it(), r[De] = s), s.frames++ < 2)
708
+ let s = r[we];
709
+ if (s || (s = new it(), r[we] = s), s.frames++ < 2)
704
710
  return;
705
711
  for (const u of Y)
706
712
  (o = u.onBeforeUpdateLOD) == null || o.call(u, this.renderer, t, e, r);
707
- this.calculateLodLevel(e, r, s, 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);
708
- let i = k.texture_lod;
713
+ this.calculateLodLevel(e, r, s, n, R), R.mesh_lod = Math.round(R.mesh_lod), R.texture_lod = Math.round(R.texture_lod), R.mesh_lod >= 0 && this.loadProgressiveMeshes(r, R.mesh_lod);
714
+ let i = R.texture_lod;
709
715
  if (r.material && i >= 0) {
710
716
  const u = r["DEBUG:LOD"];
711
717
  u != null && (i = u), this.loadProgressiveTextures(r.material, i);
712
718
  }
713
719
  for (const u of Y)
714
- (l = u.onAfterUpdatedLOD) == null || l.call(u, this.renderer, t, e, r, k);
715
- s.lastLodLevel_Mesh = k.mesh_lod, s.lastLodLevel_Texture = k.texture_lod;
720
+ (l = u.onAfterUpdatedLOD) == null || l.call(u, this.renderer, t, e, r, R);
721
+ s.lastLodLevel_Mesh = R.mesh_lod, s.lastLodLevel_Texture = R.texture_lod;
716
722
  }
717
723
  /** Load progressive textures for the given material
718
724
  * @param material the material to load the textures for
@@ -753,7 +759,7 @@ const C = class {
753
759
  return this._tempPtInside.set(s, i, r.z).applyMatrix4(e).z < 0;
754
760
  }
755
761
  calculateLodLevel(t, e, r, n, s) {
756
- var G, $;
762
+ var F, U;
757
763
  if (!e) {
758
764
  s.mesh_lod = -1, s.texture_lod = -1;
759
765
  return;
@@ -763,29 +769,35 @@ const C = class {
763
769
  return;
764
770
  }
765
771
  let o = 10 + 1, l = !1;
766
- if (I && e["DEBUG:LOD"] != null)
772
+ if (k && e["DEBUG:LOD"] != null)
767
773
  return e["DEBUG:LOD"];
768
774
  const u = b.getMeshLODInformation(e.geometry), c = u == null ? void 0 : u.lods, d = c && c.length > 0, h = b.getMaterialMinMaxLODsCount(e.material), w = (h == null ? void 0 : h.min_count) != 1 / 0 && h.min_count > 0 && h.max_count > 0;
769
775
  if (!d && !w) {
770
776
  s.mesh_lod = 0, s.texture_lod = 0;
771
777
  return;
772
778
  }
773
- if (d || (l = !0, o = 0), !((G = this.cameraFrustrum) != null && G.intersectsObject(e))) {
774
- s.mesh_lod = 99, s.texture_lod = 99;
779
+ if (d || (l = !0, o = 0), !((F = this.cameraFrustrum) != null && F.intersectsObject(e))) {
780
+ s.mesh_lod = 100, s.texture_lod = 100;
775
781
  return;
776
782
  }
777
783
  const v = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
778
784
  let M = e.geometry.boundingBox;
779
785
  if (e.type === "SkinnedMesh") {
780
- const y = e;
781
- y.boundingBox || y.computeBoundingBox(), M = y.boundingBox;
786
+ const g = e;
787
+ if (!g.boundingBox)
788
+ g.computeBoundingBox();
789
+ else if (r.frames % 30 === 0) {
790
+ const m = me(g), I = g.geometry;
791
+ m && (g.geometry = m), g.computeBoundingBox(), g.geometry = I;
792
+ }
793
+ M = g.boundingBox;
782
794
  }
783
795
  if (M && t.isPerspectiveCamera) {
784
- const y = t;
796
+ const g = t;
785
797
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
786
798
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
787
- const g = t.getWorldPosition(this._tempWorldPosition);
788
- if (this._sphere.containsPoint(g)) {
799
+ const p = t.getWorldPosition(this._tempWorldPosition);
800
+ if (this._sphere.containsPoint(p)) {
789
801
  s.mesh_lod = 0, s.texture_lod = 0;
790
802
  return;
791
803
  }
@@ -794,61 +806,61 @@ const C = class {
794
806
  s.mesh_lod = 0, s.texture_lod = 0;
795
807
  return;
796
808
  }
797
- if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && y.fov > 70) {
798
- const g = this._tempBox.min, D = this._tempBox.max;
799
- let T = g.x, P = g.y, E = D.x, te = D.y;
800
- const le = 2, me = 1.5, ce = (g.x + D.x) * 0.5, ue = (g.y + D.y) * 0.5;
801
- T = (T - ce) * le + ce, P = (P - ue) * le + ue, E = (E - ce) * le + ce, te = (te - ue) * le + ue;
802
- const Fe = T < 0 && E > 0 ? 0 : Math.min(Math.abs(g.x), Math.abs(D.x)), $e = P < 0 && te > 0 ? 0 : Math.min(Math.abs(g.y), Math.abs(D.y)), xe = Math.max(Fe, $e);
803
- r.lastCentrality = (me - xe) * (me - xe) * (me - xe);
809
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && g.fov > 70) {
810
+ const p = this._tempBox.min, D = this._tempBox.max;
811
+ let T = p.x, E = p.y, P = D.x, te = D.y;
812
+ const le = 2, xe = 1.5, ce = (p.x + D.x) * 0.5, ue = (p.y + D.y) * 0.5;
813
+ T = (T - ce) * le + ce, E = (E - ue) * le + ue, P = (P - ce) * le + ce, te = (te - ue) * le + ue;
814
+ const Fe = T < 0 && P > 0 ? 0 : Math.min(Math.abs(p.x), Math.abs(D.x)), $e = E < 0 && te > 0 ? 0 : Math.min(Math.abs(p.y), Math.abs(D.y)), Le = Math.max(Fe, $e);
815
+ r.lastCentrality = (xe - Le) * (xe - Le) * (xe - Le);
804
816
  } else
805
817
  r.lastCentrality = 1;
806
- const L = this._tempBox.getSize(this._tempBoxSize);
807
- L.multiplyScalar(0.5), screen.availHeight > 0 && v > 0 && L.multiplyScalar(v / screen.availHeight), L.x *= y.aspect;
808
- const U = t.matrixWorldInverse, X = this._tempBox2;
809
- X.copy(M), X.applyMatrix4(e.matrixWorld), X.applyMatrix4(U);
818
+ const m = this._tempBox.getSize(this._tempBoxSize);
819
+ m.multiplyScalar(0.5), screen.availHeight > 0 && v > 0 && m.multiplyScalar(v / screen.availHeight), m.x *= g.aspect;
820
+ const I = t.matrixWorldInverse, X = this._tempBox2;
821
+ X.copy(M), X.applyMatrix4(e.matrixWorld), X.applyMatrix4(I);
810
822
  const S = X.getSize(this._tempBox2Size), z = Math.max(S.x, S.y);
811
- if (Math.max(L.x, L.y) != 0 && z != 0 && (L.z = S.z / Math.max(S.x, S.y) * Math.max(L.x, L.y)), r.lastScreenCoverage = Math.max(L.x, L.y, L.z), r.lastScreenspaceVolume.copy(L), r.lastScreenCoverage *= r.lastCentrality, I && C.debugDrawLine) {
812
- const g = this.tempMatrix.copy(this.projectionScreenMatrix);
813
- g.invert();
814
- const D = C.corner0, T = C.corner1, P = C.corner2, E = C.corner3;
815
- D.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = D.x, P.copy(this._tempBox.max), P.y = D.y, E.copy(this._tempBox.max);
816
- const te = (D.z + E.z) * 0.5;
817
- D.z = T.z = P.z = E.z = te, D.applyMatrix4(g), T.applyMatrix4(g), P.applyMatrix4(g), E.applyMatrix4(g), C.debugDrawLine(D, T, 255), C.debugDrawLine(D, P, 255), C.debugDrawLine(T, E, 255), C.debugDrawLine(P, E, 255);
823
+ if (Math.max(m.x, m.y) != 0 && z != 0 && (m.z = S.z / Math.max(S.x, S.y) * Math.max(m.x, m.y)), r.lastScreenCoverage = Math.max(m.x, m.y, m.z), r.lastScreenspaceVolume.copy(m), r.lastScreenCoverage *= r.lastCentrality, k && C.debugDrawLine) {
824
+ const p = this.tempMatrix.copy(this.projectionScreenMatrix);
825
+ p.invert();
826
+ const D = C.corner0, T = C.corner1, E = C.corner2, P = C.corner3;
827
+ D.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = D.x, E.copy(this._tempBox.max), E.y = D.y, P.copy(this._tempBox.max);
828
+ const te = (D.z + P.z) * 0.5;
829
+ D.z = T.z = E.z = P.z = te, D.applyMatrix4(p), T.applyMatrix4(p), E.applyMatrix4(p), P.applyMatrix4(p), C.debugDrawLine(D, T, 255), C.debugDrawLine(D, E, 255), C.debugDrawLine(T, P, 255), C.debugDrawLine(E, P, 255);
818
830
  }
819
831
  let _ = 999;
820
832
  if (c && r.lastScreenCoverage > 0) {
821
- for (let g = 0; g < c.length; g++)
822
- if (c[g].density / r.lastScreenCoverage < n) {
823
- _ = g;
833
+ for (let p = 0; p < c.length; p++)
834
+ if (c[p].density / r.lastScreenCoverage < n) {
835
+ _ = p;
824
836
  break;
825
837
  }
826
838
  }
827
839
  _ < o && (o = _, l = !0);
828
840
  }
829
- if (l ? s.mesh_lod = o : s.mesh_lod = r.lastLodLevel_Mesh, I && s.mesh_lod != r.lastLodLevel_Mesh) {
830
- const L = c == null ? void 0 : c[s.mesh_lod];
831
- L && console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`);
841
+ if (l ? s.mesh_lod = o : s.mesh_lod = r.lastLodLevel_Mesh, k && s.mesh_lod != r.lastLodLevel_Mesh) {
842
+ const m = c == null ? void 0 : c[s.mesh_lod];
843
+ m && console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`);
832
844
  }
833
845
  if (w) {
834
- const y = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
846
+ const g = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
835
847
  if (r.lastLodLevel_Texture < 0) {
836
- if (s.texture_lod = h.max_count - 1, I) {
837
- const L = h.lods[h.max_count - 1];
838
- I && console.log(`First Texture LOD ${s.texture_lod} (${L.max_height}px) - ${e.name}`);
848
+ if (s.texture_lod = h.max_count - 1, k) {
849
+ const m = h.lods[h.max_count - 1];
850
+ k && console.log(`First Texture LOD ${s.texture_lod} (${m.max_height}px) - ${e.name}`);
839
851
  }
840
852
  } else {
841
- const L = r.lastScreenspaceVolume.x + r.lastScreenspaceVolume.y + r.lastScreenspaceVolume.z;
842
- let U = r.lastScreenCoverage * 2;
843
- (($ = this.context) == null ? void 0 : $.engine) === "model-viewer" && (U *= 2);
844
- const S = v / window.devicePixelRatio * U;
853
+ const m = r.lastScreenspaceVolume.x + r.lastScreenspaceVolume.y + r.lastScreenspaceVolume.z;
854
+ let I = r.lastScreenCoverage * 2;
855
+ ((U = this.context) == null ? void 0 : U.engine) === "model-viewer" && (I *= 2);
856
+ const S = v / window.devicePixelRatio * I;
845
857
  for (let z = h.lods.length - 1; z >= 0; z--) {
846
858
  let A = h.lods[z];
847
- if (!(y && A.max_height >= 2048) && !(je() && A.max_height > 4096) && A.max_height > S) {
859
+ if (!(g && A.max_height >= 2048) && !(je() && A.max_height > 4096) && A.max_height > S) {
848
860
  if (s.texture_lod = z, s.texture_lod < r.lastLodLevel_Texture) {
849
861
  const _ = A.max_height;
850
- I && console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${_}px
851
- Screensize: ${S.toFixed(0)}px, Coverage: ${(100 * r.lastScreenCoverage).toFixed(2)}%, Volume ${L.toFixed(1)}
862
+ k && console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${_}px
863
+ Screensize: ${S.toFixed(0)}px, Coverage: ${(100 * r.lastScreenCoverage).toFixed(2)}%, Volume ${m.toFixed(1)}
852
864
  ${e.name}`);
853
865
  }
854
866
  break;
@@ -859,10 +871,10 @@ ${e.name}`);
859
871
  s.texture_lod = 0;
860
872
  }
861
873
  };
862
- let R = C;
874
+ let G = C;
863
875
  B = new WeakMap(), W = new WeakMap(), pe = new WeakMap(), j = new WeakMap(), ee = new WeakMap(), ye = new WeakMap(), q = 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.
864
876
  */
865
- f(R, "debugDrawLine"), f(R, "corner0", new V()), f(R, "corner1", new V()), f(R, "corner2", new V()), f(R, "corner3", new V()), f(R, "_tempPtInside", new V());
877
+ f(G, "debugDrawLine"), f(G, "corner0", new V()), f(G, "corner1", new V()), f(G, "corner2", new V()), f(G, "corner3", new V()), f(G, "_tempPtInside", new V());
866
878
  class it {
867
879
  constructor() {
868
880
  f(this, "frames", 0);
@@ -873,13 +885,13 @@ class it {
873
885
  f(this, "lastCentrality", 0);
874
886
  }
875
887
  }
876
- const Pe = Symbol("NEEDLE_mesh_lod"), fe = Symbol("NEEDLE_texture_lod");
888
+ const Ee = Symbol("NEEDLE_mesh_lod"), fe = Symbol("NEEDLE_texture_lod");
877
889
  let ne = null;
878
890
  function Re() {
879
891
  const a = nt();
880
892
  a && (a.mapURLs(function(t) {
881
- return Ee(), t;
882
- }), Ee(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
893
+ return Pe(), t;
894
+ }), Pe(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
883
895
  t.forEach((e) => {
884
896
  e.addedNodes.forEach((r) => {
885
897
  r instanceof HTMLElement && r.tagName.toLowerCase() === "model-viewer" && Ge(r);
@@ -893,7 +905,7 @@ function nt() {
893
905
  console.debug("[gltf-progressive] model-viewer defined"), Re();
894
906
  }), null);
895
907
  }
896
- function Ee() {
908
+ function Pe() {
897
909
  document.querySelectorAll("model-viewer").forEach((t) => {
898
910
  Ge(t);
899
911
  });
@@ -923,8 +935,8 @@ function Ge(a) {
923
935
  }
924
936
  };
925
937
  console.debug("[gltf-progressive] setup model-viewer");
926
- const s = R.get(t, { engine: "model-viewer" });
927
- return R.addPlugin(new at()), s.enable(), s.addEventListener("changed", () => {
938
+ const s = G.get(t, { engine: "model-viewer" });
939
+ return G.addPlugin(new at()), s.enable(), s.addEventListener("changed", () => {
928
940
  r == null || r.call(a);
929
941
  }), a.addEventListener("model-visibility", (i) => {
930
942
  i.detail.visible && (r == null || r.call(a));
@@ -970,17 +982,17 @@ class at {
970
982
  for (let w = 0; w < u.length; w++) {
971
983
  const v = u[w], M = l[v];
972
984
  if ((M == null ? void 0 : M.isTexture) === !0) {
973
- const G = (d = (c = M.userData) == null ? void 0 : c.associations) == null ? void 0 : d.textures;
974
- if (G == null)
985
+ const F = (d = (c = M.userData) == null ? void 0 : c.associations) == null ? void 0 : d.textures;
986
+ if (F == null)
975
987
  continue;
976
- const $ = r.parser.json.textures[G];
977
- if (!$) {
978
- console.warn("Texture data not found for texture index " + G);
988
+ const U = r.parser.json.textures[F];
989
+ if (!U) {
990
+ console.warn("Texture data not found for texture index " + F);
979
991
  continue;
980
992
  }
981
- if ((h = $ == null ? void 0 : $.extensions) != null && h[N]) {
982
- const y = $.extensions[N];
983
- y && s && b.registerTexture(s, M, y.lods.length, G, y);
993
+ if ((h = U == null ? void 0 : U.extensions) != null && h[N]) {
994
+ const g = U.extensions[N];
995
+ g && s && b.registerTexture(s, M, g.lods.length, F, g);
984
996
  }
985
997
  }
986
998
  }
@@ -995,9 +1007,9 @@ class at {
995
1007
  }
996
1008
  tryParseMeshLOD(t, e) {
997
1009
  var i, o;
998
- if (e[Pe] == !0)
1010
+ if (e[Ee] == !0)
999
1011
  return;
1000
- e[Pe] = !0;
1012
+ e[Ee] = !0;
1001
1013
  const r = this.tryGetCurrentModelViewer(t), n = this.getUrl(r);
1002
1014
  if (!n)
1003
1015
  return;
@@ -1010,18 +1022,18 @@ class at {
1010
1022
  }
1011
1023
  function mt(a, t, e, r) {
1012
1024
  Ie(t), ke(e), e.register((s) => new b(s, a));
1013
- const n = R.get(t);
1025
+ const n = G.get(t);
1014
1026
  return (r == null ? void 0 : r.enableLODsManager) !== !1 && n.enable(), n;
1015
1027
  }
1016
1028
  Re();
1017
1029
  export {
1018
1030
  N as EXTENSION_NAME,
1019
- R as LODsManager,
1031
+ G as LODsManager,
1020
1032
  b as NEEDLE_progressive,
1021
1033
  Be as VERSION,
1022
1034
  ke as addDracoAndKTX2Loaders,
1023
1035
  Ie as createLoaders,
1024
- _e as getRaycastMesh,
1036
+ me as getRaycastMesh,
1025
1037
  Re as patchModelViewer,
1026
1038
  et as registerRaycastMesh,
1027
1039
  gt as setDracoDecoderLocation,
@@ -1,8 +1,8 @@
1
- var Re=Object.defineProperty,Ge=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Ge(t,typeof e!="symbol"?e+"":e,r),r),be=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(be(t,e,"read from private field"),r?r.call(t):e.get(t)),q=(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)},F=(t,e,r,n)=>(be(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ne,Mesh as X,Material as Fe,Texture as Q,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as Ue,Sphere as ze,Box3 as Te,Vector3 as W}from"three";import{GLTFLoader as Ve}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Xe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let ie="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",pe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ie+"draco_decoder.js",{method:"head"}).catch(t=>{ie="./include/draco/",pe="./include/ktx2/"});function He(t){ie=t}function Ye(t){pe=t}let K,le,H;function ve(t){return K||(K=new Xe,K.setDecoderPath(ie),K.setDecoderConfig({type:"js"})),H||(H=new Ke,H.setTranscoderPath(pe)),le||(le=qe),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:le}}function xe(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(H),t.meshoptDecoder||t.setMeshoptDecoder(le)}Z("debugprogressive");function Z(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const 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 ae;function Qe(){return ae!==void 0||(ae=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ae)),ae}const ye=Symbol("needle:raycast-mesh");function ue(t){return t?.[ye]instanceof ne?t[ye]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ue(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[ye]=r}}function Ze(t=!0){if(t){if(ee)return;const e=ee=X.prototype.raycast;X.prototype.raycast=function(r,n){const s=this,o=ue(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!ee)return;X.prototype.raycast=ee,ee=null}}let ee=null;function et(t){const e=new ne;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const $=new Array,j="NEEDLE_progressive",y=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),te=new Map,Me=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,te),te.forEach((s,o)=>{for(const i of s.keys){const l=o[i];if(l!=null){if(l.isBufferGeometry===!0){const u=O.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,O.assignMeshLOD(o,a),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,O.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,Me&&Me.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ae(t,e,r){var n;if(!y)return;te.has(t)||te.set(t,{keys:[],sourceId:r});const s=te.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const D=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[j];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&D.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,void 0,o),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const 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 l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&o(l,e)}return t[n]=e,e;function o(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const v=a.lods[h];v.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,v.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,v.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 X||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of $)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,D.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&&Ae(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 Fe||t.isMaterial===!0){const r=t,n=[],s=new Array;if(y&&Me.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const o=r;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i);n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,o);n.push(l),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let l=0;l<o.length;l++){const u=o[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof 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):D.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&&Ae(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[j];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,D.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&D.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[j];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&D.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=y=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const h=t;h.source&&h.source[Le]&&(a=h.source[Le])}if(a||(a=D.lodInfos.get(u)),a){if(e>0){let g=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?g=!0:A||(g=!0),g)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!h)return y&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const v=Je(l.url,h);if(v.endsWith(".glb")||v.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const g=v+"_"+a.guid,A=this.previouslyLoaded.get(g);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${g}`);let m=await A.catch(T=>(console.error(`Error loading LOD ${e} from ${v}
2
- `,T),null)),p=!1;if(m==null||(m instanceof Q&&t instanceof Q?(n=m.image)!=null&&n.data||(s=m.source)!=null&&s.data?m=this.copySettings(t,m):(p=!0,this.previouslyLoaded.delete(g)):m instanceof ne&&t instanceof ne&&((o=m.attributes.position)!=null&&o.array||(p=!0,this.previouslyLoaded.delete(g)))),!p)return m}const w=a,I=new Promise(async(m,p)=>{const T=new Ve;xe(T),y&&(await new Promise(f=>setTimeout(f,1e3)),i&&console.warn("Start loading (delayed) "+v,w.guid));let C=v;if(w&&Array.isArray(w.lods)){const f=w.lods[e];f.hash&&(C+="?v="+f.hash)}const M=await T.loadAsync(C).catch(f=>(console.error(`Error loading LOD ${e} from ${v}
3
- `,f),null));if(!M)return null;const G=M.parser;i&&console.log("Loading finished "+v,w.guid);let E=0;if(M.parser.json.textures){let f=!1;for(const d of M.parser.json.textures){if(d!=null&&d.extensions){const L=d?.extensions[j];if(L!=null&&L.guid&&L.guid===w.guid){f=!0;break}}E++}if(f){let d=await G.getDependency("texture",E);return d&&D.assignLODInformation(l.url,d,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',v,E,d,g),t instanceof Q&&(d=this.copySettings(t,d)),d&&(d.guid=w.guid),m(d)}else y&&console.warn("Could not find texture with guid",w.guid,M.parser.json)}if(E=0,M.parser.json.meshes){let f=!1;for(const d of M.parser.json.meshes){if(d!=null&&d.extensions){const L=d?.extensions[j];if(L!=null&&L.guid&&L.guid===w.guid){f=!0;break}}E++}if(f){const d=await G.getDependency("mesh",E),L=w;if(i&&console.log(`Loaded Mesh "${d.name}"`,v,E,d,g),d.isMesh===!0){const _=d.geometry;return D.assignLODInformation(l.url,_,u,e,void 0,L.density),m(_)}else{const _=new Array;for(let b=0;b<d.children.length;b++){const N=d.children[b];if(N.isMesh===!0){const V=N.geometry;D.assignLODInformation(l.url,V,u,e,b,L.density),_.push(V)}}return m(_)}}else y&&console.warn("Could not find mesh with guid",w.guid,M.parser.json)}return m(null)});return this.previouslyLoaded.set(g,I),await I}else if(t instanceof Q){i&&console.log("Load texture from uri: "+v);const g=await new We().loadAsync(v);return g?(g.guid=a.guid,g.flipY=!1,g.needsUpdate=!0,g.colorSpace=t.colorSpace,i&&console.log(a,g)):y&&console.warn("failed loading",v),g}}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 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(),y&&console.warn(`Copying texture settings
1
+ var Re=Object.defineProperty,Fe=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Fe(t,typeof e!="symbol"?e+"":e,r),r),be=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(be(t,e,"read from private field"),r?r.call(t):e.get(t)),q=(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)=>(be(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ie,Mesh as X,Material as Ge,Texture as Q,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as Ue,Sphere as ze,Box3 as Te,Vector3 as W}from"three";import{GLTFLoader as Ve}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Xe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let le="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",pe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(le+"draco_decoder.js",{method:"head"}).catch(t=>{le="./include/draco/",pe="./include/ktx2/"});function He(t){le=t}function Ye(t){pe=t}let K,ae,H;function ve(t){return K||(K=new Xe,K.setDecoderPath(le),K.setDecoderConfig({type:"js"})),H||(H=new Ke,H.setTranscoderPath(pe)),ae||(ae=qe),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 xe(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 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 ue;function Qe(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const ye=Symbol("needle:raycast-mesh");function ee(t){return t?.[ye]instanceof ie?t[ye]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[ye]=r}}function Ze(t=!0){if(t){if(te)return;const e=te=X.prototype.raycast;X.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;X.prototype.raycast=te,te=null}}let te=null;function et(t){const e=new ie;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const $=new Array,j="NEEDLE_progressive",y=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),re=new Map,Me=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 l=o[i];if(l!=null){if(l.isBufferGeometry===!0){const u=O.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,O.assignMeshLOD(o,a),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,O.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,Me&&Me.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ae(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 D=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[j];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&D.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,void 0,o),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const 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 l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&o(l,e)}return t[n]=e,e;function o(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const v=a.lods[h];v.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,v.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,v.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 X||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of $)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,D.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&&Ae(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&&Me.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const o=r;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i);n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,o);n.push(l),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let l=0;l<o.length;l++){const u=o[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof 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):D.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&&Ae(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[j];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,D.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&D.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[j];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&D.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=y=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const h=t;h.source&&h.source[Le]&&(a=h.source[Le])}if(a||(a=D.lodInfos.get(u)),a){if(e>0){let f=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?f=!0:A||(f=!0),f)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!h)return y&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const v=Je(l.url,h);if(v.endsWith(".glb")||v.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=v+"_"+a.guid,A=this.previouslyLoaded.get(f);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let g=await A.catch(b=>(console.error(`Error loading LOD ${e} from ${v}
2
+ `,b),null)),p=!1;if(g==null||(g instanceof Q&&t instanceof Q?(n=g.image)!=null&&n.data||(s=g.source)!=null&&s.data?g=this.copySettings(t,g):(p=!0,this.previouslyLoaded.delete(f)):g instanceof ie&&t instanceof ie&&((o=g.attributes.position)!=null&&o.array||(p=!0,this.previouslyLoaded.delete(f)))),!p)return g}const w=a,I=new Promise(async(g,p)=>{const b=new Ve;xe(b),y&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+v,w.guid));let C=v;if(w&&Array.isArray(w.lods)){const m=w.lods[e];m.hash&&(C+="?v="+m.hash)}const M=await b.loadAsync(C).catch(m=>(console.error(`Error loading LOD ${e} from ${v}
3
+ `,m),null));if(!M)return null;const F=M.parser;i&&console.log("Loading finished "+v,w.guid);let E=0;if(M.parser.json.textures){let m=!1;for(const d of M.parser.json.textures){if(d!=null&&d.extensions){const L=d?.extensions[j];if(L!=null&&L.guid&&L.guid===w.guid){m=!0;break}}E++}if(m){let d=await F.getDependency("texture",E);return d&&D.assignLODInformation(l.url,d,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',v,E,d,f),t instanceof Q&&(d=this.copySettings(t,d)),d&&(d.guid=w.guid),g(d)}else y&&console.warn("Could not find texture with guid",w.guid,M.parser.json)}if(E=0,M.parser.json.meshes){let m=!1;for(const d of M.parser.json.meshes){if(d!=null&&d.extensions){const L=d?.extensions[j];if(L!=null&&L.guid&&L.guid===w.guid){m=!0;break}}E++}if(m){const d=await F.getDependency("mesh",E),L=w;if(i&&console.log(`Loaded Mesh "${d.name}"`,v,E,d,f),d.isMesh===!0){const _=d.geometry;return D.assignLODInformation(l.url,_,u,e,void 0,L.density),g(_)}else{const _=new Array;for(let S=0;S<d.children.length;S++){const N=d.children[S];if(N.isMesh===!0){const V=N.geometry;D.assignLODInformation(l.url,V,u,e,S,L.density),_.push(V)}}return g(_)}}else y&&console.warn("Could not find mesh with guid",w.guid,M.parser.json)}return g(null)});return this.previouslyLoaded.set(f,I),await I}else if(t instanceof Q){i&&console.log("Load texture from uri: "+v);const f=await new We().loadAsync(v);return f?(f.guid=a.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(a,f)):y&&console.warn("failed loading",v),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,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(),y&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=D;c(O,"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[Le]=s);const o=s.guid;D.assignLODInformation(t,e,o,r,n,void 0),D.lodInfos.set(o,s),D.lowresCache.set(o,e)}),c(O,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const l=r.geometry;if(!l){y&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),D.assignLODInformation(t,l,e,n,s,o.density),D.lodInfos.set(e,o);let u=D.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],D.lowresCache.set(e,u),n>0&&!ue(r)&&Ee(r,l);for(const a of $)(i=a.onRegisteredNewMesh)==null||i.call(a,r,o)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"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 B=Z("debugprogressive"),rt=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),Y=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var S,U,_e,J,re,ce,z;const P=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Se),c(this,"cameraFrustrum",new Ne),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),q(this,S,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),q(this,U,void 0),q(this,_e,new $e),q(this,J,0),q(this,re,0),q(this,ce,0),q(this,z,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new ze),c(this,"_tempBox",new Te),c(this,"_tempBox2",new Te),c(this,"tempMatrix",new Se),c(this,"_tempWorldPosition",new W),c(this,"_tempBoxSize",new W),c(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){$.push(t)}static removePlugin(t){const e=$.indexOf(t);e>=0&&$.splice(e,1)}static get(t,e){if(t[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const r=new P(t,{engine:"unknown",...e});return t[De]=r,r}get plugins(){return $}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(x(this,U))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;F(this,U,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,F(e,J,x(e,J)+1),F(e,re,x(e,_e).getDelta()),F(e,ce,x(e,ce)+x(e,re)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,re)),F(e,z,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),B&&x(e,J)%30===0&&console.log("FPS",Math.round(x(e,z)),"Interval:",x(e,S)));const o=t++;x(e,U).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,U)&&(this.renderer.render=x(this,U),F(this,U,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,z)<40&&x(this,S)<10?(F(this,S,x(this,S)+1),B&&console.warn("\u2193 Reducing LOD updates",x(this,S),x(this,z).toFixed(0))):x(this,z)>=60&&x(this,S)>1&&(F(this,S,x(this,S)-1),B&&console.warn("\u2191 Increasing LOD updates",x(this,S),x(this,z).toFixed(0))):F(this,S,this.updateInterval),x(this,S)>0&&x(this,J)%x(this,S)!=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),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=a.geometry)==null?void 0:n.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){B&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(B==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const v=Math.random()*16777215,g=new Ue({color:v});a.object.material=g}const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=s.transparent;for(const a of l){const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const a of u){const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[we];if(i||(i=new st,r[we]=i),i.frames++<2)return;for(const u of $)(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 l=k.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of $)(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,O.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 O.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,i;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,u=!1;if(B&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),h=a?.lods,v=h&&h.length>0,g=O.getMaterialMinMaxLODsCount(e.material),A=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!v&&!A){s.mesh_lod=0,s.texture_lod=0;return}if(v||(u=!0,l=0),!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e))){s.mesh_lod=99,s.texture_lod=99;return}const w=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let I=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),I=m.boundingBox}if(I&&t.isPerspectiveCamera){const m=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(I),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.fov>70){const f=this._tempBox.min,d=this._tempBox.max;let L=f.x,_=f.y,b=d.x,N=d.y;const V=2,ge=1.5,se=(f.x+d.x)*.5,oe=(f.y+d.y)*.5;L=(L-se)*V+se,_=(_-oe)*V+oe,b=(b-se)*V+se,N=(N-oe)*V+oe;const Ce=L<0&&b>0?0:Math.min(Math.abs(f.x),Math.abs(d.x)),je=_<0&&N>0?0:Math.min(Math.abs(f.y),Math.abs(d.y)),fe=Math.max(Ce,je);r.lastCentrality=(ge-fe)*(ge-fe)*(ge-fe)}else r.lastCentrality=1;const p=this._tempBox.getSize(this._tempBoxSize);p.multiplyScalar(.5),screen.availHeight>0&&w>0&&p.multiplyScalar(w/screen.availHeight),p.x*=m.aspect;const T=t.matrixWorldInverse,C=this._tempBox2;C.copy(I),C.applyMatrix4(e.matrixWorld),C.applyMatrix4(T);const M=C.getSize(this._tempBox2Size),G=Math.max(M.x,M.y);if(Math.max(p.x,p.y)!=0&&G!=0&&(p.z=M.z/Math.max(M.x,M.y)*Math.max(p.x,p.y)),r.lastScreenCoverage=Math.max(p.x,p.y,p.z),r.lastScreenspaceVolume.copy(p),r.lastScreenCoverage*=r.lastCentrality,B&&P.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const d=P.corner0,L=P.corner1,_=P.corner2,b=P.corner3;d.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=d.x,_.copy(this._tempBox.max),_.y=d.y,b.copy(this._tempBox.max);const N=(d.z+b.z)*.5;d.z=L.z=_.z=b.z=N,d.applyMatrix4(f),L.applyMatrix4(f),_.applyMatrix4(f),b.applyMatrix4(f),P.debugDrawLine(d,L,255),P.debugDrawLine(d,_,255),P.debugDrawLine(L,b,255),P.debugDrawLine(_,b,255)}let E=999;if(h&&r.lastScreenCoverage>0){for(let f=0;f<h.length;f++)if(h[f].density/r.lastScreenCoverage<n){E=f;break}}E<l&&(l=E,u=!0)}if(u?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,B&&s.mesh_lod!=r.lastLodLevel_Mesh){const m=h?.[s.mesh_lod];m&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`)}if(A){const m="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,B){const p=g.lods[g.max_count-1];B&&console.log(`First Texture LOD ${s.texture_lod} (${p.max_height}px) - ${e.name}`)}}else{const p=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let T=r.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(T*=2);const C=w/window.devicePixelRatio*T;for(let M=g.lods.length-1;M>=0;M--){let G=g.lods[M];if(!(m&&G.max_height>=2048)&&!(Qe()&&G.max_height>4096)&&G.max_height>C){if(s.texture_lod=M,s.texture_lod<r.lastLodLevel_Texture){const E=G.max_height;B&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${E}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;c(O,"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[Le]=s);const o=s.guid;D.assignLODInformation(t,e,o,r,n,void 0),D.lodInfos.set(o,s),D.lowresCache.set(o,e)}),c(O,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const l=r.geometry;if(!l){y&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),D.assignLODInformation(t,l,e,n,s,o.density),D.lodInfos.set(e,o);let u=D.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],D.lowresCache.set(e,u),n>0&&!ee(r)&&Ee(r,l);for(const a of $)(i=a.onRegisteredNewMesh)==null||i.call(a,r,o)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"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 B=Z("debugprogressive"),rt=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),Y=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var T,U,_e,J,se,ce,z;const P=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Se),c(this,"cameraFrustrum",new Ne),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),q(this,T,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),q(this,U,void 0),q(this,_e,new $e),q(this,J,0),q(this,se,0),q(this,ce,0),q(this,z,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new ze),c(this,"_tempBox",new Te),c(this,"_tempBox2",new Te),c(this,"tempMatrix",new Se),c(this,"_tempWorldPosition",new W),c(this,"_tempBoxSize",new W),c(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){$.push(t)}static removePlugin(t){const e=$.indexOf(t);e>=0&&$.splice(e,1)}static get(t,e){if(t[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const r=new P(t,{engine:"unknown",...e});return t[De]=r,r}get plugins(){return $}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,U))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,U,this.renderer.render);const e=this;ve(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,_e).getDelta()),G(e,ce,x(e,ce)+x(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,se)),G(e,z,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),B&&x(e,J)%30===0&&console.log("FPS",Math.round(x(e,z)),"Interval:",x(e,T)));const o=t++;x(e,U).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,U)&&(this.renderer.render=x(this,U),G(this,U,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,z)<40&&x(this,T)<10?(G(this,T,x(this,T)+1),B&&console.warn("\u2193 Reducing LOD updates",x(this,T),x(this,z).toFixed(0))):x(this,z)>=60&&x(this,T)>1&&(G(this,T,x(this,T)-1),B&&console.warn("\u2191 Increasing LOD updates",x(this,T),x(this,z).toFixed(0))):G(this,T,this.updateInterval),x(this,T)>0&&x(this,J)%x(this,T)!=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),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=a.geometry)==null?void 0:n.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){B&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(B==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const v=Math.random()*16777215,f=new Ue({color:v});a.object.material=f}const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=s.transparent;for(const a of l){const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const a of u){const h=a.object;(h instanceof X||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[we];if(i||(i=new st,r[we]=i),i.frames++<2)return;for(const u of $)(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 l=k.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of $)(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,O.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 O.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,i;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,u=!1;if(B&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),h=a?.lods,v=h&&h.length>0,f=O.getMaterialMinMaxLODsCount(e.material),A=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!v&&!A){s.mesh_lod=0,s.texture_lod=0;return}if(v||(u=!0,l=0),!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e))){s.mesh_lod=100,s.texture_lod=100;return}const w=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let I=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const g=e;if(!g.boundingBox)g.computeBoundingBox();else if(r.frames%30===0){const p=ee(g),b=g.geometry;p&&(g.geometry=p),g.computeBoundingBox(),g.geometry=b}I=g.boundingBox}if(I&&t.isPerspectiveCamera){const g=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const m=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(I),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&g.fov>70){const m=this._tempBox.min,d=this._tempBox.max;let L=m.x,_=m.y,S=d.x,N=d.y;const V=2,ge=1.5,oe=(m.x+d.x)*.5,ne=(m.y+d.y)*.5;L=(L-oe)*V+oe,_=(_-ne)*V+ne,S=(S-oe)*V+oe,N=(N-ne)*V+ne;const Ce=L<0&&S>0?0:Math.min(Math.abs(m.x),Math.abs(d.x)),je=_<0&&N>0?0:Math.min(Math.abs(m.y),Math.abs(d.y)),fe=Math.max(Ce,je);r.lastCentrality=(ge-fe)*(ge-fe)*(ge-fe)}else r.lastCentrality=1;const p=this._tempBox.getSize(this._tempBoxSize);p.multiplyScalar(.5),screen.availHeight>0&&w>0&&p.multiplyScalar(w/screen.availHeight),p.x*=g.aspect;const b=t.matrixWorldInverse,C=this._tempBox2;C.copy(I),C.applyMatrix4(e.matrixWorld),C.applyMatrix4(b);const M=C.getSize(this._tempBox2Size),F=Math.max(M.x,M.y);if(Math.max(p.x,p.y)!=0&&F!=0&&(p.z=M.z/Math.max(M.x,M.y)*Math.max(p.x,p.y)),r.lastScreenCoverage=Math.max(p.x,p.y,p.z),r.lastScreenspaceVolume.copy(p),r.lastScreenCoverage*=r.lastCentrality,B&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const d=P.corner0,L=P.corner1,_=P.corner2,S=P.corner3;d.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=d.x,_.copy(this._tempBox.max),_.y=d.y,S.copy(this._tempBox.max);const N=(d.z+S.z)*.5;d.z=L.z=_.z=S.z=N,d.applyMatrix4(m),L.applyMatrix4(m),_.applyMatrix4(m),S.applyMatrix4(m),P.debugDrawLine(d,L,255),P.debugDrawLine(d,_,255),P.debugDrawLine(L,S,255),P.debugDrawLine(_,S,255)}let E=999;if(h&&r.lastScreenCoverage>0){for(let m=0;m<h.length;m++)if(h[m].density/r.lastScreenCoverage<n){E=m;break}}E<l&&(l=E,u=!0)}if(u?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,B&&s.mesh_lod!=r.lastLodLevel_Mesh){const g=h?.[s.mesh_lod];g&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${g.density.toFixed(0)}) - ${e.name}`)}if(A){const g="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=f.max_count-1,B){const p=f.lods[f.max_count-1];B&&console.log(`First Texture LOD ${s.texture_lod} (${p.max_height}px) - ${e.name}`)}}else{const p=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let b=r.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(b*=2);const C=w/window.devicePixelRatio*b;for(let M=f.lods.length-1;M>=0;M--){let F=f.lods[M];if(!(g&&F.max_height>=2048)&&!(Qe()&&F.max_height>4096)&&F.max_height>C){if(s.texture_lod=M,s.texture_lod<r.lastLodLevel_Texture){const E=F.max_height;B&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${E}px
6
6
  Screensize: ${C.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${p.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};let R=P;S=new WeakMap,U=new WeakMap,_e=new WeakMap,J=new WeakMap,re=new WeakMap,ce=new WeakMap,z=new WeakMap,c(R,"debugDrawLine"),c(R,"corner0",new W),c(R,"corner1",new W),c(R,"corner2",new W),c(R,"corner3",new W),c(R,"_tempPtInside",new W);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 W),c(this,"lastCentrality",0)}}const Ie=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let he=null;function Oe(){const t=ot();t&&(t.mapURLs(function(e){return Pe(),e}),Pe(),he?.disconnect(),he=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&ke(n)})})}),he.observe(document,{childList:!0,subtree:!0}))}function ot(){return customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Pe(){document.querySelectorAll("model-viewer").forEach(t=>{ke(t)})}const Be=new WeakSet;let nt=0;function ke(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(a=>a.toString()=="Symbol(renderer)"),l=o.find(a=>a.toString()=="Symbol(scene)"),u=o.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=R.get(e,{engine:"model-viewer"});return R.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[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 a,h,v;if(u[de]==!0)return;u[de]=!0,u.userData&&(u.userData.LOD=-1);const g=Object.keys(u);for(let A=0;A<g.length;A++){const w=g[A],I=u[w];if(I?.isTexture===!0){const m=(h=(a=I.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(m==null)continue;const p=n.parser.json.textures[m];if(!p){console.warn("Texture data not found for texture index "+m);continue}if((v=p?.extensions)!=null&&v[j]){const T=p.extensions[j];T&&o&&O.registerTexture(o,I,T.lods.length,m,T)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var n,s;if(r[Ie]==!0)return;r[Ie]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const l=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[j];if(l&&i){const u=r.uuid;O.registerMesh(i,u,r,0,l.lods.length,l)}}}function lt(t,e,r,n){ve(e),xe(r),r.register(o=>new O(o,t));const s=R.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}Oe();export{j as EXTENSION_NAME,R as LODsManager,O as NEEDLE_progressive,me as VERSION,xe as addDracoAndKTX2Loaders,ve as createLoaders,ue as getRaycastMesh,Oe as patchModelViewer,Ee as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}};let R=P;T=new WeakMap,U=new WeakMap,_e=new WeakMap,J=new WeakMap,se=new WeakMap,ce=new WeakMap,z=new WeakMap,c(R,"debugDrawLine"),c(R,"corner0",new W),c(R,"corner1",new W),c(R,"corner2",new W),c(R,"corner3",new W),c(R,"_tempPtInside",new W);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 W),c(this,"lastCentrality",0)}}const Ie=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let he=null;function Oe(){const t=ot();t&&(t.mapURLs(function(e){return Pe(),e}),Pe(),he?.disconnect(),he=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&ke(n)})})}),he.observe(document,{childList:!0,subtree:!0}))}function ot(){return customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Pe(){document.querySelectorAll("model-viewer").forEach(t=>{ke(t)})}const Be=new WeakSet;let nt=0;function ke(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(a=>a.toString()=="Symbol(renderer)"),l=o.find(a=>a.toString()=="Symbol(scene)"),u=o.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=R.get(e,{engine:"model-viewer"});return R.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[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 a,h,v;if(u[de]==!0)return;u[de]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let A=0;A<f.length;A++){const w=f[A],I=u[w];if(I?.isTexture===!0){const g=(h=(a=I.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(g==null)continue;const p=n.parser.json.textures[g];if(!p){console.warn("Texture data not found for texture index "+g);continue}if((v=p?.extensions)!=null&&v[j]){const b=p.extensions[j];b&&o&&O.registerTexture(o,I,b.lods.length,g,b)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var n,s;if(r[Ie]==!0)return;r[Ie]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const l=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[j];if(l&&i){const u=r.uuid;O.registerMesh(i,u,r,0,l.lods.length,l)}}}function lt(t,e,r,n){ve(e),xe(r),r.register(o=>new O(o,t));const s=R.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}Oe();export{j as EXTENSION_NAME,R as LODsManager,O as NEEDLE_progressive,me as VERSION,xe as addDracoAndKTX2Loaders,ve as createLoaders,ee as getRaycastMesh,Oe as patchModelViewer,Ee as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
@@ -1,8 +1,8 @@
1
- "use strict";var ke=Object.defineProperty;var Ge=(a,t,e)=>t in a?ke(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var f=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},V=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let fe="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ve="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(fe+"draco_decoder.js",{method:"head"}).catch(a=>{fe="./include/draco/",ve="./include/ktx2/"});function Ue(a){fe=a}function ze(a){ve=a}let j,ue,J;function _e(a){return j||(j=new $e.DRACOLoader,j.setDecoderPath(fe),j.setDecoderConfig({type:"js"})),J||(J=new Ne.KTX2Loader,J.setTranscoderPath(ve)),ue||(ue=Ve.MeshoptDecoder),a?J.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:ue}}function Oe(a){a.dracoLoader||a.setDRACOLoader(j),a.ktx2Loader||a.setKTX2Loader(J),a.meshoptDecoder||a.setMeshoptDecoder(ue)}oe("debugprogressive");function oe(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let te;function qe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),oe("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ge(a){return(a==null?void 0:a[Me])instanceof d.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ge(a)){const r=Ke(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Xe(a=!0){if(a){if(re)return;const t=re=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const o=this,s=ge(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;d.Mesh.prototype.raycast=re,re=null}}let re=null;function Ke(a){const t=new d.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,$="NEEDLE_progressive",x=oe("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=b.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,b.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,b.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 Te(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 O=class{constructor(t,e){f(this,"parser");f(this,"url");f(this,"_isLoadingMesh");f(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&O.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 $}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 h=0;h<c.lods.length;h++){const g=c.lods[h];g.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,g.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,g.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 d.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,O.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&&Te(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 d.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);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 d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(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&&Te(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[$];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,O.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&&O.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[$];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&&O.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 h=t;h.source&&h.source[me]&&(i=h.source[me])}if(i||(i=O.lodInfos.get(s)),i){if(e>0){let v=!1;const _=Array.isArray(i.lods);if(_&&e>=i.lods.length?v=!0:_||(v=!0),v)return this.lowresCache.get(s)}const h=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!h)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const g=We(o.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const v=g+"_"+i.guid,_=this.previouslyLoaded.get(v);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${v}`);let m=await _.catch(U=>(console.error(`Error loading LOD ${e} from ${g}
2
- `,U),null)),M=!1;if(m==null||(m instanceof d.Texture&&t instanceof d.Texture?(l=m.image)!=null&&l.data||(u=m.source)!=null&&u.data?m=this.copySettings(t,m):(M=!0,this.previouslyLoaded.delete(v)):m instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&((c=m.attributes.position)!=null&&c.array||(M=!0,this.previouslyLoaded.delete(v)))),!M)return m}const D=i,F=new Promise(async(m,M)=>{const U=new Fe.GLTFLoader;Oe(U),x&&(await new Promise(S=>setTimeout(S,1e3)),r&&console.warn("Start loading (delayed) "+g,D.guid));let X=g;if(D&&Array.isArray(D.lods)){const S=D.lods[e];S.hash&&(X+="?v="+S.hash)}const T=await U.loadAsync(X).catch(S=>(console.error(`Error loading LOD ${e} from ${g}
3
- `,S),null));if(!T)return null;const z=T.parser;r&&console.log("Loading finished "+g,D.guid);let E=0;if(T.parser.json.textures){let S=!1;for(const y of T.parser.json.textures){if(y!=null&&y.extensions){const p=y==null?void 0:y.extensions[$];if(p!=null&&p.guid&&p.guid===D.guid){S=!0;break}}E++}if(S){let y=await z.getDependency("texture",E);return y&&O.assignLODInformation(o.url,y,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+y.name+'"',g,E,y,v),t instanceof d.Texture&&(y=this.copySettings(t,y)),y&&(y.guid=D.guid),m(y)}else x&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(E=0,T.parser.json.meshes){let S=!1;for(const y of T.parser.json.meshes){if(y!=null&&y.extensions){const p=y==null?void 0:y.extensions[$];if(p!=null&&p.guid&&p.guid===D.guid){S=!0;break}}E++}if(S){const y=await z.getDependency("mesh",E),p=D;if(r&&console.log(`Loaded Mesh "${y.name}"`,g,E,y,v),y.isMesh===!0){const w=y.geometry;return O.assignLODInformation(o.url,w,s,e,void 0,p.density),m(w)}else{const w=new Array;for(let A=0;A<y.children.length;A++){const P=y.children[A];if(P.isMesh===!0){const C=P.geometry;O.assignLODInformation(o.url,C,s,e,A,p.density),w.push(C)}}return m(w)}}else x&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return m(null)});return this.previouslyLoaded.set(v,F),await F}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+g);const _=await new d.TextureLoader().loadAsync(g);return _?(_.guid=i.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=t.colorSpace,r&&console.log(i,_)):x&&console.warn("failed loading",g),_}}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 Ye(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
1
+ "use strict";var ke=Object.defineProperty;var Ge=(a,t,e)=>t in a?ke(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var f=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},$=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let de="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ve="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(de+"draco_decoder.js",{method:"head"}).catch(a=>{de="./include/draco/",ve="./include/ktx2/"});function Ue(a){de=a}function ze(a){ve=a}let j,fe,J;function _e(a){return j||(j=new $e.DRACOLoader,j.setDecoderPath(de),j.setDecoderConfig({type:"js"})),J||(J=new Ne.KTX2Loader,J.setTranscoderPath(ve)),fe||(fe=Ve.MeshoptDecoder),a?J.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:fe}}function Oe(a){a.dracoLoader||a.setDRACOLoader(j),a.ktx2Loader||a.setKTX2Loader(J),a.meshoptDecoder||a.setMeshoptDecoder(fe)}oe("debugprogressive");function oe(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let te;function qe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),oe("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ne(a){return(a==null?void 0:a[Me])instanceof d.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ne(a)){const r=Ke(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Xe(a=!0){if(a){if(re)return;const t=re=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const o=this,s=ne(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;d.Mesh.prototype.raycast=re,re=null}}let re=null;function Ke(a){const t=new d.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,N="NEEDLE_progressive",M=oe("debugprogressive"),me=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(M){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=b.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,b.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,b.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 Te(a,t,e){var o;if(!M)return;ie.has(a)||ie.set(a,{keys:[],sourceId:e});const r=ie.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const O=class{constructor(t,e){f(this,"parser");f(this,"url");f(this,"_isLoadingMesh");f(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[N];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&O.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});M&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,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(M==="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 h=0;h<c.lods.length;h++){const g=c.lods[h];g.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,g.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,g.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 d.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,O.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,M&&Te(t,"geometry",s.url)):M&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else M&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof d.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(M&&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);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 d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(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 M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(M&&o&&r){const i=this.getAssignedLODInformation(t);i&&Te(r,o,i.url)}}return s}else M=="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 M&&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[N];if(n){if(!n.lods){M&&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,O.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&&O.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[N];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&&O.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=M=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const h=t;h.source&&h.source[me]&&(i=h.source[me])}if(i||(i=O.lodInfos.get(s)),i){if(e>0){let v=!1;const _=Array.isArray(i.lods);if(_&&e>=i.lods.length?v=!0:_||(v=!0),v)return this.lowresCache.get(s)}const h=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!h)return M&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const g=We(o.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const v=g+"_"+i.guid,_=this.previouslyLoaded.get(v);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${v}`);let p=await _.catch(k=>(console.error(`Error loading LOD ${e} from ${g}
2
+ `,k),null)),x=!1;if(p==null||(p instanceof d.Texture&&t instanceof d.Texture?(l=p.image)!=null&&l.data||(u=p.source)!=null&&u.data?p=this.copySettings(t,p):(x=!0,this.previouslyLoaded.delete(v)):p instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&((c=p.attributes.position)!=null&&c.array||(x=!0,this.previouslyLoaded.delete(v)))),!x)return p}const D=i,V=new Promise(async(p,x)=>{const k=new Fe.GLTFLoader;Oe(k),M&&(await new Promise(S=>setTimeout(S,1e3)),r&&console.warn("Start loading (delayed) "+g,D.guid));let X=g;if(D&&Array.isArray(D.lods)){const S=D.lods[e];S.hash&&(X+="?v="+S.hash)}const T=await k.loadAsync(X).catch(S=>(console.error(`Error loading LOD ${e} from ${g}
3
+ `,S),null));if(!T)return null;const z=T.parser;r&&console.log("Loading finished "+g,D.guid);let E=0;if(T.parser.json.textures){let S=!1;for(const m of T.parser.json.textures){if(m!=null&&m.extensions){const y=m==null?void 0:m.extensions[N];if(y!=null&&y.guid&&y.guid===D.guid){S=!0;break}}E++}if(S){let m=await z.getDependency("texture",E);return m&&O.assignLODInformation(o.url,m,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+m.name+'"',g,E,m,v),t instanceof d.Texture&&(m=this.copySettings(t,m)),m&&(m.guid=D.guid),p(m)}else M&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(E=0,T.parser.json.meshes){let S=!1;for(const m of T.parser.json.meshes){if(m!=null&&m.extensions){const y=m==null?void 0:m.extensions[N];if(y!=null&&y.guid&&y.guid===D.guid){S=!0;break}}E++}if(S){const m=await z.getDependency("mesh",E),y=D;if(r&&console.log(`Loaded Mesh "${m.name}"`,g,E,m,v),m.isMesh===!0){const w=m.geometry;return O.assignLODInformation(o.url,w,s,e,void 0,y.density),p(w)}else{const w=new Array;for(let A=0;A<m.children.length;A++){const P=m.children[A];if(P.isMesh===!0){const C=P.geometry;O.assignLODInformation(o.url,C,s,e,A,y.density),w.push(C)}}return p(w)}}else M&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return p(null)});return this.previouslyLoaded.set(v,V),await V}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+g);const _=await new d.TextureLoader().loadAsync(g);return _?(_.guid=i.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=t.colorSpace,r&&console.log(i,_)):M&&console.warn("failed loading",g),_}}else M&&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 Ye(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(),M&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let b=O;f(b,"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;O.assignLODInformation(t,e,i,r,o,void 0),O.lodInfos.set(i,s),O.lowresCache.set(i,e)}),f(b,"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={}),O.assignLODInformation(t,n,e,o,s,i.density),O.lodInfos.set(e,i);let l=O.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(e,l),o>0&&!ge(r)&&Ce(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),f(b,"lodInfos",new Map),f(b,"previouslyLoaded",new Map),f(b,"lowresCache",new Map);class Ye{constructor(t,e,r,o,s){f(this,"url");f(this,"key");f(this,"level");f(this,"index");f(this,"density");this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const k=oe("debugprogressive"),He=oe("noprogressive"),Le=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),G={mesh_lod:-1,texture_lod:-1};var I,W,de,Q,Z,he,q;const B=class{constructor(t,e){f(this,"context");f(this,"renderer");f(this,"projectionScreenMatrix",new d.Matrix4);f(this,"cameraFrustrum",new d.Frustum);f(this,"targetTriangleDensity",2e5);f(this,"updateInterval","auto");K(this,I,1);f(this,"pause",!1);f(this,"manual",!1);f(this,"_lodchangedlisteners",[]);K(this,W,void 0);K(this,de,new d.Clock);K(this,Q,0);K(this,Z,0);K(this,he,0);K(this,q,0);f(this,"_fpsBuffer",[60,60,60,60,60]);f(this,"_sphere",new d.Sphere);f(this,"_tempBox",new d.Box3);f(this,"_tempBox2",new d.Box3);f(this,"tempMatrix",new d.Matrix4);f(this,"_tempWorldPosition",new d.Vector3);f(this,"_tempBoxSize",new d.Vector3);f(this,"_tempBox2Size",new d.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 B(t,{engine:"unknown",...e});return t[Le]=r,r}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(L(this,W))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;V(this,W,this.renderer.render);const e=this;_e(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,V(e,Q,L(e,Q)+1),V(e,Z,L(e,de).getDelta()),V(e,he,L(e,he)+L(e,Z)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,Z)),V(e,q,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),k&&L(e,Q)%30===0&&console.log("FPS",Math.round(L(e,q)),"Interval:",L(e,I)));const i=t++;L(e,W).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,W)&&(this.renderer.render=L(this,W),V(this,W,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(He||(this.updateInterval==="auto"?L(this,q)<40&&L(this,I)<10?(V(this,I,L(this,I)+1),k&&console.warn("↓ Reducing LOD updates",L(this,I),L(this,q).toFixed(0))):L(this,q)>=60&&L(this,I)>1&&(V(this,I,L(this,I)-1),k&&console.warn("↑ Increasing LOD updates",L(this,I),L(this,q).toFixed(0))):V(this,I,this.updateInterval),L(this,I)>0&&L(this,Q)%L(this,I)!=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),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);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")){k&&(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(k==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const g=Math.random()*16777215,v=new d.MeshStandardMaterial({color:g});c.object.material=v}const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}const i=r.transparent;for(const c of i){const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}const n=r.transmissive;for(const c of n){const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[xe];if(s||(s=new je,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,G),G.mesh_lod=Math.round(G.mesh_lod),G.texture_lod=Math.round(G.texture_lod),G.mesh_lod>=0&&this.loadProgressiveMeshes(r,G.mesh_lod);let i=G.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,G);s.lastLodLevel_Mesh=G.mesh_lod,s.lastLodLevel_Texture=G.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(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 b.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,N;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(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=b.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,h=c&&c.length>0,g=b.getMaterialMinMaxLODsCount(e.material),v=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!v){s.mesh_lod=0,s.texture_lod=0;return}if(h||(l=!0,n=0),!((F=this.cameraFrustrum)!=null&&F.intersectsObject(e))){s.mesh_lod=99,s.texture_lod=99;return}const _=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),D=m.boundingBox}if(D&&t.isPerspectiveCamera){const m=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const p=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(p)){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&&m.fov>70){const p=this._tempBox.min,w=this._tempBox.max;let A=p.x,P=p.y,C=w.x,ee=w.y;const ne=2,pe=1.5,ae=(p.x+w.x)*.5,le=(p.y+w.y)*.5;A=(A-ae)*ne+ae,P=(P-le)*ne+le,C=(C-ae)*ne+ae,ee=(ee-le)*ne+le;const Ie=A<0&&C>0?0:Math.min(Math.abs(p.x),Math.abs(w.x)),Re=P<0&&ee>0?0:Math.min(Math.abs(p.y),Math.abs(w.y)),ye=Math.max(Ie,Re);r.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else r.lastCentrality=1;const M=this._tempBox.getSize(this._tempBoxSize);M.multiplyScalar(.5),screen.availHeight>0&&_>0&&M.multiplyScalar(_/screen.availHeight),M.x*=m.aspect;const U=t.matrixWorldInverse,X=this._tempBox2;X.copy(D),X.applyMatrix4(e.matrixWorld),X.applyMatrix4(U);const T=X.getSize(this._tempBox2Size),z=Math.max(T.x,T.y);if(Math.max(M.x,M.y)!=0&&z!=0&&(M.z=T.z/Math.max(T.x,T.y)*Math.max(M.x,M.y)),r.lastScreenCoverage=Math.max(M.x,M.y,M.z),r.lastScreenspaceVolume.copy(M),r.lastScreenCoverage*=r.lastCentrality,k&&B.debugDrawLine){const p=this.tempMatrix.copy(this.projectionScreenMatrix);p.invert();const w=B.corner0,A=B.corner1,P=B.corner2,C=B.corner3;w.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=w.x,P.copy(this._tempBox.max),P.y=w.y,C.copy(this._tempBox.max);const ee=(w.z+C.z)*.5;w.z=A.z=P.z=C.z=ee,w.applyMatrix4(p),A.applyMatrix4(p),P.applyMatrix4(p),C.applyMatrix4(p),B.debugDrawLine(w,A,255),B.debugDrawLine(w,P,255),B.debugDrawLine(A,C,255),B.debugDrawLine(P,C,255)}let S=999;if(c&&r.lastScreenCoverage>0){for(let p=0;p<c.length;p++)if(c[p].density/r.lastScreenCoverage<o){S=p;break}}S<n&&(n=S,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,k&&s.mesh_lod!=r.lastLodLevel_Mesh){const M=c==null?void 0:c[s.mesh_lod];M&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${M.density.toFixed(0)}) - ${e.name}`)}if(v){const m="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,k){const M=g.lods[g.max_count-1];k&&console.log(`First Texture LOD ${s.texture_lod} (${M.max_height}px) - ${e.name}`)}}else{const M=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let U=r.lastScreenCoverage*2;((N=this.context)==null?void 0:N.engine)==="model-viewer"&&(U*=2);const T=_/window.devicePixelRatio*U;for(let z=g.lods.length-1;z>=0;z--){let E=g.lods[z];if(!(m&&E.max_height>=2048)&&!(qe()&&E.max_height>4096)&&E.max_height>T){if(s.texture_lod=z,s.texture_lod<r.lastLodLevel_Texture){const S=E.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${S}px
6
- Screensize: ${T.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${M.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};let R=B;I=new WeakMap,W=new WeakMap,de=new WeakMap,Q=new WeakMap,Z=new WeakMap,he=new WeakMap,q=new WeakMap,f(R,"debugDrawLine"),f(R,"corner0",new d.Vector3),f(R,"corner1",new d.Vector3),f(R,"corner2",new d.Vector3),f(R,"corner3",new d.Vector3),f(R,"_tempPtInside",new d.Vector3);class je{constructor(){f(this,"frames",0);f(this,"lastLodLevel_Mesh",-1);f(this,"lastLodLevel_Texture",-1);f(this,"lastScreenCoverage",0);f(this,"lastScreenspaceVolume",new d.Vector3);f(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let se=null;function Se(){const a=Je();a&&(a.mapURLs(function(t){return Ee(),t}),Ee(),se==null||se.disconnect(),se=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),se.observe(document,{childList:!0,subtree:!0}))}function Je(){const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function Ee(){document.querySelectorAll("model-viewer").forEach(t=>{Be(t)})}const Pe=new WeakSet;let Qe=0;function Be(a){if(!a||Pe.has(a))return null;Pe.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++Qe+`
8
- `,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const 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=R.get(t,{engine:"model-viewer"});return R.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(){f(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,h,g;if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let v=0;v<u.length;v++){const _=u[v],D=l[_];if((D==null?void 0:D.isTexture)===!0){const F=(h=(c=D.userData)==null?void 0:c.associations)==null?void 0:h.textures;if(F==null)continue;const N=r.parser.json.textures[F];if(!N){console.warn("Texture data not found for texture index "+F);continue}if((g=N==null?void 0:N.extensions)!=null&&g[$]){const m=N.extensions[$];m&&s&&b.registerTexture(s,D,m.lods.length,F,m)}}}};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[Ae]==!0)return;e[Ae]=!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[$];if(s&&o){const l=e.uuid;b.registerMesh(o,l,e,0,s.lods.length,s)}}}function et(a,t,e,r){_e(t),Oe(e),e.register(s=>new b(s,a));const o=R.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Se();exports.EXTENSION_NAME=$;exports.LODsManager=R;exports.NEEDLE_progressive=b;exports.VERSION=we;exports.addDracoAndKTX2Loaders=Oe;exports.createLoaders=_e;exports.getRaycastMesh=ge;exports.patchModelViewer=Se;exports.registerRaycastMesh=Ce;exports.setDracoDecoderLocation=Ue;exports.setKTX2TranscoderLocation=ze;exports.useNeedleProgressive=et;exports.useRaycastMeshes=Xe;
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let b=O;f(b,"registerTexture",(t,e,r,o,s)=>{if(M&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){M&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[me]=s);const i=s.guid;O.assignLODInformation(t,e,i,r,o,void 0),O.lodInfos.set(i,s),O.lowresCache.set(i,e)}),f(b,"registerMesh",(t,e,r,o,s,i)=>{var u;M&&console.log("> Progressive: register mesh",s,r.name,i,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),O.assignLODInformation(t,n,e,o,s,i.density),O.lodInfos.set(e,i);let l=O.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(e,l),o>0&&!ne(r)&&Ce(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),f(b,"lodInfos",new Map),f(b,"previouslyLoaded",new Map),f(b,"lowresCache",new Map);class Ye{constructor(t,e,r,o,s){f(this,"url");f(this,"key");f(this,"level");f(this,"index");f(this,"density");this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const G=oe("debugprogressive"),He=oe("noprogressive"),xe=Symbol("Needle:LODSManager"),Le=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),F={mesh_lod:-1,texture_lod:-1};var I,W,he,Q,Z,ge,q;const B=class{constructor(t,e){f(this,"context");f(this,"renderer");f(this,"projectionScreenMatrix",new d.Matrix4);f(this,"cameraFrustrum",new d.Frustum);f(this,"targetTriangleDensity",2e5);f(this,"updateInterval","auto");K(this,I,1);f(this,"pause",!1);f(this,"manual",!1);f(this,"_lodchangedlisteners",[]);K(this,W,void 0);K(this,he,new d.Clock);K(this,Q,0);K(this,Z,0);K(this,ge,0);K(this,q,0);f(this,"_fpsBuffer",[60,60,60,60,60]);f(this,"_sphere",new d.Sphere);f(this,"_tempBox",new d.Box3);f(this,"_tempBox2",new d.Box3);f(this,"tempMatrix",new d.Matrix4);f(this,"_tempWorldPosition",new d.Vector3);f(this,"_tempBoxSize",new d.Vector3);f(this,"_tempBox2Size",new d.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[xe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[xe];const r=new B(t,{engine:"unknown",...e});return t[xe]=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,W))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;$(this,W,this.renderer.render);const e=this;_e(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,$(e,Q,L(e,Q)+1),$(e,Z,L(e,he).getDelta()),$(e,ge,L(e,ge)+L(e,Z)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,Z)),$(e,q,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),G&&L(e,Q)%30===0&&console.log("FPS",Math.round(L(e,q)),"Interval:",L(e,I)));const i=t++;L(e,W).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,W)&&(this.renderer.render=L(this,W),$(this,W,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(He||(this.updateInterval==="auto"?L(this,q)<40&&L(this,I)<10?($(this,I,L(this,I)+1),G&&console.warn("↓ Reducing LOD updates",L(this,I),L(this,q).toFixed(0))):L(this,q)>=60&&L(this,I)>1&&($(this,I,L(this,I)-1),G&&console.warn("↑ Increasing LOD updates",L(this,I),L(this,q).toFixed(0))):$(this,I,this.updateInterval),L(this,I)>0&&L(this,Q)%L(this,I)!=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),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);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 g=Math.random()*16777215,v=new d.MeshStandardMaterial({color:g});c.object.material=v}const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}const i=r.transparent;for(const c of i){const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}const n=r.transmissive;for(const c of n){const h=c.object;(h instanceof d.Mesh||h.isMesh)&&this.updateLODs(t,e,h,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[Le];if(s||(s=new je,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,F),F.mesh_lod=Math.round(F.mesh_lod),F.texture_lod=Math.round(F.texture_lod),F.mesh_lod>=0&&this.loadProgressiveMeshes(r,F.mesh_lod);let i=F.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,F);s.lastLodLevel_Mesh=F.mesh_lod,s.lastLodLevel_Texture=F.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.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 b.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 V,U;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=b.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,h=c&&c.length>0,g=b.getMaterialMinMaxLODsCount(e.material),v=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!v){s.mesh_lod=0,s.texture_lod=0;return}if(h||(l=!0,n=0),!((V=this.cameraFrustrum)!=null&&V.intersectsObject(e))){s.mesh_lod=100,s.texture_lod=100;return}const _=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const p=e;if(!p.boundingBox)p.computeBoundingBox();else if(r.frames%30===0){const x=ne(p),k=p.geometry;x&&(p.geometry=x),p.computeBoundingBox(),p.geometry=k}D=p.boundingBox}if(D&&t.isPerspectiveCamera){const p=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&&p.fov>70){const y=this._tempBox.min,w=this._tempBox.max;let A=y.x,P=y.y,C=w.x,ee=w.y;const ae=2,pe=1.5,le=(y.x+w.x)*.5,ce=(y.y+w.y)*.5;A=(A-le)*ae+le,P=(P-ce)*ae+ce,C=(C-le)*ae+le,ee=(ee-ce)*ae+ce;const Ie=A<0&&C>0?0:Math.min(Math.abs(y.x),Math.abs(w.x)),Re=P<0&&ee>0?0:Math.min(Math.abs(y.y),Math.abs(w.y)),ye=Math.max(Ie,Re);r.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else r.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&_>0&&x.multiplyScalar(_/screen.availHeight),x.x*=p.aspect;const k=t.matrixWorldInverse,X=this._tempBox2;X.copy(D),X.applyMatrix4(e.matrixWorld),X.applyMatrix4(k);const T=X.getSize(this._tempBox2Size),z=Math.max(T.x,T.y);if(Math.max(x.x,x.y)!=0&&z!=0&&(x.z=T.z/Math.max(T.x,T.y)*Math.max(x.x,x.y)),r.lastScreenCoverage=Math.max(x.x,x.y,x.z),r.lastScreenspaceVolume.copy(x),r.lastScreenCoverage*=r.lastCentrality,G&&B.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const w=B.corner0,A=B.corner1,P=B.corner2,C=B.corner3;w.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=w.x,P.copy(this._tempBox.max),P.y=w.y,C.copy(this._tempBox.max);const ee=(w.z+C.z)*.5;w.z=A.z=P.z=C.z=ee,w.applyMatrix4(y),A.applyMatrix4(y),P.applyMatrix4(y),C.applyMatrix4(y),B.debugDrawLine(w,A,255),B.debugDrawLine(w,P,255),B.debugDrawLine(A,C,255),B.debugDrawLine(P,C,255)}let S=999;if(c&&r.lastScreenCoverage>0){for(let y=0;y<c.length;y++)if(c[y].density/r.lastScreenCoverage<o){S=y;break}}S<n&&(n=S,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const x=c==null?void 0:c[s.mesh_lod];x&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${x.density.toFixed(0)}) - ${e.name}`)}if(v){const p="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,G){const x=g.lods[g.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${x.max_height}px) - ${e.name}`)}}else{const x=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let k=r.lastScreenCoverage*2;((U=this.context)==null?void 0:U.engine)==="model-viewer"&&(k*=2);const T=_/window.devicePixelRatio*k;for(let z=g.lods.length-1;z>=0;z--){let E=g.lods[z];if(!(p&&E.max_height>=2048)&&!(qe()&&E.max_height>4096)&&E.max_height>T){if(s.texture_lod=z,s.texture_lod<r.lastLodLevel_Texture){const S=E.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${S}px
6
+ Screensize: ${T.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${x.toFixed(1)}
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}};let R=B;I=new WeakMap,W=new WeakMap,he=new WeakMap,Q=new WeakMap,Z=new WeakMap,ge=new WeakMap,q=new WeakMap,f(R,"debugDrawLine"),f(R,"corner0",new d.Vector3),f(R,"corner1",new d.Vector3),f(R,"corner2",new d.Vector3),f(R,"corner3",new d.Vector3),f(R,"_tempPtInside",new d.Vector3);class je{constructor(){f(this,"frames",0);f(this,"lastLodLevel_Mesh",-1);f(this,"lastLodLevel_Texture",-1);f(this,"lastScreenCoverage",0);f(this,"lastScreenspaceVolume",new d.Vector3);f(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),ue=Symbol("NEEDLE_texture_lod");let se=null;function Se(){const a=Je();a&&(a.mapURLs(function(t){return Ee(),t}),Ee(),se==null||se.disconnect(),se=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),se.observe(document,{childList:!0,subtree:!0}))}function Je(){const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function Ee(){document.querySelectorAll("model-viewer").forEach(t=>{Be(t)})}const Pe=new WeakSet;let Qe=0;function Be(a){if(!a||Pe.has(a))return null;Pe.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++Qe+`
8
+ `,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const 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=R.get(t,{engine:"model-viewer"});return R.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(){f(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[ue]==!0)return;e[ue]=!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,h,g;if(l[ue]==!0)return;l[ue]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let v=0;v<u.length;v++){const _=u[v],D=l[_];if((D==null?void 0:D.isTexture)===!0){const V=(h=(c=D.userData)==null?void 0:c.associations)==null?void 0:h.textures;if(V==null)continue;const U=r.parser.json.textures[V];if(!U){console.warn("Texture data not found for texture index "+V);continue}if((g=U==null?void 0:U.extensions)!=null&&g[N]){const p=U.extensions[N];p&&s&&b.registerTexture(s,D,p.lods.length,V,p)}}}};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[Ae]==!0)return;e[Ae]=!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[N];if(s&&o){const l=e.uuid;b.registerMesh(o,l,e,0,s.lods.length,s)}}}function et(a,t,e,r){_e(t),Oe(e),e.register(s=>new b(s,a));const o=R.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Se();exports.EXTENSION_NAME=N;exports.LODsManager=R;exports.NEEDLE_progressive=b;exports.VERSION=we;exports.addDracoAndKTX2Loaders=Oe;exports.createLoaders=_e;exports.getRaycastMesh=ne;exports.patchModelViewer=Se;exports.registerRaycastMesh=Ce;exports.setDracoDecoderLocation=Ue;exports.setKTX2TranscoderLocation=ze;exports.useNeedleProgressive=et;exports.useRaycastMeshes=Xe;
@@ -85,6 +85,7 @@ export declare class LODsManager {
85
85
  manual: boolean;
86
86
  private readonly _lodchangedlisteners;
87
87
  addEventListener(evt: "changed", listener: LODChangedEventListener): void;
88
+ removeEventListener(evt: "changed", listener: LODChangedEventListener): void;
88
89
  private constructor();
89
90
  private _fpsBuffer;
90
91
  /**
@@ -3,6 +3,7 @@ import { NEEDLE_progressive } from "./extension.js";
3
3
  import { createLoaders } from "./loaders.js";
4
4
  import { getParam, isMobileDevice } from "./utils.internal.js";
5
5
  import { plugins } from "./plugins/plugin.js";
6
+ import { getRaycastMesh } from "./utils.js";
6
7
  const debugProgressiveLoading = getParam("debugprogressive");
7
8
  const suppressProgressiveLoading = getParam("noprogressive");
8
9
  const $lodsManager = Symbol("Needle:LODSManager");
@@ -105,6 +106,13 @@ export class LODsManager {
105
106
  this._lodchangedlisteners.push(listener);
106
107
  }
107
108
  }
109
+ removeEventListener(evt, listener) {
110
+ if (evt === "changed") {
111
+ const index = this._lodchangedlisteners.indexOf(listener);
112
+ if (index >= 0)
113
+ this._lodchangedlisteners.splice(index, 1);
114
+ }
115
+ }
108
116
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
109
117
  constructor(renderer, context) {
110
118
  this.renderer = renderer;
@@ -431,8 +439,8 @@ export class LODsManager {
431
439
  }
432
440
  if (!this.cameraFrustrum?.intersectsObject(mesh)) {
433
441
  // the object is not visible by the camera
434
- result.mesh_lod = 99;
435
- result.texture_lod = 99;
442
+ result.mesh_lod = 100;
443
+ result.texture_lod = 100;
436
444
  return;
437
445
  }
438
446
  const canvasHeight = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
@@ -442,6 +450,17 @@ export class LODsManager {
442
450
  if (!skinnedMesh.boundingBox) {
443
451
  skinnedMesh.computeBoundingBox();
444
452
  }
453
+ // Fix: https://linear.app/needle/issue/NE-5264
454
+ else if (state.frames % 30 === 0) {
455
+ // use lowres geometry for bounding box calculation
456
+ const raycastmesh = getRaycastMesh(skinnedMesh);
457
+ const originalGeometry = skinnedMesh.geometry;
458
+ if (raycastmesh) {
459
+ skinnedMesh.geometry = raycastmesh;
460
+ }
461
+ skinnedMesh.computeBoundingBox();
462
+ skinnedMesh.geometry = originalGeometry;
463
+ }
445
464
  boundingBox = skinnedMesh.boundingBox;
446
465
  }
447
466
  if (boundingBox && camera.isPerspectiveCamera) {
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "1.2.4-beta.1";
2
+ export const version = "1.2.5-beta";
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.4-beta.1",
3
+ "version": "1.2.5-beta",
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": {