@needle-tools/gltf-progressive 3.4.0-beta.2 → 3.4.0-beta.4

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.
@@ -1,4 +1,4 @@
1
- import { BufferGeometry as E, Mesh as X, Box3 as ge, Vector3 as A, Sphere as Oe, CompressedTexture as Ge, Texture as F, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as Ne, Matrix4 as Le, Clock as qe, MeshStandardMaterial as Ve } from "three";
1
+ import { BufferGeometry as E, Mesh as X, Box3 as ge, Vector3 as R, Sphere as Se, CompressedTexture as Ge, Texture as F, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as qe, Matrix4 as ve, Clock as Ne, MeshStandardMaterial as Ve } from "three";
2
2
  import { GLTFLoader as xe } from "three/examples/jsm/loaders/GLTFLoader.js";
3
3
  import { MeshoptDecoder as Ee } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
4
  import { DRACOLoader as Xe } from "three/examples/jsm/loaders/DRACOLoader.js";
@@ -6,42 +6,42 @@ import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
6
6
  const Ke = "";
7
7
  globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
8
8
  console.debug("[gltf-progressive] version -");
9
- let I = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", j = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
- const Ye = I, He = j, Se = new URL(I + "draco_decoder.js");
11
- Se.searchParams.append("range", "true");
12
- fetch(Se, {
9
+ let B = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", j = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
+ const Ye = B, He = j, Pe = new URL(B + "draco_decoder.js");
11
+ Pe.searchParams.append("range", "true");
12
+ fetch(Pe, {
13
13
  method: "GET",
14
14
  headers: {
15
15
  Range: "bytes=0-1"
16
16
  }
17
17
  }).catch((n) => {
18
- console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), I === Ye && Je("./include/draco/"), j === He && Ze("./include/ktx2/");
18
+ console.debug(`Failed to fetch remote Draco decoder from ${B} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), B === Ye && Je("./include/draco/"), j === He && Ze("./include/ktx2/");
19
19
  }).finally(() => {
20
- Te();
20
+ Ce();
21
21
  });
22
22
  const Qe = () => ({
23
- dracoDecoderPath: I,
23
+ dracoDecoderPath: B,
24
24
  ktx2TranscoderPath: j
25
25
  });
26
26
  function Je(n) {
27
- I = n, C && C[pe] != I ? (console.debug("Updating Draco decoder path to " + n), C[pe] = I, C.setDecoderPath(I), C.preload()) : console.debug("Setting Draco decoder path to " + n);
27
+ B = n, k && k[pe] != B ? (console.debug("Updating Draco decoder path to " + n), k[pe] = B, k.setDecoderPath(B), k.preload()) : console.debug("Setting Draco decoder path to " + n);
28
28
  }
29
29
  function Ze(n) {
30
- j = n, $ && $.transcoderPath != j ? (console.debug("Updating KTX2 transcoder path to " + n), $.setTranscoderPath(j), $.init()) : console.debug("Setting KTX2 transcoder path to " + n);
30
+ j = n, G && G.transcoderPath != j ? (console.debug("Updating KTX2 transcoder path to " + n), G.setTranscoderPath(j), G.init()) : console.debug("Setting KTX2 transcoder path to " + n);
31
31
  }
32
32
  function we(n) {
33
- return Te(), n ? $.detectSupport(n) : n !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: $, meshoptDecoder: oe };
33
+ return Ce(), n ? G.detectSupport(n) : n !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: k, ktx2Loader: G, meshoptDecoder: oe };
34
34
  }
35
- function Pe(n) {
36
- n.dracoLoader || n.setDRACOLoader(C), n.ktx2Loader || n.setKTX2Loader($), n.meshoptDecoder || n.setMeshoptDecoder(oe);
35
+ function Te(n) {
36
+ n.dracoLoader || n.setDRACOLoader(k), n.ktx2Loader || n.setKTX2Loader(G), n.meshoptDecoder || n.setMeshoptDecoder(oe);
37
37
  }
38
38
  const pe = /* @__PURE__ */ Symbol("dracoDecoderPath");
39
- let C, oe, $;
40
- function Te() {
41
- C || (C = new Xe(), C[pe] = I, C.setDecoderPath(I), C.setDecoderConfig({ type: "js" }), C.preload()), $ || ($ = new je(), $.setTranscoderPath(j), $.init()), oe || (oe = Ee);
39
+ let k, oe, G;
40
+ function Ce() {
41
+ k || (k = new Xe(), k[pe] = B, k.setDecoderPath(B), k.setDecoderConfig({ type: "js" }), k.preload()), G || (G = new je(), G.setTranscoderPath(j), G.init()), oe || (oe = Ee);
42
42
  }
43
43
  const me = /* @__PURE__ */ new WeakMap();
44
- function Ce(n, t) {
44
+ function Ae(n, t) {
45
45
  let e = me.get(n);
46
46
  e ? e = Object.assign(e, t) : e = t, me.set(n, e);
47
47
  }
@@ -74,11 +74,11 @@ function st(n, t) {
74
74
  }
75
75
  return t;
76
76
  }
77
- function Ae() {
77
+ function _e() {
78
78
  return H !== void 0 || (H = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", H)), H;
79
79
  }
80
80
  let H;
81
- function ve() {
81
+ function be() {
82
82
  if (typeof window > "u") return !1;
83
83
  const n = new URL(window.location.href), t = n.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(n.hostname);
84
84
  return n.hostname === "127.0.0.1" || t;
@@ -160,9 +160,9 @@ function ut(n) {
160
160
  t.setAttribute(e, n.getAttribute(e));
161
161
  return t.setIndex(n.getIndex()), t;
162
162
  }
163
- const z = new Array(), f = N("debugprogressive");
163
+ const q = new Array(), h = N("debugprogressive");
164
164
  let Z, V = -1;
165
- if (f) {
165
+ if (h) {
166
166
  let n = function() {
167
167
  V += 1, V >= t && (V = -1), console.log(`Toggle LOD level [${V}]`);
168
168
  }, t = 6;
@@ -173,7 +173,7 @@ if (f) {
173
173
  });
174
174
  }
175
175
  function ke(n) {
176
- if (f && Z !== void 0)
176
+ if (h && Z !== void 0)
177
177
  if (Array.isArray(n))
178
178
  for (const t of n)
179
179
  ke(t);
@@ -181,18 +181,18 @@ function ke(n) {
181
181
  }
182
182
  const J = new Array();
183
183
  let ct = 0;
184
- const dt = Ae() ? 2 : 10;
184
+ const dt = _e() ? 2 : 10;
185
185
  function ft(n) {
186
186
  if (J.length < dt) {
187
187
  const s = J.length;
188
- f && console.warn(`[Worker] Creating new worker #${s}`);
189
- const r = _e.createWorker(n || {});
188
+ h && console.warn(`[Worker] Creating new worker #${s}`);
189
+ const r = Le.createWorker(n || {});
190
190
  return J.push(r), r;
191
191
  }
192
192
  const t = ct++ % J.length;
193
193
  return J[t];
194
194
  }
195
- class _e {
195
+ class Le {
196
196
  constructor(t, e) {
197
197
  this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
198
198
  const r = s.data;
@@ -219,7 +219,7 @@ class _e {
219
219
  ), {
220
220
  type: "module"
221
221
  });
222
- return new _e(e, t);
222
+ return new Le(e, t);
223
223
  }
224
224
  _running = [];
225
225
  _webglRenderer = null;
@@ -230,16 +230,16 @@ class _e {
230
230
  const { WebGLRenderer: u } = await import("three");
231
231
  return new u();
232
232
  })(), r = await this._webglRenderer);
233
- const l = we(r).ktx2Loader.workerConfig;
233
+ const a = we(r).ktx2Loader.workerConfig;
234
234
  t instanceof URL ? t = t.toString() : t.startsWith("file:") ? t = URL.createObjectURL(new Blob([t])) : !t.startsWith("blob:") && !t.startsWith("http:") && !t.startsWith("https:") && (t = new URL(t, window.location.href).toString());
235
- const a = {
235
+ const l = {
236
236
  type: "load",
237
237
  url: t,
238
238
  dracoDecoderPath: s.dracoDecoderPath,
239
239
  ktx2TranscoderPath: s.ktx2TranscoderPath,
240
- ktx2LoaderConfig: l
240
+ ktx2LoaderConfig: a
241
241
  };
242
- return this._debug && console.debug("[Worker] Sending load request", a), this.worker.postMessage(a), new Promise((u) => {
242
+ return this._debug && console.debug("[Worker] Sending load request", l), this.worker.postMessage(l), new Promise((u) => {
243
243
  this._running.push({
244
244
  url: t.toString(),
245
245
  resolve: u
@@ -261,19 +261,19 @@ function ht(n) {
261
261
  }
262
262
  if (e.morphAttributes)
263
263
  for (const r in e.morphAttributes) {
264
- const o = e.morphAttributes[r].map((l) => le(l));
264
+ const o = e.morphAttributes[r].map((a) => le(a));
265
265
  s.morphAttributes[r] = o;
266
266
  }
267
- if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new A(
267
+ if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new R(
268
268
  e.boundingBox?.min.x,
269
269
  e.boundingBox?.min.y,
270
270
  e.boundingBox?.min.z
271
- ), s.boundingBox.max = new A(
271
+ ), s.boundingBox.max = new R(
272
272
  e.boundingBox?.max.x,
273
273
  e.boundingBox?.max.y,
274
274
  e.boundingBox?.max.z
275
- ), s.boundingSphere = new Oe(
276
- new A(
275
+ ), s.boundingSphere = new Se(
276
+ new R(
277
277
  e.boundingSphere?.center.x,
278
278
  e.boundingSphere?.center.y,
279
279
  e.boundingSphere?.center.z
@@ -334,11 +334,11 @@ function le(n) {
334
334
  }
335
335
  const gt = N("gltf-progressive-worker");
336
336
  N("gltf-progressive-reduce-mipmaps");
337
- const K = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), W = "NEEDLE_progressive";
337
+ const K = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), U = "NEEDLE_progressive";
338
338
  class m {
339
339
  /** The name of the extension */
340
340
  get name() {
341
- return W;
341
+ return U;
342
342
  }
343
343
  // #region PUBLIC API
344
344
  static getMeshLODExtension(t) {
@@ -357,33 +357,33 @@ class m {
357
357
  max_count: 0,
358
358
  lods: []
359
359
  }), Array.isArray(t)) {
360
- for (const l of t)
361
- this.getMaterialMinMaxLODsCount(l, e);
360
+ for (const a of t)
361
+ this.getMaterialMinMaxLODsCount(a, e);
362
362
  return t[r] = e, e;
363
363
  }
364
- if (f === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
365
- const l = t;
366
- for (const a of Object.keys(l.uniforms)) {
367
- const u = l.uniforms[a].value;
364
+ if (h === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
365
+ const a = t;
366
+ for (const l of Object.keys(a.uniforms)) {
367
+ const u = a.uniforms[l].value;
368
368
  u?.isTexture === !0 && o(u, e);
369
369
  }
370
370
  } else if (t.isMaterial)
371
- for (const l of Object.keys(t)) {
372
- const a = t[l];
373
- a?.isTexture === !0 && o(a, e);
371
+ for (const a of Object.keys(t)) {
372
+ const l = t[a];
373
+ l?.isTexture === !0 && o(l, e);
374
374
  }
375
375
  else
376
- f && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
376
+ h && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
377
377
  return t[r] = e, e;
378
- function o(l, a) {
379
- const u = s.getAssignedLODInformation(l);
378
+ function o(a, l) {
379
+ const u = s.getAssignedLODInformation(a);
380
380
  if (u) {
381
- const c = s.lodInfos.get(u.key);
382
- if (c && c.lods) {
383
- a.min_count = Math.min(a.min_count, c.lods.length), a.max_count = Math.max(a.max_count, c.lods.length);
384
- for (let y = 0; y < c.lods.length; y++) {
385
- const w = c.lods[y];
386
- w.width && (a.lods[y] = a.lods[y] || { min_height: 1 / 0, max_height: 0 }, a.lods[y].min_height = Math.min(a.lods[y].min_height, w.height), a.lods[y].max_height = Math.max(a.lods[y].max_height, w.height));
381
+ const d = s.lodInfos.get(u.key);
382
+ if (d && d.lods) {
383
+ l.min_count = Math.min(l.min_count, d.lods.length), l.max_count = Math.max(l.max_count, d.lods.length);
384
+ for (let g = 0; g < d.lods.length; g++) {
385
+ const y = d.lods[g];
386
+ y.width && (l.lods[g] = l.lods[g] || { min_height: 1 / 0, max_height: 0 }, l.lods[g].min_height = Math.min(l.lods[g].min_height, y.height), l.lods[g].max_height = Math.max(l.lods[g].max_height, y.height));
387
387
  }
388
388
  }
389
389
  }
@@ -441,16 +441,16 @@ class m {
441
441
  const s = t.geometry, r = this.getAssignedLODInformation(s);
442
442
  if (!r)
443
443
  return Promise.resolve(null);
444
- for (const i of z)
444
+ for (const i of q)
445
445
  i.onBeforeGetLODMesh?.(t, e);
446
446
  return t["LOD:requested level"] = e, m.getOrLoadLOD(s, e).then((i) => {
447
447
  if (Array.isArray(i)) {
448
448
  const o = r.index || 0;
449
449
  i = i[o];
450
450
  }
451
- return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i : f && console.error("Invalid LOD geometry", i))), i;
451
+ return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i : h && console.error("Invalid LOD geometry", i))), i;
452
452
  }).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
453
- } else f && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
453
+ } else h && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
454
454
  return Promise.resolve(null);
455
455
  }
456
456
  static assignTextureLOD(t, e = 0) {
@@ -465,8 +465,8 @@ class m {
465
465
  }
466
466
  return Promise.all(r).then((i) => {
467
467
  const o = new Array();
468
- for (const l of i)
469
- Array.isArray(l) && o.push(...l);
468
+ for (const a of i)
469
+ Array.isArray(a) && o.push(...a);
470
470
  return o;
471
471
  });
472
472
  } else
@@ -476,28 +476,28 @@ class m {
476
476
  const s = t, r = [], i = new Array();
477
477
  if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
478
478
  const o = s;
479
- for (const l of Object.keys(o.uniforms)) {
480
- const a = o.uniforms[l].value;
481
- if (a?.isTexture === !0) {
482
- const u = this.assignTextureLODForSlot(a, e, s, l).then((c) => (c && o.uniforms[l].value != c && (o.uniforms[l].value = c, o.uniformsNeedUpdate = !0), c));
483
- r.push(u), i.push(l);
479
+ for (const a of Object.keys(o.uniforms)) {
480
+ const l = o.uniforms[a].value;
481
+ if (l?.isTexture === !0) {
482
+ const u = this.assignTextureLODForSlot(l, e, s, a).then((d) => (d && o.uniforms[a].value != d && (o.uniforms[a].value = d, o.uniformsNeedUpdate = !0), d));
483
+ r.push(u), i.push(a);
484
484
  }
485
485
  }
486
486
  } else
487
487
  for (const o of Object.keys(s)) {
488
- const l = s[o];
489
- if (l?.isTexture === !0) {
490
- const a = this.assignTextureLODForSlot(l, e, s, o);
491
- r.push(a), i.push(o);
488
+ const a = s[o];
489
+ if (a?.isTexture === !0) {
490
+ const l = this.assignTextureLODForSlot(a, e, s, o);
491
+ r.push(l), i.push(o);
492
492
  }
493
493
  }
494
494
  return Promise.all(r).then((o) => {
495
- const l = new Array();
496
- for (let a = 0; a < o.length; a++) {
497
- const u = o[a], c = i[a];
498
- u && u.isTexture === !0 ? l.push({ material: s, slot: c, texture: u, level: e }) : l.push({ material: s, slot: c, texture: null, level: e });
495
+ const a = new Array();
496
+ for (let l = 0; l < o.length; l++) {
497
+ const u = o[l], d = i[l];
498
+ u && u.isTexture === !0 ? a.push({ material: s, slot: d, texture: u, level: e }) : a.push({ material: s, slot: d, texture: null, level: e });
499
499
  }
500
- return l;
500
+ return a;
501
501
  });
502
502
  }
503
503
  if (t instanceof F || t.isTexture === !0) {
@@ -508,7 +508,7 @@ class m {
508
508
  }
509
509
  /**
510
510
  * Set the maximum number of concurrent loading tasks for LOD resources. This limits how many LOD resources (meshes or textures) can be loaded at the same time to prevent overloading the network or GPU. If the limit is reached, additional loading requests will be queued and processed as previous ones finish.
511
- * @default 50
511
+ * @default 50 on desktop, 20 on mobile devices
512
512
  */
513
513
  static set maxConcurrentLoadingTasks(t) {
514
514
  m.queue.maxConcurrent = t;
@@ -524,19 +524,19 @@ class m {
524
524
  if (i?.isTexture === !0) {
525
525
  if (i != t && s && r) {
526
526
  const o = s[r];
527
- if (o && !f) {
528
- const l = this.getAssignedLODInformation(o);
529
- if (l && l?.level < e)
530
- return f === "verbose" && console.warn("Assigned texture level is already higher: ", l.level, e, s, o, i), i && i !== o && ((f || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${l.level})`, i.uuid), i.dispose()), null;
531
- }
532
- if (this.trackTextureUsage(i), o && o !== i && this.untrackTextureUsage(o) && (f || K)) {
527
+ if (o && !h) {
533
528
  const a = this.getAssignedLODInformation(o);
534
- console.log(`[gltf-progressive] Disposed old texture LOD ${a?.level ?? "?"} → ${e} for ${s.name || s.type}.${r}`, o.uuid);
529
+ if (a && a?.level < e)
530
+ return h === "verbose" && console.warn("Assigned texture level is already higher: ", a.level, e, s, o, i), i && i !== o && ((h || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${a.level})`, i.uuid), i.dispose()), null;
531
+ }
532
+ if (this.trackTextureUsage(i), o && o !== i && this.untrackTextureUsage(o) && (h || K)) {
533
+ const l = this.getAssignedLODInformation(o);
534
+ console.log(`[gltf-progressive] Disposed old texture LOD ${l?.level ?? "?"} → ${e} for ${s.name || s.type}.${r}`, o.uuid);
535
535
  }
536
536
  s[r] = i;
537
537
  }
538
538
  return i;
539
- } else f == "verbose" && console.warn("No LOD found for", t, e);
539
+ } else h == "verbose" && console.warn("No LOD found for", t, e);
540
540
  return null;
541
541
  }).catch((i) => (console.error("Error loading LOD", t, i), null));
542
542
  }
@@ -544,12 +544,12 @@ class m {
544
544
  url;
545
545
  constructor(t) {
546
546
  const e = t.options.path;
547
- f && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
547
+ h && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
548
548
  }
549
549
  _isLoadingMesh;
550
550
  loadMesh = (t) => {
551
551
  if (this._isLoadingMesh) return null;
552
- const e = this.parser.json.meshes[t]?.extensions?.[W];
552
+ const e = this.parser.json.meshes[t]?.extensions?.[U];
553
553
  return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && m.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
554
554
  };
555
555
  // private _isLoadingTexture;
@@ -567,12 +567,12 @@ class m {
567
567
  // });
568
568
  // }
569
569
  afterRoot(t) {
570
- return f && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
570
+ return h && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
571
571
  if (e?.extensions) {
572
- const r = e?.extensions[W];
572
+ const r = e?.extensions[U];
573
573
  if (r) {
574
574
  if (!r.lods) {
575
- f && console.warn("Texture has no LODs", r);
575
+ h && console.warn("Texture has no LODs", r);
576
576
  return;
577
577
  }
578
578
  let i = !1;
@@ -585,7 +585,7 @@ class m {
585
585
  }
586
586
  }), this.parser.json.meshes?.forEach((e, s) => {
587
587
  if (e?.extensions) {
588
- const r = e?.extensions[W];
588
+ const r = e?.extensions[U];
589
589
  if (r && r.lods) {
590
590
  for (const i of this.parser.associations.keys())
591
591
  if (i.isMesh) {
@@ -601,12 +601,12 @@ class m {
601
601
  */
602
602
  static registerTexture = (t, e, s, r, i) => {
603
603
  if (!e) {
604
- f && console.error("!! gltf-progressive: Called register texture without texture");
604
+ h && console.error("!! gltf-progressive: Called register texture without texture");
605
605
  return;
606
606
  }
607
- if (f) {
608
- const l = e.image?.width || e.source?.data?.width || 0, a = e.image?.height || e.source?.data?.height || 0;
609
- console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${l}x${a}, Max: ${i.lods[0]?.width}x${i.lods[0]?.height}, uuid: ${e.uuid}`, i, e);
607
+ if (h) {
608
+ const a = e.image?.width || e.source?.data?.width || 0, l = e.image?.height || e.source?.data?.height || 0;
609
+ console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${a}x${l}, Max: ${i.lods[0]?.width}x${i.lods[0]?.height}, uuid: ${e.uuid}`, i, e);
610
610
  }
611
611
  e.source && (e.source[ue] = i);
612
612
  const o = i.guid;
@@ -616,16 +616,16 @@ class m {
616
616
  * Register a mesh with LOD information
617
617
  */
618
618
  static registerMesh = (t, e, s, r, i, o) => {
619
- const l = s.geometry;
620
- if (!l) {
621
- f && console.warn("gltf-progressive: Register mesh without geometry");
619
+ const a = s.geometry;
620
+ if (!a) {
621
+ h && console.warn("gltf-progressive: Register mesh without geometry");
622
622
  return;
623
623
  }
624
- l.userData || (l.userData = {}), f && console.log("> Progressive: register mesh " + s.name, { index: i, uuid: s.uuid }, o, s), m.assignLODInformation(t, l, e, r, i), m.lodInfos.set(e, o);
624
+ a.userData || (a.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: i, uuid: s.uuid }, o, s), m.assignLODInformation(t, a, e, r, i), m.lodInfos.set(e, o);
625
625
  let u = m.lowresCache.get(e)?.deref();
626
- u ? u.push(s.geometry) : u = [s.geometry], m.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && at(s, l);
627
- for (const c of z)
628
- c.onRegisteredNewMesh?.(s, o);
626
+ u ? u.push(s.geometry) : u = [s.geometry], m.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && at(s, a);
627
+ for (const d of q)
628
+ d.onRegisteredNewMesh?.(s, o);
629
629
  };
630
630
  /**
631
631
  * Dispose cached resources to free memory.
@@ -652,7 +652,7 @@ class m {
652
652
  for (const [s, r] of this.cache)
653
653
  s.includes(t) && (this._disposeCacheEntry(r), this.cache.delete(s));
654
654
  } else {
655
- this.lodInfos.clear();
655
+ this.cacheGeneration++, this.lodInfos.clear();
656
656
  for (const [, e] of this.lowresCache) {
657
657
  const s = e.deref();
658
658
  if (s) {
@@ -675,7 +675,7 @@ class m {
675
675
  const e = t.deref();
676
676
  e && (e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose());
677
677
  } else
678
- t.then((e) => {
678
+ this.disposedRequests.add(t), t.then((e) => {
679
679
  if (e)
680
680
  if (Array.isArray(e))
681
681
  for (const s of e) s.dispose();
@@ -699,15 +699,15 @@ class m {
699
699
  */
700
700
  static _resourceRegistry = new FinalizationRegistry((t) => {
701
701
  const e = m.cache.get(t);
702
- (f || K) && console.debug(`[gltf-progressive] Memory: Resource GC'd
703
- ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (f || K) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
702
+ (h || K) && console.debug(`[gltf-progressive] Memory: Resource GC'd
703
+ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (h || K) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
704
704
  });
705
705
  /**
706
706
  * Track texture usage by incrementing reference count
707
707
  */
708
708
  static trackTextureUsage(t) {
709
709
  const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
710
- this.textureRefCounts.set(e, s + 1), f === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
710
+ this.textureRefCounts.set(e, s + 1), h === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
711
711
  }
712
712
  /**
713
713
  * Untrack texture usage by decrementing reference count.
@@ -717,165 +717,171 @@ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (f || K) && co
717
717
  static untrackTextureUsage(t) {
718
718
  const e = t.uuid, s = this.textureRefCounts.get(e);
719
719
  if (!s)
720
- return (f === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
720
+ return (h === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
721
721
  const r = s - 1;
722
722
  if (r <= 0)
723
- return this.textureRefCounts.delete(e), (f || K) && i("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
724
- return this.textureRefCounts.set(e, r), f === "verbose" && i("[gltf-progressive] Memory: Untrack texture", r), !1;
725
- function i(o, l) {
726
- let a = t.image?.width || t.source?.data?.width || 0, u = t.image?.height || t.source?.data?.height || 0;
727
- const c = a && u ? `${a}x${u}` : "N/A";
728
- let y = "N/A";
729
- a && u && (y = `~${(it(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${c} (${y}), refCount: ${s} → ${l}
723
+ return this.textureRefCounts.delete(e), (h || K) && i("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
724
+ return this.textureRefCounts.set(e, r), h === "verbose" && i("[gltf-progressive] Memory: Untrack texture", r), !1;
725
+ function i(o, a) {
726
+ let l = t.image?.width || t.source?.data?.width || 0, u = t.image?.height || t.source?.data?.height || 0;
727
+ const d = l && u ? `${l}x${u}` : "N/A";
728
+ let g = "N/A";
729
+ l && u && (g = `~${(it(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${d} (${g}), refCount: ${s} → ${a}
730
730
  ${e}`);
731
731
  }
732
732
  }
733
733
  static workers = [];
734
+ static cacheGeneration = 0;
735
+ static disposedRequests = /* @__PURE__ */ new WeakSet();
734
736
  static _workersIndex = 0;
735
737
  static async getOrLoadLOD(t, e) {
736
- const s = f == "verbose", r = this.getAssignedLODInformation(t);
737
- if (!r)
738
- return f && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
739
- const i = r?.key;
740
- let o;
738
+ const s = this.cacheGeneration, r = h == "verbose", i = this.getAssignedLODInformation(t);
739
+ if (!i)
740
+ return h && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
741
+ const o = i?.key;
742
+ let a;
741
743
  if (t.isTexture === !0) {
742
- const a = t;
743
- a.source && a.source[ue] && (o = a.source[ue]);
744
+ const u = t;
745
+ u.source && u.source[ue] && (a = u.source[ue]);
744
746
  }
745
- if (o || (o = m.lodInfos.get(i)), !o)
746
- f && console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`, t.type, m.lodInfos);
747
+ if (a || (a = m.lodInfos.get(o)), !a)
748
+ h && console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`, t.type, m.lodInfos);
747
749
  else {
748
750
  if (e > 0) {
749
- let c = !1;
750
- const y = Array.isArray(o.lods);
751
- if (y && e >= o.lods.length ? c = !0 : y || (c = !0), c) {
752
- const w = this.lowresCache.get(i);
753
- if (w) {
754
- const _ = w.deref();
755
- if (_) return _;
756
- this.lowresCache.delete(i), f && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${i}`);
751
+ let g = !1;
752
+ const y = Array.isArray(a.lods);
753
+ if (y && e >= a.lods.length ? g = !0 : y || (g = !0), g) {
754
+ const M = this.lowresCache.get(o);
755
+ if (M) {
756
+ const L = M.deref();
757
+ if (L) return L;
758
+ this.lowresCache.delete(o), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${o}`);
757
759
  }
758
760
  return null;
759
761
  }
760
762
  }
761
- const a = Array.isArray(o.lods) ? o.lods[e]?.path : o.lods;
762
- if (!a)
763
- return f && !o["missing:uri"] && (o["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, o)), null;
764
- const u = st(r.url, a);
765
- if (u.endsWith(".glb") || u.endsWith(".gltf")) {
766
- if (!o.guid)
767
- return console.warn("missing pointer for glb/gltf texture", o), null;
768
- const c = u + "_" + o.guid, y = await this.queue.slot(u), w = this.cache.get(c);
769
- if (w !== void 0)
770
- if (s && console.log(`LOD ${e} was already loading/loaded: ${c}`), w instanceof WeakRef) {
771
- const d = w.deref();
772
- if (d) {
773
- let g = d, b = !1;
774
- if (g instanceof F && t instanceof F ? g.image?.data || g.source?.data ? g = this.copySettings(t, g) : b = !0 : g instanceof E && t instanceof E && (g.attributes.position?.array || (b = !0)), !b)
775
- return g;
763
+ const u = Array.isArray(a.lods) ? a.lods[e]?.path : a.lods;
764
+ if (!u)
765
+ return h && !a["missing:uri"] && (a["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, a)), null;
766
+ const d = st(i.url, u);
767
+ if (d.endsWith(".glb") || d.endsWith(".gltf")) {
768
+ if (!a.guid)
769
+ return console.warn("missing pointer for glb/gltf texture", a), null;
770
+ const g = d + "_" + a.guid, y = await this.queue.slot(d);
771
+ if (s !== this.cacheGeneration) return null;
772
+ const M = this.cache.get(g);
773
+ if (M !== void 0)
774
+ if (r && console.log(`LOD ${e} was already loading/loaded: ${g}`), M instanceof WeakRef) {
775
+ const f = M.deref();
776
+ if (f) {
777
+ let _ = f, D = !1;
778
+ if (_ instanceof F && t instanceof F ? _.image?.data || _.source?.data ? _ = this.copySettings(t, _) : D = !0 : _ instanceof E && t instanceof E && (_.attributes.position?.array || (D = !0)), !D)
779
+ return _;
776
780
  }
777
- this.cache.delete(c), f && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${c}`);
781
+ this.cache.delete(g), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${g}`);
778
782
  } else {
779
- let d = await w.catch((b) => (console.error(`Error loading LOD ${e} from ${u}
780
- `, b), null)), g = !1;
781
- if (d == null || (d instanceof F && t instanceof F ? d.image?.data || d.source?.data ? d = this.copySettings(t, d) : (g = !0, this.cache.delete(c)) : d instanceof E && t instanceof E && (d.attributes.position?.array || (g = !0, this.cache.delete(c)))), !g)
782
- return d;
783
+ let f = await M.catch((D) => (console.error(`Error loading LOD ${e} from ${d}
784
+ `, D), null));
785
+ if (s !== this.cacheGeneration || this.disposedRequests.has(M)) return null;
786
+ let _ = !1;
787
+ if (f == null || (f instanceof F && t instanceof F ? f.image?.data || f.source?.data ? f = this.copySettings(t, f) : (_ = !0, this.cache.delete(g)) : f instanceof E && t instanceof E && (f.attributes.position?.array || (_ = !0, this.cache.delete(g)))), !_)
788
+ return f;
783
789
  }
784
790
  if (!y.use)
785
- return f && console.log(`LOD ${e} was aborted: ${u}`), null;
786
- const _ = o, k = new Promise(async (d, g) => {
791
+ return h && console.log(`LOD ${e} was aborted: ${d}`), null;
792
+ const L = a, T = new Promise(async (f, _) => {
787
793
  if (gt) {
788
- const x = await (await ft({})).load(u);
789
- if (x.textures.length > 0)
790
- for (const h of x.textures) {
791
- let p = h.texture;
792
- return m.assignLODInformation(r.url, p, i, e, void 0), t instanceof F && (p = this.copySettings(t, p)), p && (p.guid = _.guid), d(p);
794
+ const c = await (await ft({})).load(d);
795
+ if (c.textures.length > 0)
796
+ for (const p of c.textures) {
797
+ let w = p.texture;
798
+ return m.assignLODInformation(i.url, w, o, e, void 0), t instanceof F && (w = this.copySettings(t, w)), w && (w.guid = L.guid), f(w);
793
799
  }
794
- if (x.geometries.length > 0) {
795
- const h = new Array();
796
- for (const p of x.geometries) {
797
- const O = p.geometry;
798
- m.assignLODInformation(r.url, O, i, e, p.primitiveIndex), h.push(O);
800
+ if (c.geometries.length > 0) {
801
+ const p = new Array();
802
+ for (const w of c.geometries) {
803
+ const b = w.geometry;
804
+ m.assignLODInformation(i.url, b, o, e, w.primitiveIndex), p.push(b);
799
805
  }
800
- return d(h);
806
+ return f(p);
801
807
  }
802
- return d(null);
808
+ return f(null);
803
809
  }
804
- const b = new xe();
805
- Pe(b), f && (await new Promise((L) => setTimeout(L, 1e3)), s && console.warn("Start loading (delayed) " + u, _.guid));
806
- let B = u;
807
- if (_ && Array.isArray(_.lods)) {
808
- const L = _.lods[e];
809
- L.hash && (B += "?v=" + L.hash);
810
+ const D = new xe();
811
+ Te(D), h && (await new Promise((S) => setTimeout(S, 1e3)), r && console.warn("Start loading (delayed) " + d, L.guid));
812
+ let I = d;
813
+ if (L && Array.isArray(L.lods)) {
814
+ const S = L.lods[e];
815
+ S.hash && (I += "?v=" + S.hash);
810
816
  }
811
- const D = await b.loadAsync(B).catch((L) => (console.error(`Error loading LOD ${e} from ${u}
812
- `, L), d(null)));
813
- if (!D)
814
- return d(null);
815
- const q = D.parser;
816
- s && console.log("Loading finished " + u, _.guid);
817
- let P = 0;
818
- if (D.parser.json.textures) {
819
- let L = !1;
820
- for (const x of D.parser.json.textures) {
821
- if (x?.extensions) {
822
- const h = x?.extensions[W];
823
- if (h?.guid && h.guid === _.guid) {
824
- L = !0;
817
+ const C = await D.loadAsync(I).catch((S) => (console.error(`Error loading LOD ${e} from ${d}
818
+ `, S), f(null)));
819
+ if (!C)
820
+ return f(null);
821
+ const W = C.parser;
822
+ r && console.log("Loading finished " + d, L.guid);
823
+ let O = 0;
824
+ if (C.parser.json.textures) {
825
+ let S = !1;
826
+ for (const c of C.parser.json.textures) {
827
+ if (c?.extensions) {
828
+ const p = c?.extensions[U];
829
+ if (p?.guid && p.guid === L.guid) {
830
+ S = !0;
825
831
  break;
826
832
  }
827
833
  }
828
- P++;
834
+ O++;
829
835
  }
830
- if (L) {
831
- let x = await q.getDependency("texture", P);
832
- return x && m.assignLODInformation(r.url, x, i, e, void 0), s && console.log('change "' + t.name + '" → "' + x.name + '"', u, P, x, c), t instanceof F && (x = this.copySettings(t, x)), x && (x.guid = _.guid), d(x);
833
- } else f && console.warn("Could not find texture with guid", _.guid, D.parser.json);
836
+ if (S) {
837
+ let c = await W.getDependency("texture", O);
838
+ return c && m.assignLODInformation(i.url, c, o, e, void 0), r && console.log('change "' + t.name + '" → "' + c.name + '"', d, O, c, g), t instanceof F && (c = this.copySettings(t, c)), c && (c.guid = L.guid), f(c);
839
+ } else h && console.warn("Could not find texture with guid", L.guid, C.parser.json);
834
840
  }
835
- if (P = 0, D.parser.json.meshes) {
836
- let L = !1;
837
- for (const x of D.parser.json.meshes) {
838
- if (x?.extensions) {
839
- const h = x?.extensions[W];
840
- if (h?.guid && h.guid === _.guid) {
841
- L = !0;
841
+ if (O = 0, C.parser.json.meshes) {
842
+ let S = !1;
843
+ for (const c of C.parser.json.meshes) {
844
+ if (c?.extensions) {
845
+ const p = c?.extensions[U];
846
+ if (p?.guid && p.guid === L.guid) {
847
+ S = !0;
842
848
  break;
843
849
  }
844
850
  }
845
- P++;
851
+ O++;
846
852
  }
847
- if (L) {
848
- const x = await q.getDependency("mesh", P);
849
- if (s && console.log(`Loaded Mesh "${x.name}"`, u, P, x, c), x.isMesh === !0) {
850
- const h = x.geometry;
851
- return m.assignLODInformation(r.url, h, i, e, 0), d(h);
853
+ if (S) {
854
+ const c = await W.getDependency("mesh", O);
855
+ if (r && console.log(`Loaded Mesh "${c.name}"`, d, O, c, g), c.isMesh === !0) {
856
+ const p = c.geometry;
857
+ return m.assignLODInformation(i.url, p, o, e, 0), f(p);
852
858
  } else {
853
- const h = new Array();
854
- for (let p = 0; p < x.children.length; p++) {
855
- const O = x.children[p];
856
- if (O.isMesh === !0) {
857
- const S = O.geometry;
858
- m.assignLODInformation(r.url, S, i, e, p), h.push(S);
859
+ const p = new Array();
860
+ for (let w = 0; w < c.children.length; w++) {
861
+ const b = c.children[w];
862
+ if (b.isMesh === !0) {
863
+ const A = b.geometry;
864
+ m.assignLODInformation(i.url, A, o, e, w), p.push(A);
859
865
  }
860
866
  }
861
- return d(h);
867
+ return f(p);
862
868
  }
863
- } else f && console.warn("Could not find mesh with guid", _.guid, D.parser.json);
869
+ } else h && console.warn("Could not find mesh with guid", L.guid, C.parser.json);
864
870
  }
865
- return d(null);
871
+ return f(null);
866
872
  });
867
- this.cache.set(c, k), y.use(k);
868
- const M = await k;
869
- return M != null ? M instanceof F ? (this.cache.set(c, new WeakRef(M)), m._resourceRegistry.register(M, c)) : Array.isArray(M) ? this.cache.set(c, Promise.resolve(M)) : this.cache.set(c, Promise.resolve(M)) : this.cache.set(c, Promise.resolve(null)), M;
873
+ this.cache.set(g, T), y.use(T);
874
+ const x = await T;
875
+ return s !== this.cacheGeneration || this.cache.get(g) !== T ? null : (x != null ? x instanceof F ? (this.cache.set(g, new WeakRef(x)), m._resourceRegistry.register(x, g)) : Array.isArray(x) ? this.cache.set(g, Promise.resolve(x)) : this.cache.set(g, Promise.resolve(x)) : this.cache.set(g, Promise.resolve(null)), x);
870
876
  } else if (t instanceof F) {
871
- s && console.log("Load texture from uri: " + u);
872
- const y = await new Ne().loadAsync(u);
873
- return y ? (y.guid = o.guid, y.flipY = !1, y.needsUpdate = !0, y.colorSpace = t.colorSpace, s && console.log(o, y)) : f && console.warn("failed loading", u), y;
877
+ r && console.log("Load texture from uri: " + d);
878
+ const y = await new qe().loadAsync(d);
879
+ return s !== this.cacheGeneration ? (y?.dispose(), null) : (y ? (y.guid = a.guid, y.flipY = !1, y.needsUpdate = !0, y.colorSpace = t.colorSpace, r && console.log(a, y)) : h && console.warn("failed loading", d), y);
874
880
  }
875
881
  }
876
882
  return null;
877
883
  }
878
- static queue = new rt(50, { debug: f != !1 });
884
+ static queue = new rt(_e() ? 20 : 50, { debug: h != !1 });
879
885
  static assignLODInformation(t, e, s, r, i) {
880
886
  if (!e) return;
881
887
  e.userData || (e.userData = {});
@@ -887,7 +893,7 @@ ${e}`);
887
893
  }
888
894
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
889
895
  static copySettings(t, e) {
890
- return e ? (f === "verbose" && console.debug(`Copy texture settings
896
+ return e ? (h === "verbose" && console.debug(`Copy texture settings
891
897
  `, t.uuid, `
892
898
  `, e.uuid), e = e.clone(), 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) : t;
893
899
  }
@@ -952,7 +958,7 @@ class ce {
952
958
  _seen = /* @__PURE__ */ new WeakMap();
953
959
  add(t, e, s) {
954
960
  if (this._resolved) {
955
- f && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
961
+ h && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
956
962
  return;
957
963
  }
958
964
  if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
@@ -960,7 +966,7 @@ class ce {
960
966
  if (this._seen.has(e)) {
961
967
  let r = this._seen.get(e);
962
968
  if (r >= this._maxPromisesPerObject) {
963
- f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
969
+ h && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
964
970
  return;
965
971
  }
966
972
  this._seen.set(e, r + 1);
@@ -979,7 +985,7 @@ class ce {
979
985
  });
980
986
  }
981
987
  }
982
- const R = N("debugprogressive"), mt = N("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), U = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), T = { mesh_lod: -1, texture_lod: -1 };
988
+ const $ = N("debugprogressive"), mt = N("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), z = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), P = { mesh_lod: -1, texture_lod: -1 };
983
989
  class v {
984
990
  /**
985
991
  * 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.
@@ -990,11 +996,11 @@ class v {
990
996
  return t[fe];
991
997
  }
992
998
  static addPlugin(t) {
993
- z.push(t);
999
+ q.push(t);
994
1000
  }
995
1001
  static removePlugin(t) {
996
- const e = z.indexOf(t);
997
- e >= 0 && z.splice(e, 1);
1002
+ const e = q.indexOf(t);
1003
+ e >= 0 && q.splice(e, 1);
998
1004
  }
999
1005
  /**
1000
1006
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -1012,10 +1018,10 @@ class v {
1012
1018
  }
1013
1019
  renderer;
1014
1020
  context;
1015
- projectionScreenMatrix = new Le();
1021
+ projectionScreenMatrix = new ve();
1016
1022
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
1017
1023
  get plugins() {
1018
- return z;
1024
+ return q;
1019
1025
  }
1020
1026
  /**
1021
1027
  * Force override the LOD level for all objects (meshes + textures) rendered in the scene
@@ -1061,7 +1067,7 @@ class v {
1061
1067
  const r = performance.now();
1062
1068
  return s.ready.finally(() => {
1063
1069
  const i = this._newPromiseGroups.indexOf(s);
1064
- i >= 0 && (this._newPromiseGroups.splice(i, 1), ve() && performance.measure("LODsManager:awaitLoading", {
1070
+ i >= 0 && (this._newPromiseGroups.splice(i, 1), be() && performance.measure("LODsManager:awaitLoading", {
1065
1071
  start: r,
1066
1072
  detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
1067
1073
  }));
@@ -1087,7 +1093,7 @@ class v {
1087
1093
  this.renderer = t, this.context = { ...e };
1088
1094
  }
1089
1095
  #t;
1090
- #o = new qe();
1096
+ #o = new Ne();
1091
1097
  #r = 0;
1092
1098
  #i = 0;
1093
1099
  #n = 0;
@@ -1104,7 +1110,7 @@ class v {
1104
1110
  const e = this;
1105
1111
  we(this.renderer), this.renderer.render = function(s, r) {
1106
1112
  const i = e.renderer.getRenderTarget();
1107
- (i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#o.getDelta(), e.#n += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((l, a) => l + a) / e._fpsBuffer.length, R && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1113
+ (i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#o.getDelta(), e.#n += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((a, l) => a + l) / e._fpsBuffer.length, $ && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1108
1114
  const o = t++;
1109
1115
  e.#t.call(this, s, r), e.onAfterRender(s, r, o);
1110
1116
  };
@@ -1120,11 +1126,11 @@ class v {
1120
1126
  const i = this.renderer.renderLists.get(t, 0).opaque;
1121
1127
  let o = !0;
1122
1128
  if (i.length === 1) {
1123
- const l = i[0].material;
1124
- (l.name === "EffectMaterial" || l.name === "CopyShader") && (o = !1);
1129
+ const a = i[0].material;
1130
+ (a.name === "EffectMaterial" || a.name === "CopyShader") && (o = !1);
1125
1131
  }
1126
1132
  if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
1127
- if (mt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, R && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, R && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
1133
+ if (mt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, $ && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, $ && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
1128
1134
  return;
1129
1135
  this.internalUpdate(t, e), this._postprocessPromiseGroups();
1130
1136
  }
@@ -1136,12 +1142,12 @@ class v {
1136
1142
  const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
1137
1143
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
1138
1144
  const i = this.targetTriangleDensity;
1139
- for (const a of r) {
1140
- if (a.material && (a.geometry?.type === "BoxGeometry" || a.geometry?.type === "BufferGeometry") && (a.material.name === "SphericalGaussianBlur" || a.material.name == "BackgroundCubeMaterial" || a.material.name === "CubemapFromEquirect" || a.material.name === "EquirectangularToCubeUV")) {
1141
- R && (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)));
1145
+ for (const l of r) {
1146
+ if (l.material && (l.geometry?.type === "BoxGeometry" || l.geometry?.type === "BufferGeometry") && (l.material.name === "SphericalGaussianBlur" || l.material.name == "BackgroundCubeMaterial" || l.material.name === "CubemapFromEquirect" || l.material.name === "EquirectangularToCubeUV")) {
1147
+ $ && (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", l, l.material.name, l.material.type)));
1142
1148
  continue;
1143
1149
  }
1144
- switch (a.material.type) {
1150
+ switch (l.material.type) {
1145
1151
  case "LineBasicMaterial":
1146
1152
  case "LineDashedMaterial":
1147
1153
  case "PointsMaterial":
@@ -1150,22 +1156,22 @@ class v {
1150
1156
  case "MeshDepthMaterial":
1151
1157
  continue;
1152
1158
  }
1153
- if (R === "color" && a.material && !a.object.progressive_debug_color) {
1154
- a.object.progressive_debug_color = !0;
1155
- const c = Math.random() * 16777215, y = new Ve({ color: c });
1156
- a.object.material = y;
1159
+ if ($ === "color" && l.material && !l.object.progressive_debug_color) {
1160
+ l.object.progressive_debug_color = !0;
1161
+ const d = Math.random() * 16777215, g = new Ve({ color: d });
1162
+ l.object.material = g;
1157
1163
  }
1158
- const u = a.object;
1164
+ const u = l.object;
1159
1165
  (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1160
1166
  }
1161
1167
  const o = s.transparent;
1162
- for (const a of o) {
1163
- const u = a.object;
1168
+ for (const l of o) {
1169
+ const u = l.object;
1164
1170
  (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1165
1171
  }
1166
- const l = s.transmissive;
1167
- for (const a of l) {
1168
- const u = a.object;
1172
+ const a = s.transmissive;
1173
+ for (const l of a) {
1174
+ const u = l.object;
1169
1175
  (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1170
1176
  }
1171
1177
  }
@@ -1175,13 +1181,13 @@ class v {
1175
1181
  let i = s[fe];
1176
1182
  if (i || (i = new yt(), s[fe] = i), i.frames++ < 2)
1177
1183
  return;
1178
- for (const l of z)
1179
- l.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1184
+ for (const a of q)
1185
+ a.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1180
1186
  const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : V;
1181
- o >= 0 ? (T.mesh_lod = o, T.texture_lod = o) : (this.calculateLodLevel(e, s, i, r, T), T.mesh_lod = Math.round(T.mesh_lod), T.texture_lod = Math.round(T.texture_lod)), T.mesh_lod >= 0 && this.loadProgressiveMeshes(s, T.mesh_lod), s.material && T.texture_lod >= 0 && this.loadProgressiveTextures(s.material, T.texture_lod, o), f && s.material && !s.isGizmo && ke(s.material);
1182
- for (const l of z)
1183
- l.onAfterUpdatedLOD?.(this.renderer, t, e, s, T);
1184
- i.lastLodLevel_Mesh = T.mesh_lod, i.lastLodLevel_Texture = T.texture_lod;
1187
+ o >= 0 ? (P.mesh_lod = o, P.texture_lod = o) : (this.calculateLodLevel(e, s, i, r, P), P.mesh_lod = Math.round(P.mesh_lod), P.texture_lod = Math.round(P.texture_lod)), P.mesh_lod >= 0 && this.loadProgressiveMeshes(s, P.mesh_lod), s.material && P.texture_lod >= 0 && this.loadProgressiveTextures(s.material, P.texture_lod, o), h && s.material && !s.isGizmo && ke(s.material);
1188
+ for (const a of q)
1189
+ a.onAfterUpdatedLOD?.(this.renderer, t, e, s, P);
1190
+ i.lastLodLevel_Mesh = P.mesh_lod, i.lastLodLevel_Texture = P.texture_lod;
1185
1191
  }
1186
1192
  /** Load progressive textures for the given material
1187
1193
  * @param material the material to load the textures for
@@ -1196,10 +1202,10 @@ class v {
1196
1202
  return;
1197
1203
  }
1198
1204
  let r = !1;
1199
- if ((t[U] === void 0 || e < t[U]) && (r = !0), s !== void 0 && s >= 0 && (r = t[U] != s, e = s), r) {
1200
- t[U] = e;
1205
+ if ((t[z] === void 0 || e < t[z]) && (r = !0), s !== void 0 && s >= 0 && (r = t[z] != s, e = s), r) {
1206
+ t[z] = e;
1201
1207
  const i = m.assignTextureLOD(t, e).then((o) => {
1202
- this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
1208
+ this._lodchangedlisteners.forEach((a) => a({ type: "texture", level: e, object: t }));
1203
1209
  });
1204
1210
  ce.addPromise("texture", t, i, this._newPromiseGroups);
1205
1211
  }
@@ -1212,28 +1218,28 @@ class v {
1212
1218
  */
1213
1219
  loadProgressiveMeshes(t, e) {
1214
1220
  if (!t) return Promise.resolve(null);
1215
- let s = t[U] !== e;
1221
+ let s = t[z] !== e;
1216
1222
  const r = t["DEBUG:LOD"];
1217
- if (r != null && (s = t[U] != r, e = r), s) {
1218
- t[U] = e;
1219
- const i = t.geometry, o = m.assignMeshLOD(t, e).then((l) => (l && t[U] == e && i != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), l));
1223
+ if (r != null && (s = t[z] != r, e = r), s) {
1224
+ t[z] = e;
1225
+ const i = t.geometry, o = m.assignMeshLOD(t, e).then((a) => (a && t[z] == e && i != t.geometry && this._lodchangedlisteners.forEach((l) => l({ type: "mesh", level: e, object: t })), a));
1220
1226
  return ce.addPromise("mesh", t, o, this._newPromiseGroups), o;
1221
1227
  }
1222
1228
  return Promise.resolve(null);
1223
1229
  }
1224
1230
  // private testIfLODLevelsAreAvailable() {
1225
- _sphere = new Oe();
1231
+ _sphere = new Se();
1226
1232
  _tempBox = new ge();
1227
1233
  _tempBox2 = new ge();
1228
- tempMatrix = new Le();
1229
- _tempWorldPosition = new A();
1230
- _tempBoxSize = new A();
1231
- _tempBox2Size = new A();
1232
- static corner0 = new A();
1233
- static corner1 = new A();
1234
- static corner2 = new A();
1235
- static corner3 = new A();
1236
- static _tempPtInside = new A();
1234
+ tempMatrix = new ve();
1235
+ _tempWorldPosition = new R();
1236
+ _tempBoxSize = new R();
1237
+ _tempBox2Size = new R();
1238
+ static corner0 = new R();
1239
+ static corner1 = new R();
1240
+ static corner2 = new R();
1241
+ static corner3 = new R();
1242
+ static _tempPtInside = new R();
1237
1243
  static isInside(t, e) {
1238
1244
  const s = t.min, r = t.max, i = (s.x + r.x) * 0.5, o = (s.y + r.y) * 0.5;
1239
1245
  return this._tempPtInside.set(i, o, s.z).applyMatrix4(e).z < 0;
@@ -1250,105 +1256,105 @@ class v {
1250
1256
  i.mesh_lod = -1, i.texture_lod = -1;
1251
1257
  return;
1252
1258
  }
1253
- let l = 10 + 1, a = !1;
1254
- if (R && e["DEBUG:LOD"] != null)
1259
+ let a = 10 + 1, l = !1;
1260
+ if ($ && e["DEBUG:LOD"] != null)
1255
1261
  return e["DEBUG:LOD"];
1256
- const u = m.getMeshLODExtension(e.geometry)?.lods, c = m.getPrimitiveIndex(e.geometry), y = u && u.length > 0, w = m.getMaterialMinMaxLODsCount(e.material), _ = w.min_count !== 1 / 0 && w.min_count >= 0 && w.max_count >= 0;
1257
- if (!y && !_) {
1262
+ const u = m.getMeshLODExtension(e.geometry)?.lods, d = m.getPrimitiveIndex(e.geometry), g = u && u.length > 0, y = m.getMaterialMinMaxLODsCount(e.material), M = y.min_count !== 1 / 0 && y.min_count >= 0 && y.max_count >= 0;
1263
+ if (!g && !M) {
1258
1264
  i.mesh_lod = 0, i.texture_lod = 0;
1259
1265
  return;
1260
1266
  }
1261
- y || (a = !0, l = 0);
1262
- const k = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1263
- let M = e.geometry.boundingBox;
1267
+ g || (l = !0, a = 0);
1268
+ const L = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1269
+ let T = e.geometry.boundingBox;
1264
1270
  if (e.type === "SkinnedMesh") {
1265
- const d = e;
1266
- if (!d.boundingBox)
1267
- d.computeBoundingBox();
1271
+ const x = e;
1272
+ if (!x.boundingBox)
1273
+ x.computeBoundingBox();
1268
1274
  else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
1269
- if (!d[v.$skinnedMeshBoundsOffset]) {
1270
- const b = v.skinnedMeshBoundsFrameOffsetCounter++;
1271
- d[v.$skinnedMeshBoundsOffset] = b;
1275
+ if (!x[v.$skinnedMeshBoundsOffset]) {
1276
+ const _ = v.skinnedMeshBoundsFrameOffsetCounter++;
1277
+ x[v.$skinnedMeshBoundsOffset] = _;
1272
1278
  }
1273
- const g = d[v.$skinnedMeshBoundsOffset];
1274
- if ((s.frames + g) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1275
- const b = ee(d), B = d.geometry;
1276
- b && (d.geometry = b), d.computeBoundingBox(), d.geometry = B;
1279
+ const f = x[v.$skinnedMeshBoundsOffset];
1280
+ if ((s.frames + f) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1281
+ const _ = ee(x), D = x.geometry;
1282
+ _ && (x.geometry = _), x.computeBoundingBox(), x.geometry = D;
1277
1283
  }
1278
1284
  }
1279
- M = d.boundingBox;
1285
+ T = x.boundingBox;
1280
1286
  }
1281
- if (M) {
1282
- const d = t;
1287
+ if (T) {
1288
+ const x = t;
1283
1289
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
1284
1290
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
1285
- const h = t.getWorldPosition(this._tempWorldPosition);
1286
- if (this._sphere.containsPoint(h)) {
1291
+ const c = t.getWorldPosition(this._tempWorldPosition);
1292
+ if (this._sphere.containsPoint(c)) {
1287
1293
  i.mesh_lod = 0, i.texture_lod = 0;
1288
1294
  return;
1289
1295
  }
1290
1296
  }
1291
- if (this._tempBox.copy(M), this._tempBox.applyMatrix4(e.matrixWorld), d.isPerspectiveCamera && v.isInside(this._tempBox, this.projectionScreenMatrix)) {
1297
+ if (this._tempBox.copy(T), this._tempBox.applyMatrix4(e.matrixWorld), x.isPerspectiveCamera && v.isInside(this._tempBox, this.projectionScreenMatrix)) {
1292
1298
  i.mesh_lod = 0, i.texture_lod = 0;
1293
1299
  return;
1294
1300
  }
1295
- if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && d.isPerspectiveCamera && d.fov > 70) {
1296
- const h = this._tempBox.min, p = this._tempBox.max;
1297
- let O = h.x, S = h.y, G = p.x, Y = p.y;
1298
- const te = 2, ne = 1.5, se = (h.x + p.x) * 0.5, re = (h.y + p.y) * 0.5;
1299
- O = (O - se) * te + se, S = (S - re) * te + re, G = (G - se) * te + se, Y = (Y - re) * te + re;
1300
- const $e = O < 0 && G > 0 ? 0 : Math.min(Math.abs(h.x), Math.abs(p.x)), Be = S < 0 && Y > 0 ? 0 : Math.min(Math.abs(h.y), Math.abs(p.y)), ae = Math.max($e, Be);
1301
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && x.isPerspectiveCamera && x.fov > 70) {
1302
+ const c = this._tempBox.min, p = this._tempBox.max;
1303
+ let w = c.x, b = c.y, A = p.x, Y = p.y;
1304
+ const te = 2, ne = 1.5, se = (c.x + p.x) * 0.5, re = (c.y + p.y) * 0.5;
1305
+ w = (w - se) * te + se, b = (b - re) * te + re, A = (A - se) * te + se, Y = (Y - re) * te + re;
1306
+ const $e = w < 0 && A > 0 ? 0 : Math.min(Math.abs(c.x), Math.abs(p.x)), Be = b < 0 && Y > 0 ? 0 : Math.min(Math.abs(c.y), Math.abs(p.y)), ae = Math.max($e, Be);
1301
1307
  s.lastCentrality = (ne - ae) * (ne - ae) * (ne - ae);
1302
1308
  } else
1303
1309
  s.lastCentrality = 1;
1304
- const g = this._tempBox.getSize(this._tempBoxSize);
1305
- g.multiplyScalar(0.5), screen.availHeight > 0 && k > 0 && g.multiplyScalar(k / screen.availHeight), t.isPerspectiveCamera ? g.x *= t.aspect : t.isOrthographicCamera;
1306
- const b = t.matrixWorldInverse, B = this._tempBox2;
1307
- B.copy(M), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(b);
1308
- const D = B.getSize(this._tempBox2Size), q = Math.max(D.x, D.y);
1309
- if (Math.max(g.x, g.y) != 0 && q != 0 && (g.z = D.z / Math.max(D.x, D.y) * Math.max(g.x, g.y)), s.lastScreenCoverage = Math.max(g.x, g.y, g.z), s.lastScreenspaceVolume.copy(g), s.lastScreenCoverage *= s.lastCentrality, R && v.debugDrawLine) {
1310
- const h = this.tempMatrix.copy(this.projectionScreenMatrix);
1311
- h.invert();
1312
- const p = v.corner0, O = v.corner1, S = v.corner2, G = v.corner3;
1313
- p.copy(this._tempBox.min), O.copy(this._tempBox.max), O.x = p.x, S.copy(this._tempBox.max), S.y = p.y, G.copy(this._tempBox.max);
1314
- const Y = (p.z + G.z) * 0.5;
1315
- p.z = O.z = S.z = G.z = Y, p.applyMatrix4(h), O.applyMatrix4(h), S.applyMatrix4(h), G.applyMatrix4(h), v.debugDrawLine(p, O, 255), v.debugDrawLine(p, S, 255), v.debugDrawLine(O, G, 255), v.debugDrawLine(S, G, 255);
1310
+ const f = this._tempBox.getSize(this._tempBoxSize);
1311
+ f.multiplyScalar(0.5), screen.availHeight > 0 && L > 0 && f.multiplyScalar(L / screen.availHeight), t.isPerspectiveCamera ? f.x *= t.aspect : t.isOrthographicCamera;
1312
+ const _ = t.matrixWorldInverse, D = this._tempBox2;
1313
+ D.copy(T), D.applyMatrix4(e.matrixWorld), D.applyMatrix4(_);
1314
+ const I = D.getSize(this._tempBox2Size), C = Math.max(I.x, I.y);
1315
+ if (Math.max(f.x, f.y) != 0 && C != 0 && (f.z = I.z / Math.max(I.x, I.y) * Math.max(f.x, f.y)), s.lastScreenCoverage = Math.max(f.x, f.y, f.z), s.lastScreenspaceVolume.copy(f), s.lastScreenCoverage *= s.lastCentrality, $ && v.debugDrawLine) {
1316
+ const c = this.tempMatrix.copy(this.projectionScreenMatrix);
1317
+ c.invert();
1318
+ const p = v.corner0, w = v.corner1, b = v.corner2, A = v.corner3;
1319
+ p.copy(this._tempBox.min), w.copy(this._tempBox.max), w.x = p.x, b.copy(this._tempBox.max), b.y = p.y, A.copy(this._tempBox.max);
1320
+ const Y = (p.z + A.z) * 0.5;
1321
+ p.z = w.z = b.z = A.z = Y, p.applyMatrix4(c), w.applyMatrix4(c), b.applyMatrix4(c), A.applyMatrix4(c), v.debugDrawLine(p, w, 255), v.debugDrawLine(p, b, 255), v.debugDrawLine(w, A, 255), v.debugDrawLine(b, A, 255);
1316
1322
  }
1317
- let L = 999;
1323
+ let O = 999;
1318
1324
  if (u && s.lastScreenCoverage > 0)
1319
- for (let h = 0; h < u.length; h++) {
1320
- const p = u[h], S = (p.densities?.[c] || p.density || 1e-5) / s.lastScreenCoverage;
1321
- if (c > 0 && ve() && !p.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), S < r) {
1322
- L = h;
1325
+ for (let c = 0; c < u.length; c++) {
1326
+ const p = u[c], b = (p.densities?.[d] || p.density || 1e-5) / s.lastScreenCoverage;
1327
+ if (d > 0 && be() && !p.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), b < r) {
1328
+ O = c;
1323
1329
  break;
1324
1330
  }
1325
1331
  }
1326
- L < l && (l = L, a = !0);
1332
+ O < a && (a = O, l = !0);
1327
1333
  }
1328
- if (a ? i.mesh_lod = l : i.mesh_lod = s.lastLodLevel_Mesh, R && i.mesh_lod != s.lastLodLevel_Mesh) {
1329
- const g = u?.[i.mesh_lod];
1330
- g && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${g.densities?.[c].toFixed(0)}) | ${e.name}`);
1334
+ if (l ? i.mesh_lod = a : i.mesh_lod = s.lastLodLevel_Mesh, $ && i.mesh_lod != s.lastLodLevel_Mesh) {
1335
+ const f = u?.[i.mesh_lod];
1336
+ f && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${f.densities?.[d].toFixed(0)}) | ${e.name}`);
1331
1337
  }
1332
- if (_) {
1333
- const d = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1338
+ if (M) {
1339
+ const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1334
1340
  if (s.lastLodLevel_Texture < 0) {
1335
- if (i.texture_lod = w.max_count - 1, R) {
1336
- const g = w.lods[w.max_count - 1];
1337
- R && console.log(`First Texture LOD ${i.texture_lod} (${g.max_height}px) - ${e.name}`);
1341
+ if (i.texture_lod = y.max_count - 1, $) {
1342
+ const f = y.lods[y.max_count - 1];
1343
+ $ && console.log(`First Texture LOD ${i.texture_lod} (${f.max_height}px) - ${e.name}`);
1338
1344
  }
1339
1345
  } else {
1340
- const g = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1341
- let b = s.lastScreenCoverage * 4;
1342
- this.context?.engine === "model-viewer" && (b *= 1.5);
1343
- const D = k / window.devicePixelRatio * b;
1344
- let q = !1;
1345
- for (let P = w.lods.length - 1; P >= 0; P--) {
1346
- const L = w.lods[P];
1347
- if (!(d && L.max_height >= 2048) && !(Ae() && L.max_height > 4096) && (L.max_height > D || !q && P === 0)) {
1348
- if (q = !0, i.texture_lod = P, R && i.texture_lod < s.lastLodLevel_Texture) {
1349
- const x = L.max_height;
1350
- console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${x}px
1351
- Screensize: ${D.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
1346
+ const f = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1347
+ let _ = s.lastScreenCoverage * 4;
1348
+ this.context?.engine === "model-viewer" && (_ *= 1.5);
1349
+ const I = L / window.devicePixelRatio * _;
1350
+ let C = !1;
1351
+ for (let W = y.lods.length - 1; W >= 0; W--) {
1352
+ const O = y.lods[W];
1353
+ if (!(x && O.max_height >= 2048) && !(_e() && O.max_height > 4096) && (O.max_height > I || !C && W === 0)) {
1354
+ if (C = !0, i.texture_lod = W, $ && i.texture_lod < s.lastLodLevel_Texture) {
1355
+ const S = O.max_height;
1356
+ console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${S}px
1357
+ Screensize: ${I.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${f.toFixed(1)}
1352
1358
  ${e.name}`);
1353
1359
  }
1354
1360
  break;
@@ -1364,16 +1370,16 @@ class yt {
1364
1370
  lastLodLevel_Mesh = -1;
1365
1371
  lastLodLevel_Texture = -1;
1366
1372
  lastScreenCoverage = 0;
1367
- lastScreenspaceVolume = new A();
1373
+ lastScreenspaceVolume = new R();
1368
1374
  lastCentrality = 0;
1369
1375
  }
1370
- const be = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1376
+ const Me = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1371
1377
  let he = null;
1372
1378
  function Re() {
1373
1379
  const n = xt();
1374
1380
  n && (n.mapURLs(function(t) {
1375
- return Me(), t;
1376
- }), Me(), he?.disconnect(), he = new MutationObserver((t) => {
1381
+ return De(), t;
1382
+ }), De(), he?.disconnect(), he = new MutationObserver((t) => {
1377
1383
  t.forEach((e) => {
1378
1384
  e.addedNodes.forEach((s) => {
1379
1385
  s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ie(s);
@@ -1388,30 +1394,30 @@ function xt() {
1388
1394
  console.debug("[gltf-progressive] model-viewer defined"), Re();
1389
1395
  }), null);
1390
1396
  }
1391
- function Me() {
1397
+ function De() {
1392
1398
  if (typeof document > "u") return;
1393
1399
  document.querySelectorAll("model-viewer").forEach((t) => {
1394
1400
  Ie(t);
1395
1401
  });
1396
1402
  }
1397
- const De = /* @__PURE__ */ new WeakSet();
1403
+ const Oe = /* @__PURE__ */ new WeakSet();
1398
1404
  let wt = 0;
1399
1405
  function Ie(n) {
1400
- if (!n || De.has(n))
1406
+ if (!n || Oe.has(n))
1401
1407
  return null;
1402
- De.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
1408
+ Oe.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
1403
1409
  `, n.getAttribute("src"));
1404
1410
  let t = null, e = null, s = null;
1405
1411
  for (let r = n; r != null; r = Object.getPrototypeOf(r)) {
1406
- const i = Object.getOwnPropertySymbols(r), o = i.find((u) => u.toString() == "Symbol(renderer)"), l = i.find((u) => u.toString() == "Symbol(scene)"), a = i.find((u) => u.toString() == "Symbol(needsRender)");
1407
- !t && o != null && (t = n[o].threeRenderer), !e && l != null && (e = n[l]), !s && a != null && (s = n[a]);
1412
+ const i = Object.getOwnPropertySymbols(r), o = i.find((u) => u.toString() == "Symbol(renderer)"), a = i.find((u) => u.toString() == "Symbol(scene)"), l = i.find((u) => u.toString() == "Symbol(needsRender)");
1413
+ !t && o != null && (t = n[o].threeRenderer), !e && a != null && (e = n[a]), !s && l != null && (s = n[l]);
1408
1414
  }
1409
1415
  if (t && e) {
1410
1416
  let r = function() {
1411
1417
  if (s) {
1412
- let o = 0, l = setInterval(() => {
1418
+ let o = 0, a = setInterval(() => {
1413
1419
  if (o++ > 5) {
1414
- clearInterval(l);
1420
+ clearInterval(a);
1415
1421
  return;
1416
1422
  }
1417
1423
  s?.call(n);
@@ -1454,39 +1460,39 @@ class _t {
1454
1460
  e[ie] = !0;
1455
1461
  const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
1456
1462
  if (i && s && e.material) {
1457
- let o = function(a) {
1458
- if (a[ie] == !0) return;
1459
- a[ie] = !0, a.userData && (a.userData.LOD = -1);
1460
- const u = Object.keys(a);
1461
- for (let c = 0; c < u.length; c++) {
1462
- const y = u[c], w = a[y];
1463
- if (w?.isTexture === !0) {
1464
- const _ = w.userData?.associations?.textures;
1465
- if (_ == null) continue;
1466
- const k = s.parser.json.textures[_];
1467
- if (!k) {
1468
- console.warn("Texture data not found for texture index " + _);
1463
+ let o = function(l) {
1464
+ if (l[ie] == !0) return;
1465
+ l[ie] = !0, l.userData && (l.userData.LOD = -1);
1466
+ const u = Object.keys(l);
1467
+ for (let d = 0; d < u.length; d++) {
1468
+ const g = u[d], y = l[g];
1469
+ if (y?.isTexture === !0) {
1470
+ const M = y.userData?.associations?.textures;
1471
+ if (M == null) continue;
1472
+ const L = s.parser.json.textures[M];
1473
+ if (!L) {
1474
+ console.warn("Texture data not found for texture index " + M);
1469
1475
  continue;
1470
1476
  }
1471
- if (k?.extensions?.[W]) {
1472
- const M = k.extensions[W];
1473
- M && i && m.registerTexture(i, w, M.lods.length, _, M);
1477
+ if (L?.extensions?.[U]) {
1478
+ const T = L.extensions[U];
1479
+ T && i && m.registerTexture(i, y, T.lods.length, M, T);
1474
1480
  }
1475
1481
  }
1476
1482
  }
1477
1483
  };
1478
- const l = e.material;
1479
- if (Array.isArray(l)) for (const a of l) o(a);
1480
- else o(l);
1484
+ const a = e.material;
1485
+ if (Array.isArray(a)) for (const l of a) o(l);
1486
+ else o(a);
1481
1487
  }
1482
1488
  }
1483
1489
  tryParseMeshLOD(t, e) {
1484
- if (e[be] == !0) return;
1485
- e[be] = !0;
1490
+ if (e[Me] == !0) return;
1491
+ e[Me] = !0;
1486
1492
  const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
1487
1493
  if (!r)
1488
1494
  return;
1489
- const i = e.userData?.gltfExtensions?.[W];
1495
+ const i = e.userData?.gltfExtensions?.[U];
1490
1496
  if (i && r) {
1491
1497
  const o = e.uuid;
1492
1498
  m.registerMesh(r, o, e, 0, i.lods.length, i);
@@ -1508,7 +1514,7 @@ function Lt(...n) {
1508
1514
  default:
1509
1515
  throw new Error("Invalid arguments");
1510
1516
  }
1511
- we(e), Pe(s), Ce(s, {
1517
+ we(e), Te(s), Ae(s, {
1512
1518
  progressive: !0,
1513
1519
  ...r?.hints
1514
1520
  }), s.register((o) => new m(o));
@@ -1521,7 +1527,7 @@ if (!nt) {
1521
1527
  gltfProgressive: {
1522
1528
  useNeedleProgressive: Lt,
1523
1529
  LODsManager: v,
1524
- configureLoader: Ce,
1530
+ configureLoader: Ae,
1525
1531
  getRaycastMesh: ee,
1526
1532
  useRaycastMeshes: lt
1527
1533
  }
@@ -1533,12 +1539,12 @@ if (!nt) {
1533
1539
  globalThis.Needle[t] = n[t];
1534
1540
  }
1535
1541
  export {
1536
- W as EXTENSION_NAME,
1542
+ U as EXTENSION_NAME,
1537
1543
  v as LODsManager,
1538
1544
  m as NEEDLE_progressive,
1539
1545
  Ke as VERSION,
1540
- Pe as addDracoAndKTX2Loaders,
1541
- Ce as configureLoader,
1546
+ Te as addDracoAndKTX2Loaders,
1547
+ Ae as configureLoader,
1542
1548
  we as createLoaders,
1543
1549
  ee as getRaycastMesh,
1544
1550
  Re as patchModelViewer,