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

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";
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";
5
- import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
6
- const Ke = "";
7
- globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
1
+ import { BufferGeometry as j, Mesh as K, Box3 as le, Vector3 as k, Sphere as Se, CompressedTexture as ze, Texture as G, Matrix3 as Ee, InterleavedBuffer as Ne, InterleavedBufferAttribute as Ve, BufferAttribute as Xe, TextureLoader as je, Color as Ce, Matrix4 as Pe, Clock as Ke } from "three";
2
+ import { GLTFLoader as we } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ import { MeshoptDecoder as Ye } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
+ import { DRACOLoader as He } from "three/examples/jsm/loaders/DRACOLoader.js";
5
+ import { KTX2Loader as Qe } from "three/examples/jsm/loaders/KTX2Loader.js";
6
+ const Je = "";
7
+ globalThis.GLTF_PROGRESSIVE_VERSION = Je;
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/", Y = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
+ const Ze = I, et = Y, ke = new URL(I + "draco_decoder.js");
11
+ ke.searchParams.append("range", "true");
12
+ fetch(ke, {
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 === Ze && st("./include/draco/"), Y === et && rt("./include/ktx2/");
19
19
  }).finally(() => {
20
- Ce();
20
+ Re();
21
21
  });
22
- const Qe = () => ({
22
+ const tt = () => ({
23
23
  dracoDecoderPath: I,
24
- ktx2TranscoderPath: j
24
+ ktx2TranscoderPath: Y
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 st(i) {
27
+ I = i, P && P[me] != I ? (console.debug("Updating Draco decoder path to " + i), P[me] = I, P.setDecoderPath(I), P.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 rt(i) {
30
+ Y = i, $ && $.transcoderPath != Y ? (console.debug("Updating KTX2 transcoder path to " + i), $.setTranscoderPath(Y), $.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 Le(i) {
33
+ return Re(), i ? $.detectSupport(i) : i !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: P, ktx2Loader: $, meshoptDecoder: ae };
34
34
  }
35
- function Te(n) {
36
- n.dracoLoader || n.setDRACOLoader(C), n.ktx2Loader || n.setKTX2Loader($), n.meshoptDecoder || n.setMeshoptDecoder(oe);
35
+ function Ae(i) {
36
+ i.dracoLoader || i.setDRACOLoader(P), i.ktx2Loader || i.setKTX2Loader($), i.meshoptDecoder || i.setMeshoptDecoder(ae);
37
37
  }
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);
38
+ const me = /* @__PURE__ */ Symbol("dracoDecoderPath");
39
+ let P, ae, $;
40
+ function Re() {
41
+ P || (P = new He(), P[me] = I, P.setDecoderPath(I), P.setDecoderConfig({ type: "js" }), P.preload()), $ || ($ = new Qe(), $.setTranscoderPath(Y), $.init()), ae || (ae = Ye);
42
42
  }
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);
43
+ const ye = /* @__PURE__ */ new WeakMap();
44
+ function Ie(i, t) {
45
+ let e = ye.get(i);
46
+ e ? e = Object.assign(e, t) : e = t, ye.set(i, e);
47
47
  }
48
- const et = xe.prototype.load;
49
- function tt(...n) {
50
- const t = me.get(this);
51
- let e = n[0];
48
+ const nt = we.prototype.load;
49
+ function ot(...i) {
50
+ const t = ye.get(this);
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, nt?.call(this, ...i);
58
58
  }
59
- xe.prototype.load = tt;
60
- q("debugprogressive");
61
- function q(n) {
59
+ we.prototype.load = ot;
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 it(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 ve() {
78
+ return Z !== void 0 || (Z = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", Z)), Z;
79
79
  }
80
- let H;
81
- function be() {
80
+ let Z;
81
+ function $e() {
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 at {
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 lt(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 = ut(i);
122
+ return t * e * s * n * (1 - Math.pow(0.25, r)) / (1 - 0.25);
123
123
  }
124
- function ot(n) {
124
+ function ut(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 ct = typeof window > "u" && typeof document > "u", xe = /* @__PURE__ */ Symbol("needle:raycast-mesh");
133
+ function ne(i) {
134
+ return i?.[xe] instanceof j ? i[xe] : 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 dt(i, t) {
137
+ if ((i.type === "Mesh" || i.type === "SkinnedMesh") && !ne(i)) {
138
+ const s = ht(t);
139
+ s.userData = { isRaycastMesh: !0 }, i[xe] = s;
140
140
  }
141
141
  }
142
- function lt(n = !0) {
143
- if (n) {
144
- if (Q) return;
145
- const t = Q = X.prototype.raycast;
146
- X.prototype.raycast = function(e, s) {
147
- const r = this, i = ee(r);
142
+ function ft(i = !0) {
143
+ if (i) {
144
+ if (ee) return;
145
+ const t = ee = K.prototype.raycast;
146
+ K.prototype.raycast = function(e, s) {
147
+ const r = this, n = ne(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 (!ee) return;
153
+ K.prototype.raycast = ee, ee = 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 ee = null;
157
+ function ht(i) {
158
+ const t = new j();
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;
163
+ const E = new Array(), f = N("debugprogressive");
164
+ let re, X = -1;
165
165
  if (f) {
166
- let n = function() {
167
- V += 1, V >= t && (V = -1), console.log(`Toggle LOD level [${V}]`);
168
- }, t = 6;
166
+ let i = function() {
167
+ X += 1, X >= t && (X = -1), console.log(`Toggle LOD level [${X}]`);
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" && (re = !re, console.log(`Toggle wireframe [${re}]`));
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 && (X = s, console.log(`Set LOD level to [${X}]`));
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 Be(i) {
177
+ if (f && re !== void 0)
178
+ if (Array.isArray(i))
179
+ for (const t of i)
180
+ Be(t);
181
+ else i && "wireframe" in i && (i.wireframe = re === !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;
183
+ const te = new Array();
184
+ let gt = 0;
185
+ const pt = ve() ? 2 : 10;
186
+ function mt(i) {
187
+ if (te.length < pt) {
188
+ const s = te.length;
188
189
  f && console.warn(`[Worker] Creating new worker #${s}`);
189
- const r = Le.createWorker(n || {});
190
- return J.push(r), r;
190
+ const r = _e.createWorker(i || {});
191
+ return te.push(r), r;
191
192
  }
192
- const t = ct++ % J.length;
193
- return J[t];
193
+ const t = gt++ % te.length;
194
+ return te[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
+ yt(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 = tt();
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 = Le(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 yt(i) {
253
+ for (const t of i.geometries) {
254
+ const e = t.geometry, s = new j();
254
255
  if (s.name = e.name || "", e.index) {
255
256
  const r = e.index;
256
- s.setIndex(le(r));
257
+ s.setIndex(ce(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 = ce(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) => ce(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 le(), s.boundingBox.min = new k(
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 k(
272
273
  e.boundingBox?.max.x,
273
274
  e.boundingBox?.max.y,
274
275
  e.boundingBox?.max.z
275
276
  ), s.boundingSphere = new Se(
276
- new A(
277
+ new k(
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 ze(
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 G(
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 Ee(...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 ce(i) {
329
+ let t = i;
330
+ if ("isInterleavedBufferAttribute" in i && i.isInterleavedBufferAttribute) {
331
+ const e = i.data, s = e.array, r = new Ne(s, e.stride);
332
+ t = new Ve(r, i.itemSize, s.byteOffset, i.normalized), t.offset = i.offset;
333
+ } else "isBufferAttribute" in i && i.isBufferAttribute && (t = new Xe(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 xt = N("gltf-progressive-worker");
337
+ N("gltf-progressive-reduce-mipmaps");
338
+ const se = N("gltf-progressive-gc"), de = /* @__PURE__ */ Symbol("needle-progressive-texture"), F = "NEEDLE_progressive";
339
+ class h {
339
340
  /** The name of the extension */
340
341
  get name() {
341
- return W;
342
+ return F;
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
388
  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);
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
400
  f && 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 d = 0; d < c.lods.length; d++) {
409
+ const g = c.lods[d];
410
+ g.width && (a.lods[d] = a.lods[d] || { min_height: 1 / 0, max_height: 0 }, a.lods[d].min_height = Math.min(a.lods[d].min_height, g.height), a.lods[d].max_height = Math.max(a.lods[d].max_height, g.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
  }
@@ -435,74 +459,75 @@ class m {
435
459
  * });
436
460
  * ```
437
461
  */
438
- static assignMeshLOD(t, e) {
462
+ static assignMeshLOD(t, e, s) {
439
463
  if (!t) return Promise.resolve(null);
440
- if (t instanceof X || t.isMesh === !0) {
441
- const s = t.geometry, r = this.getAssignedLODInformation(s);
442
- if (!r)
464
+ if (t instanceof K || t.isMesh === !0) {
465
+ const r = t.geometry, n = this.getAssignedLODInformation(r);
466
+ if (!n)
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)) {
448
- const o = r.index || 0;
449
- i = i[o];
468
+ for (const o of E)
469
+ o.onBeforeGetLODMesh?.(t, e);
470
+ return t["LOD:requested level"] = e, h.getOrLoadLOD(r, e).then((o) => {
471
+ if (Array.isArray(o)) {
472
+ const u = n.index || 0;
473
+ o = o[u];
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));
475
+ return t["LOD:requested level"] === e && (delete t["LOD:requested level"], o && r != o && (o?.isBufferGeometry ? typeof s?.apply == "function" ? s.apply(o, e, t) : s?.apply !== !1 && (t.geometry = o) : f && console.error("Invalid LOD geometry", o))), o;
476
+ }).catch((o) => (console.error("Error loading mesh LOD", t, o), null));
453
477
  } else f && 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 d = this.assignTextureLODForSlot(c, e, n, l, r).then((g) => (g && a.uniforms[l].value != g && (a.uniforms[l].value = g, a.uniformsNeedUpdate = !0), g));
508
+ o.push(d), 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 d = a[c], g = u[c];
523
+ d && d.isTexture === !0 ? l.push({ material: n, slot: g, texture: d, level: e }) : l.push({ material: n, slot: g, 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 G || 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,34 +536,107 @@ 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
+ h.queue.maxConcurrent = t;
515
540
  }
516
541
  static get maxConcurrentLoadingTasks() {
517
- return m.queue.maxConcurrent;
542
+ return h.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 = h.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;
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 f === "verbose" && console.warn("Assigned texture level is already higher: ", c.level, e, s, l, a), null;
531
568
  }
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);
535
- }
536
- s[r] = i;
569
+ this.assignTrackedTextureSlot(s, r, a);
537
570
  }
538
- return i;
571
+ return a;
539
572
  } else f == "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) && (f || se)) {
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;
@@ -549,8 +647,8 @@ class m {
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?.[F];
651
+ return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && h.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
554
652
  };
555
653
  // private _isLoadingTexture;
556
654
  // loadTexture = (textureIndex: number) => {
@@ -569,62 +667,80 @@ class m {
569
667
  afterRoot(t) {
570
668
  return f && 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[F];
573
671
  if (r) {
574
672
  if (!r.lods) {
575
673
  f && 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, h.registerTexture(this.url, o, r.lods?.length, s, r));
679
+ n || this.parser.getDependency("texture", s).then((o) => {
680
+ o && h.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[F];
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 && h.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
710
  f && console.error("!! gltf-progressive: Called register texture without texture");
605
711
  return;
606
712
  }
607
713
  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);
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[de] = n);
718
+ const o = n.guid;
719
+ h.assignLODInformation(t, e, o, s, r), h.lodInfos.set(o, n), h.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) {
734
+ static registerMesh = (t, e, s, r, n, o) => {
735
+ const u = s.geometry;
736
+ if (!u) {
621
737
  f && 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 = {}), f && console.log("> Progressive: register mesh " + s.name, { index: n, uuid: s.uuid }, o, s), h.assignLODInformation(t, u, e, r, n), h.lodInfos.set(e, o);
741
+ let l = h.lowresCache.get(e)?.deref();
742
+ l ? l.push(s.geometry) : l = [s.geometry], h.lowresCache.set(e, new WeakRef(l)), r > 0 && !ne(s) && dt(s, u);
743
+ for (const c of E)
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,9 +814,9 @@ 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 = h.cache.get(t);
818
+ (f || se) && console.debug(`[gltf-progressive] Memory: Resource GC'd
819
+ ${t}`), e instanceof WeakRef && (e.deref() || (h.cache.delete(t), (f || se) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
704
820
  });
705
821
  /**
706
822
  * Track texture usage by incrementing reference count
@@ -717,16 +833,15 @@ ${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 (f === "verbose" || se) && 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), (f || se) && n("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
840
+ return this.textureRefCounts.set(e, r), f === "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 d = "N/A";
844
+ a && l && (d = `~${(lt(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${c} (${d}), refCount: ${s} → ${u}
730
845
  ${e}`);
731
846
  }
732
847
  }
@@ -736,24 +851,24 @@ ${e}`);
736
851
  const s = f == "verbose", r = this.getAssignedLODInformation(t);
737
852
  if (!r)
738
853
  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;
854
+ const n = r?.key;
740
855
  let o;
741
856
  if (t.isTexture === !0) {
742
857
  const a = t;
743
- a.source && a.source[ue] && (o = a.source[ue]);
858
+ a.source && a.source[de] && (o = a.source[de]);
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 = h.lodInfos.get(n)), !o)
861
+ f && console.warn(`Can not load LOD ${e}: no LOD info found for "${n}" ${t.name}`, t.type, h.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 d = Array.isArray(o.lods);
866
+ if (d && e >= o.lods.length ? c = !0 : d || (c = !0), c) {
867
+ const g = this.lowresCache.get(n);
868
+ if (g) {
869
+ const m = g.deref();
870
+ if (m) return m;
871
+ this.lowresCache.delete(n), f && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${n}`);
757
872
  }
758
873
  return null;
759
874
  }
@@ -761,128 +876,132 @@ ${e}`);
761
876
  const a = Array.isArray(o.lods) ? o.lods[e]?.path : o.lods;
762
877
  if (!a)
763
878
  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")) {
879
+ const l = it(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
- }
784
- 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);
883
+ const c = l + "_" + o.guid, d = await this.tryResolveLODCacheEntry(this.cache.get(c), c, l, t, e, s);
884
+ if (d.found) return d.value;
885
+ const g = await this.queue.slot(l), m = await this.tryResolveLODCacheEntry(this.cache.get(c), c, l, t, e, s);
886
+ if (m.found) return m.value;
887
+ if (!g.use)
888
+ return f && console.log(`LOD ${e} was aborted: ${l}`), null;
889
+ const x = o, v = new Promise(async (_, C) => {
890
+ if (xt) {
891
+ const y = await (await mt({})).load(l);
892
+ if (y.textures.length > 0)
893
+ for (const M of y.textures) {
894
+ let b = M.texture;
895
+ return h.assignLODInformation(r.url, b, n, e, void 0), t instanceof G && (b = this.copySettings(t, b)), b && (b.guid = x.guid), _(b);
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 (y.geometries.length > 0) {
898
+ const M = new Array();
899
+ for (const b of y.geometries) {
900
+ const B = b.geometry;
901
+ h.assignLODInformation(r.url, B, n, e, b.primitiveIndex), M.push(B);
799
902
  }
800
- return d(h);
903
+ return _(M);
801
904
  }
802
- return d(null);
905
+ return _(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;
807
- if (_ && Array.isArray(_.lods)) {
808
- const L = _.lods[e];
809
- L.hash && (B += "?v=" + L.hash);
907
+ const W = new we();
908
+ Ae(W), f && (await new Promise((D) => setTimeout(D, 1e3)), s && console.warn("Start loading (delayed) " + l, x.guid));
909
+ let L = l;
910
+ if (x && Array.isArray(x.lods)) {
911
+ const D = x.lods[e];
912
+ D.hash && (L += "?v=" + D.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 w = await W.loadAsync(L).catch((D) => (console.error(`Error loading LOD ${e} from ${l}
915
+ `, D), _(null)));
916
+ if (!w)
917
+ return _(null);
918
+ const S = w.parser;
919
+ s && console.log("Loading finished " + l, x.guid);
920
+ let O = 0;
921
+ if (w.parser.json.textures) {
922
+ let D = !1;
923
+ for (const y of w.parser.json.textures) {
924
+ if (y?.extensions) {
925
+ const M = y?.extensions[F];
926
+ if (M?.guid && M.guid === x.guid) {
927
+ D = !0;
825
928
  break;
826
929
  }
827
930
  }
828
- P++;
931
+ O++;
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 (D) {
934
+ let y = await S.getDependency("texture", O);
935
+ return y && h.assignLODInformation(r.url, y, n, e, void 0), s && console.log('change "' + t.name + '" → "' + y.name + '"', l, O, y, c), t instanceof G && (y = this.copySettings(t, y)), y && (y.guid = x.guid), _(y);
936
+ } else f && console.warn("Could not find texture with guid", x.guid, w.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 (O = 0, w.parser.json.meshes) {
939
+ let D = !1;
940
+ for (const y of w.parser.json.meshes) {
941
+ if (y?.extensions) {
942
+ const M = y?.extensions[F];
943
+ if (M?.guid && M.guid === x.guid) {
944
+ D = !0;
842
945
  break;
843
946
  }
844
947
  }
845
- P++;
948
+ O++;
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 (D) {
951
+ const y = await S.getDependency("mesh", O);
952
+ if (s && console.log(`Loaded Mesh "${y.name}"`, l, O, y, c), y.isMesh === !0) {
953
+ const M = y.geometry;
954
+ return h.assignLODInformation(r.url, M, n, e, 0), _(M);
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 M = new Array();
957
+ for (let b = 0; b < y.children.length; b++) {
958
+ const B = y.children[b];
959
+ if (B.isMesh === !0) {
960
+ const V = B.geometry;
961
+ h.assignLODInformation(r.url, V, n, e, b), M.push(V);
859
962
  }
860
963
  }
861
- return d(h);
964
+ return _(M);
862
965
  }
863
- } else f && console.warn("Could not find mesh with guid", _.guid, D.parser.json);
966
+ } else f && console.warn("Could not find mesh with guid", x.guid, w.parser.json);
864
967
  }
865
- return d(null);
968
+ return _(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, v), g.use(v);
971
+ const p = await v;
972
+ return p != null ? p instanceof G ? (this.cache.set(c, new WeakRef(p)), h._resourceRegistry.register(p, c)) : Array.isArray(p) ? this.cache.set(c, Promise.resolve(p)) : this.cache.set(c, Promise.resolve(p)) : this.cache.set(c, Promise.resolve(null)), p;
973
+ } else if (t instanceof G) {
974
+ s && console.log("Load texture from uri: " + l);
975
+ const d = await new je().loadAsync(l);
976
+ return d ? (d.guid = o.guid, d.flipY = !1, d.needsUpdate = !0, d.colorSpace = t.colorSpace, s && console.log(o, d)) : f && console.warn("failed loading", l), d;
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, d = !1;
988
+ if (c instanceof G && r instanceof G ? c.image?.data || c.source?.data ? c = this.copySettings(r, c) : d = !0 : c instanceof j && r instanceof j && (c.attributes.position?.array || (d = !0)), !d)
989
+ return { found: !0, value: c };
990
+ }
991
+ return this.cache.delete(e), f && 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 G && r instanceof G ? u.image?.data || u.source?.data ? u = this.copySettings(r, u) : (a = !0, this.cache.delete(e)) : u instanceof j && r instanceof j && (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 at(ve() ? 20 : 50, { debug: f != !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 wt(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) {
@@ -895,7 +1014,7 @@ ${e}`);
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 wt {
899
1018
  url;
900
1019
  /** the key to lookup the LOD information */
901
1020
  key;
@@ -906,10 +1025,10 @@ class pt {
906
1025
  this.url = t, this.key = e, this.level = s, r != null && (this.index = r);
907
1026
  }
908
1027
  }
909
- class ce {
1028
+ class oe {
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", () => {
@@ -961,7 +1080,7 @@ class ce {
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
1085
  f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
967
1086
  return;
@@ -982,22 +1101,112 @@ 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 A = N("debugprogressive"), Lt = A === "colors", vt = N("noprogressive"), fe = /* @__PURE__ */ Symbol("Needle:LODSManager"), he = /* @__PURE__ */ Symbol("Needle:LODState"), q = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), T = { mesh_lod: -1, texture_lod: -1 }, _t = new Ce(), Me = [
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
+ ], ge = new le(), z = new le(), De = new le(), Mt = new k(), Dt = new k(), bt = new Pe(), U = new k(), H = new k(), Q = new k(), J = new k();
1138
+ function Ot(i, t) {
1139
+ const e = i.min, s = i.max, r = (e.x + s.x) * 0.5, n = (e.y + s.y) * 0.5;
1140
+ return U.set(r, n, e.z).applyMatrix4(t).z < 0;
1141
+ }
1142
+ function Tt(i) {
1143
+ const {
1144
+ geometry: t,
1145
+ matrixWorld: e,
1146
+ camera: s,
1147
+ projectionScreenMatrix: r,
1148
+ desiredDensity: n,
1149
+ canvasHeight: o = 0,
1150
+ currentLevel: u = -1,
1151
+ xrEnabled: a = !1,
1152
+ debugDrawLine: l,
1153
+ warnMissingPrimitiveDensities: c = !1
1154
+ } = i, d = h.getMeshLODExtension(t)?.lods, g = h.getPrimitiveIndex(t), m = i.target ?? {
1155
+ level: u,
1156
+ primitiveIndex: g,
1157
+ screenCoverage: 0,
1158
+ screenspaceVolume: new k(),
1159
+ centrality: 1
1160
+ };
1161
+ if (m.level = u, m.primitiveIndex = g, m.screenCoverage = 0, m.screenspaceVolume.set(0, 0, 0), m.centrality = 1, !d?.length) return m;
1162
+ let x = i.boundingBox ?? t.boundingBox;
1163
+ if (x || (t.computeBoundingBox(), x = t.boundingBox), !x) return m;
1164
+ if (ge.copy(x).applyMatrix4(e), s.isPerspectiveCamera && Ot(ge, r))
1165
+ return m.level = 0, m.screenCoverage = 1 / 0, m.screenspaceVolume.set(1 / 0, 1 / 0, 1 / 0), m;
1166
+ if (z.copy(ge).applyMatrix4(r), a && s.isPerspectiveCamera && s.fov > 70) {
1167
+ const L = z.min, w = z.max;
1168
+ let S = L.x, O = L.y, D = w.x, y = w.y;
1169
+ const M = 2, b = 1.5, B = (L.x + w.x) * 0.5, V = (L.y + w.y) * 0.5;
1170
+ S = (S - B) * M + B, O = (O - V) * M + V, D = (D - B) * M + B, y = (y - V) * M + V;
1171
+ const Fe = S < 0 && D > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(w.x)), qe = O < 0 && y > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(w.y)), ue = Math.max(Fe, qe);
1172
+ m.centrality = (b - ue) * (b - ue) * (b - ue);
1173
+ }
1174
+ const v = z.getSize(Mt);
1175
+ v.multiplyScalar(0.5), globalThis.screen?.availHeight > 0 && o > 0 && v.multiplyScalar(o / globalThis.screen.availHeight), s.isPerspectiveCamera && (v.x *= s.aspect), De.copy(x).applyMatrix4(e).applyMatrix4(s.matrixWorldInverse);
1176
+ const p = De.getSize(Dt), _ = Math.max(v.x, v.y), C = Math.max(p.x, p.y);
1177
+ _ !== 0 && C !== 0 && (v.z = p.z / C * _);
1178
+ const W = Math.max(v.x, v.y, v.z) * m.centrality;
1179
+ if (m.screenCoverage = W, m.screenspaceVolume.copy(v), W <= 0) return m;
1180
+ if (l) {
1181
+ const L = bt.copy(r);
1182
+ L.invert(), U.copy(z.min), H.copy(z.max), H.x = U.x, Q.copy(z.max), Q.y = U.y, J.copy(z.max);
1183
+ const w = (U.z + J.z) * 0.5;
1184
+ U.z = H.z = Q.z = J.z = w, U.applyMatrix4(L), H.applyMatrix4(L), Q.applyMatrix4(L), J.applyMatrix4(L), l(U, H, 255), l(U, Q, 255), l(H, J, 255), l(Q, J, 255);
1185
+ }
1186
+ for (let L = 0; L < d.length; L++) {
1187
+ const w = d[L], S = w.densities?.[g] || w.density || 1e-5;
1188
+ if (g > 0 && c && $e() && !w.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (globalThis["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 / W < n) {
1189
+ m.level = L;
1190
+ break;
1191
+ }
1192
+ }
1193
+ return m;
1194
+ }
1195
+ class R {
987
1196
  /**
988
1197
  * 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
1198
  */
990
1199
  static debugDrawLine;
991
1200
  /** @internal */
992
1201
  static getObjectLODState(t) {
993
- return t[fe];
1202
+ return t[he];
994
1203
  }
995
1204
  static addPlugin(t) {
996
- z.push(t);
1205
+ E.push(t);
997
1206
  }
998
1207
  static removePlugin(t) {
999
- const e = z.indexOf(t);
1000
- e >= 0 && z.splice(e, 1);
1208
+ const e = E.indexOf(t);
1209
+ e >= 0 && E.splice(e, 1);
1001
1210
  }
1002
1211
  /**
1003
1212
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -1005,20 +1214,20 @@ class v {
1005
1214
  * @returns The LODsManager instance.
1006
1215
  */
1007
1216
  static get(t, e) {
1008
- if (t[de])
1009
- return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[de];
1010
- const s = new v(t, {
1217
+ if (t[fe])
1218
+ return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[fe];
1219
+ const s = new R(t, {
1011
1220
  engine: "unknown",
1012
1221
  ...e
1013
1222
  });
1014
- return t[de] = s, s;
1223
+ return t[fe] = s, s;
1015
1224
  }
1016
1225
  renderer;
1017
1226
  context;
1018
- projectionScreenMatrix = new ve();
1227
+ projectionScreenMatrix = new Pe();
1019
1228
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
1020
1229
  get plugins() {
1021
- return z;
1230
+ return E;
1022
1231
  }
1023
1232
  /**
1024
1233
  * Force override the LOD level for all objects (meshes + textures) rendered in the scene
@@ -1056,44 +1265,98 @@ class v {
1056
1265
  _newPromiseGroups = [];
1057
1266
  _promiseGroupIds = 0;
1058
1267
  /**
1059
- * Call to await LODs loading during the next render cycle.
1268
+ * Returns a promise that resolves once all LOD requests initiated during the next render cycles have finished loading.
1269
+ * This is useful for hiding low-resolution placeholders (e.g. with a loading overlay or CSS blur) until high-quality assets are ready.
1270
+ *
1271
+ * By default, the returned promise captures LOD loading requests for 2 frames and resolves when all of them complete.
1272
+ * Use `waitForFirstCapture` if no LOD requests may happen immediately (e.g. after a scene switch).
1273
+ *
1274
+ * @param opts - Optional configuration for how long to capture and what to wait for. See {@link PromiseGroupOptions}.
1275
+ * @returns A promise that resolves with `{ cancelled, awaited_count, resolved_count }` once all captured LOD loads complete (or the signal aborts).
1276
+ *
1277
+ * @example
1278
+ * ```ts
1279
+ * // Wait for initial LODs to finish loading, then remove a blur overlay
1280
+ * const result = await lodsManager.awaitLoading({
1281
+ * frames: 5,
1282
+ * signal: AbortSignal.timeout(10_000),
1283
+ * });
1284
+ * console.log(`Loaded ${result.resolved_count} of ${result.awaited_count} LODs`);
1285
+ * document.querySelector('.blur-overlay')?.remove();
1286
+ * ```
1287
+ *
1288
+ * @example
1289
+ * ```ts
1290
+ * // Wait until at least one LOD starts loading before resolving
1291
+ * await lodsManager.awaitLoading({ waitForFirstCapture: true });
1292
+ * ```
1060
1293
  */
1061
1294
  awaitLoading(t) {
1062
- const e = this._promiseGroupIds++, s = new ce(this.#r, { ...t });
1295
+ const e = this._promiseGroupIds++, s = new oe(this.#r, { ...t });
1063
1296
  this._newPromiseGroups.push(s);
1064
1297
  const r = performance.now();
1065
1298
  return s.ready.finally(() => {
1066
- const i = this._newPromiseGroups.indexOf(s);
1067
- i >= 0 && (this._newPromiseGroups.splice(i, 1), be() && performance.measure("LODsManager:awaitLoading", {
1299
+ const n = this._newPromiseGroups.indexOf(s);
1300
+ n >= 0 && (this._newPromiseGroups.splice(n, 1), $e() && performance.measure("LODsManager:awaitLoading", {
1068
1301
  start: r,
1069
1302
  detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
1070
1303
  }));
1071
1304
  }), s.ready;
1072
1305
  }
1306
+ /** Track LOD work started outside this manager so {@link awaitLoading} waits for it too. */
1307
+ trackLoadingPromise(t, e, s) {
1308
+ return oe.addPromise(t, e, s, this._newPromiseGroups), s;
1309
+ }
1073
1310
  _postprocessPromiseGroups() {
1074
1311
  if (this._newPromiseGroups.length !== 0)
1075
1312
  for (let t = this._newPromiseGroups.length - 1; t >= 0; t--)
1076
1313
  this._newPromiseGroups[t].update(this.#r);
1077
1314
  }
1078
1315
  _lodchangedlisteners = [];
1316
+ /**
1317
+ * Register a listener that is called whenever a mesh or texture LOD level has finished loading and has been applied.
1318
+ * The listener receives the type of asset (`"mesh"` or `"texture"`), the new LOD level, and the affected object.
1319
+ *
1320
+ * @param evt - The event type. Currently only `"changed"` is supported.
1321
+ * @param listener - Callback invoked after a LOD swap completes.
1322
+ * @return A function to unregister the listener.
1323
+ *
1324
+ * @example
1325
+ * ```ts
1326
+ * lodsManager.addEventListener("changed", ({ type, level, object }) => {
1327
+ * console.log(`${type} LOD changed to level ${level}`, object);
1328
+ * });
1329
+ * ```
1330
+ */
1079
1331
  addEventListener(t, e) {
1080
- t === "changed" && this._lodchangedlisteners.push(e);
1332
+ return t === "changed" ? (this._lodchangedlisteners.push(e), () => {
1333
+ this.removeEventListener(t, e);
1334
+ }) : () => {
1335
+ };
1081
1336
  }
1337
+ /**
1338
+ * Remove a previously registered `"changed"` event listener.
1339
+ * @param evt - The event type (`"changed"`).
1340
+ * @param listener - The listener to remove.
1341
+ * @return `true` if the listener was found and removed, `false` otherwise.
1342
+ */
1082
1343
  removeEventListener(t, e) {
1344
+ let s = !1;
1083
1345
  if (t === "changed") {
1084
- const s = this._lodchangedlisteners.indexOf(e);
1085
- s >= 0 && this._lodchangedlisteners.splice(s, 1);
1346
+ const r = this._lodchangedlisteners.indexOf(e);
1347
+ r >= 0 && (this._lodchangedlisteners.splice(r, 1), s = !0);
1086
1348
  }
1349
+ return s;
1087
1350
  }
1088
1351
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
1089
1352
  constructor(t, e) {
1090
1353
  this.renderer = t, this.context = { ...e };
1091
1354
  }
1092
1355
  #t;
1093
- #o = new Ne();
1356
+ #o = new Ke();
1094
1357
  #r = 0;
1095
- #i = 0;
1096
1358
  #n = 0;
1359
+ #i = 0;
1097
1360
  #s = 0;
1098
1361
  _fpsBuffer = [60, 60, 60, 60, 60];
1099
1362
  /**
@@ -1105,9 +1368,9 @@ class v {
1105
1368
  let t = 0;
1106
1369
  this.#t = this.renderer.render;
1107
1370
  const e = this;
1108
- 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));
1371
+ Le(this.renderer), this.renderer.render = function(s, r) {
1372
+ const n = e.renderer.getRenderTarget();
1373
+ (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, A && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1111
1374
  const o = t++;
1112
1375
  e.#t.call(this, s, r), e.onAfterRender(s, r, o);
1113
1376
  };
@@ -1115,19 +1378,34 @@ class v {
1115
1378
  disable() {
1116
1379
  this.#t && (console.debug("[gltf-progressive] Disabling LODsManager for renderer"), this.renderer.render = this.#t, this.#t = void 0);
1117
1380
  }
1381
+ /**
1382
+ * Manually trigger a LOD update for a scene and camera.
1383
+ * Only needed when {@link manual} is set to `true` — otherwise LOD updates happen automatically on each render call.
1384
+ *
1385
+ * @param scene - The scene containing objects with progressive LODs.
1386
+ * @param camera - The camera used to determine screen coverage and LOD levels.
1387
+ *
1388
+ * @example
1389
+ * ```ts
1390
+ * const lodsManager = LODsManager.get(renderer);
1391
+ * lodsManager.manual = true;
1392
+ * // ... later, trigger an update at a specific point:
1393
+ * lodsManager.update(scene, camera);
1394
+ * ```
1395
+ */
1118
1396
  update(t, e) {
1119
1397
  this.internalUpdate(t, e);
1120
1398
  }
1121
1399
  onAfterRender(t, e, s) {
1122
1400
  if (this.pause) return;
1123
- const i = this.renderer.renderLists.get(t, 0).opaque;
1401
+ const n = this.renderer.renderLists.get(t, 0).opaque;
1124
1402
  let o = !0;
1125
- if (i.length === 1) {
1126
- const l = i[0].material;
1127
- (l.name === "EffectMaterial" || l.name === "CopyShader") && (o = !1);
1403
+ if (n.length === 1) {
1404
+ const u = n[0].material;
1405
+ (u.name === "EffectMaterial" || u.name === "CopyShader") && (o = !1);
1128
1406
  }
1129
1407
  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))
1408
+ if (vt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, A && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, A && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
1131
1409
  return;
1132
1410
  this.internalUpdate(t, e), this._postprocessPromiseGroups();
1133
1411
  }
@@ -1138,10 +1416,10 @@ class v {
1138
1416
  internalUpdate(t, e) {
1139
1417
  const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
1140
1418
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
1141
- const i = this.targetTriangleDensity;
1419
+ const n = this.targetTriangleDensity;
1142
1420
  for (const a of r) {
1143
1421
  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
- 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)));
1422
+ A && (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", a, a.material.name, a.material.type)));
1145
1423
  continue;
1146
1424
  }
1147
1425
  switch (a.material.type) {
@@ -1153,38 +1431,33 @@ class v {
1153
1431
  case "MeshDepthMaterial":
1154
1432
  continue;
1155
1433
  }
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);
1434
+ const l = a.object;
1435
+ (l instanceof K || l.isMesh) && this.updateLODs(t, e, l, n);
1163
1436
  }
1164
1437
  const o = s.transparent;
1165
1438
  for (const a of o) {
1166
- const u = a.object;
1167
- (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1439
+ const l = a.object;
1440
+ (l instanceof K || l.isMesh) && this.updateLODs(t, e, l, n);
1168
1441
  }
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);
1442
+ const u = s.transmissive;
1443
+ for (const a of u) {
1444
+ const l = a.object;
1445
+ (l instanceof K || l.isMesh) && this.updateLODs(t, e, l, n);
1173
1446
  }
1174
1447
  }
1175
1448
  /** Update the LOD levels for the renderer. */
1176
1449
  updateLODs(t, e, s, r) {
1177
1450
  s.userData || (s.userData = {});
1178
- let i = s[fe];
1179
- if (i || (i = new yt(), s[fe] = i), i.frames++ < 2)
1451
+ let n = s[he];
1452
+ if (n || (n = new St(), s[he] = n), n.frames++ < 2)
1180
1453
  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;
1454
+ for (const u of E)
1455
+ u.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1456
+ const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : X;
1457
+ o >= 0 ? (T.mesh_lod = o, T.texture_lod = o) : (this.calculateLodLevel(e, s, n, 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 && Be(s.material), Lt && s.material && !s.isGizmo && !s.isBatchedMesh && Ge(s.material, T.mesh_lod);
1458
+ for (const u of E)
1459
+ u.onAfterUpdatedLOD?.(this.renderer, t, e, s, T);
1460
+ n.lastLodLevel_Mesh = T.mesh_lod, n.lastLodLevel_Texture = T.texture_lod;
1188
1461
  }
1189
1462
  /** Load progressive textures for the given material
1190
1463
  * @param material the material to load the textures for
@@ -1194,17 +1467,19 @@ class v {
1194
1467
  loadProgressiveTextures(t, e, s) {
1195
1468
  if (!t) return;
1196
1469
  if (Array.isArray(t)) {
1197
- for (const i of t)
1198
- this.loadProgressiveTextures(i, e);
1470
+ for (const o of t)
1471
+ this.loadProgressiveTextures(o, e, s);
1199
1472
  return;
1200
1473
  }
1201
1474
  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) => {
1475
+ (t[q] === void 0 || e < t[q]) && (r = !0);
1476
+ const n = s !== void 0 && s >= 0;
1477
+ if (n && (r = t[q] != s, e = s), r) {
1478
+ t[q] = e;
1479
+ const o = n ? { force: !0 } : void 0, u = h.assignTextureLOD(t, e, o).then((a) => {
1205
1480
  this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
1206
1481
  });
1207
- ce.addPromise("texture", t, i, this._newPromiseGroups);
1482
+ oe.addPromise("texture", t, u, this._newPromiseGroups);
1208
1483
  }
1209
1484
  }
1210
1485
  /** Load progressive meshes for the given mesh
@@ -1215,143 +1490,110 @@ class v {
1215
1490
  */
1216
1491
  loadProgressiveMeshes(t, e) {
1217
1492
  if (!t) return Promise.resolve(null);
1218
- let s = t[U] !== e;
1493
+ let s = t[q] !== e;
1219
1494
  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));
1223
- return ce.addPromise("mesh", t, o, this._newPromiseGroups), o;
1495
+ if (r != null && (s = t[q] != r, e = r), s) {
1496
+ t[q] = e;
1497
+ const n = t.geometry, o = h.assignMeshLOD(t, e).then((u) => (u && t[q] == e && n != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), u));
1498
+ return oe.addPromise("mesh", t, o, this._newPromiseGroups), o;
1224
1499
  }
1225
1500
  return Promise.resolve(null);
1226
1501
  }
1227
1502
  // private testIfLODLevelsAreAvailable() {
1228
1503
  _sphere = new Se();
1229
- _tempBox = new ge();
1230
- _tempBox2 = new ge();
1231
- 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();
1240
- 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;
1243
- }
1504
+ _tempWorldPosition = new k();
1244
1505
  static skinnedMeshBoundsFrameOffsetCounter = 0;
1245
1506
  static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
1246
1507
  // #region calculateLodLevel
1247
- calculateLodLevel(t, e, s, r, i) {
1508
+ calculateLodLevel(t, e, s, r, n) {
1248
1509
  if (!e) {
1249
- i.mesh_lod = -1, i.texture_lod = -1;
1510
+ n.mesh_lod = -1, n.texture_lod = -1;
1250
1511
  return;
1251
1512
  }
1252
1513
  if (!t) {
1253
- i.mesh_lod = -1, i.texture_lod = -1;
1514
+ n.mesh_lod = -1, n.texture_lod = -1;
1254
1515
  return;
1255
1516
  }
1256
- let l = 10 + 1, a = !1;
1257
- if (R && e["DEBUG:LOD"] != null)
1517
+ let u = 10 + 1, a = !1;
1518
+ if (A && e["DEBUG:LOD"] != null)
1258
1519
  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;
1520
+ const l = h.getMeshLODExtension(e.geometry)?.lods, c = h.getPrimitiveIndex(e.geometry), d = l && l.length > 0, g = h.getMaterialMinMaxLODsCount(e.material), m = g.min_count !== 1 / 0 && g.min_count >= 0 && g.max_count >= 0;
1521
+ if (!d && !m) {
1522
+ n.mesh_lod = 0, n.texture_lod = 0;
1262
1523
  return;
1263
1524
  }
1264
- y || (a = !0, l = 0);
1265
- const k = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1266
- let M = e.geometry.boundingBox;
1525
+ d || (a = !0, u = 0);
1526
+ const x = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1527
+ let v = e.geometry.boundingBox;
1267
1528
  if (e.type === "SkinnedMesh") {
1268
- const d = e;
1269
- if (!d.boundingBox)
1270
- d.computeBoundingBox();
1529
+ const p = e;
1530
+ if (!p.boundingBox)
1531
+ p.computeBoundingBox();
1271
1532
  else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
1272
- if (!d[v.$skinnedMeshBoundsOffset]) {
1273
- const b = v.skinnedMeshBoundsFrameOffsetCounter++;
1274
- d[v.$skinnedMeshBoundsOffset] = b;
1533
+ if (!p[R.$skinnedMeshBoundsOffset]) {
1534
+ const C = R.skinnedMeshBoundsFrameOffsetCounter++;
1535
+ p[R.$skinnedMeshBoundsOffset] = C;
1275
1536
  }
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;
1537
+ const _ = p[R.$skinnedMeshBoundsOffset];
1538
+ if ((s.frames + _) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1539
+ const C = ne(p), W = p.geometry;
1540
+ C && (p.geometry = C), p.computeBoundingBox(), p.geometry = W;
1280
1541
  }
1281
1542
  }
1282
- M = d.boundingBox;
1543
+ v = p.boundingBox;
1283
1544
  }
1284
- if (M) {
1285
- const d = t;
1545
+ if (v) {
1286
1546
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
1287
1547
  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;
1548
+ const C = t.getWorldPosition(this._tempWorldPosition);
1549
+ if (this._sphere.containsPoint(C)) {
1550
+ n.mesh_lod = 0, n.texture_lod = 0;
1291
1551
  return;
1292
1552
  }
1293
1553
  }
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;
1554
+ const p = Tt({
1555
+ geometry: e.geometry,
1556
+ matrixWorld: e.matrixWorld,
1557
+ camera: t,
1558
+ projectionScreenMatrix: this.projectionScreenMatrix,
1559
+ desiredDensity: r,
1560
+ canvasHeight: x,
1561
+ currentLevel: s.lastLodLevel_Mesh,
1562
+ boundingBox: v,
1563
+ xrEnabled: this.renderer.xr.enabled,
1564
+ debugDrawLine: A ? R.debugDrawLine : void 0,
1565
+ warnMissingPrimitiveDensities: !0
1566
+ });
1567
+ if (s.lastCentrality = p.centrality, s.lastScreenCoverage = p.screenCoverage, s.lastScreenspaceVolume.copy(p.screenspaceVolume), p.screenCoverage === 1 / 0) {
1568
+ n.mesh_lod = 0, n.texture_lod = 0;
1296
1569
  return;
1297
1570
  }
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);
1305
- } else
1306
- 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);
1319
- }
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;
1326
- break;
1327
- }
1328
- }
1329
- L < l && (l = L, a = !0);
1571
+ p.level >= 0 && p.level < u && (u = p.level, a = !0);
1330
1572
  }
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}`);
1573
+ if (a ? n.mesh_lod = u : n.mesh_lod = s.lastLodLevel_Mesh, A && n.mesh_lod != s.lastLodLevel_Mesh) {
1574
+ const _ = l?.[n.mesh_lod];
1575
+ _ && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${_.densities?.[c].toFixed(0)}) | ${e.name}`);
1334
1576
  }
1335
- if (_) {
1336
- const d = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1577
+ if (m) {
1578
+ const p = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1337
1579
  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}`);
1580
+ if (n.texture_lod = g.max_count - 1, A) {
1581
+ const _ = g.lods[g.max_count - 1];
1582
+ A && console.log(`First Texture LOD ${n.texture_lod} (${_.max_height}px) - ${e.name}`);
1341
1583
  }
1342
1584
  } 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)}
1585
+ const _ = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1586
+ let C = s.lastScreenCoverage * 4;
1587
+ this.context?.engine === "model-viewer" && (C *= 1.5);
1588
+ const L = x / window.devicePixelRatio * C;
1589
+ let w = !1;
1590
+ for (let S = g.lods.length - 1; S >= 0; S--) {
1591
+ const O = g.lods[S];
1592
+ if (!(p && O.max_height >= 2048) && !(ve() && O.max_height > 4096) && (O.max_height > L || !w && S === 0)) {
1593
+ if (w = !0, n.texture_lod = S, A && n.texture_lod < s.lastLodLevel_Texture) {
1594
+ const D = O.max_height;
1595
+ console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${D}px
1596
+ Screensize: ${L.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${_.toFixed(1)}
1355
1597
  ${e.name}`);
1356
1598
  }
1357
1599
  break;
@@ -1359,83 +1601,98 @@ ${e.name}`);
1359
1601
  }
1360
1602
  }
1361
1603
  } else
1362
- i.texture_lod = 0;
1604
+ n.texture_lod = 0;
1363
1605
  }
1364
1606
  }
1365
- class yt {
1607
+ class St {
1366
1608
  frames = 0;
1367
1609
  lastLodLevel_Mesh = -1;
1368
1610
  lastLodLevel_Texture = -1;
1369
1611
  lastScreenCoverage = 0;
1370
- lastScreenspaceVolume = new A();
1612
+ lastScreenspaceVolume = new k();
1371
1613
  lastCentrality = 0;
1372
1614
  }
1373
- const Me = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1374
- 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) => {
1615
+ function Ge(i, t) {
1616
+ if (!(t < 0)) {
1617
+ if (Array.isArray(i)) {
1618
+ for (const e of i)
1619
+ Ge(e, t);
1620
+ return;
1621
+ }
1622
+ "color" in i && i.color instanceof Ce && (i.color.copy(Ct(t, _t)), i.needsUpdate = !0);
1623
+ }
1624
+ }
1625
+ function Ct(i, t) {
1626
+ const e = Math.max(0, Math.min(Me.length - 1, Math.floor(i)));
1627
+ return t.setHex(Me[e]);
1628
+ }
1629
+ const be = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1630
+ let pe = null;
1631
+ function We() {
1632
+ const i = Pt();
1633
+ i && (i.mapURLs(function(t) {
1634
+ return Oe(), t;
1635
+ }), Oe(), pe?.disconnect(), pe = new MutationObserver((t) => {
1380
1636
  t.forEach((e) => {
1381
1637
  e.addedNodes.forEach((s) => {
1382
- s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ie(s);
1638
+ s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ue(s);
1383
1639
  });
1384
1640
  });
1385
- }), he.observe(document, { childList: !0, subtree: !0 }));
1641
+ }), pe.observe(document, { childList: !0, subtree: !0 }));
1386
1642
  }
1387
- function xt() {
1643
+ function Pt() {
1388
1644
  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();
1645
+ const i = customElements.get("model-viewer");
1646
+ return i || (customElements.whenDefined("model-viewer").then(() => {
1647
+ console.debug("[gltf-progressive] model-viewer defined"), We();
1392
1648
  }), null);
1393
1649
  }
1394
- function De() {
1650
+ function Oe() {
1395
1651
  if (typeof document > "u") return;
1396
1652
  document.querySelectorAll("model-viewer").forEach((t) => {
1397
- Ie(t);
1653
+ Ue(t);
1398
1654
  });
1399
1655
  }
1400
- const Oe = /* @__PURE__ */ new WeakSet();
1401
- let wt = 0;
1402
- function Ie(n) {
1403
- if (!n || Oe.has(n))
1656
+ const Te = /* @__PURE__ */ new WeakSet();
1657
+ let kt = 0;
1658
+ function Ue(i) {
1659
+ if (!i || Te.has(i))
1404
1660
  return null;
1405
- Oe.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
1406
- `, n.getAttribute("src"));
1661
+ Te.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++kt + `
1662
+ `, i.getAttribute("src"));
1407
1663
  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]);
1664
+ for (let r = i; r != null; r = Object.getPrototypeOf(r)) {
1665
+ 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)");
1666
+ !t && o != null && (t = i[o].threeRenderer), !e && u != null && (e = i[u]), !s && a != null && (s = i[a]);
1411
1667
  }
1412
1668
  if (t && e) {
1413
1669
  let r = function() {
1414
1670
  if (s) {
1415
- let o = 0, l = setInterval(() => {
1671
+ let o = 0;
1672
+ const u = setInterval(() => {
1416
1673
  if (o++ > 5) {
1417
- clearInterval(l);
1674
+ clearInterval(u);
1418
1675
  return;
1419
1676
  }
1420
- s?.call(n);
1677
+ s?.call(i);
1421
1678
  }, 300);
1422
1679
  }
1423
1680
  };
1424
1681
  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", () => {
1682
+ const n = R.get(t, { engine: "model-viewer" });
1683
+ return R.addPlugin(new At()), n.enable(), n.addEventListener("changed", () => {
1684
+ s?.call(i);
1685
+ }), i.addEventListener("model-visibility", (o) => {
1686
+ o.detail.visible && s?.call(i);
1687
+ }), i.addEventListener("load", () => {
1431
1688
  r();
1432
1689
  }), () => {
1433
- i.disable();
1690
+ n.disable();
1434
1691
  };
1435
1692
  }
1436
1693
  return null;
1437
1694
  }
1438
- class _t {
1695
+ class At {
1439
1696
  _didWarnAboutMissingUrl = !1;
1440
1697
  onBeforeUpdateLOD(t, e, s, r) {
1441
1698
  this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
@@ -1455,99 +1712,102 @@ class _t {
1455
1712
  tryParseTextureLOD(t, e) {
1456
1713
  if (e[ie] == !0) return;
1457
1714
  e[ie] = !0;
1458
- const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
1459
- if (i && s && e.material) {
1715
+ const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), n = this.getUrl(r);
1716
+ if (n && s && e.material) {
1460
1717
  let o = function(a) {
1461
1718
  if (a[ie] == !0) return;
1462
1719
  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 " + _);
1720
+ const l = Object.keys(a);
1721
+ for (let c = 0; c < l.length; c++) {
1722
+ const d = l[c], g = a[d];
1723
+ if (g?.isTexture === !0) {
1724
+ const m = g.userData?.associations?.textures;
1725
+ if (m == null) continue;
1726
+ const x = s.parser.json.textures[m];
1727
+ if (!x) {
1728
+ console.warn("Texture data not found for texture index " + m);
1472
1729
  continue;
1473
1730
  }
1474
- if (k?.extensions?.[W]) {
1475
- const M = k.extensions[W];
1476
- M && i && m.registerTexture(i, w, M.lods.length, _, M);
1731
+ if (x?.extensions?.[F]) {
1732
+ const v = x.extensions[F];
1733
+ v && n && h.registerTexture(n, g, v.lods.length, m, v);
1477
1734
  }
1478
1735
  }
1479
1736
  }
1480
1737
  };
1481
- const l = e.material;
1482
- if (Array.isArray(l)) for (const a of l) o(a);
1483
- else o(l);
1738
+ const u = e.material;
1739
+ if (Array.isArray(u)) for (const a of u) o(a);
1740
+ else o(u);
1484
1741
  }
1485
1742
  }
1486
1743
  tryParseMeshLOD(t, e) {
1487
- if (e[Me] == !0) return;
1488
- e[Me] = !0;
1744
+ if (e[be] == !0) return;
1745
+ e[be] = !0;
1489
1746
  const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
1490
1747
  if (!r)
1491
1748
  return;
1492
- const i = e.userData?.gltfExtensions?.[W];
1493
- if (i && r) {
1749
+ const n = e.userData?.gltfExtensions?.[F];
1750
+ if (n && r) {
1494
1751
  const o = e.uuid;
1495
- m.registerMesh(r, o, e, 0, i.lods.length, i);
1752
+ h.registerMesh(r, o, e, 0, n.lods.length, n);
1496
1753
  }
1497
1754
  }
1498
1755
  }
1499
- function Lt(...n) {
1756
+ function Rt(...i) {
1500
1757
  let t, e, s, r;
1501
- switch (n.length) {
1758
+ switch (i.length) {
1502
1759
  case 2:
1503
- [s, e] = n, r = {};
1760
+ [s, e] = i, r = {};
1504
1761
  break;
1505
1762
  case 3:
1506
- [s, e, r] = n;
1763
+ [s, e, r] = i;
1507
1764
  break;
1508
1765
  case 4:
1509
- [t, e, s, r] = n;
1766
+ [t, e, s, r] = i;
1510
1767
  break;
1511
1768
  default:
1512
1769
  throw new Error("Invalid arguments");
1513
1770
  }
1514
- we(e), Te(s), Ae(s, {
1771
+ Le(e), Ae(s), Ie(s, {
1515
1772
  progressive: !0,
1516
1773
  ...r?.hints
1517
- }), s.register((o) => new m(o));
1518
- const i = v.get(e);
1519
- return r?.enableLODsManager !== !1 && i.enable(), i;
1774
+ }), s.register((o) => new h(o));
1775
+ const n = R.get(e);
1776
+ return r?.enableLODsManager !== !1 && n.enable(), n;
1520
1777
  }
1521
- Re();
1522
- if (!nt) {
1523
- const n = {
1778
+ We();
1779
+ if (!ct) {
1780
+ const i = {
1524
1781
  gltfProgressive: {
1525
- useNeedleProgressive: Lt,
1526
- LODsManager: v,
1527
- configureLoader: Ae,
1528
- getRaycastMesh: ee,
1529
- useRaycastMeshes: lt
1782
+ useNeedleProgressive: Rt,
1783
+ LODsManager: R,
1784
+ configureLoader: Ie,
1785
+ getRaycastMesh: ne,
1786
+ useRaycastMeshes: ft
1530
1787
  }
1531
1788
  };
1532
1789
  if (!globalThis.Needle)
1533
- globalThis.Needle = n;
1790
+ globalThis.Needle = i;
1534
1791
  else
1535
- for (const t in n)
1536
- globalThis.Needle[t] = n[t];
1792
+ for (const t in i)
1793
+ globalThis.Needle[t] = i[t];
1537
1794
  }
1538
1795
  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,
1545
- we as createLoaders,
1546
- 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
1796
+ F as EXTENSION_NAME,
1797
+ R as LODsManager,
1798
+ h as NEEDLE_progressive,
1799
+ Je as VERSION,
1800
+ Ae as addDracoAndKTX2Loaders,
1801
+ Tt as calculateMeshLODLevel,
1802
+ Ie as configureLoader,
1803
+ Le as createLoaders,
1804
+ Ct as getLODColor,
1805
+ ne as getRaycastMesh,
1806
+ Me as lodDebugColors,
1807
+ We as patchModelViewer,
1808
+ dt as registerRaycastMesh,
1809
+ st as setDracoDecoderLocation,
1810
+ rt as setKTX2TranscoderLocation,
1811
+ Rt as useNeedleProgressive,
1812
+ ft as useRaycastMeshes
1553
1813
  };