@needle-tools/gltf-progressive 3.5.0-rc → 3.6.0-alpha.1

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,89 +1,89 @@
1
- import { BufferGeometry as E, Mesh as X, Box3 as ge, Vector3 as A, 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";
1
+ import { BufferGeometry as V, Mesh as X, Box3 as ge, Vector3 as P, Sphere as Oe, CompressedTexture as Ue, Texture as W, Matrix3 as ze, InterleavedBuffer as qe, InterleavedBufferAttribute as Ne, BufferAttribute as Ee, TextureLoader as Ve, Color as ke, Matrix4 as ve, Clock as Xe } from "three";
2
2
  import { GLTFLoader as xe } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { MeshoptDecoder as Ee } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
- import { DRACOLoader as Xe } from "three/examples/jsm/loaders/DRACOLoader.js";
3
+ import { MeshoptDecoder as Ke } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
+ import { DRACOLoader as Ye } from "three/examples/jsm/loaders/DRACOLoader.js";
5
5
  import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
6
- const Ke = "";
7
- globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
6
+ const He = "";
7
+ globalThis.GLTF_PROGRESSIVE_VERSION = He;
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, Pe = new URL(I + "draco_decoder.js");
11
- Pe.searchParams.append("range", "true");
12
- fetch(Pe, {
9
+ let I = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", K = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
+ const Qe = I, Je = K, Ce = new URL(I + "draco_decoder.js");
11
+ Ce.searchParams.append("range", "true");
12
+ fetch(Ce, {
13
13
  method: "GET",
14
14
  headers: {
15
15
  Range: "bytes=0-1"
16
16
  }
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/");
17
+ }).catch((i) => {
18
+ console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), I === Qe && et("./include/draco/"), K === Je && tt("./include/ktx2/");
19
19
  }).finally(() => {
20
- Ce();
20
+ Ae();
21
21
  });
22
- const Qe = () => ({
22
+ const Ze = () => ({
23
23
  dracoDecoderPath: I,
24
- ktx2TranscoderPath: j
24
+ ktx2TranscoderPath: K
25
25
  });
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);
26
+ function et(i) {
27
+ I = i, k && k[pe] != I ? (console.debug("Updating Draco decoder path to " + i), k[pe] = I, k.setDecoderPath(I), k.preload()) : console.debug("Setting Draco decoder path to " + i);
28
28
  }
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);
29
+ function tt(i) {
30
+ K = i, $ && $.transcoderPath != K ? (console.debug("Updating KTX2 transcoder path to " + i), $.setTranscoderPath(K), $.init()) : console.debug("Setting KTX2 transcoder path to " + i);
31
31
  }
32
- function we(n) {
33
- return Ce(), n ? $.detectSupport(n) : n !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: $, meshoptDecoder: oe };
32
+ function we(i) {
33
+ return Ae(), i ? $.detectSupport(i) : i !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: k, ktx2Loader: $, meshoptDecoder: oe };
34
34
  }
35
- function Te(n) {
36
- n.dracoLoader || n.setDRACOLoader(C), n.ktx2Loader || n.setKTX2Loader($), n.meshoptDecoder || n.setMeshoptDecoder(oe);
35
+ function Pe(i) {
36
+ i.dracoLoader || i.setDRACOLoader(k), i.ktx2Loader || i.setKTX2Loader($), i.meshoptDecoder || i.setMeshoptDecoder(oe);
37
37
  }
38
38
  const pe = /* @__PURE__ */ Symbol("dracoDecoderPath");
39
- let C, oe, $;
40
- function Ce() {
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, $;
40
+ function Ae() {
41
+ k || (k = new Ye(), k[pe] = I, k.setDecoderPath(I), k.setDecoderConfig({ type: "js" }), k.preload()), $ || ($ = new je(), $.setTranscoderPath(K), $.init()), oe || (oe = Ke);
42
42
  }
43
43
  const me = /* @__PURE__ */ new WeakMap();
44
- function Ae(n, t) {
45
- let e = me.get(n);
46
- e ? e = Object.assign(e, t) : e = t, me.set(n, e);
44
+ function Re(i, t) {
45
+ let e = me.get(i);
46
+ e ? e = Object.assign(e, t) : e = t, me.set(i, e);
47
47
  }
48
- const et = xe.prototype.load;
49
- function tt(...n) {
48
+ const st = xe.prototype.load;
49
+ function rt(...i) {
50
50
  const t = me.get(this);
51
- let e = n[0];
51
+ let e = i[0];
52
52
  const s = new URL(e, window.location.href);
53
53
  if (s.hostname.endsWith("needle.tools")) {
54
- const i = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
55
- i ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
54
+ const n = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
55
+ n ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
56
56
  }
57
- return n[0] = e, et?.call(this, ...n);
57
+ return i[0] = e, st?.call(this, ...i);
58
58
  }
59
- xe.prototype.load = tt;
60
- q("debugprogressive");
61
- function q(n) {
59
+ xe.prototype.load = rt;
60
+ N("debugprogressive");
61
+ function N(i) {
62
62
  if (typeof window > "u") return !1;
63
- const e = new URL(window.location.href).searchParams.get(n);
63
+ const e = new URL(window.location.href).searchParams.get(i);
64
64
  return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
65
65
  }
66
- function st(n, t) {
67
- if (t === void 0 || n === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
66
+ function nt(i, t) {
67
+ if (t === void 0 || i === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
68
68
  return t;
69
- const e = n.lastIndexOf("/");
69
+ const e = i.lastIndexOf("/");
70
70
  if (e >= 0) {
71
- const s = n.substring(0, e + 1);
71
+ const s = i.substring(0, e + 1);
72
72
  for (; s.endsWith("/") && t.startsWith("/"); ) t = t.substring(1);
73
73
  return s + t;
74
74
  }
75
75
  return t;
76
76
  }
77
- function _e() {
78
- return H !== void 0 || (H = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), q("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", H)), H;
77
+ function Le() {
78
+ return j !== void 0 || (j = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", j)), j;
79
79
  }
80
- let H;
81
- function be() {
80
+ let j;
81
+ function Me() {
82
82
  if (typeof window > "u") return !1;
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
- return n.hostname === "127.0.0.1" || t;
83
+ const i = new URL(window.location.href), t = i.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);
84
+ return i.hostname === "127.0.0.1" || t;
85
85
  }
86
- class rt {
86
+ class ot {
87
87
  constructor(t, e = {}) {
88
88
  this.maxConcurrent = t, this.debug = e.debug ?? !1, typeof window < "u" && window.requestAnimationFrame(this.tick);
89
89
  }
@@ -112,96 +112,97 @@ class rt {
112
112
  this.debug && console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);
113
113
  const { key: s, resolve: r } = this._queue.shift();
114
114
  r({
115
- use: (i) => this.add(s, i)
115
+ use: (n) => this.add(s, n)
116
116
  });
117
117
  }
118
118
  }
119
119
  }
120
- function it(n) {
121
- const t = n.image?.width ?? 0, e = n.image?.height ?? 0, s = n.image?.depth ?? 1, r = Math.floor(Math.log2(Math.max(t, e, s))) + 1, i = ot(n);
122
- return t * e * s * i * (1 - Math.pow(0.25, r)) / (1 - 0.25);
120
+ function it(i) {
121
+ const t = i.image?.width ?? 0, e = i.image?.height ?? 0, s = i.image?.depth ?? 1, r = Math.floor(Math.log2(Math.max(t, e, s))) + 1, n = at(i);
122
+ return t * e * s * n * (1 - Math.pow(0.25, r)) / (1 - 0.25);
123
123
  }
124
- function ot(n) {
124
+ function at(i) {
125
125
  let t = 4;
126
- const e = n.format;
126
+ const e = i.format;
127
127
  e === 1024 || e === 1025 ? t = 1 : e === 1026 || e === 1027 ? t = 2 : e === 1022 || e === 1029 ? t = 3 : (e === 1023 || e === 1033) && (t = 4);
128
128
  let s = 1;
129
- const r = n.type;
129
+ const r = i.type;
130
130
  return r === 1009 || r === 1010 ? s = 1 : r === 1011 || r === 1012 ? s = 2 : r === 1013 || r === 1014 || r === 1015 ? s = 4 : r === 1016 && (s = 2), t * s;
131
131
  }
132
- const nt = typeof window > "u" && typeof document > "u", ye = /* @__PURE__ */ Symbol("needle:raycast-mesh");
133
- function ee(n) {
134
- return n?.[ye] instanceof E ? n[ye] : null;
132
+ const lt = typeof window > "u" && typeof document > "u", ye = /* @__PURE__ */ Symbol("needle:raycast-mesh");
133
+ function ee(i) {
134
+ return i?.[ye] instanceof V ? i[ye] : null;
135
135
  }
136
- function at(n, t) {
137
- if ((n.type === "Mesh" || n.type === "SkinnedMesh") && !ee(n)) {
138
- const s = ut(t);
139
- s.userData = { isRaycastMesh: !0 }, n[ye] = s;
136
+ function ut(i, t) {
137
+ if ((i.type === "Mesh" || i.type === "SkinnedMesh") && !ee(i)) {
138
+ const s = dt(t);
139
+ s.userData = { isRaycastMesh: !0 }, i[ye] = s;
140
140
  }
141
141
  }
142
- function lt(n = !0) {
143
- if (n) {
144
- if (Q) return;
145
- const t = Q = X.prototype.raycast;
142
+ function ct(i = !0) {
143
+ if (i) {
144
+ if (H) return;
145
+ const t = H = X.prototype.raycast;
146
146
  X.prototype.raycast = function(e, s) {
147
- const r = this, i = ee(r);
147
+ const r = this, n = ee(r);
148
148
  let o;
149
- i && r.isMesh && (o = r.geometry, r.geometry = i), t.call(this, e, s), o && (r.geometry = o);
149
+ n && r.isMesh && (o = r.geometry, r.geometry = n), t.call(this, e, s), o && (r.geometry = o);
150
150
  };
151
151
  } else {
152
- if (!Q) return;
153
- X.prototype.raycast = Q, Q = null;
152
+ if (!H) return;
153
+ X.prototype.raycast = H, H = null;
154
154
  }
155
155
  }
156
- let Q = null;
157
- function ut(n) {
158
- const t = new E();
159
- for (const e in n.attributes)
160
- t.setAttribute(e, n.getAttribute(e));
161
- return t.setIndex(n.getIndex()), t;
156
+ let H = null;
157
+ function dt(i) {
158
+ const t = new V();
159
+ for (const e in i.attributes)
160
+ t.setAttribute(e, i.getAttribute(e));
161
+ return t.setIndex(i.getIndex()), t;
162
162
  }
163
- const z = new Array(), f = q("debugprogressive");
164
- let Z, V = -1;
165
- if (f) {
166
- let n = function() {
167
- V += 1, V >= t && (V = -1), console.log(`Toggle LOD level [${V}]`);
168
- }, t = 6;
163
+ const q = new Array(), h = N("debugprogressive");
164
+ let Z, E = -1;
165
+ if (h) {
166
+ let i = function() {
167
+ E += 1, E >= t && (E = -1), console.log(`Toggle LOD level [${E}]`);
168
+ };
169
+ const t = 6;
169
170
  window.addEventListener("keyup", (e) => {
170
- e.key === "p" && n(), e.key === "w" && (Z = !Z, console.log(`Toggle wireframe [${Z}]`));
171
+ e.key === "p" && i(), e.key === "w" && (Z = !Z, console.log(`Toggle wireframe [${Z}]`));
171
172
  const s = parseInt(e.key);
172
- !isNaN(s) && s >= 0 && (V = s, console.log(`Set LOD level to [${V}]`));
173
+ !isNaN(s) && s >= 0 && (E = s, console.log(`Set LOD level to [${E}]`));
173
174
  });
174
175
  }
175
- function ke(n) {
176
- if (f && Z !== void 0)
177
- if (Array.isArray(n))
178
- for (const t of n)
179
- ke(t);
180
- else n && "wireframe" in n && (n.wireframe = Z === !0);
176
+ function Ie(i) {
177
+ if (h && Z !== void 0)
178
+ if (Array.isArray(i))
179
+ for (const t of i)
180
+ Ie(t);
181
+ else i && "wireframe" in i && (i.wireframe = Z === !0);
181
182
  }
182
- const J = new Array();
183
- let ct = 0;
184
- const dt = _e() ? 2 : 10;
185
- function ft(n) {
186
- if (J.length < dt) {
187
- const s = J.length;
188
- f && console.warn(`[Worker] Creating new worker #${s}`);
189
- const r = Le.createWorker(n || {});
190
- return J.push(r), r;
191
- }
192
- const t = ct++ % J.length;
193
- return J[t];
183
+ const Q = new Array();
184
+ let ft = 0;
185
+ const ht = Le() ? 2 : 10;
186
+ function gt(i) {
187
+ if (Q.length < ht) {
188
+ const s = Q.length;
189
+ h && console.warn(`[Worker] Creating new worker #${s}`);
190
+ const r = _e.createWorker(i || {});
191
+ return Q.push(r), r;
192
+ }
193
+ const t = ft++ % Q.length;
194
+ return Q[t];
194
195
  }
195
- class Le {
196
+ class _e {
196
197
  constructor(t, e) {
197
198
  this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
198
199
  const r = s.data;
199
200
  switch (this._debug && console.log("[Worker] EVENT", r), r.type) {
200
201
  case "loaded-gltf":
201
- for (const i of this._running)
202
- if (i.url === r.result.url) {
203
- ht(r.result), i.resolve(r.result);
204
- const o = i.url;
202
+ for (const n of this._running)
203
+ if (n.url === r.result.url) {
204
+ pt(r.result), n.resolve(r.result);
205
+ const o = n.url;
205
206
  o.startsWith("blob:") && URL.revokeObjectURL(o);
206
207
  }
207
208
  }
@@ -219,61 +220,61 @@ class Le {
219
220
  ), {
220
221
  type: "module"
221
222
  });
222
- return new Le(e, t);
223
+ return new _e(e, t);
223
224
  }
224
225
  _running = [];
225
226
  _webglRenderer = null;
226
227
  async load(t, e) {
227
- const s = Qe();
228
+ const s = Ze();
228
229
  let r = e?.renderer;
229
230
  r || (this._webglRenderer ??= (async () => {
230
- const { WebGLRenderer: u } = await import("three");
231
- return new u();
231
+ const { WebGLRenderer: l } = await import("three");
232
+ return new l();
232
233
  })(), r = await this._webglRenderer);
233
- const l = we(r).ktx2Loader.workerConfig;
234
+ const u = we(r).ktx2Loader.workerConfig;
234
235
  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
236
  const a = {
236
237
  type: "load",
237
238
  url: t,
238
239
  dracoDecoderPath: s.dracoDecoderPath,
239
240
  ktx2TranscoderPath: s.ktx2TranscoderPath,
240
- ktx2LoaderConfig: l
241
+ ktx2LoaderConfig: u
241
242
  };
242
- return this._debug && console.debug("[Worker] Sending load request", a), this.worker.postMessage(a), new Promise((u) => {
243
+ return this._debug && console.debug("[Worker] Sending load request", a), this.worker.postMessage(a), new Promise((l) => {
243
244
  this._running.push({
244
245
  url: t.toString(),
245
- resolve: u
246
+ resolve: l
246
247
  });
247
248
  });
248
249
  }
249
250
  _debug = !1;
250
251
  }
251
- function ht(n) {
252
- for (const t of n.geometries) {
253
- const e = t.geometry, s = new E();
252
+ function pt(i) {
253
+ for (const t of i.geometries) {
254
+ const e = t.geometry, s = new V();
254
255
  if (s.name = e.name || "", e.index) {
255
256
  const r = e.index;
256
257
  s.setIndex(le(r));
257
258
  }
258
259
  for (const r in e.attributes) {
259
- const i = e.attributes[r], o = le(i);
260
+ const n = e.attributes[r], o = le(n);
260
261
  s.setAttribute(r, o);
261
262
  }
262
263
  if (e.morphAttributes)
263
264
  for (const r in e.morphAttributes) {
264
- const o = e.morphAttributes[r].map((l) => le(l));
265
+ const o = e.morphAttributes[r].map((u) => le(u));
265
266
  s.morphAttributes[r] = o;
266
267
  }
267
- if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new A(
268
+ if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new P(
268
269
  e.boundingBox?.min.x,
269
270
  e.boundingBox?.min.y,
270
271
  e.boundingBox?.min.z
271
- ), s.boundingBox.max = new A(
272
+ ), s.boundingBox.max = new P(
272
273
  e.boundingBox?.max.x,
273
274
  e.boundingBox?.max.y,
274
275
  e.boundingBox?.max.z
275
- ), s.boundingSphere = new Se(
276
- new A(
276
+ ), s.boundingSphere = new Oe(
277
+ new P(
277
278
  e.boundingSphere?.center.x,
278
279
  e.boundingSphere?.center.y,
279
280
  e.boundingSphere?.center.z
@@ -284,14 +285,14 @@ function ht(n) {
284
285
  s.addGroup(r.start, r.count, r.materialIndex);
285
286
  e.userData && (s.userData = e.userData), t.geometry = s;
286
287
  }
287
- for (const t of n.textures) {
288
+ for (const t of i.textures) {
288
289
  const e = t.texture;
289
290
  let s = null;
290
291
  if (e.isCompressedTexture) {
291
- const r = e.mipmaps, i = e.image?.width || e.source?.data?.width || -1, o = e.image?.height || e.source?.data?.height || -1;
292
- s = new Ge(
292
+ const r = e.mipmaps, n = e.image?.width || e.source?.data?.width || -1, o = e.image?.height || e.source?.data?.height || -1;
293
+ s = new Ue(
293
294
  r,
294
- i,
295
+ n,
295
296
  o,
296
297
  e.format,
297
298
  e.type,
@@ -304,7 +305,7 @@ function ht(n) {
304
305
  e.colorSpace
305
306
  );
306
307
  } else
307
- s = new F(
308
+ s = new W(
308
309
  e.image,
309
310
  e.mapping,
310
311
  e.wrapS,
@@ -315,75 +316,98 @@ function ht(n) {
315
316
  e.type,
316
317
  e.anisotropy,
317
318
  e.colorSpace
318
- ), s.mipmaps = e.mipmaps, s.channel = e.channel, s.source.data = e.source.data, s.flipY = e.flipY, s.premultiplyAlpha = e.premultiplyAlpha, s.unpackAlignment = e.unpackAlignment, s.matrix = new Fe(...e.matrix.elements);
319
+ ), s.mipmaps = e.mipmaps, s.channel = e.channel, s.source.data = e.source.data, s.flipY = e.flipY, s.premultiplyAlpha = e.premultiplyAlpha, s.unpackAlignment = e.unpackAlignment, s.matrix = new ze(...e.matrix.elements);
319
320
  if (!s) {
320
321
  console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");
321
322
  continue;
322
323
  }
323
324
  t.texture = s;
324
325
  }
325
- return n;
326
+ return i;
326
327
  }
327
- function le(n) {
328
- let t = n;
329
- if ("isInterleavedBufferAttribute" in n && n.isInterleavedBufferAttribute) {
330
- const e = n.data, s = e.array, r = new We(s, e.stride);
331
- t = new Ue(r, n.itemSize, s.byteOffset, n.normalized), t.offset = n.offset;
332
- } else "isBufferAttribute" in n && n.isBufferAttribute && (t = new ze(n.array, n.itemSize, n.normalized), t.usage = n.usage, t.gpuType = n.gpuType, t.updateRanges = n.updateRanges);
328
+ function le(i) {
329
+ let t = i;
330
+ if ("isInterleavedBufferAttribute" in i && i.isInterleavedBufferAttribute) {
331
+ const e = i.data, s = e.array, r = new qe(s, e.stride);
332
+ t = new Ne(r, i.itemSize, s.byteOffset, i.normalized), t.offset = i.offset;
333
+ } else "isBufferAttribute" in i && i.isBufferAttribute && (t = new Ee(i.array, i.itemSize, i.normalized), t.usage = i.usage, t.gpuType = i.gpuType, t.updateRanges = i.updateRanges);
333
334
  return t;
334
335
  }
335
- const gt = q("gltf-progressive-worker");
336
- q("gltf-progressive-reduce-mipmaps");
337
- const K = q("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), W = "NEEDLE_progressive";
338
- class m {
336
+ const mt = N("gltf-progressive-worker");
337
+ N("gltf-progressive-reduce-mipmaps");
338
+ const J = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), U = "NEEDLE_progressive";
339
+ class p {
339
340
  /** The name of the extension */
340
341
  get name() {
341
- return W;
342
+ return U;
342
343
  }
343
344
  // #region PUBLIC API
345
+ /**
346
+ * Get the progressive mesh LOD extension data associated with a geometry.
347
+ * Returns the extension metadata (available LOD levels, vertex/index counts, densities) if the geometry was registered with progressive LODs, or `null` otherwise.
348
+ *
349
+ * @param geo - The buffer geometry to look up.
350
+ * @returns The mesh LOD extension data, or `null` if no progressive LODs are registered for this geometry.
351
+ */
344
352
  static getMeshLODExtension(t) {
345
353
  const e = this.getAssignedLODInformation(t);
346
354
  return e?.key ? this.lodInfos.get(e.key) : null;
347
355
  }
356
+ /**
357
+ * Get the glTF primitive index for a geometry within its parent mesh.
358
+ * A single glTF mesh node can contain multiple primitives (sub-geometries). This returns which primitive the geometry corresponds to.
359
+ *
360
+ * @param geo - The buffer geometry to look up.
361
+ * @returns The zero-based primitive index, or `-1` if no LOD information is assigned to this geometry.
362
+ */
348
363
  static getPrimitiveIndex(t) {
349
364
  const e = this.getAssignedLODInformation(t)?.index;
350
365
  return e ?? -1;
351
366
  }
367
+ /**
368
+ * Compute the minimum and maximum number of texture LOD levels across all textures of a material (or array of materials).
369
+ * Iterates over all texture slots on the material and collects LOD count ranges and per-level resolution bounds.
370
+ * Results are cached on the material so subsequent calls are free.
371
+ *
372
+ * @param material - A single material or an array of materials to inspect.
373
+ * @param minmax - Optional accumulator to merge results into (used internally for recursive calls with material arrays).
374
+ * @returns An object with `min_count` / `max_count` (the range of LOD levels across all textures) and a per-level `lods` array with `min_height` / `max_height`.
375
+ */
352
376
  static getMaterialMinMaxLODsCount(t, e) {
353
- const s = this, r = "LODS:minmax", i = t[r];
354
- if (i != null) return i;
377
+ const s = this, r = "LODS:minmax", n = t[r];
378
+ if (n != null) return n;
355
379
  if (e || (e = {
356
380
  min_count: 1 / 0,
357
381
  max_count: 0,
358
382
  lods: []
359
383
  }), Array.isArray(t)) {
360
- for (const l of t)
361
- this.getMaterialMinMaxLODsCount(l, e);
384
+ for (const u of t)
385
+ this.getMaterialMinMaxLODsCount(u, e);
362
386
  return t[r] = e, e;
363
387
  }
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;
368
- u?.isTexture === !0 && o(u, e);
388
+ if (h === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
389
+ const u = t;
390
+ for (const a of Object.keys(u.uniforms)) {
391
+ const l = u.uniforms[a].value;
392
+ l?.isTexture === !0 && o(l, e);
369
393
  }
370
394
  } else if (t.isMaterial)
371
- for (const l of Object.keys(t)) {
372
- const a = t[l];
395
+ for (const u of Object.keys(t)) {
396
+ const a = t[u];
373
397
  a?.isTexture === !0 && o(a, e);
374
398
  }
375
399
  else
376
- f && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
400
+ h && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
377
401
  return t[r] = e, e;
378
- function o(l, a) {
379
- const u = s.getAssignedLODInformation(l);
380
- if (u) {
381
- const c = s.lodInfos.get(u.key);
402
+ function o(u, a) {
403
+ const l = s.getAssignedLODInformation(u);
404
+ if (l) {
405
+ const c = s.lodInfos.get(l.key);
382
406
  if (c && c.lods) {
383
407
  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));
408
+ for (let f = 0; f < c.lods.length; f++) {
409
+ const y = c.lods[f];
410
+ y.width && (a.lods[f] = a.lods[f] || { min_height: 1 / 0, max_height: 0 }, a.lods[f].min_height = Math.min(a.lods[f].min_height, y.height), a.lods[f].max_height = Math.max(a.lods[f].max_height, y.height));
387
411
  }
388
412
  }
389
413
  }
@@ -396,26 +420,26 @@ class m {
396
420
  */
397
421
  static hasLODLevelAvailable(t, e) {
398
422
  if (Array.isArray(t)) {
399
- for (const i of t)
400
- if (this.hasLODLevelAvailable(i, e)) return !0;
423
+ for (const n of t)
424
+ if (this.hasLODLevelAvailable(n, e)) return !0;
401
425
  return !1;
402
426
  }
403
427
  if (t.isMaterial === !0) {
404
- for (const i of Object.keys(t)) {
405
- const o = t[i];
428
+ for (const n of Object.keys(t)) {
429
+ const o = t[n];
406
430
  if (o && o.isTexture && this.hasLODLevelAvailable(o, e))
407
431
  return !0;
408
432
  }
409
433
  return !1;
410
434
  } else if (t.isGroup === !0) {
411
- for (const i of t.children)
412
- if (i.isMesh === !0 && this.hasLODLevelAvailable(i, e))
435
+ for (const n of t.children)
436
+ if (n.isMesh === !0 && this.hasLODLevelAvailable(n, e))
413
437
  return !0;
414
438
  }
415
439
  let s, r;
416
440
  if (t.isMesh ? s = t.geometry : (t.isBufferGeometry || t.isTexture) && (s = t), s && s?.userData?.LODS) {
417
- const i = s.userData.LODS;
418
- if (r = this.lodInfos.get(i.key), e === void 0) return r != null;
441
+ const n = s.userData.LODS;
442
+ if (r = this.lodInfos.get(n.key), e === void 0) return r != null;
419
443
  if (r)
420
444
  return Array.isArray(r.lods) ? e < r.lods.length : e === 0;
421
445
  }
@@ -441,68 +465,69 @@ class m {
441
465
  const s = t.geometry, r = this.getAssignedLODInformation(s);
442
466
  if (!r)
443
467
  return Promise.resolve(null);
444
- for (const i of z)
445
- i.onBeforeGetLODMesh?.(t, e);
446
- return t["LOD:requested level"] = e, m.getOrLoadLOD(s, e).then((i) => {
447
- if (Array.isArray(i)) {
468
+ for (const n of q)
469
+ n.onBeforeGetLODMesh?.(t, e);
470
+ return t["LOD:requested level"] = e, p.getOrLoadLOD(s, e).then((n) => {
471
+ if (Array.isArray(n)) {
448
472
  const o = r.index || 0;
449
- i = i[o];
473
+ n = n[o];
450
474
  }
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;
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);
475
+ return t["LOD:requested level"] === e && (delete t["LOD:requested level"], n && s != n && (n?.isBufferGeometry ? t.geometry = n : h && console.error("Invalid LOD geometry", n))), n;
476
+ }).catch((n) => (console.error("Error loading mesh LOD", t, n), null));
477
+ } else h && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
454
478
  return Promise.resolve(null);
455
479
  }
456
- static assignTextureLOD(t, e = 0) {
480
+ static assignTextureLOD(t, e = 0, s) {
457
481
  if (!t) return Promise.resolve(null);
482
+ const r = s?.force === !0;
458
483
  if (t.isMesh === !0) {
459
- const s = t;
460
- if (Array.isArray(s.material)) {
461
- const r = new Array();
462
- for (const i of s.material) {
463
- const o = this.assignTextureLOD(i, e);
464
- r.push(o);
484
+ const n = t;
485
+ if (Array.isArray(n.material)) {
486
+ const o = new Array();
487
+ for (const u of n.material) {
488
+ const a = this.assignTextureLOD(u, e, s);
489
+ o.push(a);
465
490
  }
466
- return Promise.all(r).then((i) => {
467
- const o = new Array();
468
- for (const l of i)
469
- Array.isArray(l) && o.push(...l);
470
- return o;
491
+ return Promise.all(o).then((u) => {
492
+ const a = new Array();
493
+ for (const l of u)
494
+ Array.isArray(l) && a.push(...l);
495
+ return a;
471
496
  });
472
497
  } else
473
- return this.assignTextureLOD(s.material, e);
498
+ return this.assignTextureLOD(n.material, e, s);
474
499
  }
475
500
  if (t.isMaterial === !0) {
476
- const s = t, r = [], i = new Array();
477
- if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
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);
501
+ const n = t, o = [], u = new Array();
502
+ if (this.trackCurrentMaterialTextureSlots(n), n.uniforms && (n.isRawShaderMaterial || n.isShaderMaterial === !0)) {
503
+ const a = n;
504
+ for (const l of Object.keys(a.uniforms)) {
505
+ const c = a.uniforms[l].value;
506
+ if (c?.isTexture === !0) {
507
+ const f = this.assignTextureLODForSlot(c, e, n, l, r).then((y) => (y && a.uniforms[l].value != y && (a.uniforms[l].value = y, a.uniformsNeedUpdate = !0), y));
508
+ o.push(f), u.push(l);
484
509
  }
485
510
  }
486
511
  } else
487
- for (const o of Object.keys(s)) {
488
- const l = s[o];
512
+ for (const a of Object.keys(n)) {
513
+ const l = n[a];
489
514
  if (l?.isTexture === !0) {
490
- const a = this.assignTextureLODForSlot(l, e, s, o);
491
- r.push(a), i.push(o);
515
+ const c = this.assignTextureLODForSlot(l, e, n, a, r);
516
+ o.push(c), u.push(a);
492
517
  }
493
518
  }
494
- return Promise.all(r).then((o) => {
519
+ return Promise.all(o).then((a) => {
495
520
  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 });
521
+ for (let c = 0; c < a.length; c++) {
522
+ const f = a[c], y = u[c];
523
+ f && f.isTexture === !0 ? l.push({ material: n, slot: y, texture: f, level: e }) : l.push({ material: n, slot: y, texture: null, level: e });
499
524
  }
500
525
  return l;
501
526
  });
502
527
  }
503
- if (t instanceof F || t.isTexture === !0) {
504
- const s = t;
505
- return this.assignTextureLODForSlot(s, e, null, null);
528
+ if (t instanceof W || t.isTexture === !0) {
529
+ const n = t;
530
+ return this.assignTextureLODForSlot(n, e, null, null, r);
506
531
  }
507
532
  return Promise.resolve(null);
508
533
  }
@@ -511,46 +536,119 @@ class m {
511
536
  * @default 50 on desktop, 20 on mobile devices
512
537
  */
513
538
  static set maxConcurrentLoadingTasks(t) {
514
- m.queue.maxConcurrent = t;
539
+ p.queue.maxConcurrent = t;
515
540
  }
516
541
  static get maxConcurrentLoadingTasks() {
517
- return m.queue.maxConcurrent;
542
+ return p.queue.maxConcurrent;
518
543
  }
519
544
  // #region INTERNAL
520
- static assignTextureLODForSlot(t, e, s, r) {
521
- return t?.isTexture !== !0 ? Promise.resolve(null) : r === "glyphMap" ? Promise.resolve(t) : m.getOrLoadLOD(t, e).then((i) => {
522
- if (Array.isArray(i))
545
+ static assignTextureLODForSlot(t, e, s, r, n) {
546
+ if (t?.isTexture !== !0)
547
+ return Promise.resolve(null);
548
+ if (r === "glyphMap")
549
+ return Promise.resolve(t);
550
+ const o = this.getAssignedLODInformation(t);
551
+ if (o && (o.level === e || !n && o.level < e))
552
+ return Promise.resolve(t);
553
+ if (s && r) {
554
+ const a = this.getPendingTextureSlotRequest(s, r);
555
+ if (a && a.level === e && a.force === n)
556
+ return a.promise;
557
+ }
558
+ const u = p.getOrLoadLOD(t, e).then((a) => {
559
+ if (Array.isArray(a))
523
560
  return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), null;
524
- if (i?.isTexture === !0) {
525
- if (i != t && s && r) {
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)) {
533
- 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);
561
+ if (a?.isTexture === !0) {
562
+ if (a != t && s && r) {
563
+ const l = this.getMaterialTextureSlot(s, r) ?? t;
564
+ if (l && !n) {
565
+ const c = this.getAssignedLODInformation(l);
566
+ if (c && c?.level < e)
567
+ return h === "verbose" && console.warn("Assigned texture level is already higher: ", c.level, e, s, l, a), null;
535
568
  }
536
- s[r] = i;
569
+ this.assignTrackedTextureSlot(s, r, a);
537
570
  }
538
- return i;
539
- } else f == "verbose" && console.warn("No LOD found for", t, e);
571
+ return a;
572
+ } else h == "verbose" && console.warn("No LOD found for", t, e);
540
573
  return null;
541
- }).catch((i) => (console.error("Error loading LOD", t, i), null));
574
+ }).catch((a) => (console.error("Error loading LOD", t, a), null));
575
+ return s && r && this.setPendingTextureSlotRequest(s, r, e, n, u), u;
576
+ }
577
+ // Track material slots, not just texture objects. A shared fallback texture can be
578
+ // referenced by many slots and should only be disposed after every slot moved away.
579
+ static trackedTextureSlots = /* @__PURE__ */ new WeakMap();
580
+ static pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
581
+ static trackCurrentMaterialTextureSlots(t) {
582
+ if (t.uniforms && (t.isRawShaderMaterial || t.isShaderMaterial === !0)) {
583
+ const e = t;
584
+ for (const s of Object.keys(e.uniforms)) {
585
+ const r = e.uniforms[s].value;
586
+ r?.isTexture === !0 && this.ensureTrackedTextureSlot(t, s, r);
587
+ }
588
+ return;
589
+ }
590
+ for (const e of Object.keys(t)) {
591
+ const s = t[e];
592
+ s?.isTexture === !0 && this.ensureTrackedTextureSlot(t, e, s);
593
+ }
594
+ }
595
+ static getPendingTextureSlotRequest(t, e) {
596
+ return this.pendingTextureSlotRequests.get(t)?.get(e);
597
+ }
598
+ static setPendingTextureSlotRequest(t, e, s, r, n) {
599
+ let o = this.pendingTextureSlotRequests.get(t);
600
+ o || (o = /* @__PURE__ */ new Map(), this.pendingTextureSlotRequests.set(t, o));
601
+ const u = { level: s, force: r, promise: n };
602
+ o.set(e, u), n.finally(() => {
603
+ o.get(e) === u && o.delete(e);
604
+ });
605
+ }
606
+ static getMaterialTextureSlot(t, e) {
607
+ const r = t.uniforms?.[e];
608
+ if (r?.value?.isTexture === !0)
609
+ return r.value;
610
+ const n = t[e];
611
+ return n?.isTexture === !0 ? n : null;
612
+ }
613
+ static setMaterialTextureSlot(t, e, s) {
614
+ const n = t.uniforms?.[e];
615
+ if (n?.value?.isTexture === !0) {
616
+ n.value = s, t.uniformsNeedUpdate = !0;
617
+ return;
618
+ }
619
+ t[e] = s;
620
+ }
621
+ static assignTrackedTextureSlot(t, e, s) {
622
+ let r = this.trackedTextureSlots.get(t);
623
+ r || (r = /* @__PURE__ */ new Map(), this.trackedTextureSlots.set(t, r));
624
+ const n = this.getMaterialTextureSlot(t, e);
625
+ let o = r.get(e);
626
+ !o && n ? o = this.ensureTrackedTextureSlot(t, e, n) : o && n && o !== n && (this.releaseTrackedTextureSlot(t, e, o), o = this.ensureTrackedTextureSlot(t, e, n)), !(o === s && n === s) && (o && o !== s && this.releaseTrackedTextureSlot(t, e, o), o !== s && (this.trackTextureUsage(s), r.set(e, s)), n !== s && this.setMaterialTextureSlot(t, e, s));
627
+ }
628
+ static ensureTrackedTextureSlot(t, e, s) {
629
+ let r = this.trackedTextureSlots.get(t);
630
+ r || (r = /* @__PURE__ */ new Map(), this.trackedTextureSlots.set(t, r));
631
+ const n = r.get(e);
632
+ return n === s ? n : (n && this.releaseTrackedTextureSlot(t, e, n), this.trackTextureUsage(s), r.set(e, s), s);
633
+ }
634
+ static releaseTrackedTextureSlot(t, e, s) {
635
+ const r = this.trackedTextureSlots.get(t);
636
+ if (r?.get(e) === s && r.delete(e), this.untrackTextureUsage(s) && (h || J)) {
637
+ const o = this.getAssignedLODInformation(s);
638
+ console.log(`[gltf-progressive] Disposed old texture LOD ${o?.level ?? "?"} for ${t.name || t.type}.${e}`, s.uuid);
639
+ }
542
640
  }
543
641
  parser;
544
642
  url;
545
643
  constructor(t) {
546
644
  const e = t.options.path;
547
- f && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
645
+ h && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
548
646
  }
549
647
  _isLoadingMesh;
550
648
  loadMesh = (t) => {
551
649
  if (this._isLoadingMesh) return null;
552
- const e = this.parser.json.meshes[t]?.extensions?.[W];
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;
650
+ const e = this.parser.json.meshes[t]?.extensions?.[U];
651
+ return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && p.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
554
652
  };
555
653
  // private _isLoadingTexture;
556
654
  // loadTexture = (textureIndex: number) => {
@@ -567,64 +665,82 @@ class m {
567
665
  // });
568
666
  // }
569
667
  afterRoot(t) {
570
- return f && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
668
+ return h && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
571
669
  if (e?.extensions) {
572
- const r = e?.extensions[W];
670
+ const r = e?.extensions[U];
573
671
  if (r) {
574
672
  if (!r.lods) {
575
- f && console.warn("Texture has no LODs", r);
673
+ h && console.warn("Texture has no LODs", r);
576
674
  return;
577
675
  }
578
- let i = !1;
676
+ let n = !1;
579
677
  for (const o of this.parser.associations.keys())
580
- o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (i = !0, m.registerTexture(this.url, o, r.lods?.length, s, r));
581
- i || this.parser.getDependency("texture", s).then((o) => {
582
- o && m.registerTexture(this.url, o, r.lods?.length, s, r);
678
+ o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (n = !0, p.registerTexture(this.url, o, r.lods?.length, s, r));
679
+ n || this.parser.getDependency("texture", s).then((o) => {
680
+ o && p.registerTexture(this.url, o, r.lods?.length, s, r);
583
681
  });
584
682
  }
585
683
  }
586
684
  }), this.parser.json.meshes?.forEach((e, s) => {
587
685
  if (e?.extensions) {
588
- const r = e?.extensions[W];
686
+ const r = e?.extensions[U];
589
687
  if (r && r.lods) {
590
- for (const i of this.parser.associations.keys())
591
- if (i.isMesh) {
592
- const o = this.parser.associations.get(i);
593
- o?.meshes === s && m.registerMesh(this.url, r.guid, i, r.lods.length, o.primitives, r);
688
+ for (const n of this.parser.associations.keys())
689
+ if (n.isMesh) {
690
+ const o = this.parser.associations.get(n);
691
+ o?.meshes === s && p.registerMesh(this.url, r.guid, n, r.lods.length, o.primitives, r);
594
692
  }
595
693
  }
596
694
  }
597
695
  }), null;
598
696
  }
599
697
  /**
600
- * Register a texture with LOD information
698
+ * Register a texture with progressive LOD information. This associates the texture with its LOD extension data
699
+ * so the LODs manager can later swap it for higher or lower resolution versions based on screen coverage.
700
+ * Typically called during glTF loading when the progressive extension is parsed.
701
+ *
702
+ * @param url - The source URL of the glTF file this texture was loaded from.
703
+ * @param tex - The three.js Texture instance to register.
704
+ * @param level - The LOD level this texture represents (0 = highest resolution).
705
+ * @param index - The texture index within the glTF file.
706
+ * @param ext - The parsed progressive texture extension data containing all available LOD levels and their dimensions.
601
707
  */
602
- static registerTexture = (t, e, s, r, i) => {
708
+ static registerTexture = (t, e, s, r, n) => {
603
709
  if (!e) {
604
- f && console.error("!! gltf-progressive: Called register texture without texture");
710
+ h && console.error("!! gltf-progressive: Called register texture without texture");
605
711
  return;
606
712
  }
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);
713
+ if (h) {
714
+ const u = e.image?.width || e.source?.data?.width || 0, a = e.image?.height || e.source?.data?.height || 0;
715
+ console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${u}x${a}, Max: ${n.lods[0]?.width}x${n.lods[0]?.height}, uuid: ${e.uuid}`, n, e);
610
716
  }
611
- e.source && (e.source[ue] = i);
612
- const o = i.guid;
613
- m.assignLODInformation(t, e, o, s, r), m.lodInfos.set(o, i), m.lowresCache.set(o, new WeakRef(e));
717
+ e.source && (e.source[ue] = n);
718
+ const o = n.guid;
719
+ p.assignLODInformation(t, e, o, s, r), p.lodInfos.set(o, n), p.lowresCache.set(o, new WeakRef(e));
614
720
  };
615
721
  /**
616
- * Register a mesh with LOD information
722
+ * Register a mesh with progressive LOD information. This associates the mesh geometry with its LOD extension data
723
+ * so the LODs manager can later swap it for higher or lower density versions based on screen coverage.
724
+ * Typically called during glTF loading when the progressive extension is parsed.
725
+ * If the mesh is registered at a level > 0 (i.e. not full resolution), a raycast mesh is automatically preserved for accurate picking.
726
+ *
727
+ * @param url - The source URL of the glTF file this mesh was loaded from.
728
+ * @param key - A unique key identifying this mesh's LOD group (typically derived from the extension GUID).
729
+ * @param mesh - The three.js Mesh instance to register.
730
+ * @param level - The LOD level this mesh represents (0 = highest resolution / full density).
731
+ * @param index - The primitive index within the glTF mesh node.
732
+ * @param ext - The parsed progressive mesh extension data containing all available LOD levels with vertex/index counts and densities.
617
733
  */
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");
734
+ static registerMesh = (t, e, s, r, n, o) => {
735
+ const u = s.geometry;
736
+ if (!u) {
737
+ h && console.warn("gltf-progressive: Register mesh without geometry");
622
738
  return;
623
739
  }
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);
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)
740
+ u.userData || (u.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: n, uuid: s.uuid }, o, s), p.assignLODInformation(t, u, e, r, n), p.lodInfos.set(e, o);
741
+ let l = p.lowresCache.get(e)?.deref();
742
+ l ? l.push(s.geometry) : l = [s.geometry], p.lowresCache.set(e, new WeakRef(l)), r > 0 && !ee(s) && ut(s, u);
743
+ for (const c of q)
628
744
  c.onRegisteredNewMesh?.(s, o);
629
745
  };
630
746
  /**
@@ -666,7 +782,7 @@ class m {
666
782
  this.lowresCache.clear();
667
783
  for (const [, e] of this.cache)
668
784
  this._disposeCacheEntry(e);
669
- this.cache.clear(), this.textureRefCounts.clear();
785
+ this.cache.clear(), this.textureRefCounts.clear(), this.trackedTextureSlots = /* @__PURE__ */ new WeakMap(), this.pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
670
786
  }
671
787
  }
672
788
  /** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
@@ -698,16 +814,16 @@ class m {
698
814
  * The held value is the cache key string used in `previouslyLoaded`.
699
815
  */
700
816
  static _resourceRegistry = new FinalizationRegistry((t) => {
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)")));
817
+ const e = p.cache.get(t);
818
+ (h || J) && console.debug(`[gltf-progressive] Memory: Resource GC'd
819
+ ${t}`), e instanceof WeakRef && (e.deref() || (p.cache.delete(t), (h || J) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
704
820
  });
705
821
  /**
706
822
  * Track texture usage by incrementing reference count
707
823
  */
708
824
  static trackTextureUsage(t) {
709
825
  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}`);
826
+ this.textureRefCounts.set(e, s + 1), h === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
711
827
  }
712
828
  /**
713
829
  * Untrack texture usage by decrementing reference count.
@@ -717,172 +833,175 @@ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (f || K) && co
717
833
  static untrackTextureUsage(t) {
718
834
  const e = t.uuid, s = this.textureRefCounts.get(e);
719
835
  if (!s)
720
- return (f === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
836
+ return (h === "verbose" || J) && n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
721
837
  const r = s - 1;
722
838
  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}
839
+ return this.textureRefCounts.delete(e), (h || J) && n("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
840
+ return this.textureRefCounts.set(e, r), h === "verbose" && n("[gltf-progressive] Memory: Untrack texture", r), !1;
841
+ function n(o, u) {
842
+ const a = t.image?.width || t.source?.data?.width || 0, l = t.image?.height || t.source?.data?.height || 0, c = a && l ? `${a}x${l}` : "N/A";
843
+ let f = "N/A";
844
+ a && l && (f = `~${(it(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${c} (${f}), refCount: ${s} → ${u}
730
845
  ${e}`);
731
846
  }
732
847
  }
733
848
  static workers = [];
734
849
  static _workersIndex = 0;
735
850
  static async getOrLoadLOD(t, e) {
736
- const s = f == "verbose", r = this.getAssignedLODInformation(t);
851
+ const s = h == "verbose", r = this.getAssignedLODInformation(t);
737
852
  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;
853
+ return h && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
854
+ const n = r?.key;
740
855
  let o;
741
856
  if (t.isTexture === !0) {
742
857
  const a = t;
743
858
  a.source && a.source[ue] && (o = a.source[ue]);
744
859
  }
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);
860
+ if (o || (o = p.lodInfos.get(n)), !o)
861
+ h && console.warn(`Can not load LOD ${e}: no LOD info found for "${n}" ${t.name}`, t.type, p.lodInfos);
747
862
  else {
748
863
  if (e > 0) {
749
864
  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}`);
865
+ const f = Array.isArray(o.lods);
866
+ if (f && e >= o.lods.length ? c = !0 : f || (c = !0), c) {
867
+ const y = this.lowresCache.get(n);
868
+ if (y) {
869
+ const T = y.deref();
870
+ if (T) return T;
871
+ this.lowresCache.delete(n), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${n}`);
757
872
  }
758
873
  return null;
759
874
  }
760
875
  }
761
876
  const a = Array.isArray(o.lods) ? o.lods[e]?.path : o.lods;
762
877
  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")) {
878
+ return h && !o["missing:uri"] && (o["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, o)), null;
879
+ const l = nt(r.url, a);
880
+ if (l.endsWith(".glb") || l.endsWith(".gltf")) {
766
881
  if (!o.guid)
767
882
  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;
776
- }
777
- this.cache.delete(c), f && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${c}`);
778
- } 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
- }
883
+ const c = l + "_" + o.guid, f = await this.tryResolveLODCacheEntry(this.cache.get(c), c, l, t, e, s);
884
+ if (f.found) return f.value;
885
+ const y = await this.queue.slot(l), T = await this.tryResolveLODCacheEntry(this.cache.get(c), c, l, t, e, s);
886
+ if (T.found) return T.value;
784
887
  if (!y.use)
785
- return f && console.log(`LOD ${e} was aborted: ${u}`), null;
786
- const _ = o, k = new Promise(async (d, g) => {
787
- 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);
888
+ return h && console.log(`LOD ${e} was aborted: ${l}`), null;
889
+ const _ = o, C = new Promise(async (m, B) => {
890
+ if (mt) {
891
+ const d = await (await gt({})).load(l);
892
+ if (d.textures.length > 0)
893
+ for (const g of d.textures) {
894
+ let w = g.texture;
895
+ return p.assignLODInformation(r.url, w, n, e, void 0), t instanceof W && (w = this.copySettings(t, w)), w && (w.guid = _.guid), m(w);
793
896
  }
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);
897
+ if (d.geometries.length > 0) {
898
+ const g = new Array();
899
+ for (const w of d.geometries) {
900
+ const v = w.geometry;
901
+ p.assignLODInformation(r.url, v, n, e, w.primitiveIndex), g.push(v);
799
902
  }
800
- return d(h);
903
+ return m(g);
801
904
  }
802
- return d(null);
905
+ return m(null);
803
906
  }
804
- const b = new xe();
805
- Te(b), f && (await new Promise((L) => setTimeout(L, 1e3)), s && console.warn("Start loading (delayed) " + u, _.guid));
806
- let B = u;
907
+ const G = new xe();
908
+ Pe(G), h && (await new Promise((b) => setTimeout(b, 1e3)), s && console.warn("Start loading (delayed) " + l, _.guid));
909
+ let A = l;
807
910
  if (_ && Array.isArray(_.lods)) {
808
- const L = _.lods[e];
809
- L.hash && (B += "?v=" + L.hash);
911
+ const b = _.lods[e];
912
+ b.hash && (A += "?v=" + b.hash);
810
913
  }
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 N = 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;
914
+ const S = await G.loadAsync(A).catch((b) => (console.error(`Error loading LOD ${e} from ${l}
915
+ `, b), m(null)));
916
+ if (!S)
917
+ return m(null);
918
+ const F = S.parser;
919
+ s && console.log("Loading finished " + l, _.guid);
920
+ let M = 0;
921
+ if (S.parser.json.textures) {
922
+ let b = !1;
923
+ for (const d of S.parser.json.textures) {
924
+ if (d?.extensions) {
925
+ const g = d?.extensions[U];
926
+ if (g?.guid && g.guid === _.guid) {
927
+ b = !0;
825
928
  break;
826
929
  }
827
930
  }
828
- P++;
931
+ M++;
829
932
  }
830
- if (L) {
831
- let x = await N.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);
933
+ if (b) {
934
+ let d = await F.getDependency("texture", M);
935
+ return d && p.assignLODInformation(r.url, d, n, e, void 0), s && console.log('change "' + t.name + '" → "' + d.name + '"', l, M, d, c), t instanceof W && (d = this.copySettings(t, d)), d && (d.guid = _.guid), m(d);
936
+ } else h && console.warn("Could not find texture with guid", _.guid, S.parser.json);
834
937
  }
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;
938
+ if (M = 0, S.parser.json.meshes) {
939
+ let b = !1;
940
+ for (const d of S.parser.json.meshes) {
941
+ if (d?.extensions) {
942
+ const g = d?.extensions[U];
943
+ if (g?.guid && g.guid === _.guid) {
944
+ b = !0;
842
945
  break;
843
946
  }
844
947
  }
845
- P++;
948
+ M++;
846
949
  }
847
- if (L) {
848
- const x = await N.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);
950
+ if (b) {
951
+ const d = await F.getDependency("mesh", M);
952
+ if (s && console.log(`Loaded Mesh "${d.name}"`, l, M, d, c), d.isMesh === !0) {
953
+ const g = d.geometry;
954
+ return p.assignLODInformation(r.url, g, n, e, 0), m(g);
852
955
  } 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);
956
+ const g = new Array();
957
+ for (let w = 0; w < d.children.length; w++) {
958
+ const v = d.children[w];
959
+ if (v.isMesh === !0) {
960
+ const O = v.geometry;
961
+ p.assignLODInformation(r.url, O, n, e, w), g.push(O);
859
962
  }
860
963
  }
861
- return d(h);
964
+ return m(g);
862
965
  }
863
- } else f && console.warn("Could not find mesh with guid", _.guid, D.parser.json);
966
+ } else h && console.warn("Could not find mesh with guid", _.guid, S.parser.json);
864
967
  }
865
- return d(null);
968
+ return m(null);
866
969
  });
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;
870
- } else if (t instanceof F) {
871
- s && console.log("Load texture from uri: " + u);
872
- const y = await new qe().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;
970
+ this.cache.set(c, C), y.use(C);
971
+ const x = await C;
972
+ return x != null ? x instanceof W ? (this.cache.set(c, new WeakRef(x)), p._resourceRegistry.register(x, c)) : Array.isArray(x) ? this.cache.set(c, Promise.resolve(x)) : this.cache.set(c, Promise.resolve(x)) : this.cache.set(c, Promise.resolve(null)), x;
973
+ } else if (t instanceof W) {
974
+ s && console.log("Load texture from uri: " + l);
975
+ const f = await new Ve().loadAsync(l);
976
+ return f ? (f.guid = o.guid, f.flipY = !1, f.needsUpdate = !0, f.colorSpace = t.colorSpace, s && console.log(o, f)) : h && console.warn("failed loading", l), f;
874
977
  }
875
978
  }
876
979
  return null;
877
980
  }
981
+ static async tryResolveLODCacheEntry(t, e, s, r, n, o) {
982
+ if (t === void 0)
983
+ return { found: !1 };
984
+ if (o && console.log(`LOD ${n} was already loading/loaded: ${e}`), t instanceof WeakRef) {
985
+ const l = t.deref();
986
+ if (l) {
987
+ let c = l, f = !1;
988
+ if (c instanceof W && r instanceof W ? c.image?.data || c.source?.data ? c = this.copySettings(r, c) : f = !0 : c instanceof V && r instanceof V && (c.attributes.position?.array || (f = !0)), !f)
989
+ return { found: !0, value: c };
990
+ }
991
+ return this.cache.delete(e), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`), { found: !1 };
992
+ }
993
+ let u = await t.catch((l) => (console.error(`Error loading LOD ${n} from ${s}
994
+ `, l), null)), a = !1;
995
+ return u == null || (u instanceof W && r instanceof W ? u.image?.data || u.source?.data ? u = this.copySettings(r, u) : (a = !0, this.cache.delete(e)) : u instanceof V && r instanceof V && (u.attributes.position?.array || (a = !0, this.cache.delete(e)))), a ? { found: !1 } : { found: !0, value: u };
996
+ }
878
997
  static _queue;
879
998
  static get queue() {
880
- return this._queue ??= new rt(_e() ? 20 : 50, { debug: f != !1 });
999
+ return this._queue ??= new ot(Le() ? 20 : 50, { debug: h != !1 });
881
1000
  }
882
- static assignLODInformation(t, e, s, r, i) {
1001
+ static assignLODInformation(t, e, s, r, n) {
883
1002
  if (!e) return;
884
1003
  e.userData || (e.userData = {});
885
- const o = new pt(t, s, r, i);
1004
+ const o = new yt(t, s, r, n);
886
1005
  e.userData.LODS = o, "source" in e && typeof e.source == "object" && (e.source.LODS = o);
887
1006
  }
888
1007
  static getAssignedLODInformation(t) {
@@ -890,12 +1009,12 @@ ${e}`);
890
1009
  }
891
1010
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
892
1011
  static copySettings(t, e) {
893
- return e ? (f === "verbose" && console.debug(`Copy texture settings
1012
+ return e ? (h === "verbose" && console.debug(`Copy texture settings
894
1013
  `, t.uuid, `
895
1014
  `, 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;
896
1015
  }
897
1016
  }
898
- class pt {
1017
+ class yt {
899
1018
  url;
900
1019
  /** the key to lookup the LOD information */
901
1020
  key;
@@ -908,8 +1027,8 @@ class pt {
908
1027
  }
909
1028
  class ce {
910
1029
  static addPromise = (t, e, s, r) => {
911
- r.forEach((i) => {
912
- i.add(t, e, s);
1030
+ r.forEach((n) => {
1031
+ n.add(t, e, s);
913
1032
  });
914
1033
  };
915
1034
  ready;
@@ -940,8 +1059,8 @@ class ce {
940
1059
  _maxPromisesPerObject = 1;
941
1060
  constructor(t, e) {
942
1061
  const r = Math.max(e.frames ?? 2, 2);
943
- this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture = r, this.ready = new Promise((i) => {
944
- this._resolve = i;
1062
+ this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture = r, this.ready = new Promise((n) => {
1063
+ this._resolve = n;
945
1064
  }), this.ready.finally(() => {
946
1065
  this._resolved = !0, this._awaiting.length = 0;
947
1066
  }), this._signal = e.signal, this._signal?.addEventListener("abort", () => {
@@ -955,15 +1074,15 @@ class ce {
955
1074
  _seen = /* @__PURE__ */ new WeakMap();
956
1075
  add(t, e, s) {
957
1076
  if (this._resolved) {
958
- f && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
1077
+ h && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
959
1078
  return;
960
1079
  }
961
1080
  if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
962
1081
  if (this._maxPromisesPerObject >= 1)
963
1082
  if (this._seen.has(e)) {
964
- let r = this._seen.get(e);
1083
+ const r = this._seen.get(e);
965
1084
  if (r >= this._maxPromisesPerObject) {
966
- f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
1085
+ h && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
967
1086
  return;
968
1087
  }
969
1088
  this._seen.set(e, r + 1);
@@ -982,8 +1101,41 @@ class ce {
982
1101
  });
983
1102
  }
984
1103
  }
985
- const R = q("debugprogressive"), mt = q("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), U = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), T = { mesh_lod: -1, texture_lod: -1 };
986
- class v {
1104
+ const R = N("debugprogressive"), xt = R === "colors", wt = N("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), z = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), D = { mesh_lod: -1, texture_lod: -1 }, Lt = new ke(), be = [
1105
+ 3526751,
1106
+ 11065402,
1107
+ 15978811,
1108
+ 15897394,
1109
+ 15749691,
1110
+ 11032304,
1111
+ 4827122,
1112
+ 3332036,
1113
+ 16739229,
1114
+ 7306743,
1115
+ 14053330,
1116
+ 3516499,
1117
+ 12035359,
1118
+ 14703919,
1119
+ 3963096,
1120
+ 42662,
1121
+ 14100029,
1122
+ 8344319,
1123
+ 4633680,
1124
+ 16229681,
1125
+ 3120096,
1126
+ 12076434,
1127
+ 9083434,
1128
+ 2060171,
1129
+ 15751837,
1130
+ 10182117,
1131
+ 48121,
1132
+ 62932,
1133
+ 16704576,
1134
+ 15817653,
1135
+ 5083278,
1136
+ 5592405
1137
+ ];
1138
+ class L {
987
1139
  /**
988
1140
  * 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.
989
1141
  */
@@ -993,11 +1145,11 @@ class v {
993
1145
  return t[fe];
994
1146
  }
995
1147
  static addPlugin(t) {
996
- z.push(t);
1148
+ q.push(t);
997
1149
  }
998
1150
  static removePlugin(t) {
999
- const e = z.indexOf(t);
1000
- e >= 0 && z.splice(e, 1);
1151
+ const e = q.indexOf(t);
1152
+ e >= 0 && q.splice(e, 1);
1001
1153
  }
1002
1154
  /**
1003
1155
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -1007,7 +1159,7 @@ class v {
1007
1159
  static get(t, e) {
1008
1160
  if (t[de])
1009
1161
  return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[de];
1010
- const s = new v(t, {
1162
+ const s = new L(t, {
1011
1163
  engine: "unknown",
1012
1164
  ...e
1013
1165
  });
@@ -1018,7 +1170,7 @@ class v {
1018
1170
  projectionScreenMatrix = new ve();
1019
1171
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
1020
1172
  get plugins() {
1021
- return z;
1173
+ return q;
1022
1174
  }
1023
1175
  /**
1024
1176
  * Force override the LOD level for all objects (meshes + textures) rendered in the scene
@@ -1056,15 +1208,39 @@ class v {
1056
1208
  _newPromiseGroups = [];
1057
1209
  _promiseGroupIds = 0;
1058
1210
  /**
1059
- * Call to await LODs loading during the next render cycle.
1211
+ * Returns a promise that resolves once all LOD requests initiated during the next render cycles have finished loading.
1212
+ * This is useful for hiding low-resolution placeholders (e.g. with a loading overlay or CSS blur) until high-quality assets are ready.
1213
+ *
1214
+ * By default, the returned promise captures LOD loading requests for 2 frames and resolves when all of them complete.
1215
+ * Use `waitForFirstCapture` if no LOD requests may happen immediately (e.g. after a scene switch).
1216
+ *
1217
+ * @param opts - Optional configuration for how long to capture and what to wait for. See {@link PromiseGroupOptions}.
1218
+ * @returns A promise that resolves with `{ cancelled, awaited_count, resolved_count }` once all captured LOD loads complete (or the signal aborts).
1219
+ *
1220
+ * @example
1221
+ * ```ts
1222
+ * // Wait for initial LODs to finish loading, then remove a blur overlay
1223
+ * const result = await lodsManager.awaitLoading({
1224
+ * frames: 5,
1225
+ * signal: AbortSignal.timeout(10_000),
1226
+ * });
1227
+ * console.log(`Loaded ${result.resolved_count} of ${result.awaited_count} LODs`);
1228
+ * document.querySelector('.blur-overlay')?.remove();
1229
+ * ```
1230
+ *
1231
+ * @example
1232
+ * ```ts
1233
+ * // Wait until at least one LOD starts loading before resolving
1234
+ * await lodsManager.awaitLoading({ waitForFirstCapture: true });
1235
+ * ```
1060
1236
  */
1061
1237
  awaitLoading(t) {
1062
1238
  const e = this._promiseGroupIds++, s = new ce(this.#r, { ...t });
1063
1239
  this._newPromiseGroups.push(s);
1064
1240
  const r = performance.now();
1065
1241
  return s.ready.finally(() => {
1066
- const i = this._newPromiseGroups.indexOf(s);
1067
- i >= 0 && (this._newPromiseGroups.splice(i, 1), be() && performance.measure("LODsManager:awaitLoading", {
1242
+ const n = this._newPromiseGroups.indexOf(s);
1243
+ n >= 0 && (this._newPromiseGroups.splice(n, 1), Me() && performance.measure("LODsManager:awaitLoading", {
1068
1244
  start: r,
1069
1245
  detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
1070
1246
  }));
@@ -1076,24 +1252,50 @@ class v {
1076
1252
  this._newPromiseGroups[t].update(this.#r);
1077
1253
  }
1078
1254
  _lodchangedlisteners = [];
1255
+ /**
1256
+ * Register a listener that is called whenever a mesh or texture LOD level has finished loading and has been applied.
1257
+ * The listener receives the type of asset (`"mesh"` or `"texture"`), the new LOD level, and the affected object.
1258
+ *
1259
+ * @param evt - The event type. Currently only `"changed"` is supported.
1260
+ * @param listener - Callback invoked after a LOD swap completes.
1261
+ * @return A function to unregister the listener.
1262
+ *
1263
+ * @example
1264
+ * ```ts
1265
+ * lodsManager.addEventListener("changed", ({ type, level, object }) => {
1266
+ * console.log(`${type} LOD changed to level ${level}`, object);
1267
+ * });
1268
+ * ```
1269
+ */
1079
1270
  addEventListener(t, e) {
1080
- t === "changed" && this._lodchangedlisteners.push(e);
1271
+ return t === "changed" ? (this._lodchangedlisteners.push(e), () => {
1272
+ this.removeEventListener(t, e);
1273
+ }) : () => {
1274
+ };
1081
1275
  }
1276
+ /**
1277
+ * Remove a previously registered `"changed"` event listener.
1278
+ * @param evt - The event type (`"changed"`).
1279
+ * @param listener - The listener to remove.
1280
+ * @return `true` if the listener was found and removed, `false` otherwise.
1281
+ */
1082
1282
  removeEventListener(t, e) {
1283
+ let s = !1;
1083
1284
  if (t === "changed") {
1084
- const s = this._lodchangedlisteners.indexOf(e);
1085
- s >= 0 && this._lodchangedlisteners.splice(s, 1);
1285
+ const r = this._lodchangedlisteners.indexOf(e);
1286
+ r >= 0 && (this._lodchangedlisteners.splice(r, 1), s = !0);
1086
1287
  }
1288
+ return s;
1087
1289
  }
1088
1290
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
1089
1291
  constructor(t, e) {
1090
1292
  this.renderer = t, this.context = { ...e };
1091
1293
  }
1092
1294
  #t;
1093
- #o = new Ne();
1295
+ #o = new Xe();
1094
1296
  #r = 0;
1095
- #i = 0;
1096
1297
  #n = 0;
1298
+ #i = 0;
1097
1299
  #s = 0;
1098
1300
  _fpsBuffer = [60, 60, 60, 60, 60];
1099
1301
  /**
@@ -1106,8 +1308,8 @@ class v {
1106
1308
  this.#t = this.renderer.render;
1107
1309
  const e = this;
1108
1310
  we(this.renderer), this.renderer.render = function(s, r) {
1109
- const i = e.renderer.getRenderTarget();
1110
- (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));
1311
+ const n = e.renderer.getRenderTarget();
1312
+ (n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#r += 1, e.#n = e.#o.getDelta(), e.#i += e.#n, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#n), e.#s = e._fpsBuffer.reduce((u, a) => u + a) / e._fpsBuffer.length, R && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1111
1313
  const o = t++;
1112
1314
  e.#t.call(this, s, r), e.onAfterRender(s, r, o);
1113
1315
  };
@@ -1115,19 +1317,34 @@ class v {
1115
1317
  disable() {
1116
1318
  this.#t && (console.debug("[gltf-progressive] Disabling LODsManager for renderer"), this.renderer.render = this.#t, this.#t = void 0);
1117
1319
  }
1320
+ /**
1321
+ * Manually trigger a LOD update for a scene and camera.
1322
+ * Only needed when {@link manual} is set to `true` — otherwise LOD updates happen automatically on each render call.
1323
+ *
1324
+ * @param scene - The scene containing objects with progressive LODs.
1325
+ * @param camera - The camera used to determine screen coverage and LOD levels.
1326
+ *
1327
+ * @example
1328
+ * ```ts
1329
+ * const lodsManager = LODsManager.get(renderer);
1330
+ * lodsManager.manual = true;
1331
+ * // ... later, trigger an update at a specific point:
1332
+ * lodsManager.update(scene, camera);
1333
+ * ```
1334
+ */
1118
1335
  update(t, e) {
1119
1336
  this.internalUpdate(t, e);
1120
1337
  }
1121
1338
  onAfterRender(t, e, s) {
1122
1339
  if (this.pause) return;
1123
- const i = this.renderer.renderLists.get(t, 0).opaque;
1340
+ const n = this.renderer.renderLists.get(t, 0).opaque;
1124
1341
  let o = !0;
1125
- if (i.length === 1) {
1126
- const l = i[0].material;
1127
- (l.name === "EffectMaterial" || l.name === "CopyShader") && (o = !1);
1342
+ if (n.length === 1) {
1343
+ const u = n[0].material;
1344
+ (u.name === "EffectMaterial" || u.name === "CopyShader") && (o = !1);
1128
1345
  }
1129
1346
  if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
1130
- 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))
1347
+ if (wt || (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))
1131
1348
  return;
1132
1349
  this.internalUpdate(t, e), this._postprocessPromiseGroups();
1133
1350
  }
@@ -1138,7 +1355,7 @@ class v {
1138
1355
  internalUpdate(t, e) {
1139
1356
  const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
1140
1357
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
1141
- const i = this.targetTriangleDensity;
1358
+ const n = this.targetTriangleDensity;
1142
1359
  for (const a of r) {
1143
1360
  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")) {
1144
1361
  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)));
@@ -1153,38 +1370,33 @@ class v {
1153
1370
  case "MeshDepthMaterial":
1154
1371
  continue;
1155
1372
  }
1156
- if (R === "color" && a.material && !a.object.progressive_debug_color) {
1157
- a.object.progressive_debug_color = !0;
1158
- const c = Math.random() * 16777215, y = new Ve({ color: c });
1159
- a.object.material = y;
1160
- }
1161
- const u = a.object;
1162
- (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1373
+ const l = a.object;
1374
+ (l instanceof X || l.isMesh) && this.updateLODs(t, e, l, n);
1163
1375
  }
1164
1376
  const o = s.transparent;
1165
1377
  for (const a of o) {
1166
- const u = a.object;
1167
- (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1378
+ const l = a.object;
1379
+ (l instanceof X || l.isMesh) && this.updateLODs(t, e, l, n);
1168
1380
  }
1169
- const l = s.transmissive;
1170
- for (const a of l) {
1171
- const u = a.object;
1172
- (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1381
+ const u = s.transmissive;
1382
+ for (const a of u) {
1383
+ const l = a.object;
1384
+ (l instanceof X || l.isMesh) && this.updateLODs(t, e, l, n);
1173
1385
  }
1174
1386
  }
1175
1387
  /** Update the LOD levels for the renderer. */
1176
1388
  updateLODs(t, e, s, r) {
1177
1389
  s.userData || (s.userData = {});
1178
- let i = s[fe];
1179
- if (i || (i = new yt(), s[fe] = i), i.frames++ < 2)
1390
+ let n = s[fe];
1391
+ if (n || (n = new _t(), s[fe] = n), n.frames++ < 2)
1180
1392
  return;
1181
- for (const l of z)
1182
- l.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1183
- const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : V;
1184
- 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);
1185
- for (const l of z)
1186
- l.onAfterUpdatedLOD?.(this.renderer, t, e, s, T);
1187
- i.lastLodLevel_Mesh = T.mesh_lod, i.lastLodLevel_Texture = T.texture_lod;
1393
+ for (const u of q)
1394
+ u.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1395
+ const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : E;
1396
+ o >= 0 ? (D.mesh_lod = o, D.texture_lod = o) : (this.calculateLodLevel(e, s, n, r, D), D.mesh_lod = Math.round(D.mesh_lod), D.texture_lod = Math.round(D.texture_lod)), D.mesh_lod >= 0 && this.loadProgressiveMeshes(s, D.mesh_lod), s.material && D.texture_lod >= 0 && this.loadProgressiveTextures(s.material, D.texture_lod, o), h && s.material && !s.isGizmo && Ie(s.material), xt && s.material && !s.isGizmo && !s.isBatchedMesh && $e(s.material, D.mesh_lod);
1397
+ for (const u of q)
1398
+ u.onAfterUpdatedLOD?.(this.renderer, t, e, s, D);
1399
+ n.lastLodLevel_Mesh = D.mesh_lod, n.lastLodLevel_Texture = D.texture_lod;
1188
1400
  }
1189
1401
  /** Load progressive textures for the given material
1190
1402
  * @param material the material to load the textures for
@@ -1194,17 +1406,19 @@ class v {
1194
1406
  loadProgressiveTextures(t, e, s) {
1195
1407
  if (!t) return;
1196
1408
  if (Array.isArray(t)) {
1197
- for (const i of t)
1198
- this.loadProgressiveTextures(i, e);
1409
+ for (const o of t)
1410
+ this.loadProgressiveTextures(o, e, s);
1199
1411
  return;
1200
1412
  }
1201
1413
  let r = !1;
1202
- if ((t[U] === void 0 || e < t[U]) && (r = !0), s !== void 0 && s >= 0 && (r = t[U] != s, e = s), r) {
1203
- t[U] = e;
1204
- const i = m.assignTextureLOD(t, e).then((o) => {
1414
+ (t[z] === void 0 || e < t[z]) && (r = !0);
1415
+ const n = s !== void 0 && s >= 0;
1416
+ if (n && (r = t[z] != s, e = s), r) {
1417
+ t[z] = e;
1418
+ const o = n ? { force: !0 } : void 0, u = p.assignTextureLOD(t, e, o).then((a) => {
1205
1419
  this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
1206
1420
  });
1207
- ce.addPromise("texture", t, i, this._newPromiseGroups);
1421
+ ce.addPromise("texture", t, u, this._newPromiseGroups);
1208
1422
  }
1209
1423
  }
1210
1424
  /** Load progressive meshes for the given mesh
@@ -1215,143 +1429,143 @@ class v {
1215
1429
  */
1216
1430
  loadProgressiveMeshes(t, e) {
1217
1431
  if (!t) return Promise.resolve(null);
1218
- let s = t[U] !== e;
1432
+ let s = t[z] !== e;
1219
1433
  const r = t["DEBUG:LOD"];
1220
- if (r != null && (s = t[U] != r, e = r), s) {
1221
- t[U] = e;
1222
- 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));
1434
+ if (r != null && (s = t[z] != r, e = r), s) {
1435
+ t[z] = e;
1436
+ const n = t.geometry, o = p.assignMeshLOD(t, e).then((u) => (u && t[z] == e && n != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), u));
1223
1437
  return ce.addPromise("mesh", t, o, this._newPromiseGroups), o;
1224
1438
  }
1225
1439
  return Promise.resolve(null);
1226
1440
  }
1227
1441
  // private testIfLODLevelsAreAvailable() {
1228
- _sphere = new Se();
1442
+ _sphere = new Oe();
1229
1443
  _tempBox = new ge();
1230
1444
  _tempBox2 = new ge();
1231
1445
  tempMatrix = new ve();
1232
- _tempWorldPosition = new A();
1233
- _tempBoxSize = new A();
1234
- _tempBox2Size = new A();
1235
- static corner0 = new A();
1236
- static corner1 = new A();
1237
- static corner2 = new A();
1238
- static corner3 = new A();
1239
- static _tempPtInside = new A();
1446
+ _tempWorldPosition = new P();
1447
+ _tempBoxSize = new P();
1448
+ _tempBox2Size = new P();
1449
+ static corner0 = new P();
1450
+ static corner1 = new P();
1451
+ static corner2 = new P();
1452
+ static corner3 = new P();
1453
+ static _tempPtInside = new P();
1240
1454
  static isInside(t, e) {
1241
- const s = t.min, r = t.max, i = (s.x + r.x) * 0.5, o = (s.y + r.y) * 0.5;
1242
- return this._tempPtInside.set(i, o, s.z).applyMatrix4(e).z < 0;
1455
+ const s = t.min, r = t.max, n = (s.x + r.x) * 0.5, o = (s.y + r.y) * 0.5;
1456
+ return this._tempPtInside.set(n, o, s.z).applyMatrix4(e).z < 0;
1243
1457
  }
1244
1458
  static skinnedMeshBoundsFrameOffsetCounter = 0;
1245
1459
  static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
1246
1460
  // #region calculateLodLevel
1247
- calculateLodLevel(t, e, s, r, i) {
1461
+ calculateLodLevel(t, e, s, r, n) {
1248
1462
  if (!e) {
1249
- i.mesh_lod = -1, i.texture_lod = -1;
1463
+ n.mesh_lod = -1, n.texture_lod = -1;
1250
1464
  return;
1251
1465
  }
1252
1466
  if (!t) {
1253
- i.mesh_lod = -1, i.texture_lod = -1;
1467
+ n.mesh_lod = -1, n.texture_lod = -1;
1254
1468
  return;
1255
1469
  }
1256
- let l = 10 + 1, a = !1;
1470
+ let u = 10 + 1, a = !1;
1257
1471
  if (R && e["DEBUG:LOD"] != null)
1258
1472
  return e["DEBUG:LOD"];
1259
- 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;
1260
- if (!y && !_) {
1261
- i.mesh_lod = 0, i.texture_lod = 0;
1473
+ const l = p.getMeshLODExtension(e.geometry)?.lods, c = p.getPrimitiveIndex(e.geometry), f = l && l.length > 0, y = p.getMaterialMinMaxLODsCount(e.material), T = y.min_count !== 1 / 0 && y.min_count >= 0 && y.max_count >= 0;
1474
+ if (!f && !T) {
1475
+ n.mesh_lod = 0, n.texture_lod = 0;
1262
1476
  return;
1263
1477
  }
1264
- y || (a = !0, l = 0);
1265
- const k = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1266
- let M = e.geometry.boundingBox;
1478
+ f || (a = !0, u = 0);
1479
+ const _ = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1480
+ let C = e.geometry.boundingBox;
1267
1481
  if (e.type === "SkinnedMesh") {
1268
- const d = e;
1269
- if (!d.boundingBox)
1270
- d.computeBoundingBox();
1482
+ const x = e;
1483
+ if (!x.boundingBox)
1484
+ x.computeBoundingBox();
1271
1485
  else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
1272
- if (!d[v.$skinnedMeshBoundsOffset]) {
1273
- const b = v.skinnedMeshBoundsFrameOffsetCounter++;
1274
- d[v.$skinnedMeshBoundsOffset] = b;
1486
+ if (!x[L.$skinnedMeshBoundsOffset]) {
1487
+ const B = L.skinnedMeshBoundsFrameOffsetCounter++;
1488
+ x[L.$skinnedMeshBoundsOffset] = B;
1275
1489
  }
1276
- const g = d[v.$skinnedMeshBoundsOffset];
1277
- if ((s.frames + g) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1278
- const b = ee(d), B = d.geometry;
1279
- b && (d.geometry = b), d.computeBoundingBox(), d.geometry = B;
1490
+ const m = x[L.$skinnedMeshBoundsOffset];
1491
+ if ((s.frames + m) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1492
+ const B = ee(x), G = x.geometry;
1493
+ B && (x.geometry = B), x.computeBoundingBox(), x.geometry = G;
1280
1494
  }
1281
1495
  }
1282
- M = d.boundingBox;
1496
+ C = x.boundingBox;
1283
1497
  }
1284
- if (M) {
1285
- const d = t;
1498
+ if (C) {
1499
+ const x = t;
1286
1500
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
1287
1501
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
1288
- const h = t.getWorldPosition(this._tempWorldPosition);
1289
- if (this._sphere.containsPoint(h)) {
1290
- i.mesh_lod = 0, i.texture_lod = 0;
1502
+ const d = t.getWorldPosition(this._tempWorldPosition);
1503
+ if (this._sphere.containsPoint(d)) {
1504
+ n.mesh_lod = 0, n.texture_lod = 0;
1291
1505
  return;
1292
1506
  }
1293
1507
  }
1294
- if (this._tempBox.copy(M), this._tempBox.applyMatrix4(e.matrixWorld), d.isPerspectiveCamera && v.isInside(this._tempBox, this.projectionScreenMatrix)) {
1295
- i.mesh_lod = 0, i.texture_lod = 0;
1508
+ if (this._tempBox.copy(C), this._tempBox.applyMatrix4(e.matrixWorld), x.isPerspectiveCamera && L.isInside(this._tempBox, this.projectionScreenMatrix)) {
1509
+ n.mesh_lod = 0, n.texture_lod = 0;
1296
1510
  return;
1297
1511
  }
1298
- if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && d.isPerspectiveCamera && d.fov > 70) {
1299
- const h = this._tempBox.min, p = this._tempBox.max;
1300
- let O = h.x, S = h.y, G = p.x, Y = p.y;
1301
- const te = 2, ne = 1.5, se = (h.x + p.x) * 0.5, re = (h.y + p.y) * 0.5;
1302
- O = (O - se) * te + se, S = (S - re) * te + re, G = (G - se) * te + se, Y = (Y - re) * te + re;
1303
- 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);
1304
- s.lastCentrality = (ne - ae) * (ne - ae) * (ne - ae);
1512
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && x.isPerspectiveCamera && x.fov > 70) {
1513
+ const d = this._tempBox.min, g = this._tempBox.max;
1514
+ let w = d.x, v = d.y, O = g.x, Y = g.y;
1515
+ const te = 2, ie = 1.5, se = (d.x + g.x) * 0.5, re = (d.y + g.y) * 0.5;
1516
+ w = (w - se) * te + se, v = (v - re) * te + re, O = (O - se) * te + se, Y = (Y - re) * te + re;
1517
+ const We = w < 0 && O > 0 ? 0 : Math.min(Math.abs(d.x), Math.abs(g.x)), Fe = v < 0 && Y > 0 ? 0 : Math.min(Math.abs(d.y), Math.abs(g.y)), ae = Math.max(We, Fe);
1518
+ s.lastCentrality = (ie - ae) * (ie - ae) * (ie - ae);
1305
1519
  } else
1306
1520
  s.lastCentrality = 1;
1307
- const g = this._tempBox.getSize(this._tempBoxSize);
1308
- g.multiplyScalar(0.5), screen.availHeight > 0 && k > 0 && g.multiplyScalar(k / screen.availHeight), t.isPerspectiveCamera ? g.x *= t.aspect : t.isOrthographicCamera;
1309
- const b = t.matrixWorldInverse, B = this._tempBox2;
1310
- B.copy(M), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(b);
1311
- const D = B.getSize(this._tempBox2Size), N = Math.max(D.x, D.y);
1312
- if (Math.max(g.x, g.y) != 0 && N != 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) {
1313
- const h = this.tempMatrix.copy(this.projectionScreenMatrix);
1314
- h.invert();
1315
- const p = v.corner0, O = v.corner1, S = v.corner2, G = v.corner3;
1316
- 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);
1317
- const Y = (p.z + G.z) * 0.5;
1318
- 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);
1521
+ const m = this._tempBox.getSize(this._tempBoxSize);
1522
+ m.multiplyScalar(0.5), screen.availHeight > 0 && _ > 0 && m.multiplyScalar(_ / screen.availHeight), t.isPerspectiveCamera ? m.x *= t.aspect : t.isOrthographicCamera;
1523
+ const B = t.matrixWorldInverse, G = this._tempBox2;
1524
+ G.copy(C), G.applyMatrix4(e.matrixWorld), G.applyMatrix4(B);
1525
+ const A = G.getSize(this._tempBox2Size), S = Math.max(A.x, A.y);
1526
+ if (Math.max(m.x, m.y) != 0 && S != 0 && (m.z = A.z / Math.max(A.x, A.y) * Math.max(m.x, m.y)), s.lastScreenCoverage = Math.max(m.x, m.y, m.z), s.lastScreenspaceVolume.copy(m), s.lastScreenCoverage *= s.lastCentrality, R && L.debugDrawLine) {
1527
+ const d = this.tempMatrix.copy(this.projectionScreenMatrix);
1528
+ d.invert();
1529
+ const g = L.corner0, w = L.corner1, v = L.corner2, O = L.corner3;
1530
+ g.copy(this._tempBox.min), w.copy(this._tempBox.max), w.x = g.x, v.copy(this._tempBox.max), v.y = g.y, O.copy(this._tempBox.max);
1531
+ const Y = (g.z + O.z) * 0.5;
1532
+ g.z = w.z = v.z = O.z = Y, g.applyMatrix4(d), w.applyMatrix4(d), v.applyMatrix4(d), O.applyMatrix4(d), L.debugDrawLine(g, w, 255), L.debugDrawLine(g, v, 255), L.debugDrawLine(w, O, 255), L.debugDrawLine(v, O, 255);
1319
1533
  }
1320
- let L = 999;
1321
- if (u && s.lastScreenCoverage > 0)
1322
- for (let h = 0; h < u.length; h++) {
1323
- const p = u[h], S = (p.densities?.[c] || p.density || 1e-5) / s.lastScreenCoverage;
1324
- if (c > 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.")), S < r) {
1325
- L = h;
1534
+ let M = 999;
1535
+ if (l && s.lastScreenCoverage > 0)
1536
+ for (let d = 0; d < l.length; d++) {
1537
+ const g = l[d], v = (g.densities?.[c] || g.density || 1e-5) / s.lastScreenCoverage;
1538
+ if (c > 0 && Me() && !g.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.")), v < r) {
1539
+ M = d;
1326
1540
  break;
1327
1541
  }
1328
1542
  }
1329
- L < l && (l = L, a = !0);
1543
+ M < u && (u = M, a = !0);
1330
1544
  }
1331
- if (a ? i.mesh_lod = l : i.mesh_lod = s.lastLodLevel_Mesh, R && i.mesh_lod != s.lastLodLevel_Mesh) {
1332
- const g = u?.[i.mesh_lod];
1333
- g && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${g.densities?.[c].toFixed(0)}) | ${e.name}`);
1545
+ if (a ? n.mesh_lod = u : n.mesh_lod = s.lastLodLevel_Mesh, R && n.mesh_lod != s.lastLodLevel_Mesh) {
1546
+ const m = l?.[n.mesh_lod];
1547
+ m && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${m.densities?.[c].toFixed(0)}) | ${e.name}`);
1334
1548
  }
1335
- if (_) {
1336
- const d = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1549
+ if (T) {
1550
+ const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1337
1551
  if (s.lastLodLevel_Texture < 0) {
1338
- if (i.texture_lod = w.max_count - 1, R) {
1339
- const g = w.lods[w.max_count - 1];
1340
- R && console.log(`First Texture LOD ${i.texture_lod} (${g.max_height}px) - ${e.name}`);
1552
+ if (n.texture_lod = y.max_count - 1, R) {
1553
+ const m = y.lods[y.max_count - 1];
1554
+ R && console.log(`First Texture LOD ${n.texture_lod} (${m.max_height}px) - ${e.name}`);
1341
1555
  }
1342
1556
  } else {
1343
- const g = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1344
- let b = s.lastScreenCoverage * 4;
1345
- this.context?.engine === "model-viewer" && (b *= 1.5);
1346
- const D = k / window.devicePixelRatio * b;
1347
- let N = !1;
1348
- for (let P = w.lods.length - 1; P >= 0; P--) {
1349
- const L = w.lods[P];
1350
- if (!(d && L.max_height >= 2048) && !(_e() && L.max_height > 4096) && (L.max_height > D || !N && P === 0)) {
1351
- if (N = !0, i.texture_lod = P, R && i.texture_lod < s.lastLodLevel_Texture) {
1352
- const x = L.max_height;
1353
- console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${x}px
1354
- Screensize: ${D.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
1557
+ const m = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1558
+ let B = s.lastScreenCoverage * 4;
1559
+ this.context?.engine === "model-viewer" && (B *= 1.5);
1560
+ const A = _ / window.devicePixelRatio * B;
1561
+ let S = !1;
1562
+ for (let F = y.lods.length - 1; F >= 0; F--) {
1563
+ const M = y.lods[F];
1564
+ if (!(x && M.max_height >= 2048) && !(Le() && M.max_height > 4096) && (M.max_height > A || !S && F === 0)) {
1565
+ if (S = !0, n.texture_lod = F, R && n.texture_lod < s.lastLodLevel_Texture) {
1566
+ const b = M.max_height;
1567
+ console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${b}px
1568
+ Screensize: ${A.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${m.toFixed(1)}
1355
1569
  ${e.name}`);
1356
1570
  }
1357
1571
  break;
@@ -1359,83 +1573,98 @@ ${e.name}`);
1359
1573
  }
1360
1574
  }
1361
1575
  } else
1362
- i.texture_lod = 0;
1576
+ n.texture_lod = 0;
1363
1577
  }
1364
1578
  }
1365
- class yt {
1579
+ class _t {
1366
1580
  frames = 0;
1367
1581
  lastLodLevel_Mesh = -1;
1368
1582
  lastLodLevel_Texture = -1;
1369
1583
  lastScreenCoverage = 0;
1370
- lastScreenspaceVolume = new A();
1584
+ lastScreenspaceVolume = new P();
1371
1585
  lastCentrality = 0;
1372
1586
  }
1373
- const Me = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1587
+ function $e(i, t) {
1588
+ if (!(t < 0)) {
1589
+ if (Array.isArray(i)) {
1590
+ for (const e of i)
1591
+ $e(e, t);
1592
+ return;
1593
+ }
1594
+ "color" in i && i.color instanceof ke && (i.color.copy(vt(t, Lt)), i.needsUpdate = !0);
1595
+ }
1596
+ }
1597
+ function vt(i, t) {
1598
+ const e = Math.max(0, Math.min(be.length - 1, Math.floor(i)));
1599
+ return t.setHex(be[e]);
1600
+ }
1601
+ const De = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ne = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1374
1602
  let he = null;
1375
- function Re() {
1376
- const n = xt();
1377
- n && (n.mapURLs(function(t) {
1378
- return De(), t;
1379
- }), De(), he?.disconnect(), he = new MutationObserver((t) => {
1603
+ function Be() {
1604
+ const i = Mt();
1605
+ i && (i.mapURLs(function(t) {
1606
+ return Te(), t;
1607
+ }), Te(), he?.disconnect(), he = new MutationObserver((t) => {
1380
1608
  t.forEach((e) => {
1381
1609
  e.addedNodes.forEach((s) => {
1382
- s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ie(s);
1610
+ s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ge(s);
1383
1611
  });
1384
1612
  });
1385
1613
  }), he.observe(document, { childList: !0, subtree: !0 }));
1386
1614
  }
1387
- function xt() {
1615
+ function Mt() {
1388
1616
  if (typeof customElements > "u") return null;
1389
- const n = customElements.get("model-viewer");
1390
- return n || (customElements.whenDefined("model-viewer").then(() => {
1391
- console.debug("[gltf-progressive] model-viewer defined"), Re();
1617
+ const i = customElements.get("model-viewer");
1618
+ return i || (customElements.whenDefined("model-viewer").then(() => {
1619
+ console.debug("[gltf-progressive] model-viewer defined"), Be();
1392
1620
  }), null);
1393
1621
  }
1394
- function De() {
1622
+ function Te() {
1395
1623
  if (typeof document > "u") return;
1396
1624
  document.querySelectorAll("model-viewer").forEach((t) => {
1397
- Ie(t);
1625
+ Ge(t);
1398
1626
  });
1399
1627
  }
1400
- const Oe = /* @__PURE__ */ new WeakSet();
1401
- let wt = 0;
1402
- function Ie(n) {
1403
- if (!n || Oe.has(n))
1628
+ const Se = /* @__PURE__ */ new WeakSet();
1629
+ let bt = 0;
1630
+ function Ge(i) {
1631
+ if (!i || Se.has(i))
1404
1632
  return null;
1405
- Oe.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
1406
- `, n.getAttribute("src"));
1633
+ Se.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++bt + `
1634
+ `, i.getAttribute("src"));
1407
1635
  let t = null, e = null, s = null;
1408
- for (let r = n; r != null; r = Object.getPrototypeOf(r)) {
1409
- 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)");
1410
- !t && o != null && (t = n[o].threeRenderer), !e && l != null && (e = n[l]), !s && a != null && (s = n[a]);
1636
+ for (let r = i; r != null; r = Object.getPrototypeOf(r)) {
1637
+ const n = Object.getOwnPropertySymbols(r), o = n.find((l) => l.toString() == "Symbol(renderer)"), u = n.find((l) => l.toString() == "Symbol(scene)"), a = n.find((l) => l.toString() == "Symbol(needsRender)");
1638
+ !t && o != null && (t = i[o].threeRenderer), !e && u != null && (e = i[u]), !s && a != null && (s = i[a]);
1411
1639
  }
1412
1640
  if (t && e) {
1413
1641
  let r = function() {
1414
1642
  if (s) {
1415
- let o = 0, l = setInterval(() => {
1643
+ let o = 0;
1644
+ const u = setInterval(() => {
1416
1645
  if (o++ > 5) {
1417
- clearInterval(l);
1646
+ clearInterval(u);
1418
1647
  return;
1419
1648
  }
1420
- s?.call(n);
1649
+ s?.call(i);
1421
1650
  }, 300);
1422
1651
  }
1423
1652
  };
1424
1653
  console.debug("[gltf-progressive] setup model-viewer");
1425
- const i = v.get(t, { engine: "model-viewer" });
1426
- return v.addPlugin(new _t()), i.enable(), i.addEventListener("changed", () => {
1427
- s?.call(n);
1428
- }), n.addEventListener("model-visibility", (o) => {
1429
- o.detail.visible && s?.call(n);
1430
- }), n.addEventListener("load", () => {
1654
+ const n = L.get(t, { engine: "model-viewer" });
1655
+ return L.addPlugin(new Dt()), n.enable(), n.addEventListener("changed", () => {
1656
+ s?.call(i);
1657
+ }), i.addEventListener("model-visibility", (o) => {
1658
+ o.detail.visible && s?.call(i);
1659
+ }), i.addEventListener("load", () => {
1431
1660
  r();
1432
1661
  }), () => {
1433
- i.disable();
1662
+ n.disable();
1434
1663
  };
1435
1664
  }
1436
1665
  return null;
1437
1666
  }
1438
- class _t {
1667
+ class Dt {
1439
1668
  _didWarnAboutMissingUrl = !1;
1440
1669
  onBeforeUpdateLOD(t, e, s, r) {
1441
1670
  this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
@@ -1453,101 +1682,103 @@ class _t {
1453
1682
  return t.element;
1454
1683
  }
1455
1684
  tryParseTextureLOD(t, e) {
1456
- if (e[ie] == !0) return;
1457
- e[ie] = !0;
1458
- const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
1459
- if (i && s && e.material) {
1685
+ if (e[ne] == !0) return;
1686
+ e[ne] = !0;
1687
+ const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), n = this.getUrl(r);
1688
+ if (n && s && e.material) {
1460
1689
  let o = function(a) {
1461
- if (a[ie] == !0) return;
1462
- a[ie] = !0, a.userData && (a.userData.LOD = -1);
1463
- const u = Object.keys(a);
1464
- for (let c = 0; c < u.length; c++) {
1465
- const y = u[c], w = a[y];
1466
- if (w?.isTexture === !0) {
1467
- const _ = w.userData?.associations?.textures;
1468
- if (_ == null) continue;
1469
- const k = s.parser.json.textures[_];
1470
- if (!k) {
1471
- console.warn("Texture data not found for texture index " + _);
1690
+ if (a[ne] == !0) return;
1691
+ a[ne] = !0, a.userData && (a.userData.LOD = -1);
1692
+ const l = Object.keys(a);
1693
+ for (let c = 0; c < l.length; c++) {
1694
+ const f = l[c], y = a[f];
1695
+ if (y?.isTexture === !0) {
1696
+ const T = y.userData?.associations?.textures;
1697
+ if (T == null) continue;
1698
+ const _ = s.parser.json.textures[T];
1699
+ if (!_) {
1700
+ console.warn("Texture data not found for texture index " + T);
1472
1701
  continue;
1473
1702
  }
1474
- if (k?.extensions?.[W]) {
1475
- const M = k.extensions[W];
1476
- M && i && m.registerTexture(i, w, M.lods.length, _, M);
1703
+ if (_?.extensions?.[U]) {
1704
+ const C = _.extensions[U];
1705
+ C && n && p.registerTexture(n, y, C.lods.length, T, C);
1477
1706
  }
1478
1707
  }
1479
1708
  }
1480
1709
  };
1481
- const l = e.material;
1482
- if (Array.isArray(l)) for (const a of l) o(a);
1483
- else o(l);
1710
+ const u = e.material;
1711
+ if (Array.isArray(u)) for (const a of u) o(a);
1712
+ else o(u);
1484
1713
  }
1485
1714
  }
1486
1715
  tryParseMeshLOD(t, e) {
1487
- if (e[Me] == !0) return;
1488
- e[Me] = !0;
1716
+ if (e[De] == !0) return;
1717
+ e[De] = !0;
1489
1718
  const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
1490
1719
  if (!r)
1491
1720
  return;
1492
- const i = e.userData?.gltfExtensions?.[W];
1493
- if (i && r) {
1721
+ const n = e.userData?.gltfExtensions?.[U];
1722
+ if (n && r) {
1494
1723
  const o = e.uuid;
1495
- m.registerMesh(r, o, e, 0, i.lods.length, i);
1724
+ p.registerMesh(r, o, e, 0, n.lods.length, n);
1496
1725
  }
1497
1726
  }
1498
1727
  }
1499
- function Lt(...n) {
1728
+ function Tt(...i) {
1500
1729
  let t, e, s, r;
1501
- switch (n.length) {
1730
+ switch (i.length) {
1502
1731
  case 2:
1503
- [s, e] = n, r = {};
1732
+ [s, e] = i, r = {};
1504
1733
  break;
1505
1734
  case 3:
1506
- [s, e, r] = n;
1735
+ [s, e, r] = i;
1507
1736
  break;
1508
1737
  case 4:
1509
- [t, e, s, r] = n;
1738
+ [t, e, s, r] = i;
1510
1739
  break;
1511
1740
  default:
1512
1741
  throw new Error("Invalid arguments");
1513
1742
  }
1514
- we(e), Te(s), Ae(s, {
1743
+ we(e), Pe(s), Re(s, {
1515
1744
  progressive: !0,
1516
1745
  ...r?.hints
1517
- }), s.register((o) => new m(o));
1518
- const i = v.get(e);
1519
- return r?.enableLODsManager !== !1 && i.enable(), i;
1746
+ }), s.register((o) => new p(o));
1747
+ const n = L.get(e);
1748
+ return r?.enableLODsManager !== !1 && n.enable(), n;
1520
1749
  }
1521
- Re();
1522
- if (!nt) {
1523
- const n = {
1750
+ Be();
1751
+ if (!lt) {
1752
+ const i = {
1524
1753
  gltfProgressive: {
1525
- useNeedleProgressive: Lt,
1526
- LODsManager: v,
1527
- configureLoader: Ae,
1754
+ useNeedleProgressive: Tt,
1755
+ LODsManager: L,
1756
+ configureLoader: Re,
1528
1757
  getRaycastMesh: ee,
1529
- useRaycastMeshes: lt
1758
+ useRaycastMeshes: ct
1530
1759
  }
1531
1760
  };
1532
1761
  if (!globalThis.Needle)
1533
- globalThis.Needle = n;
1762
+ globalThis.Needle = i;
1534
1763
  else
1535
- for (const t in n)
1536
- globalThis.Needle[t] = n[t];
1764
+ for (const t in i)
1765
+ globalThis.Needle[t] = i[t];
1537
1766
  }
1538
1767
  export {
1539
- W as EXTENSION_NAME,
1540
- v as LODsManager,
1541
- m as NEEDLE_progressive,
1542
- Ke as VERSION,
1543
- Te as addDracoAndKTX2Loaders,
1544
- Ae as configureLoader,
1768
+ U as EXTENSION_NAME,
1769
+ L as LODsManager,
1770
+ p as NEEDLE_progressive,
1771
+ He as VERSION,
1772
+ Pe as addDracoAndKTX2Loaders,
1773
+ Re as configureLoader,
1545
1774
  we as createLoaders,
1775
+ vt as getLODColor,
1546
1776
  ee as getRaycastMesh,
1547
- Re as patchModelViewer,
1548
- at as registerRaycastMesh,
1549
- Je as setDracoDecoderLocation,
1550
- Ze as setKTX2TranscoderLocation,
1551
- Lt as useNeedleProgressive,
1552
- lt as useRaycastMeshes
1777
+ be as lodDebugColors,
1778
+ Be as patchModelViewer,
1779
+ ut as registerRaycastMesh,
1780
+ et as setDracoDecoderLocation,
1781
+ tt as setKTX2TranscoderLocation,
1782
+ Tt as useNeedleProgressive,
1783
+ ct as useRaycastMeshes
1553
1784
  };