@needle-tools/gltf-progressive 3.6.0-alpha.2 → 3.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +42 -8
  3. package/examples/modelviewer-multiple.html +4 -4
  4. package/examples/modelviewer.html +4 -4
  5. package/examples/offscreen/index.html +15 -0
  6. package/examples/offscreen/main.js +98 -0
  7. package/examples/react-three-fiber/index.html +2 -2
  8. package/examples/react-three-fiber/package-lock.json +482 -484
  9. package/examples/react-three-fiber/package.json +4 -4
  10. package/examples/react-three-fiber/src/App.tsx +76 -21
  11. package/examples/react-three-fiber/src/styles.css +2 -4
  12. package/examples/react-three-fiber/vite.config.js +2 -2
  13. package/examples/shared/example-utils.js +297 -0
  14. package/examples/shared/example.css +44 -0
  15. package/examples/shared/runtime.js +34 -0
  16. package/examples/threejs/index.html +6 -10
  17. package/examples/threejs/main.js +5 -23
  18. package/examples/webgpu/index.html +15 -0
  19. package/examples/webgpu/main.js +105 -0
  20. package/examples/worker-rendering/index.html +15 -0
  21. package/examples/worker-rendering/main.js +109 -0
  22. package/examples/worker-rendering/worker.js +166 -0
  23. package/gltf-progressive.js +670 -559
  24. package/gltf-progressive.min.js +9 -9
  25. package/gltf-progressive.umd.cjs +9 -9
  26. package/lib/extension.d.ts +6 -0
  27. package/lib/extension.js +85 -16
  28. package/lib/loaders.d.ts +1 -8
  29. package/lib/loaders.js +15 -2
  30. package/lib/lods.debug.js +1 -1
  31. package/lib/lods.manager.d.ts +3 -0
  32. package/lib/lods.manager.js +62 -18
  33. package/lib/utils.d.ts +1 -1
  34. package/lib/utils.internal.d.ts +27 -0
  35. package/lib/utils.internal.js +68 -25
  36. package/lib/version.js +1 -1
  37. package/lib/worker/loader.mainthread.js +6 -4
  38. package/package.json +8 -3
@@ -1,69 +1,99 @@
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;
1
+ import * as Xe from "three";
2
+ import { RedFormat as je, RedIntegerFormat as Ke, RGFormat as Ye, RGIntegerFormat as He, RGBFormat as Qe, RGBAFormat as Je, RGBAIntegerFormat as Ze, BufferGeometry as j, Mesh as K, Box3 as ue, Vector3 as k, Sphere as Ae, CompressedTexture as et, Texture as q, Matrix3 as tt, InterleavedBuffer as st, InterleavedBufferAttribute as rt, BufferAttribute as nt, TextureLoader as it, Color as Ie, Matrix4 as $e } from "three";
3
+ import { GLTFLoader as De } from "three/examples/jsm/loaders/GLTFLoader.js";
4
+ import { MeshoptDecoder as ot } from "three/examples/jsm/libs/meshopt_decoder.module.js";
5
+ import { DRACOLoader as at } from "three/examples/jsm/loaders/DRACOLoader.js";
6
+ import { KTX2Loader as lt } from "three/examples/jsm/loaders/KTX2Loader.js";
7
+ const ut = "";
8
+ globalThis.GLTF_PROGRESSIVE_VERSION = ut;
8
9
  console.debug("[gltf-progressive] version -");
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, {
10
+ let $ = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", Y = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
11
+ const ct = $, ft = Y, Be = new URL($ + "draco_decoder.js");
12
+ Be.searchParams.append("range", "true");
13
+ fetch(Be, {
13
14
  method: "GET",
14
15
  headers: {
15
16
  Range: "bytes=0-1"
16
17
  }
17
18
  }).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
+ console.debug(`Failed to fetch remote Draco decoder from ${$} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), $ === ct && ht("./include/draco/"), Y === ft && gt("./include/ktx2/");
19
20
  }).finally(() => {
20
- Re();
21
+ qe();
21
22
  });
22
- const tt = () => ({
23
- dracoDecoderPath: I,
23
+ const dt = () => ({
24
+ dracoDecoderPath: $,
24
25
  ktx2TranscoderPath: Y
25
26
  });
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);
27
+ function ht(i) {
28
+ $ = i, C && C[ye] != $ ? (console.debug("Updating Draco decoder path to " + i), C[ye] = $, C.setDecoderPath($), C.preload()) : console.debug("Setting Draco decoder path to " + i);
28
29
  }
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);
30
+ function gt(i) {
31
+ Y = i, B && B.transcoderPath != Y ? (console.debug("Updating KTX2 transcoder path to " + i), B.setTranscoderPath(Y), B.init()) : console.debug("Setting KTX2 transcoder path to " + i);
31
32
  }
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 };
33
+ function _e(i) {
34
+ return qe(), i ? B.detectSupport(i) : i !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: B, meshoptDecoder: le };
34
35
  }
35
- function Ae(i) {
36
- i.dracoLoader || i.setDRACOLoader(P), i.ktx2Loader || i.setKTX2Loader($), i.meshoptDecoder || i.setMeshoptDecoder(ae);
36
+ function Ge(i) {
37
+ i.dracoLoader || i.setDRACOLoader(C), i.ktx2Loader || i.setKTX2Loader(B), i.meshoptDecoder || i.setMeshoptDecoder(le);
37
38
  }
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);
39
+ const ye = /* @__PURE__ */ Symbol("dracoDecoderPath");
40
+ let C, le, B;
41
+ function qe() {
42
+ C || (C = new at(), C[ye] = $, C.setDecoderPath($), C.setDecoderConfig({ type: "js" }), C.preload()), B || (B = new lt(), B.setTranscoderPath(Y), B.init()), le || (le = ot);
42
43
  }
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);
44
+ const xe = /* @__PURE__ */ new WeakMap();
45
+ function We(i, t) {
46
+ let e = xe.get(i);
47
+ e ? e = Object.assign(e, t) : e = t, xe.set(i, e);
47
48
  }
48
- const nt = we.prototype.load;
49
- function ot(...i) {
50
- const t = ye.get(this);
49
+ const pt = De.prototype.load;
50
+ function mt(...i) {
51
+ const t = xe.get(this);
51
52
  let e = i[0];
52
- const s = new URL(e, window.location.href);
53
- if (s.hostname.endsWith("needle.tools")) {
53
+ const s = yt(e);
54
+ if (s?.hostname.endsWith("needle.tools")) {
54
55
  const n = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
55
56
  n ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
56
57
  }
57
- return i[0] = e, nt?.call(this, ...i);
58
+ return i[0] = e, pt?.call(this, ...i);
59
+ }
60
+ De.prototype.load = mt;
61
+ function yt(i) {
62
+ try {
63
+ if (i instanceof URL)
64
+ return i;
65
+ const t = globalThis.location?.href;
66
+ return t ? new URL(i, t) : new URL(i);
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+ function Te(i) {
72
+ return i != null && i.data != null;
58
73
  }
59
- we.prototype.load = ot;
60
- N("debugprogressive");
61
- function N(i) {
62
- if (typeof window > "u") return !1;
63
- const e = new URL(window.location.href).searchParams.get(i);
64
- return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
74
+ function Le(i) {
75
+ const t = i.source?.data;
76
+ return t != null && typeof t == "object" ? t : null;
65
77
  }
66
- function it(i, t) {
78
+ function xt(i) {
79
+ const t = i.image;
80
+ return t != null && typeof t == "object" ? t : null;
81
+ }
82
+ function we(i) {
83
+ const t = xt(i), e = Le(i);
84
+ return {
85
+ width: t?.width || e?.width || 0,
86
+ height: t?.height || e?.height || 0
87
+ };
88
+ }
89
+ V("debugprogressive");
90
+ function V(i) {
91
+ const t = globalThis.location?.href;
92
+ if (!t) return !1;
93
+ const s = new URL(t).searchParams.get(i);
94
+ return s == null || s === "0" || s === "false" ? !1 : s === "" ? !0 : s;
95
+ }
96
+ function Lt(i, t) {
67
97
  if (t === void 0 || i === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
68
98
  return t;
69
99
  const e = i.lastIndexOf("/");
@@ -74,18 +104,21 @@ function it(i, t) {
74
104
  }
75
105
  return t;
76
106
  }
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;
107
+ function Me() {
108
+ if (Z !== void 0) return Z;
109
+ const i = globalThis.navigator?.userAgent || "";
110
+ return Z = /iPhone|iPad|iPod|Android|IEMobile/i.test(i), V("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", Z), Z;
79
111
  }
80
112
  let Z;
81
- function $e() {
82
- if (typeof window > "u") return !1;
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;
113
+ function Fe() {
114
+ const i = globalThis.location?.href;
115
+ if (!i) return !1;
116
+ const t = new URL(i), e = t.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);
117
+ return t.hostname === "127.0.0.1" || e;
85
118
  }
86
- class at {
119
+ class wt {
87
120
  constructor(t, e = {}) {
88
- this.maxConcurrent = t, this.debug = e.debug ?? !1, typeof window < "u" && window.requestAnimationFrame(this.tick);
121
+ this.maxConcurrent = t, this.debug = e.debug ?? !1, typeof globalThis.requestAnimationFrame == "function" ? globalThis.requestAnimationFrame(this.tick) : setTimeout(this.tick, 0);
89
122
  }
90
123
  _running = /* @__PURE__ */ new Map();
91
124
  _queue = [];
@@ -117,29 +150,29 @@ class at {
117
150
  }
118
151
  }
119
152
  }
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);
153
+ function vt(i) {
154
+ const t = i.image, e = t?.width ?? 0, s = t?.height ?? 0, r = t?.depth ?? 1, n = Math.floor(Math.log2(Math.max(e, s, r))) + 1, o = Dt(i);
155
+ return e * s * r * o * (1 - Math.pow(0.25, n)) / (1 - 0.25);
123
156
  }
124
- function ut(i) {
157
+ function Dt(i) {
125
158
  let t = 4;
126
159
  const e = i.format;
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);
160
+ e === je || e === Ke ? t = 1 : e === Ye || e === He ? t = 2 : e === Qe || e === 1029 ? t = 3 : (e === Je || e === Ze) && (t = 4);
128
161
  let s = 1;
129
162
  const r = i.type;
130
163
  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
164
  }
132
- const ct = typeof window > "u" && typeof document > "u", xe = /* @__PURE__ */ Symbol("needle:raycast-mesh");
165
+ const _t = typeof window > "u" && typeof document > "u", ve = /* @__PURE__ */ Symbol("needle:raycast-mesh");
133
166
  function ne(i) {
134
- return i?.[xe] instanceof j ? i[xe] : null;
167
+ return i?.[ve] instanceof j ? i[ve] : null;
135
168
  }
136
- function dt(i, t) {
169
+ function Mt(i, t) {
137
170
  if ((i.type === "Mesh" || i.type === "SkinnedMesh") && !ne(i)) {
138
- const s = ht(t);
139
- s.userData = { isRaycastMesh: !0 }, i[xe] = s;
171
+ const s = Tt(t);
172
+ s.userData = { isRaycastMesh: !0 }, i[ve] = s;
140
173
  }
141
174
  }
142
- function ft(i = !0) {
175
+ function bt(i = !0) {
143
176
  if (i) {
144
177
  if (ee) return;
145
178
  const t = ee = K.prototype.raycast;
@@ -154,15 +187,15 @@ function ft(i = !0) {
154
187
  }
155
188
  }
156
189
  let ee = null;
157
- function ht(i) {
190
+ function Tt(i) {
158
191
  const t = new j();
159
192
  for (const e in i.attributes)
160
193
  t.setAttribute(e, i.getAttribute(e));
161
194
  return t.setIndex(i.getIndex()), t;
162
195
  }
163
- const E = new Array(), f = N("debugprogressive");
196
+ const F = new Array(), h = V("debugprogressive");
164
197
  let re, X = -1;
165
- if (f) {
198
+ if (h && typeof window < "u") {
166
199
  let i = function() {
167
200
  X += 1, X >= t && (X = -1), console.log(`Toggle LOD level [${X}]`);
168
201
  };
@@ -173,27 +206,27 @@ if (f) {
173
206
  !isNaN(s) && s >= 0 && (X = s, console.log(`Set LOD level to [${X}]`));
174
207
  });
175
208
  }
176
- function Be(i) {
177
- if (f && re !== void 0)
209
+ function Ue(i) {
210
+ if (h && re !== void 0)
178
211
  if (Array.isArray(i))
179
212
  for (const t of i)
180
- Be(t);
213
+ Ue(t);
181
214
  else i && "wireframe" in i && (i.wireframe = re === !0);
182
215
  }
183
216
  const te = new Array();
184
- let gt = 0;
185
- const pt = ve() ? 2 : 10;
186
- function mt(i) {
187
- if (te.length < pt) {
217
+ let Ot = 0;
218
+ const St = Me() ? 2 : 10;
219
+ function Rt(i) {
220
+ if (te.length < St) {
188
221
  const s = te.length;
189
- f && console.warn(`[Worker] Creating new worker #${s}`);
190
- const r = _e.createWorker(i || {});
222
+ h && console.warn(`[Worker] Creating new worker #${s}`);
223
+ const r = be.createWorker(i || {});
191
224
  return te.push(r), r;
192
225
  }
193
- const t = gt++ % te.length;
226
+ const t = Ot++ % te.length;
194
227
  return te[t];
195
228
  }
196
- class _e {
229
+ class be {
197
230
  constructor(t, e) {
198
231
  this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
199
232
  const r = s.data;
@@ -201,7 +234,7 @@ class _e {
201
234
  case "loaded-gltf":
202
235
  for (const n of this._running)
203
236
  if (n.url === r.result.url) {
204
- yt(r.result), n.resolve(r.result);
237
+ Ct(r.result), n.resolve(r.result);
205
238
  const o = n.url;
206
239
  o.startsWith("blob:") && URL.revokeObjectURL(o);
207
240
  }
@@ -220,52 +253,59 @@ class _e {
220
253
  ), {
221
254
  type: "module"
222
255
  });
223
- return new _e(e, t);
256
+ return new be(e, t);
224
257
  }
225
258
  _running = [];
226
259
  _webglRenderer = null;
227
260
  async load(t, e) {
228
- const s = tt();
261
+ const s = dt();
229
262
  let r = e?.renderer;
230
263
  r || (this._webglRenderer ??= (async () => {
231
- const { WebGLRenderer: l } = await import("three");
232
- return new l();
264
+ const { WebGLRenderer: u } = await import("three");
265
+ return new u();
233
266
  })(), r = await this._webglRenderer);
234
- const u = Le(r).ktx2Loader.workerConfig;
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());
236
- const a = {
267
+ const a = _e(r).ktx2Loader.workerConfig;
268
+ if (t instanceof URL)
269
+ t = t.toString();
270
+ else if (t.startsWith("file:"))
271
+ t = URL.createObjectURL(new Blob([t]));
272
+ else if (!t.startsWith("blob:") && !t.startsWith("http:") && !t.startsWith("https:")) {
273
+ const u = globalThis.location?.href;
274
+ u && (t = new URL(t, u).toString());
275
+ }
276
+ const l = {
237
277
  type: "load",
238
278
  url: t,
239
279
  dracoDecoderPath: s.dracoDecoderPath,
240
280
  ktx2TranscoderPath: s.ktx2TranscoderPath,
241
- ktx2LoaderConfig: u
281
+ ktx2LoaderConfig: a
242
282
  };
243
- return this._debug && console.debug("[Worker] Sending load request", a), this.worker.postMessage(a), new Promise((l) => {
283
+ return this._debug && console.debug("[Worker] Sending load request", l), this.worker.postMessage(l), new Promise((u) => {
244
284
  this._running.push({
245
285
  url: t.toString(),
246
- resolve: l
286
+ resolve: u
247
287
  });
248
288
  });
249
289
  }
250
290
  _debug = !1;
251
291
  }
252
- function yt(i) {
292
+ function Ct(i) {
253
293
  for (const t of i.geometries) {
254
294
  const e = t.geometry, s = new j();
255
295
  if (s.name = e.name || "", e.index) {
256
296
  const r = e.index;
257
- s.setIndex(ce(r));
297
+ s.setIndex(fe(r));
258
298
  }
259
299
  for (const r in e.attributes) {
260
- const n = e.attributes[r], o = ce(n);
300
+ const n = e.attributes[r], o = fe(n);
261
301
  s.setAttribute(r, o);
262
302
  }
263
303
  if (e.morphAttributes)
264
304
  for (const r in e.morphAttributes) {
265
- const o = e.morphAttributes[r].map((u) => ce(u));
305
+ const o = e.morphAttributes[r].map((a) => fe(a));
266
306
  s.morphAttributes[r] = o;
267
307
  }
268
- if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new le(), s.boundingBox.min = new k(
308
+ if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ue(), s.boundingBox.min = new k(
269
309
  e.boundingBox?.min.x,
270
310
  e.boundingBox?.min.y,
271
311
  e.boundingBox?.min.z
@@ -273,7 +313,7 @@ function yt(i) {
273
313
  e.boundingBox?.max.x,
274
314
  e.boundingBox?.max.y,
275
315
  e.boundingBox?.max.z
276
- ), s.boundingSphere = new Se(
316
+ ), s.boundingSphere = new Ae(
277
317
  new k(
278
318
  e.boundingSphere?.center.x,
279
319
  e.boundingSphere?.center.y,
@@ -289,8 +329,8 @@ function yt(i) {
289
329
  const e = t.texture;
290
330
  let s = null;
291
331
  if (e.isCompressedTexture) {
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(
332
+ const r = e.mipmaps, { width: n, height: o } = we(e);
333
+ s = new et(
294
334
  r,
295
335
  n,
296
336
  o,
@@ -305,7 +345,7 @@ function yt(i) {
305
345
  e.colorSpace
306
346
  );
307
347
  } else
308
- s = new G(
348
+ s = new q(
309
349
  e.image,
310
350
  e.mapping,
311
351
  e.wrapS,
@@ -316,7 +356,7 @@ function yt(i) {
316
356
  e.type,
317
357
  e.anisotropy,
318
358
  e.colorSpace
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);
359
+ ), 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 tt(...e.matrix.elements);
320
360
  if (!s) {
321
361
  console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");
322
362
  continue;
@@ -325,21 +365,21 @@ function yt(i) {
325
365
  }
326
366
  return i;
327
367
  }
328
- function ce(i) {
368
+ function fe(i) {
329
369
  let t = i;
330
370
  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);
371
+ const e = i.data, s = e.array, r = new st(s, e.stride);
372
+ t = new rt(r, i.itemSize, s.byteOffset, i.normalized), t.offset = i.offset;
373
+ } else "isBufferAttribute" in i && i.isBufferAttribute && (t = new nt(i.array, i.itemSize, i.normalized), t.usage = i.usage, t.gpuType = i.gpuType, t.updateRanges = i.updateRanges);
334
374
  return t;
335
375
  }
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 {
376
+ const Pt = V("gltf-progressive-worker");
377
+ V("gltf-progressive-reduce-mipmaps");
378
+ const se = V("gltf-progressive-gc"), de = /* @__PURE__ */ Symbol("needle-progressive-texture"), U = "NEEDLE_progressive";
379
+ class g {
340
380
  /** The name of the extension */
341
381
  get name() {
342
- return F;
382
+ return U;
343
383
  }
344
384
  // #region PUBLIC API
345
385
  /**
@@ -381,33 +421,33 @@ class h {
381
421
  max_count: 0,
382
422
  lods: []
383
423
  }), Array.isArray(t)) {
384
- for (const u of t)
385
- this.getMaterialMinMaxLODsCount(u, e);
424
+ for (const a of t)
425
+ this.getMaterialMinMaxLODsCount(a, e);
386
426
  return t[r] = e, e;
387
427
  }
388
- if (f === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
389
- const u = t;
390
- for (const a of Object.keys(u.uniforms)) {
391
- const l = u.uniforms[a].value;
392
- l?.isTexture === !0 && o(l, e);
428
+ if (h === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
429
+ const a = t;
430
+ for (const l of Object.keys(a.uniforms)) {
431
+ const u = a.uniforms[l].value;
432
+ u?.isTexture === !0 && o(u, e);
393
433
  }
394
434
  } else if (t.isMaterial)
395
- for (const u of Object.keys(t)) {
396
- const a = t[u];
397
- a?.isTexture === !0 && o(a, e);
435
+ for (const a of Object.keys(t)) {
436
+ const l = t[a];
437
+ l?.isTexture === !0 && o(l, e);
398
438
  }
399
439
  else
400
- f && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
440
+ h && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
401
441
  return t[r] = e, e;
402
- function o(u, a) {
403
- const l = s.getAssignedLODInformation(u);
404
- if (l) {
405
- const c = s.lodInfos.get(l.key);
406
- if (c && c.lods) {
407
- a.min_count = Math.min(a.min_count, c.lods.length), a.max_count = Math.max(a.max_count, c.lods.length);
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));
442
+ function o(a, l) {
443
+ const u = s.getAssignedLODInformation(a);
444
+ if (u) {
445
+ const f = s.lodInfos.get(u.key);
446
+ if (f && f.lods) {
447
+ l.min_count = Math.min(l.min_count, f.lods.length), l.max_count = Math.max(l.max_count, f.lods.length);
448
+ for (let c = 0; c < f.lods.length; c++) {
449
+ const d = f.lods[c];
450
+ d.width && (l.lods[c] = l.lods[c] || { min_height: 1 / 0, max_height: 0 }, l.lods[c].min_height = Math.min(l.lods[c].min_height, d.height), l.lods[c].max_height = Math.max(l.lods[c].max_height, d.height));
411
451
  }
412
452
  }
413
453
  }
@@ -465,16 +505,21 @@ class h {
465
505
  const r = t.geometry, n = this.getAssignedLODInformation(r);
466
506
  if (!n)
467
507
  return Promise.resolve(null);
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)) {
508
+ for (const a of F)
509
+ a.onBeforeGetLODMesh?.(t, e);
510
+ t["LOD:requested level"] = e;
511
+ const o = () => t["LOD:requested level"] === e || this.shouldApplyStaleMeshLOD(t, e);
512
+ return g.getOrLoadLOD(r, e, {
513
+ isCurrent: o
514
+ }).then((a) => {
515
+ if (Array.isArray(a)) {
472
516
  const u = n.index || 0;
473
- o = o[u];
517
+ a = a[u];
474
518
  }
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));
477
- } else f && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
519
+ const l = t["LOD:requested level"] === e;
520
+ return (l || this.shouldApplyStaleMeshLOD(t, e)) && (l && delete t["LOD:requested level"], a && r != a && (a?.isBufferGeometry ? typeof s?.apply == "function" ? s.apply(a, e, t) : s?.apply !== !1 && (t.geometry = a) : h && console.error("Invalid LOD geometry", a))), a;
521
+ }).catch((a) => (console.error("Error loading mesh LOD", t, a), null));
522
+ } else h && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
478
523
  return Promise.resolve(null);
479
524
  }
480
525
  static assignTextureLOD(t, e = 0, s) {
@@ -484,48 +529,48 @@ class h {
484
529
  const n = t;
485
530
  if (Array.isArray(n.material)) {
486
531
  const o = new Array();
487
- for (const u of n.material) {
488
- const a = this.assignTextureLOD(u, e, s);
489
- o.push(a);
532
+ for (const a of n.material) {
533
+ const l = this.assignTextureLOD(a, e, s);
534
+ o.push(l);
490
535
  }
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;
536
+ return Promise.all(o).then((a) => {
537
+ const l = new Array();
538
+ for (const u of a)
539
+ Array.isArray(u) && l.push(...u);
540
+ return l;
496
541
  });
497
542
  } else
498
543
  return this.assignTextureLOD(n.material, e, s);
499
544
  }
500
545
  if (t.isMaterial === !0) {
501
- const n = t, o = [], u = new Array();
546
+ const n = t, o = [], a = new Array();
502
547
  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);
548
+ const l = n;
549
+ for (const u of Object.keys(l.uniforms)) {
550
+ const f = l.uniforms[u].value;
551
+ if (f?.isTexture === !0) {
552
+ const c = this.assignTextureLODForSlot(f, e, n, u, r).then((d) => (d && l.uniforms[u].value != d && (l.uniforms[u].value = d, l.uniformsNeedUpdate = !0), d));
553
+ o.push(c), a.push(u);
509
554
  }
510
555
  }
511
556
  } else
512
- for (const a of Object.keys(n)) {
513
- const l = n[a];
514
- if (l?.isTexture === !0) {
515
- const c = this.assignTextureLODForSlot(l, e, n, a, r);
516
- o.push(c), u.push(a);
557
+ for (const l of Object.keys(n)) {
558
+ const u = n[l];
559
+ if (u?.isTexture === !0) {
560
+ const f = this.assignTextureLODForSlot(u, e, n, l, r);
561
+ o.push(f), a.push(l);
517
562
  }
518
563
  }
519
- return Promise.all(o).then((a) => {
520
- const l = new Array();
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 });
564
+ return Promise.all(o).then((l) => {
565
+ const u = new Array();
566
+ for (let f = 0; f < l.length; f++) {
567
+ const c = l[f], d = a[f];
568
+ c && c.isTexture === !0 ? u.push({ material: n, slot: d, texture: c, level: e }) : u.push({ material: n, slot: d, texture: null, level: e });
524
569
  }
525
- return l;
570
+ return u;
526
571
  });
527
572
  }
528
- if (t instanceof G || t.isTexture === !0) {
573
+ if (t instanceof q || t.isTexture === !0) {
529
574
  const n = t;
530
575
  return this.assignTextureLODForSlot(n, e, null, null, r);
531
576
  }
@@ -536,10 +581,10 @@ class h {
536
581
  * @default 50 on desktop, 20 on mobile devices
537
582
  */
538
583
  static set maxConcurrentLoadingTasks(t) {
539
- h.queue.maxConcurrent = t;
584
+ g.queue.maxConcurrent = t;
540
585
  }
541
586
  static get maxConcurrentLoadingTasks() {
542
- return h.queue.maxConcurrent;
587
+ return g.queue.maxConcurrent;
543
588
  }
544
589
  // #region INTERNAL
545
590
  static assignTextureLODForSlot(t, e, s, r, n) {
@@ -551,33 +596,38 @@ class h {
551
596
  if (o && (o.level === e || !n && o.level < e))
552
597
  return Promise.resolve(t);
553
598
  if (s && r) {
554
- const a = this.getPendingTextureSlotRequest(s, r);
555
- if (a && a.level === e && a.force === n)
556
- return a.promise;
599
+ const c = this.getPendingTextureSlotRequest(s, r);
600
+ if (c && c.level === e && c.force === n)
601
+ return c.promise;
557
602
  }
558
- const u = h.getOrLoadLOD(t, e).then((a) => {
559
- if (Array.isArray(a))
603
+ const a = s && r ? this.nextTextureSlotRequestId(s, r, e, n) : 0, l = () => !s || !r || this.getLatestTextureSlotRequest(s, r)?.id === a, u = () => l() || this.shouldApplyStaleTextureSlotLOD(s, r, e, n), f = g.getOrLoadLOD(t, e, {
604
+ isCurrent: u
605
+ }).then((c) => {
606
+ if (!l() && !this.shouldApplyStaleTextureSlotLOD(s, r, e, n)) return null;
607
+ if (Array.isArray(c))
560
608
  return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), 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;
609
+ if (c?.isTexture === !0) {
610
+ if (c != t && s && r) {
611
+ const d = this.getMaterialTextureSlot(s, r) ?? t;
612
+ if (d && !n) {
613
+ const p = this.getAssignedLODInformation(d);
614
+ if (p && p?.level < e)
615
+ return h === "verbose" && console.warn("Assigned texture level is already higher: ", p.level, e, s, d, c), null;
568
616
  }
569
- this.assignTrackedTextureSlot(s, r, a);
617
+ this.assignTrackedTextureSlot(s, r, c);
570
618
  }
571
- return a;
572
- } else f == "verbose" && console.warn("No LOD found for", t, e);
619
+ return c;
620
+ } else h == "verbose" && console.warn("No LOD found for", t, e);
573
621
  return null;
574
- }).catch((a) => (console.error("Error loading LOD", t, a), null));
575
- return s && r && this.setPendingTextureSlotRequest(s, r, e, n, u), u;
622
+ }).catch((c) => (console.error("Error loading LOD", t, c), null));
623
+ return s && r && this.setPendingTextureSlotRequest(s, r, e, n, a, f), f;
576
624
  }
577
625
  // Track material slots, not just texture objects. A shared fallback texture can be
578
626
  // referenced by many slots and should only be disposed after every slot moved away.
579
627
  static trackedTextureSlots = /* @__PURE__ */ new WeakMap();
580
628
  static pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
629
+ static latestTextureSlotRequests = /* @__PURE__ */ new WeakMap();
630
+ static textureSlotRequestId = 0;
581
631
  static trackCurrentMaterialTextureSlots(t) {
582
632
  if (t.uniforms && (t.isRawShaderMaterial || t.isShaderMaterial === !0)) {
583
633
  const e = t;
@@ -595,12 +645,32 @@ class h {
595
645
  static getPendingTextureSlotRequest(t, e) {
596
646
  return this.pendingTextureSlotRequests.get(t)?.get(e);
597
647
  }
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);
648
+ static nextTextureSlotRequestId(t, e, s, r) {
649
+ let n = this.latestTextureSlotRequests.get(t);
650
+ n || (n = /* @__PURE__ */ new Map(), this.latestTextureSlotRequests.set(t, n));
651
+ const o = ++this.textureSlotRequestId;
652
+ return n.set(e, { id: o, level: s, force: r }), o;
653
+ }
654
+ static getLatestTextureSlotRequest(t, e) {
655
+ return this.latestTextureSlotRequests.get(t)?.get(e);
656
+ }
657
+ static shouldApplyStaleTextureSlotLOD(t, e, s, r) {
658
+ if (!t || !e) return !1;
659
+ const n = this.getLatestTextureSlotRequest(t, e), o = this.getMaterialTextureSlot(t, e), a = this.getAssignedLODInformation(o)?.level ?? 1 / 0;
660
+ return s >= a ? !1 : r ? n ? s >= n.level : !1 : !0;
661
+ }
662
+ static shouldApplyStaleMeshLOD(t, e) {
663
+ const s = t["LOD:requested level"];
664
+ if (typeof s != "number") return !1;
665
+ const r = this.getAssignedLODInformation(t.geometry)?.level ?? 1 / 0;
666
+ return e < r && e >= s;
667
+ }
668
+ static setPendingTextureSlotRequest(t, e, s, r, n, o) {
669
+ let a = this.pendingTextureSlotRequests.get(t);
670
+ a || (a = /* @__PURE__ */ new Map(), this.pendingTextureSlotRequests.set(t, a));
671
+ const l = { level: s, force: r, id: n, promise: o };
672
+ a.set(e, l), o.finally(() => {
673
+ a.get(e)?.id === n && a.delete(e);
604
674
  });
605
675
  }
606
676
  static getMaterialTextureSlot(t, e) {
@@ -633,7 +703,7 @@ class h {
633
703
  }
634
704
  static releaseTrackedTextureSlot(t, e, s) {
635
705
  const r = this.trackedTextureSlots.get(t);
636
- if (r?.get(e) === s && r.delete(e), this.untrackTextureUsage(s) && (f || se)) {
706
+ if (r?.get(e) === s && r.delete(e), this.untrackTextureUsage(s) && (h || se)) {
637
707
  const o = this.getAssignedLODInformation(s);
638
708
  console.log(`[gltf-progressive] Disposed old texture LOD ${o?.level ?? "?"} for ${t.name || t.type}.${e}`, s.uuid);
639
709
  }
@@ -642,13 +712,13 @@ class h {
642
712
  url;
643
713
  constructor(t) {
644
714
  const e = t.options.path;
645
- f && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
715
+ h && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
646
716
  }
647
717
  _isLoadingMesh;
648
718
  loadMesh = (t) => {
649
719
  if (this._isLoadingMesh) return 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;
720
+ const e = this.parser.json.meshes[t]?.extensions?.[U];
721
+ return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && g.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
652
722
  };
653
723
  // private _isLoadingTexture;
654
724
  // loadTexture = (textureIndex: number) => {
@@ -665,30 +735,30 @@ class h {
665
735
  // });
666
736
  // }
667
737
  afterRoot(t) {
668
- return f && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
738
+ return h && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
669
739
  if (e?.extensions) {
670
- const r = e?.extensions[F];
740
+ const r = e?.extensions[U];
671
741
  if (r) {
672
742
  if (!r.lods) {
673
- f && console.warn("Texture has no LODs", r);
743
+ h && console.warn("Texture has no LODs", r);
674
744
  return;
675
745
  }
676
746
  let n = !1;
677
747
  for (const o of this.parser.associations.keys())
678
- o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (n = !0, h.registerTexture(this.url, o, r.lods?.length, s, r));
748
+ o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (n = !0, g.registerTexture(this.url, o, r.lods?.length, s, r));
679
749
  n || this.parser.getDependency("texture", s).then((o) => {
680
- o && h.registerTexture(this.url, o, r.lods?.length, s, r);
750
+ o && g.registerTexture(this.url, o, r.lods?.length, s, r);
681
751
  });
682
752
  }
683
753
  }
684
754
  }), this.parser.json.meshes?.forEach((e, s) => {
685
755
  if (e?.extensions) {
686
- const r = e?.extensions[F];
756
+ const r = e?.extensions[U];
687
757
  if (r && r.lods) {
688
758
  for (const n of this.parser.associations.keys())
689
759
  if (n.isMesh) {
690
760
  const o = this.parser.associations.get(n);
691
- o?.meshes === s && h.registerMesh(this.url, r.guid, n, r.lods.length, o.primitives, r);
761
+ o?.meshes === s && g.registerMesh(this.url, r.guid, n, r.lods.length, o.primitives, r);
692
762
  }
693
763
  }
694
764
  }
@@ -707,16 +777,16 @@ class h {
707
777
  */
708
778
  static registerTexture = (t, e, s, r, n) => {
709
779
  if (!e) {
710
- f && console.error("!! gltf-progressive: Called register texture without texture");
780
+ h && console.error("!! gltf-progressive: Called register texture without texture");
711
781
  return;
712
782
  }
713
- if (f) {
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);
783
+ if (h) {
784
+ const { width: a, height: l } = we(e);
785
+ console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${a}x${l}, Max: ${n.lods[0]?.width}x${n.lods[0]?.height}, uuid: ${e.uuid}`, n, e);
716
786
  }
717
787
  e.source && (e.source[de] = n);
718
788
  const o = n.guid;
719
- h.assignLODInformation(t, e, o, s, r), h.lodInfos.set(o, n), h.lowresCache.set(o, new WeakRef(e));
789
+ g.assignLODInformation(t, e, o, s, r), g.lodInfos.set(o, n), g.lowresCache.set(o, new WeakRef(e));
720
790
  };
721
791
  /**
722
792
  * Register a mesh with progressive LOD information. This associates the mesh geometry with its LOD extension data
@@ -732,16 +802,16 @@ class h {
732
802
  * @param ext - The parsed progressive mesh extension data containing all available LOD levels with vertex/index counts and densities.
733
803
  */
734
804
  static registerMesh = (t, e, s, r, n, o) => {
735
- const u = s.geometry;
736
- if (!u) {
737
- f && console.warn("gltf-progressive: Register mesh without geometry");
805
+ const a = s.geometry;
806
+ if (!a) {
807
+ h && console.warn("gltf-progressive: Register mesh without geometry");
738
808
  return;
739
809
  }
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)
744
- c.onRegisteredNewMesh?.(s, o);
810
+ a.userData || (a.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: n, uuid: s.uuid }, o, s), g.assignLODInformation(t, a, e, r, n), g.lodInfos.set(e, o);
811
+ let u = g.lowresCache.get(e)?.deref();
812
+ u ? u.push(s.geometry) : u = [s.geometry], g.lowresCache.set(e, new WeakRef(u)), r > 0 && !ne(s) && Mt(s, a);
813
+ for (const f of F)
814
+ f.onRegisteredNewMesh?.(s, o);
745
815
  };
746
816
  /**
747
817
  * Dispose cached resources to free memory.
@@ -782,7 +852,7 @@ class h {
782
852
  this.lowresCache.clear();
783
853
  for (const [, e] of this.cache)
784
854
  this._disposeCacheEntry(e);
785
- this.cache.clear(), this.textureRefCounts.clear(), this.trackedTextureSlots = /* @__PURE__ */ new WeakMap(), this.pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
855
+ this.cache.clear(), this.textureRefCounts.clear(), this.trackedTextureSlots = /* @__PURE__ */ new WeakMap(), this.pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap(), this.latestTextureSlotRequests = /* @__PURE__ */ new WeakMap(), this.textureSlotRequestId = 0;
786
856
  }
787
857
  }
788
858
  /** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
@@ -814,16 +884,16 @@ class h {
814
884
  * The held value is the cache key string used in `previouslyLoaded`.
815
885
  */
816
886
  static _resourceRegistry = new FinalizationRegistry((t) => {
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)")));
887
+ const e = g.cache.get(t);
888
+ (h || se) && console.debug(`[gltf-progressive] Memory: Resource GC'd
889
+ ${t}`), e instanceof WeakRef && (e.deref() || (g.cache.delete(t), (h || se) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
820
890
  });
821
891
  /**
822
892
  * Track texture usage by incrementing reference count
823
893
  */
824
894
  static trackTextureUsage(t) {
825
895
  const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
826
- this.textureRefCounts.set(e, s + 1), f === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
896
+ this.textureRefCounts.set(e, s + 1), h === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
827
897
  }
828
898
  /**
829
899
  * Untrack texture usage by decrementing reference count.
@@ -833,147 +903,155 @@ ${t}`), e instanceof WeakRef && (e.deref() || (h.cache.delete(t), (f || se) && c
833
903
  static untrackTextureUsage(t) {
834
904
  const e = t.uuid, s = this.textureRefCounts.get(e);
835
905
  if (!s)
836
- return (f === "verbose" || se) && n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
906
+ return (h === "verbose" || se) && n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
837
907
  const r = s - 1;
838
908
  if (r <= 0)
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}
909
+ return this.textureRefCounts.delete(e), (h || se) && n("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
910
+ return this.textureRefCounts.set(e, r), h === "verbose" && n("[gltf-progressive] Memory: Untrack texture", r), !1;
911
+ function n(o, a) {
912
+ let { width: l, height: u } = we(t);
913
+ const f = l && u ? `${l}x${u}` : "N/A";
914
+ let c = "N/A";
915
+ l && u && (c = `~${(vt(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${f} (${c}), refCount: ${s} → ${a}
845
916
  ${e}`);
846
917
  }
847
918
  }
848
919
  static workers = [];
849
920
  static _workersIndex = 0;
850
- static async getOrLoadLOD(t, e) {
851
- const s = f == "verbose", r = this.getAssignedLODInformation(t);
852
- if (!r)
853
- return f && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
854
- const n = r?.key;
855
- let o;
921
+ static async getOrLoadLOD(t, e, s) {
922
+ const r = h == "verbose", n = this.getAssignedLODInformation(t);
923
+ if (!n)
924
+ return h && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
925
+ const o = n?.key;
926
+ let a;
856
927
  if (t.isTexture === !0) {
857
- const a = t;
858
- a.source && a.source[de] && (o = a.source[de]);
928
+ const u = t;
929
+ u.source && u.source[de] && (a = u.source[de]);
859
930
  }
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);
931
+ if (a || (a = g.lodInfos.get(o)), !a)
932
+ h && console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`, t.type, g.lodInfos);
862
933
  else {
863
934
  if (e > 0) {
864
935
  let c = !1;
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}`);
936
+ const d = Array.isArray(a.lods);
937
+ if (d && e >= a.lods.length ? c = !0 : d || (c = !0), c) {
938
+ const p = this.lowresCache.get(o);
939
+ if (p) {
940
+ const b = p.deref();
941
+ if (b) return b;
942
+ this.lowresCache.delete(o), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${o}`);
872
943
  }
873
944
  return null;
874
945
  }
875
946
  }
876
- const a = Array.isArray(o.lods) ? o.lods[e]?.path : o.lods;
877
- if (!a)
878
- return f && !o["missing:uri"] && (o["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, o)), null;
879
- const l = it(r.url, a);
880
- if (l.endsWith(".glb") || l.endsWith(".gltf")) {
881
- if (!o.guid)
882
- return console.warn("missing pointer for glb/gltf texture", o), null;
883
- const c = l + "_" + o.guid, d = await this.tryResolveLODCacheEntry(this.cache.get(c), c, l, t, e, s);
947
+ const u = Array.isArray(a.lods) ? a.lods[e]?.path : a.lods;
948
+ if (!u)
949
+ return h && !a["missing:uri"] && (a["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, a)), null;
950
+ const f = Lt(n.url, u);
951
+ if (f.endsWith(".glb") || f.endsWith(".gltf")) {
952
+ if (!a.guid)
953
+ return console.warn("missing pointer for glb/gltf texture", a), null;
954
+ const c = f + "_" + a.guid, d = await this.tryResolveLODCacheEntry(this.cache.get(c), c, f, t, e, r);
884
955
  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);
956
+ if (s?.isCurrent?.() === !1)
957
+ return r && console.log(`Skipping stale LOD ${e} request before queue: ${f}`), null;
958
+ const p = await this.queue.slot(f);
959
+ if (s?.isCurrent?.() === !1)
960
+ return r && console.log(`Skipping stale LOD ${e} request after queue: ${f}`), null;
961
+ const b = await this.tryResolveLODCacheEntry(this.cache.get(c), c, f, t, e, r);
962
+ if (b.found) return b.value;
963
+ if (!p.use)
964
+ return h && console.log(`LOD ${e} was aborted: ${f}`), null;
965
+ const y = a, x = new Promise(async (L, z) => {
966
+ if (Pt) {
967
+ const m = await (await Rt({})).load(f);
968
+ if (m.textures.length > 0)
969
+ for (const D of m.textures) {
970
+ let M = D.texture;
971
+ return g.assignLODInformation(n.url, M, o, e, void 0), t instanceof q && (M = this.copySettings(t, M)), M && (M.guid = y.guid), L(M);
896
972
  }
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);
973
+ if (m.geometries.length > 0) {
974
+ const D = new Array();
975
+ for (const M of m.geometries) {
976
+ const G = M.geometry;
977
+ g.assignLODInformation(n.url, G, o, e, M.primitiveIndex), D.push(G);
902
978
  }
903
- return _(M);
979
+ return L(D);
904
980
  }
905
- return _(null);
981
+ return L(null);
906
982
  }
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);
983
+ const v = new De();
984
+ Ge(v), h && (await new Promise((_) => setTimeout(_, 1e3)), r && console.warn("Start loading (delayed) " + f, y.guid));
985
+ let T = f;
986
+ if (y && Array.isArray(y.lods)) {
987
+ const _ = y.lods[e];
988
+ _.hash && (T += "?v=" + _.hash);
913
989
  }
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;
990
+ const O = await v.loadAsync(T).catch((_) => (console.error(`Error loading LOD ${e} from ${f}
991
+ `, _), L(null)));
992
+ if (!O)
993
+ return L(null);
994
+ const P = O.parser;
995
+ r && console.log("Loading finished " + f, y.guid);
996
+ let S = 0;
997
+ if (O.parser.json.textures) {
998
+ let _ = !1;
999
+ for (const m of O.parser.json.textures) {
1000
+ if (m?.extensions) {
1001
+ const D = m?.extensions[U];
1002
+ if (D?.guid && D.guid === y.guid) {
1003
+ _ = !0;
928
1004
  break;
929
1005
  }
930
1006
  }
931
- O++;
1007
+ S++;
932
1008
  }
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);
1009
+ if (_) {
1010
+ let m = await P.getDependency("texture", S);
1011
+ return m && g.assignLODInformation(n.url, m, o, e, void 0), r && console.log('change "' + t.name + '" → "' + m.name + '"', f, S, m, c), t instanceof q && (m = this.copySettings(t, m)), m && (m.guid = y.guid), L(m);
1012
+ } else h && console.warn("Could not find texture with guid", y.guid, O.parser.json);
937
1013
  }
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;
1014
+ if (S = 0, O.parser.json.meshes) {
1015
+ let _ = !1;
1016
+ for (const m of O.parser.json.meshes) {
1017
+ if (m?.extensions) {
1018
+ const D = m?.extensions[U];
1019
+ if (D?.guid && D.guid === y.guid) {
1020
+ _ = !0;
945
1021
  break;
946
1022
  }
947
1023
  }
948
- O++;
1024
+ S++;
949
1025
  }
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);
1026
+ if (_) {
1027
+ const m = await P.getDependency("mesh", S);
1028
+ if (r && console.log(`Loaded Mesh "${m.name}"`, f, S, m, c), m.isMesh === !0) {
1029
+ const D = m.geometry;
1030
+ return g.assignLODInformation(n.url, D, o, e, 0), L(D);
955
1031
  } else {
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);
1032
+ const D = new Array();
1033
+ for (let M = 0; M < m.children.length; M++) {
1034
+ const G = m.children[M];
1035
+ if (G.isMesh === !0) {
1036
+ const ie = G.geometry;
1037
+ g.assignLODInformation(n.url, ie, o, e, M), D.push(ie);
962
1038
  }
963
1039
  }
964
- return _(M);
1040
+ return L(D);
965
1041
  }
966
- } else f && console.warn("Could not find mesh with guid", x.guid, w.parser.json);
1042
+ } else h && console.warn("Could not find mesh with guid", y.guid, O.parser.json);
967
1043
  }
968
- return _(null);
1044
+ return L(null);
969
1045
  });
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;
1046
+ this.cache.set(c, x), p.use(x);
1047
+ const w = await x;
1048
+ return w != null ? w instanceof q ? (this.cache.set(c, new WeakRef(w)), g._resourceRegistry.register(w, c)) : Array.isArray(w) ? this.cache.set(c, Promise.resolve(w)) : this.cache.set(c, Promise.resolve(w)) : this.cache.set(c, Promise.resolve(null)), w;
1049
+ } else if (t instanceof q) {
1050
+ if (s?.isCurrent?.() === !1)
1051
+ return r && console.log(`Skipping stale texture LOD ${e} request: ${f}`), null;
1052
+ r && console.log("Load texture from uri: " + f);
1053
+ const d = await new it().loadAsync(f);
1054
+ return s?.isCurrent?.() === !1 ? (d?.dispose(), null) : (d ? (d.guid = a.guid, d.flipY = !1, d.needsUpdate = !0, d.colorSpace = t.colorSpace, r && console.log(a, d)) : h && console.warn("failed loading", f), d);
977
1055
  }
978
1056
  }
979
1057
  return null;
@@ -982,26 +1060,26 @@ ${e}`);
982
1060
  if (t === void 0)
983
1061
  return { found: !1 };
984
1062
  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 };
1063
+ const u = t.deref();
1064
+ if (u) {
1065
+ let f = u, c = !1;
1066
+ if (f instanceof q && r instanceof q ? Te(f.image) || Le(f) ? f = this.copySettings(r, f) : c = !0 : f instanceof j && r instanceof j && (f.attributes.position?.array || (c = !0)), !c)
1067
+ return { found: !0, value: f };
990
1068
  }
991
- return this.cache.delete(e), f && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`), { found: !1 };
1069
+ return this.cache.delete(e), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`), { found: !1 };
992
1070
  }
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 };
1071
+ let a = await t.catch((u) => (console.error(`Error loading LOD ${n} from ${s}
1072
+ `, u), null)), l = !1;
1073
+ return a == null || (a instanceof q && r instanceof q ? Te(a.image) || Le(a) ? a = this.copySettings(r, a) : (l = !0, this.cache.delete(e)) : a instanceof j && r instanceof j && (a.attributes.position?.array || (l = !0, this.cache.delete(e)))), l ? { found: !1 } : { found: !0, value: a };
996
1074
  }
997
1075
  static _queue;
998
1076
  static get queue() {
999
- return this._queue ??= new at(ve() ? 20 : 50, { debug: f != !1 });
1077
+ return this._queue ??= new wt(Me() ? 20 : 50, { debug: h != !1 });
1000
1078
  }
1001
1079
  static assignLODInformation(t, e, s, r, n) {
1002
1080
  if (!e) return;
1003
1081
  e.userData || (e.userData = {});
1004
- const o = new wt(t, s, r, n);
1082
+ const o = new kt(t, s, r, n);
1005
1083
  e.userData.LODS = o, "source" in e && typeof e.source == "object" && (e.source.LODS = o);
1006
1084
  }
1007
1085
  static getAssignedLODInformation(t) {
@@ -1009,12 +1087,12 @@ ${e}`);
1009
1087
  }
1010
1088
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
1011
1089
  static copySettings(t, e) {
1012
- return e ? (f === "verbose" && console.debug(`Copy texture settings
1090
+ return e ? (h === "verbose" && console.debug(`Copy texture settings
1013
1091
  `, t.uuid, `
1014
1092
  `, 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;
1015
1093
  }
1016
1094
  }
1017
- class wt {
1095
+ class kt {
1018
1096
  url;
1019
1097
  /** the key to lookup the LOD information */
1020
1098
  key;
@@ -1074,7 +1152,7 @@ class oe {
1074
1152
  _seen = /* @__PURE__ */ new WeakMap();
1075
1153
  add(t, e, s) {
1076
1154
  if (this._resolved) {
1077
- f && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
1155
+ h && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
1078
1156
  return;
1079
1157
  }
1080
1158
  if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
@@ -1082,7 +1160,7 @@ class oe {
1082
1160
  if (this._seen.has(e)) {
1083
1161
  const r = this._seen.get(e);
1084
1162
  if (r >= this._maxPromisesPerObject) {
1085
- f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
1163
+ h && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
1086
1164
  return;
1087
1165
  }
1088
1166
  this._seen.set(e, r + 1);
@@ -1101,7 +1179,7 @@ class oe {
1101
1179
  });
1102
1180
  }
1103
1181
  }
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 = [
1182
+ const A = V("debugprogressive"), At = A === "colors", It = V("noprogressive"), he = /* @__PURE__ */ Symbol("Needle:LODSManager"), ge = /* @__PURE__ */ Symbol("Needle:LODState"), E = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), Oe = Xe, R = { mesh_lod: -1, texture_lod: -1 }, $t = new Ie(), Se = [
1105
1183
  3526751,
1106
1184
  11065402,
1107
1185
  15978811,
@@ -1134,12 +1212,17 @@ const A = N("debugprogressive"), Lt = A === "colors", vt = N("noprogressive"), f
1134
1212
  15817653,
1135
1213
  5083278,
1136
1214
  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) {
1215
+ ];
1216
+ function Bt() {
1217
+ const i = Oe.Timer || Oe.Clock;
1218
+ return new i();
1219
+ }
1220
+ const pe = new ue(), N = new ue(), Re = new ue(), Gt = new k(), qt = new k(), Wt = new $e(), W = new k(), H = new k(), Q = new k(), J = new k();
1221
+ function Ft(i, t) {
1139
1222
  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;
1223
+ return W.set(r, n, e.z).applyMatrix4(t).z < 0;
1141
1224
  }
1142
- function Tt(i) {
1225
+ function Ut(i) {
1143
1226
  const {
1144
1227
  geometry: t,
1145
1228
  matrixWorld: e,
@@ -1147,66 +1230,71 @@ function Tt(i) {
1147
1230
  projectionScreenMatrix: r,
1148
1231
  desiredDensity: n,
1149
1232
  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,
1233
+ currentLevel: a = -1,
1234
+ xrEnabled: l = !1,
1235
+ debugDrawLine: u,
1236
+ warnMissingPrimitiveDensities: f = !1
1237
+ } = i, c = g.getMeshLODExtension(t)?.lods, d = g.getPrimitiveIndex(t), p = i.target ?? {
1238
+ level: a,
1239
+ primitiveIndex: d,
1157
1240
  screenCoverage: 0,
1158
1241
  screenspaceVolume: new k(),
1159
1242
  centrality: 1
1160
1243
  };
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;
1244
+ p.level = a, p.primitiveIndex = d, p.screenCoverage = 0, p.screenspaceVolume.set(0, 0, 0), p.centrality = 1;
1245
+ let b = i.boundingBox ?? t.boundingBox;
1246
+ if (b || (t.computeBoundingBox(), b = t.boundingBox), !b) return p;
1247
+ if (pe.copy(b).applyMatrix4(e), s.isPerspectiveCamera && Ft(pe, r))
1248
+ return p.level = 0, p.screenCoverage = 1 / 0, p.screenspaceVolume.set(1 / 0, 1 / 0, 1 / 0), p;
1249
+ if (N.copy(pe).applyMatrix4(r), l && s.isPerspectiveCamera && s.fov > 70) {
1250
+ const v = N.min, T = N.max;
1251
+ let O = v.x, P = v.y, S = T.x, _ = T.y;
1252
+ const m = 2, D = 1.5, M = (v.x + T.x) * 0.5, G = (v.y + T.y) * 0.5;
1253
+ O = (O - M) * m + M, P = (P - G) * m + G, S = (S - M) * m + M, _ = (_ - G) * m + G;
1254
+ const ie = O < 0 && S > 0 ? 0 : Math.min(Math.abs(v.x), Math.abs(T.x)), Ve = P < 0 && _ > 0 ? 0 : Math.min(Math.abs(v.y), Math.abs(T.y)), ce = Math.max(ie, Ve);
1255
+ p.centrality = (D - ce) * (D - ce) * (D - ce);
1256
+ }
1257
+ const y = N.getSize(Gt);
1258
+ y.multiplyScalar(0.5), globalThis.screen?.availHeight > 0 && o > 0 && y.multiplyScalar(o / globalThis.screen.availHeight), s.isPerspectiveCamera && (y.x *= s.aspect), Re.copy(b).applyMatrix4(e).applyMatrix4(s.matrixWorldInverse);
1259
+ const x = Re.getSize(qt), w = Math.max(y.x, y.y), L = Math.max(x.x, x.y);
1260
+ w !== 0 && L !== 0 && (y.z = x.z / L * w);
1261
+ const z = Math.max(y.x, y.y, y.z) * p.centrality;
1262
+ if (p.screenCoverage = z, p.screenspaceVolume.copy(y), z <= 0) return p;
1263
+ if (u) {
1264
+ const v = Wt.copy(r);
1265
+ v.invert(), W.copy(N.min), H.copy(N.max), H.x = W.x, Q.copy(N.max), Q.y = W.y, J.copy(N.max);
1266
+ const T = (W.z + J.z) * 0.5;
1267
+ W.z = H.z = Q.z = J.z = T, W.applyMatrix4(v), H.applyMatrix4(v), Q.applyMatrix4(v), J.applyMatrix4(v), u(W, H, 255), u(W, Q, 255), u(H, J, 255), u(Q, J, 255);
1268
+ }
1269
+ if (c?.length)
1270
+ for (let v = 0; v < c.length; v++) {
1271
+ const T = c[v], O = T.densities?.[d] || T.density || 1e-5;
1272
+ if (d > 0 && f && Fe() && !T.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.")), O / z < n) {
1273
+ p.level = v;
1274
+ break;
1275
+ }
1191
1276
  }
1192
- }
1193
- return m;
1277
+ return p;
1194
1278
  }
1195
- class R {
1279
+ class I {
1196
1280
  /**
1197
1281
  * 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.
1198
1282
  */
1199
1283
  static debugDrawLine;
1200
1284
  /** @internal */
1201
1285
  static getObjectLODState(t) {
1202
- return t[he];
1286
+ return t[ge];
1203
1287
  }
1204
1288
  static addPlugin(t) {
1205
- E.push(t);
1289
+ F.push(t);
1206
1290
  }
1207
1291
  static removePlugin(t) {
1208
- const e = E.indexOf(t);
1209
- e >= 0 && E.splice(e, 1);
1292
+ const e = F.indexOf(t);
1293
+ e >= 0 && F.splice(e, 1);
1294
+ }
1295
+ /** Read-only snapshot of the currently registered plugins, for inspection. Use {@link addPlugin} / {@link removePlugin} to modify the registry. */
1296
+ static getPlugins() {
1297
+ return F;
1210
1298
  }
1211
1299
  /**
1212
1300
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -1214,20 +1302,20 @@ class R {
1214
1302
  * @returns The LODsManager instance.
1215
1303
  */
1216
1304
  static get(t, e) {
1217
- if (t[fe])
1218
- return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[fe];
1219
- const s = new R(t, {
1305
+ if (t[he])
1306
+ return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[he];
1307
+ const s = new I(t, {
1220
1308
  engine: "unknown",
1221
1309
  ...e
1222
1310
  });
1223
- return t[fe] = s, s;
1311
+ return t[he] = s, s;
1224
1312
  }
1225
1313
  renderer;
1226
1314
  context;
1227
- projectionScreenMatrix = new Pe();
1315
+ projectionScreenMatrix = new $e();
1228
1316
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
1229
1317
  get plugins() {
1230
- return E;
1318
+ return F;
1231
1319
  }
1232
1320
  /**
1233
1321
  * Force override the LOD level for all objects (meshes + textures) rendered in the scene
@@ -1297,7 +1385,7 @@ class R {
1297
1385
  const r = performance.now();
1298
1386
  return s.ready.finally(() => {
1299
1387
  const n = this._newPromiseGroups.indexOf(s);
1300
- n >= 0 && (this._newPromiseGroups.splice(n, 1), $e() && performance.measure("LODsManager:awaitLoading", {
1388
+ n >= 0 && (this._newPromiseGroups.splice(n, 1), Fe() && performance.measure("LODsManager:awaitLoading", {
1301
1389
  start: r,
1302
1390
  detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
1303
1391
  }));
@@ -1353,11 +1441,11 @@ class R {
1353
1441
  this.renderer = t, this.context = { ...e };
1354
1442
  }
1355
1443
  #t;
1356
- #o = new Ke();
1357
1444
  #r = 0;
1358
1445
  #n = 0;
1359
- #i = 0;
1446
+ #o = 0;
1360
1447
  #s = 0;
1448
+ #i = Bt();
1361
1449
  _fpsBuffer = [60, 60, 60, 60, 60];
1362
1450
  /**
1363
1451
  * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
@@ -1368,9 +1456,9 @@ class R {
1368
1456
  let t = 0;
1369
1457
  this.#t = this.renderer.render;
1370
1458
  const e = this;
1371
- Le(this.renderer), this.renderer.render = function(s, r) {
1459
+ _e(this.renderer), this.renderer.render = function(s, r) {
1372
1460
  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));
1461
+ (n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i.update?.(), e.#n = Math.max(e.#i.getDelta(), 1 / 1e3), e.#o += e.#n, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#n), e.#s = e._fpsBuffer.reduce((a, l) => a + l) / e._fpsBuffer.length, A && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1374
1462
  const o = t++;
1375
1463
  e.#t.call(this, s, r), e.onAfterRender(s, r, o);
1376
1464
  };
@@ -1398,14 +1486,16 @@ class R {
1398
1486
  }
1399
1487
  onAfterRender(t, e, s) {
1400
1488
  if (this.pause) return;
1401
- const n = this.renderer.renderLists.get(t, 0).opaque;
1489
+ const r = this.getRenderList(t, e, s);
1490
+ if (!r) return;
1491
+ const n = r.opaque;
1402
1492
  let o = !0;
1403
1493
  if (n.length === 1) {
1404
- const u = n[0].material;
1405
- (u.name === "EffectMaterial" || u.name === "CopyShader") && (o = !1);
1494
+ const a = n[0].material;
1495
+ (a.name === "EffectMaterial" || a.name === "CopyShader") && (o = !1);
1406
1496
  }
1407
1497
  if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
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))
1498
+ if (It || (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))
1409
1499
  return;
1410
1500
  this.internalUpdate(t, e), this._postprocessPromiseGroups();
1411
1501
  }
@@ -1414,15 +1504,17 @@ class R {
1414
1504
  * Update LODs in a scene
1415
1505
  */
1416
1506
  internalUpdate(t, e) {
1417
- const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
1507
+ const s = this.getRenderList(t, e, 0);
1508
+ if (!s) return;
1509
+ const r = s.opaque;
1418
1510
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
1419
1511
  const n = this.targetTriangleDensity;
1420
- for (const a of r) {
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")) {
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)));
1512
+ for (const l of r) {
1513
+ if (l.material && (l.geometry?.type === "BoxGeometry" || l.geometry?.type === "BufferGeometry") && (l.material.name === "SphericalGaussianBlur" || l.material.name == "BackgroundCubeMaterial" || l.material.name === "CubemapFromEquirect" || l.material.name === "EquirectangularToCubeUV")) {
1514
+ A && (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", l, l.material.name, l.material.type)));
1423
1515
  continue;
1424
1516
  }
1425
- switch (a.material.type) {
1517
+ switch (l.material.type) {
1426
1518
  case "LineBasicMaterial":
1427
1519
  case "LineDashedMaterial":
1428
1520
  case "PointsMaterial":
@@ -1431,33 +1523,52 @@ class R {
1431
1523
  case "MeshDepthMaterial":
1432
1524
  continue;
1433
1525
  }
1434
- const l = a.object;
1435
- (l instanceof K || l.isMesh) && this.updateLODs(t, e, l, n);
1526
+ const u = l.object;
1527
+ (u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
1436
1528
  }
1437
1529
  const o = s.transparent;
1438
- for (const a of o) {
1439
- const l = a.object;
1440
- (l instanceof K || l.isMesh) && this.updateLODs(t, e, l, n);
1530
+ for (const l of o) {
1531
+ const u = l.object;
1532
+ (u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
1533
+ }
1534
+ const a = s.transmissive;
1535
+ for (const l of a) {
1536
+ const u = l.object;
1537
+ (u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
1441
1538
  }
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);
1539
+ }
1540
+ getRenderList(t, e, s) {
1541
+ const r = this.renderer;
1542
+ let n = null;
1543
+ if (r.isWebGPURenderer === !0) {
1544
+ const o = r._renderLists;
1545
+ if (!o) return null;
1546
+ n = o.get(t, e);
1547
+ } else if (r.isWebGLRenderer === !0) {
1548
+ const o = r.renderLists;
1549
+ if (!o) return null;
1550
+ n = o.get(t, s);
1446
1551
  }
1552
+ return n ? {
1553
+ opaque: n.opaque || [],
1554
+ transparent: n.transparent || [],
1555
+ transmissive: n.transmissive || n.transparentDoublePass || [],
1556
+ transparentDoublePass: n.transparentDoublePass || []
1557
+ } : null;
1447
1558
  }
1448
1559
  /** Update the LOD levels for the renderer. */
1449
1560
  updateLODs(t, e, s, r) {
1450
1561
  s.userData || (s.userData = {});
1451
- let n = s[he];
1452
- if (n || (n = new St(), s[he] = n), n.frames++ < 2)
1562
+ let n = s[ge];
1563
+ if (n || (n = new zt(), s[ge] = n), n.frames++ < 2)
1453
1564
  return;
1454
- for (const u of E)
1455
- u.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1565
+ for (const a of F)
1566
+ a.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1456
1567
  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;
1568
+ o >= 0 ? (R.mesh_lod = o, R.texture_lod = o) : (this.calculateLodLevel(e, s, n, r, R), R.mesh_lod = Math.round(R.mesh_lod), R.texture_lod = Math.round(R.texture_lod)), R.mesh_lod >= 0 && this.loadProgressiveMeshes(s, R.mesh_lod), s.material && R.texture_lod >= 0 && this.loadProgressiveTextures(s.material, R.texture_lod, o), h && s.material && !s.isGizmo && Ue(s.material), At && s.material && !s.isGizmo && !s.isBatchedMesh && ze(s.material, R.mesh_lod);
1569
+ for (const a of F)
1570
+ a.onAfterUpdatedLOD?.(this.renderer, t, e, s, R);
1571
+ n.lastLodLevel_Mesh = R.mesh_lod, n.lastLodLevel_Texture = R.texture_lod;
1461
1572
  }
1462
1573
  /** Load progressive textures for the given material
1463
1574
  * @param material the material to load the textures for
@@ -1472,14 +1583,14 @@ class R {
1472
1583
  return;
1473
1584
  }
1474
1585
  let r = !1;
1475
- (t[q] === void 0 || e < t[q]) && (r = !0);
1586
+ (t[E] === void 0 || e < t[E]) && (r = !0);
1476
1587
  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) => {
1480
- this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
1588
+ if (n && (r = t[E] != s, e = s), r) {
1589
+ t[E] = e;
1590
+ const o = n ? { force: !0 } : void 0, a = g.assignTextureLOD(t, e, o).then((l) => {
1591
+ this._lodchangedlisteners.forEach((u) => u({ type: "texture", level: e, object: t }));
1481
1592
  });
1482
- oe.addPromise("texture", t, u, this._newPromiseGroups);
1593
+ oe.addPromise("texture", t, a, this._newPromiseGroups);
1483
1594
  }
1484
1595
  }
1485
1596
  /** Load progressive meshes for the given mesh
@@ -1490,17 +1601,17 @@ class R {
1490
1601
  */
1491
1602
  loadProgressiveMeshes(t, e) {
1492
1603
  if (!t) return Promise.resolve(null);
1493
- let s = t[q] !== e;
1604
+ let s = t[E] !== e;
1494
1605
  const r = t["DEBUG:LOD"];
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));
1606
+ if (r != null && (s = t[E] != r, e = r), s) {
1607
+ t[E] = e;
1608
+ const n = t.geometry, o = g.assignMeshLOD(t, e).then((a) => (a && t[E] == e && n != t.geometry && this._lodchangedlisteners.forEach((l) => l({ type: "mesh", level: e, object: t })), a));
1498
1609
  return oe.addPromise("mesh", t, o, this._newPromiseGroups), o;
1499
1610
  }
1500
1611
  return Promise.resolve(null);
1501
1612
  }
1502
1613
  // private testIfLODLevelsAreAvailable() {
1503
- _sphere = new Se();
1614
+ _sphere = new Ae();
1504
1615
  _tempWorldPosition = new k();
1505
1616
  static skinnedMeshBoundsFrameOffsetCounter = 0;
1506
1617
  static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
@@ -1514,86 +1625,86 @@ class R {
1514
1625
  n.mesh_lod = -1, n.texture_lod = -1;
1515
1626
  return;
1516
1627
  }
1517
- let u = 10 + 1, a = !1;
1628
+ let a = 10 + 1, l = !1;
1518
1629
  if (A && e["DEBUG:LOD"] != null)
1519
1630
  return e["DEBUG:LOD"];
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) {
1631
+ const u = g.getMeshLODExtension(e.geometry)?.lods, f = g.getPrimitiveIndex(e.geometry), c = u && u.length > 0, d = g.getMaterialMinMaxLODsCount(e.material), p = d.min_count !== 1 / 0 && d.min_count >= 0 && d.max_count >= 0;
1632
+ if (!c && !p) {
1522
1633
  n.mesh_lod = 0, n.texture_lod = 0;
1523
1634
  return;
1524
1635
  }
1525
- d || (a = !0, u = 0);
1526
- const x = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1527
- let v = e.geometry.boundingBox;
1636
+ c || (l = !0, a = 0);
1637
+ const b = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1638
+ let y = e.geometry.boundingBox;
1528
1639
  if (e.type === "SkinnedMesh") {
1529
- const p = e;
1530
- if (!p.boundingBox)
1531
- p.computeBoundingBox();
1640
+ const x = e;
1641
+ if (!x.boundingBox)
1642
+ x.computeBoundingBox();
1532
1643
  else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
1533
- if (!p[R.$skinnedMeshBoundsOffset]) {
1534
- const C = R.skinnedMeshBoundsFrameOffsetCounter++;
1535
- p[R.$skinnedMeshBoundsOffset] = C;
1644
+ if (!x[I.$skinnedMeshBoundsOffset]) {
1645
+ const L = I.skinnedMeshBoundsFrameOffsetCounter++;
1646
+ x[I.$skinnedMeshBoundsOffset] = L;
1536
1647
  }
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;
1648
+ const w = x[I.$skinnedMeshBoundsOffset];
1649
+ if ((s.frames + w) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1650
+ const L = ne(x), z = x.geometry;
1651
+ L && (x.geometry = L), x.computeBoundingBox(), x.geometry = z;
1541
1652
  }
1542
1653
  }
1543
- v = p.boundingBox;
1654
+ y = x.boundingBox;
1544
1655
  }
1545
- if (v) {
1656
+ if (y) {
1546
1657
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
1547
1658
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
1548
- const C = t.getWorldPosition(this._tempWorldPosition);
1549
- if (this._sphere.containsPoint(C)) {
1659
+ const L = t.getWorldPosition(this._tempWorldPosition);
1660
+ if (this._sphere.containsPoint(L)) {
1550
1661
  n.mesh_lod = 0, n.texture_lod = 0;
1551
1662
  return;
1552
1663
  }
1553
1664
  }
1554
- const p = Tt({
1665
+ const x = Ut({
1555
1666
  geometry: e.geometry,
1556
1667
  matrixWorld: e.matrixWorld,
1557
1668
  camera: t,
1558
1669
  projectionScreenMatrix: this.projectionScreenMatrix,
1559
1670
  desiredDensity: r,
1560
- canvasHeight: x,
1671
+ canvasHeight: b,
1561
1672
  currentLevel: s.lastLodLevel_Mesh,
1562
- boundingBox: v,
1673
+ boundingBox: y,
1563
1674
  xrEnabled: this.renderer.xr.enabled,
1564
- debugDrawLine: A ? R.debugDrawLine : void 0,
1675
+ debugDrawLine: A ? I.debugDrawLine : void 0,
1565
1676
  warnMissingPrimitiveDensities: !0
1566
1677
  });
1567
- if (s.lastCentrality = p.centrality, s.lastScreenCoverage = p.screenCoverage, s.lastScreenspaceVolume.copy(p.screenspaceVolume), p.screenCoverage === 1 / 0) {
1678
+ if (s.lastCentrality = x.centrality, s.lastScreenCoverage = x.screenCoverage, s.lastScreenspaceVolume.copy(x.screenspaceVolume), x.screenCoverage === 1 / 0) {
1568
1679
  n.mesh_lod = 0, n.texture_lod = 0;
1569
1680
  return;
1570
1681
  }
1571
- p.level >= 0 && p.level < u && (u = p.level, a = !0);
1682
+ x.level >= 0 && x.level < a && (a = x.level, l = !0);
1572
1683
  }
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}`);
1684
+ if (l ? n.mesh_lod = a : n.mesh_lod = s.lastLodLevel_Mesh, A && n.mesh_lod != s.lastLodLevel_Mesh) {
1685
+ const w = u?.[n.mesh_lod];
1686
+ w && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${w.densities?.[f].toFixed(0)}) | ${e.name}`);
1576
1687
  }
1577
- if (m) {
1578
- const p = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1688
+ if (p) {
1689
+ const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1579
1690
  if (s.lastLodLevel_Texture < 0) {
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}`);
1691
+ if (n.texture_lod = d.max_count - 1, A) {
1692
+ const w = d.lods[d.max_count - 1];
1693
+ A && console.log(`First Texture LOD ${n.texture_lod} (${w.max_height}px) - ${e.name}`);
1583
1694
  }
1584
1695
  } else {
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)}
1696
+ const w = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1697
+ let L = s.lastScreenCoverage * 4;
1698
+ this.context?.engine === "model-viewer" && (L *= 1.5);
1699
+ const z = this.renderer.getPixelRatio?.() || globalThis.devicePixelRatio || 1, T = b / z * L;
1700
+ let O = !1;
1701
+ for (let P = d.lods.length - 1; P >= 0; P--) {
1702
+ const S = d.lods[P];
1703
+ if (!(x && S.max_height >= 2048) && !(Me() && S.max_height > 4096) && (S.max_height > T || !O && P === 0)) {
1704
+ if (O = !0, n.texture_lod = P, A && n.texture_lod < s.lastLodLevel_Texture) {
1705
+ const _ = S.max_height;
1706
+ console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${_}px
1707
+ Screensize: ${T.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
1597
1708
  ${e.name}`);
1598
1709
  }
1599
1710
  break;
@@ -1604,7 +1715,7 @@ ${e.name}`);
1604
1715
  n.texture_lod = 0;
1605
1716
  }
1606
1717
  }
1607
- class St {
1718
+ class zt {
1608
1719
  frames = 0;
1609
1720
  lastLodLevel_Mesh = -1;
1610
1721
  lastLodLevel_Texture = -1;
@@ -1612,66 +1723,66 @@ class St {
1612
1723
  lastScreenspaceVolume = new k();
1613
1724
  lastCentrality = 0;
1614
1725
  }
1615
- function Ge(i, t) {
1726
+ function ze(i, t) {
1616
1727
  if (!(t < 0)) {
1617
1728
  if (Array.isArray(i)) {
1618
1729
  for (const e of i)
1619
- Ge(e, t);
1730
+ ze(e, t);
1620
1731
  return;
1621
1732
  }
1622
- "color" in i && i.color instanceof Ce && (i.color.copy(Ct(t, _t)), i.needsUpdate = !0);
1733
+ "color" in i && i.color instanceof Ie && (i.color.copy(Et(t, $t)), i.needsUpdate = !0);
1623
1734
  }
1624
1735
  }
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]);
1736
+ function Et(i, t) {
1737
+ const e = Math.max(0, Math.min(Se.length - 1, Math.floor(i)));
1738
+ return t.setHex(Se[e]);
1628
1739
  }
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();
1740
+ const Ce = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ae = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1741
+ let me = null;
1742
+ function Ee() {
1743
+ const i = Nt();
1633
1744
  i && (i.mapURLs(function(t) {
1634
- return Oe(), t;
1635
- }), Oe(), pe?.disconnect(), pe = new MutationObserver((t) => {
1745
+ return Pe(), t;
1746
+ }), Pe(), me?.disconnect(), me = new MutationObserver((t) => {
1636
1747
  t.forEach((e) => {
1637
1748
  e.addedNodes.forEach((s) => {
1638
- s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ue(s);
1749
+ s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ne(s);
1639
1750
  });
1640
1751
  });
1641
- }), pe.observe(document, { childList: !0, subtree: !0 }));
1752
+ }), me.observe(document, { childList: !0, subtree: !0 }));
1642
1753
  }
1643
- function Pt() {
1754
+ function Nt() {
1644
1755
  if (typeof customElements > "u") return null;
1645
1756
  const i = customElements.get("model-viewer");
1646
1757
  return i || (customElements.whenDefined("model-viewer").then(() => {
1647
- console.debug("[gltf-progressive] model-viewer defined"), We();
1758
+ console.debug("[gltf-progressive] model-viewer defined"), Ee();
1648
1759
  }), null);
1649
1760
  }
1650
- function Oe() {
1761
+ function Pe() {
1651
1762
  if (typeof document > "u") return;
1652
1763
  document.querySelectorAll("model-viewer").forEach((t) => {
1653
- Ue(t);
1764
+ Ne(t);
1654
1765
  });
1655
1766
  }
1656
- const Te = /* @__PURE__ */ new WeakSet();
1657
- let kt = 0;
1658
- function Ue(i) {
1659
- if (!i || Te.has(i))
1767
+ const ke = /* @__PURE__ */ new WeakSet();
1768
+ let Vt = 0;
1769
+ function Ne(i) {
1770
+ if (!i || ke.has(i))
1660
1771
  return null;
1661
- Te.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++kt + `
1772
+ ke.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++Vt + `
1662
1773
  `, i.getAttribute("src"));
1663
1774
  let t = null, e = null, s = null;
1664
1775
  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]);
1776
+ const n = Object.getOwnPropertySymbols(r), o = n.find((u) => u.toString() == "Symbol(renderer)"), a = n.find((u) => u.toString() == "Symbol(scene)"), l = n.find((u) => u.toString() == "Symbol(needsRender)");
1777
+ !t && o != null && (t = i[o].threeRenderer), !e && a != null && (e = i[a]), !s && l != null && (s = i[l]);
1667
1778
  }
1668
1779
  if (t && e) {
1669
1780
  let r = function() {
1670
1781
  if (s) {
1671
1782
  let o = 0;
1672
- const u = setInterval(() => {
1783
+ const a = setInterval(() => {
1673
1784
  if (o++ > 5) {
1674
- clearInterval(u);
1785
+ clearInterval(a);
1675
1786
  return;
1676
1787
  }
1677
1788
  s?.call(i);
@@ -1679,8 +1790,8 @@ function Ue(i) {
1679
1790
  }
1680
1791
  };
1681
1792
  console.debug("[gltf-progressive] setup model-viewer");
1682
- const n = R.get(t, { engine: "model-viewer" });
1683
- return R.addPlugin(new At()), n.enable(), n.addEventListener("changed", () => {
1793
+ const n = I.get(t, { engine: "model-viewer" });
1794
+ return I.addPlugin(new Xt()), n.enable(), n.addEventListener("changed", () => {
1684
1795
  s?.call(i);
1685
1796
  }), i.addEventListener("model-visibility", (o) => {
1686
1797
  o.detail.visible && s?.call(i);
@@ -1692,7 +1803,7 @@ function Ue(i) {
1692
1803
  }
1693
1804
  return null;
1694
1805
  }
1695
- class At {
1806
+ class Xt {
1696
1807
  _didWarnAboutMissingUrl = !1;
1697
1808
  onBeforeUpdateLOD(t, e, s, r) {
1698
1809
  this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
@@ -1710,50 +1821,50 @@ class At {
1710
1821
  return t.element;
1711
1822
  }
1712
1823
  tryParseTextureLOD(t, e) {
1713
- if (e[ie] == !0) return;
1714
- e[ie] = !0;
1824
+ if (e[ae] == !0) return;
1825
+ e[ae] = !0;
1715
1826
  const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), n = this.getUrl(r);
1716
1827
  if (n && s && e.material) {
1717
- let o = function(a) {
1718
- if (a[ie] == !0) return;
1719
- a[ie] = !0, a.userData && (a.userData.LOD = -1);
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);
1828
+ let o = function(l) {
1829
+ if (l[ae] == !0) return;
1830
+ l[ae] = !0, l.userData && (l.userData.LOD = -1);
1831
+ const u = Object.keys(l);
1832
+ for (let f = 0; f < u.length; f++) {
1833
+ const c = u[f], d = l[c];
1834
+ if (d?.isTexture === !0) {
1835
+ const p = d.userData?.associations?.textures;
1836
+ if (p == null) continue;
1837
+ const b = s.parser.json.textures[p];
1838
+ if (!b) {
1839
+ console.warn("Texture data not found for texture index " + p);
1729
1840
  continue;
1730
1841
  }
1731
- if (x?.extensions?.[F]) {
1732
- const v = x.extensions[F];
1733
- v && n && h.registerTexture(n, g, v.lods.length, m, v);
1842
+ if (b?.extensions?.[U]) {
1843
+ const y = b.extensions[U];
1844
+ y && n && g.registerTexture(n, d, y.lods.length, p, y);
1734
1845
  }
1735
1846
  }
1736
1847
  }
1737
1848
  };
1738
- const u = e.material;
1739
- if (Array.isArray(u)) for (const a of u) o(a);
1740
- else o(u);
1849
+ const a = e.material;
1850
+ if (Array.isArray(a)) for (const l of a) o(l);
1851
+ else o(a);
1741
1852
  }
1742
1853
  }
1743
1854
  tryParseMeshLOD(t, e) {
1744
- if (e[be] == !0) return;
1745
- e[be] = !0;
1855
+ if (e[Ce] == !0) return;
1856
+ e[Ce] = !0;
1746
1857
  const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
1747
1858
  if (!r)
1748
1859
  return;
1749
- const n = e.userData?.gltfExtensions?.[F];
1860
+ const n = e.userData?.gltfExtensions?.[U];
1750
1861
  if (n && r) {
1751
1862
  const o = e.uuid;
1752
- h.registerMesh(r, o, e, 0, n.lods.length, n);
1863
+ g.registerMesh(r, o, e, 0, n.lods.length, n);
1753
1864
  }
1754
1865
  }
1755
1866
  }
1756
- function Rt(...i) {
1867
+ function jt(...i) {
1757
1868
  let t, e, s, r;
1758
1869
  switch (i.length) {
1759
1870
  case 2:
@@ -1768,22 +1879,22 @@ function Rt(...i) {
1768
1879
  default:
1769
1880
  throw new Error("Invalid arguments");
1770
1881
  }
1771
- Le(e), Ae(s), Ie(s, {
1882
+ _e(e), Ge(s), We(s, {
1772
1883
  progressive: !0,
1773
1884
  ...r?.hints
1774
- }), s.register((o) => new h(o));
1775
- const n = R.get(e);
1885
+ }), s.register((o) => new g(o));
1886
+ const n = I.get(e);
1776
1887
  return r?.enableLODsManager !== !1 && n.enable(), n;
1777
1888
  }
1778
- We();
1779
- if (!ct) {
1889
+ Ee();
1890
+ if (!_t) {
1780
1891
  const i = {
1781
1892
  gltfProgressive: {
1782
- useNeedleProgressive: Rt,
1783
- LODsManager: R,
1784
- configureLoader: Ie,
1893
+ useNeedleProgressive: jt,
1894
+ LODsManager: I,
1895
+ configureLoader: We,
1785
1896
  getRaycastMesh: ne,
1786
- useRaycastMeshes: ft
1897
+ useRaycastMeshes: bt
1787
1898
  }
1788
1899
  };
1789
1900
  if (!globalThis.Needle)
@@ -1793,21 +1904,21 @@ if (!ct) {
1793
1904
  globalThis.Needle[t] = i[t];
1794
1905
  }
1795
1906
  export {
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,
1907
+ U as EXTENSION_NAME,
1908
+ I as LODsManager,
1909
+ g as NEEDLE_progressive,
1910
+ ut as VERSION,
1911
+ Ge as addDracoAndKTX2Loaders,
1912
+ Ut as calculateMeshLODLevel,
1913
+ We as configureLoader,
1914
+ _e as createLoaders,
1915
+ Et as getLODColor,
1805
1916
  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
1917
+ Se as lodDebugColors,
1918
+ Ee as patchModelViewer,
1919
+ Mt as registerRaycastMesh,
1920
+ ht as setDracoDecoderLocation,
1921
+ gt as setKTX2TranscoderLocation,
1922
+ jt as useNeedleProgressive,
1923
+ bt as useRaycastMeshes
1813
1924
  };