@needle-tools/gltf-progressive 3.3.5 → 3.4.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.
@@ -1,89 +1,89 @@
1
- import { BufferGeometry as J, Mesh as q, Box3 as he, Vector3 as A, Sphere as De, CompressedTexture as $e, Texture as E, Matrix3 as Ge, InterleavedBuffer as Fe, InterleavedBufferAttribute as We, BufferAttribute as Ue, TextureLoader as ze, Matrix4 as _e, Clock as Ee, MeshStandardMaterial as Ne } from "three";
2
- import { GLTFLoader as ye } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { MeshoptDecoder as qe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
- import { DRACOLoader as Ve } from "three/examples/jsm/loaders/DRACOLoader.js";
5
- import { KTX2Loader as Xe } from "three/examples/jsm/loaders/KTX2Loader.js";
6
- const je = "";
7
- globalThis.GLTF_PROGRESSIVE_VERSION = je;
1
+ import { BufferGeometry as V, Mesh as X, Box3 as ge, Vector3 as A, Sphere as Oe, CompressedTexture as Ge, Texture as F, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as Ne, Matrix4 as Le, Clock as qe, MeshStandardMaterial as Ee } from "three";
2
+ import { GLTFLoader as xe } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ import { MeshoptDecoder as Ve } from "three/examples/jsm/libs/meshopt_decoder.module.js";
4
+ import { DRACOLoader as Xe } from "three/examples/jsm/loaders/DRACOLoader.js";
5
+ import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
6
+ const Ke = "";
7
+ globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
8
8
  console.debug("[gltf-progressive] version -");
9
- let C = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", V = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
- const Ke = C, Ye = V, Oe = new URL(C + "draco_decoder.js");
11
- Oe.searchParams.append("range", "true");
12
- fetch(Oe, {
9
+ let I = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", j = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
10
+ const Ye = I, He = j, Se = new URL(I + "draco_decoder.js");
11
+ Se.searchParams.append("range", "true");
12
+ fetch(Se, {
13
13
  method: "GET",
14
14
  headers: {
15
15
  Range: "bytes=0-1"
16
16
  }
17
- }).catch((i) => {
18
- console.debug(`Failed to fetch remote Draco decoder from ${C} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), C === Ke && Qe("./include/draco/"), V === Ye && Je("./include/ktx2/");
17
+ }).catch((n) => {
18
+ console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), I === Ye && Je("./include/draco/"), j === He && Ze("./include/ktx2/");
19
19
  }).finally(() => {
20
- Pe();
20
+ Te();
21
21
  });
22
- const He = () => ({
23
- dracoDecoderPath: C,
24
- ktx2TranscoderPath: V
22
+ const Qe = () => ({
23
+ dracoDecoderPath: I,
24
+ ktx2TranscoderPath: j
25
25
  });
26
- function Qe(i) {
27
- C = i, T && T[ge] != C ? (console.debug("Updating Draco decoder path to " + i), T[ge] = C, T.setDecoderPath(C), T.preload()) : console.debug("Setting Draco decoder path to " + i);
26
+ function Je(n) {
27
+ I = n, C && C[pe] != I ? (console.debug("Updating Draco decoder path to " + n), C[pe] = I, C.setDecoderPath(I), C.preload()) : console.debug("Setting Draco decoder path to " + n);
28
28
  }
29
- function Je(i) {
30
- V = i, R && R.transcoderPath != V ? (console.debug("Updating KTX2 transcoder path to " + i), R.setTranscoderPath(V), R.init()) : console.debug("Setting KTX2 transcoder path to " + i);
29
+ function Ze(n) {
30
+ j = n, $ && $.transcoderPath != j ? (console.debug("Updating KTX2 transcoder path to " + n), $.setTranscoderPath(j), $.init()) : console.debug("Setting KTX2 transcoder path to " + n);
31
31
  }
32
- function xe(i) {
33
- return Pe(), i ? R.detectSupport(i) : i !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: T, ktx2Loader: R, meshoptDecoder: ne };
32
+ function we(n) {
33
+ return Te(), n ? $.detectSupport(n) : n !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: $, meshoptDecoder: oe };
34
34
  }
35
- function Se(i) {
36
- i.dracoLoader || i.setDRACOLoader(T), i.ktx2Loader || i.setKTX2Loader(R), i.meshoptDecoder || i.setMeshoptDecoder(ne);
35
+ function Pe(n) {
36
+ n.dracoLoader || n.setDRACOLoader(C), n.ktx2Loader || n.setKTX2Loader($), n.meshoptDecoder || n.setMeshoptDecoder(oe);
37
37
  }
38
- const ge = Symbol("dracoDecoderPath");
39
- let T, ne, R;
40
- function Pe() {
41
- T || (T = new Ve(), T[ge] = C, T.setDecoderPath(C), T.setDecoderConfig({ type: "js" }), T.preload()), R || (R = new Xe(), R.setTranscoderPath(V), R.init()), ne || (ne = qe);
38
+ const pe = /* @__PURE__ */ Symbol("dracoDecoderPath");
39
+ let C, oe, $;
40
+ function Te() {
41
+ C || (C = new Xe(), C[pe] = I, C.setDecoderPath(I), C.setDecoderConfig({ type: "js" }), C.preload()), $ || ($ = new je(), $.setTranscoderPath(j), $.init()), oe || (oe = Ve);
42
42
  }
43
- const pe = /* @__PURE__ */ new WeakMap();
44
- function Te(i, t) {
45
- let e = pe.get(i);
46
- e ? e = Object.assign(e, t) : e = t, pe.set(i, e);
43
+ const me = /* @__PURE__ */ new WeakMap();
44
+ function Ce(n, t) {
45
+ let e = me.get(n);
46
+ e ? e = Object.assign(e, t) : e = t, me.set(n, e);
47
47
  }
48
- const Ze = ye.prototype.load;
49
- function et(...i) {
50
- const t = pe.get(this);
51
- let e = i[0];
48
+ const et = xe.prototype.load;
49
+ function tt(...n) {
50
+ const t = me.get(this);
51
+ let e = n[0];
52
52
  const s = new URL(e, window.location.href);
53
53
  if (s.hostname.endsWith("needle.tools")) {
54
- const r = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
55
- r ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
54
+ const i = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
55
+ i ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
56
56
  }
57
- return i[0] = e, Ze?.call(this, ...i);
57
+ return n[0] = e, et?.call(this, ...n);
58
58
  }
59
- ye.prototype.load = et;
60
- X("debugprogressive");
61
- function X(i) {
59
+ xe.prototype.load = tt;
60
+ N("debugprogressive");
61
+ function N(n) {
62
62
  if (typeof window > "u") return !1;
63
- const e = new URL(window.location.href).searchParams.get(i);
63
+ const e = new URL(window.location.href).searchParams.get(n);
64
64
  return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
65
65
  }
66
- function tt(i, t) {
67
- if (t === void 0 || i === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
66
+ function st(n, t) {
67
+ if (t === void 0 || n === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
68
68
  return t;
69
- const e = i.lastIndexOf("/");
69
+ const e = n.lastIndexOf("/");
70
70
  if (e >= 0) {
71
- const s = i.substring(0, e + 1);
71
+ const s = n.substring(0, e + 1);
72
72
  for (; s.endsWith("/") && t.startsWith("/"); ) t = t.substring(1);
73
73
  return s + t;
74
74
  }
75
75
  return t;
76
76
  }
77
77
  function Ae() {
78
- return K !== void 0 || (K = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), X("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", K)), K;
78
+ return H !== void 0 || (H = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", H)), H;
79
79
  }
80
- let K;
81
- function Le() {
80
+ let H;
81
+ function ve() {
82
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;
83
+ const n = new URL(window.location.href), t = n.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(n.hostname);
84
+ return n.hostname === "127.0.0.1" || t;
85
85
  }
86
- class st {
86
+ class rt {
87
87
  constructor(t = 100, e = {}) {
88
88
  this.maxConcurrent = t, this.debug = e.debug ?? !1, window.requestAnimationFrame(this.tick);
89
89
  }
@@ -110,86 +110,98 @@ class st {
110
110
  const t = this.maxConcurrent - this._running.size;
111
111
  for (let e = 0; e < t && this._queue.length > 0; e++) {
112
112
  this.debug && console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);
113
- const { key: s, resolve: n } = this._queue.shift();
114
- n({
115
- use: (r) => this.add(s, r)
113
+ const { key: s, resolve: r } = this._queue.shift();
114
+ r({
115
+ use: (i) => this.add(s, i)
116
116
  });
117
117
  }
118
118
  }
119
119
  }
120
- const rt = typeof window > "u" && typeof document > "u", me = Symbol("needle:raycast-mesh");
121
- function Z(i) {
122
- return i?.[me] instanceof J ? i[me] : null;
120
+ function it(n) {
121
+ const t = n.image?.width ?? 0, e = n.image?.height ?? 0, s = n.image?.depth ?? 1, r = Math.floor(Math.log2(Math.max(t, e, s))) + 1, i = ot(n);
122
+ return t * e * s * i * (1 - Math.pow(0.25, r)) / (1 - 0.25);
123
123
  }
124
- function nt(i, t) {
125
- if ((i.type === "Mesh" || i.type === "SkinnedMesh") && !Z(i)) {
126
- const s = it(t);
127
- s.userData = { isRaycastMesh: !0 }, i[me] = s;
124
+ function ot(n) {
125
+ let t = 4;
126
+ const e = n.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);
128
+ let s = 1;
129
+ const r = n.type;
130
+ return r === 1009 || r === 1010 ? s = 1 : r === 1011 || r === 1012 ? s = 2 : r === 1013 || r === 1014 || r === 1015 ? s = 4 : r === 1016 && (s = 2), t * s;
131
+ }
132
+ const nt = typeof window > "u" && typeof document > "u", ye = /* @__PURE__ */ Symbol("needle:raycast-mesh");
133
+ function ee(n) {
134
+ return n?.[ye] instanceof V ? n[ye] : null;
135
+ }
136
+ function at(n, t) {
137
+ if ((n.type === "Mesh" || n.type === "SkinnedMesh") && !ee(n)) {
138
+ const s = ut(t);
139
+ s.userData = { isRaycastMesh: !0 }, n[ye] = s;
128
140
  }
129
141
  }
130
- function ot(i = !0) {
131
- if (i) {
132
- if (Y) return;
133
- const t = Y = q.prototype.raycast;
134
- q.prototype.raycast = function(e, s) {
135
- const n = this, r = Z(n);
142
+ function lt(n = !0) {
143
+ if (n) {
144
+ if (Q) return;
145
+ const t = Q = X.prototype.raycast;
146
+ X.prototype.raycast = function(e, s) {
147
+ const r = this, i = ee(r);
136
148
  let o;
137
- r && n.isMesh && (o = n.geometry, n.geometry = r), t.call(this, e, s), o && (n.geometry = o);
149
+ i && r.isMesh && (o = r.geometry, r.geometry = i), t.call(this, e, s), o && (r.geometry = o);
138
150
  };
139
151
  } else {
140
- if (!Y) return;
141
- q.prototype.raycast = Y, Y = null;
152
+ if (!Q) return;
153
+ X.prototype.raycast = Q, Q = null;
142
154
  }
143
155
  }
144
- let Y = null;
145
- function it(i) {
146
- const t = new J();
147
- for (const e in i.attributes)
148
- t.setAttribute(e, i.getAttribute(e));
149
- return t.setIndex(i.getIndex()), t;
156
+ let Q = null;
157
+ function ut(n) {
158
+ const t = new V();
159
+ for (const e in n.attributes)
160
+ t.setAttribute(e, n.getAttribute(e));
161
+ return t.setIndex(n.getIndex()), t;
150
162
  }
151
- const U = new Array(), g = X("debugprogressive");
152
- let Q, N = -1;
153
- if (g) {
154
- let i = function() {
155
- N += 1, N >= t && (N = -1), console.log(`Toggle LOD level [${N}]`);
163
+ const z = new Array(), f = N("debugprogressive");
164
+ let Z, E = -1;
165
+ if (f) {
166
+ let n = function() {
167
+ E += 1, E >= t && (E = -1), console.log(`Toggle LOD level [${E}]`);
156
168
  }, t = 6;
157
169
  window.addEventListener("keyup", (e) => {
158
- e.key === "p" && i(), e.key === "w" && (Q = !Q, console.log(`Toggle wireframe [${Q}]`));
170
+ e.key === "p" && n(), e.key === "w" && (Z = !Z, console.log(`Toggle wireframe [${Z}]`));
159
171
  const s = parseInt(e.key);
160
- !isNaN(s) && s >= 0 && (N = s, console.log(`Set LOD level to [${N}]`));
172
+ !isNaN(s) && s >= 0 && (E = s, console.log(`Set LOD level to [${E}]`));
161
173
  });
162
174
  }
163
- function Ie(i) {
164
- if (g && Q !== void 0)
165
- if (Array.isArray(i))
166
- for (const t of i)
167
- Ie(t);
168
- else i && "wireframe" in i && (i.wireframe = Q === !0);
175
+ function ke(n) {
176
+ if (f && Z !== void 0)
177
+ if (Array.isArray(n))
178
+ for (const t of n)
179
+ ke(t);
180
+ else n && "wireframe" in n && (n.wireframe = Z === !0);
169
181
  }
170
- const H = new Array();
171
- let at = 0;
172
- const lt = Ae() ? 2 : 10;
173
- function ut(i) {
174
- if (H.length < lt) {
175
- const s = H.length;
176
- g && console.warn(`[Worker] Creating new worker #${s}`);
177
- const n = we.createWorker(i || {});
178
- return H.push(n), n;
179
- }
180
- const t = at++ % H.length;
181
- return H[t];
182
+ const J = new Array();
183
+ let ct = 0;
184
+ const dt = Ae() ? 2 : 10;
185
+ function ft(n) {
186
+ if (J.length < dt) {
187
+ const s = J.length;
188
+ f && console.warn(`[Worker] Creating new worker #${s}`);
189
+ const r = _e.createWorker(n || {});
190
+ return J.push(r), r;
191
+ }
192
+ const t = ct++ % J.length;
193
+ return J[t];
182
194
  }
183
- class we {
195
+ class _e {
184
196
  constructor(t, e) {
185
197
  this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
186
- const n = s.data;
187
- switch (this._debug && console.log("[Worker] EVENT", n), n.type) {
198
+ const r = s.data;
199
+ switch (this._debug && console.log("[Worker] EVENT", r), r.type) {
188
200
  case "loaded-gltf":
189
- for (const r of this._running)
190
- if (r.url === n.result.url) {
191
- dt(n.result), r.resolve(n.result);
192
- const o = r.url;
201
+ for (const i of this._running)
202
+ if (i.url === r.result.url) {
203
+ ht(r.result), i.resolve(r.result);
204
+ const o = i.url;
193
205
  o.startsWith("blob:") && URL.revokeObjectURL(o);
194
206
  }
195
207
  }
@@ -202,23 +214,23 @@ class we {
202
214
  static async createWorker(t) {
203
215
  const e = new Worker(new URL(
204
216
  /* @vite-ignore */
205
- "/assets/loader.worker-CwaLRBn2.js",
217
+ "/assets/loader.worker-CCrD-Ycm.js",
206
218
  import.meta.url
207
219
  ), {
208
220
  type: "module"
209
221
  });
210
- return new we(e, t);
222
+ return new _e(e, t);
211
223
  }
212
224
  _running = [];
213
225
  _webglRenderer = null;
214
226
  async load(t, e) {
215
- const s = He();
216
- let n = e?.renderer;
217
- n || (this._webglRenderer ??= (async () => {
227
+ const s = Qe();
228
+ let r = e?.renderer;
229
+ r || (this._webglRenderer ??= (async () => {
218
230
  const { WebGLRenderer: u } = await import("three");
219
231
  return new u();
220
- })(), n = await this._webglRenderer);
221
- const l = xe(n).ktx2Loader.workerConfig;
232
+ })(), r = await this._webglRenderer);
233
+ const l = we(r).ktx2Loader.workerConfig;
222
234
  t instanceof URL ? t = t.toString() : t.startsWith("file:") ? t = URL.createObjectURL(new Blob([t])) : !t.startsWith("blob:") && !t.startsWith("http:") && !t.startsWith("https:") && (t = new URL(t, window.location.href).toString());
223
235
  const a = {
224
236
  type: "load",
@@ -236,23 +248,23 @@ class we {
236
248
  }
237
249
  _debug = !1;
238
250
  }
239
- function dt(i) {
240
- for (const t of i.geometries) {
241
- const e = t.geometry, s = new J();
251
+ function ht(n) {
252
+ for (const t of n.geometries) {
253
+ const e = t.geometry, s = new V();
242
254
  if (s.name = e.name || "", e.index) {
243
- const n = e.index;
244
- s.setIndex(ae(n));
255
+ const r = e.index;
256
+ s.setIndex(le(r));
245
257
  }
246
- for (const n in e.attributes) {
247
- const r = e.attributes[n], o = ae(r);
248
- s.setAttribute(n, o);
258
+ for (const r in e.attributes) {
259
+ const i = e.attributes[r], o = le(i);
260
+ s.setAttribute(r, o);
249
261
  }
250
262
  if (e.morphAttributes)
251
- for (const n in e.morphAttributes) {
252
- const o = e.morphAttributes[n].map((l) => ae(l));
253
- s.morphAttributes[n] = o;
263
+ for (const r in e.morphAttributes) {
264
+ const o = e.morphAttributes[r].map((l) => le(l));
265
+ s.morphAttributes[r] = o;
254
266
  }
255
- if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new he(), s.boundingBox.min = new A(
267
+ if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new A(
256
268
  e.boundingBox?.min.x,
257
269
  e.boundingBox?.min.y,
258
270
  e.boundingBox?.min.z
@@ -260,7 +272,7 @@ function dt(i) {
260
272
  e.boundingBox?.max.x,
261
273
  e.boundingBox?.max.y,
262
274
  e.boundingBox?.max.z
263
- ), s.boundingSphere = new De(
275
+ ), s.boundingSphere = new Oe(
264
276
  new A(
265
277
  e.boundingSphere?.center.x,
266
278
  e.boundingSphere?.center.y,
@@ -268,18 +280,18 @@ function dt(i) {
268
280
  ),
269
281
  e.boundingSphere?.radius
270
282
  ), e.groups)
271
- for (const n of e.groups)
272
- s.addGroup(n.start, n.count, n.materialIndex);
283
+ for (const r of e.groups)
284
+ s.addGroup(r.start, r.count, r.materialIndex);
273
285
  e.userData && (s.userData = e.userData), t.geometry = s;
274
286
  }
275
- for (const t of i.textures) {
287
+ for (const t of n.textures) {
276
288
  const e = t.texture;
277
289
  let s = null;
278
290
  if (e.isCompressedTexture) {
279
- const n = e.mipmaps, r = e.image?.width || e.source?.data?.width || -1, o = e.image?.height || e.source?.data?.height || -1;
280
- s = new $e(
281
- n,
291
+ const r = e.mipmaps, i = e.image?.width || e.source?.data?.width || -1, o = e.image?.height || e.source?.data?.height || -1;
292
+ s = new Ge(
282
293
  r,
294
+ i,
283
295
  o,
284
296
  e.format,
285
297
  e.type,
@@ -292,7 +304,7 @@ function dt(i) {
292
304
  e.colorSpace
293
305
  );
294
306
  } else
295
- s = new E(
307
+ s = new F(
296
308
  e.image,
297
309
  e.mapping,
298
310
  e.wrapS,
@@ -303,28 +315,30 @@ function dt(i) {
303
315
  e.type,
304
316
  e.anisotropy,
305
317
  e.colorSpace
306
- ), 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 Ge(...e.matrix.elements);
318
+ ), s.mipmaps = e.mipmaps, s.channel = e.channel, s.source.data = e.source.data, s.flipY = e.flipY, s.premultiplyAlpha = e.premultiplyAlpha, s.unpackAlignment = e.unpackAlignment, s.matrix = new Fe(...e.matrix.elements);
307
319
  if (!s) {
308
320
  console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");
309
321
  continue;
310
322
  }
311
323
  t.texture = s;
312
324
  }
313
- return i;
325
+ return n;
314
326
  }
315
- function ae(i) {
316
- let t = i;
317
- if ("isInterleavedBufferAttribute" in i && i.isInterleavedBufferAttribute) {
318
- const e = i.data, s = e.array, n = new Fe(s, e.stride);
319
- t = new We(n, i.itemSize, s.byteOffset, i.normalized), t.offset = i.offset;
320
- } else "isBufferAttribute" in i && i.isBufferAttribute && (t = new Ue(i.array, i.itemSize, i.normalized), t.usage = i.usage, t.gpuType = i.gpuType, t.updateRanges = i.updateRanges);
327
+ function le(n) {
328
+ let t = n;
329
+ if ("isInterleavedBufferAttribute" in n && n.isInterleavedBufferAttribute) {
330
+ const e = n.data, s = e.array, r = new We(s, e.stride);
331
+ t = new Ue(r, n.itemSize, s.byteOffset, n.normalized), t.offset = n.offset;
332
+ } else "isBufferAttribute" in n && n.isBufferAttribute && (t = new ze(n.array, n.itemSize, n.normalized), t.usage = n.usage, t.gpuType = n.gpuType, t.updateRanges = n.updateRanges);
321
333
  return t;
322
334
  }
323
- const ct = X("gltf-progressive-worker"), ft = X("gltf-progressive-reduce-mipmaps"), le = Symbol("needle-progressive-texture"), F = "NEEDLE_progressive";
335
+ const gt = N("gltf-progressive-worker");
336
+ N("gltf-progressive-reduce-mipmaps");
337
+ const K = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), W = "NEEDLE_progressive";
324
338
  class y {
325
339
  /** The name of the extension */
326
340
  get name() {
327
- return F;
341
+ return W;
328
342
  }
329
343
  // #region PUBLIC API
330
344
  static getMeshLODExtension(t) {
@@ -336,8 +350,8 @@ class y {
336
350
  return e ?? -1;
337
351
  }
338
352
  static getMaterialMinMaxLODsCount(t, e) {
339
- const s = this, n = "LODS:minmax", r = t[n];
340
- if (r != null) return r;
353
+ const s = this, r = "LODS:minmax", i = t[r];
354
+ if (i != null) return i;
341
355
  if (e || (e = {
342
356
  min_count: 1 / 0,
343
357
  max_count: 0,
@@ -345,9 +359,9 @@ class y {
345
359
  }), Array.isArray(t)) {
346
360
  for (const l of t)
347
361
  this.getMaterialMinMaxLODsCount(l, e);
348
- return t[n] = e, e;
362
+ return t[r] = e, e;
349
363
  }
350
- if (g === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
364
+ if (f === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
351
365
  const l = t;
352
366
  for (const a of Object.keys(l.uniforms)) {
353
367
  const u = l.uniforms[a].value;
@@ -359,17 +373,17 @@ class y {
359
373
  a?.isTexture === !0 && o(a, e);
360
374
  }
361
375
  else
362
- g && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
363
- return t[n] = e, e;
376
+ f && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
377
+ return t[r] = e, e;
364
378
  function o(l, a) {
365
379
  const u = s.getAssignedLODInformation(l);
366
380
  if (u) {
367
381
  const c = s.lodInfos.get(u.key);
368
382
  if (c && c.lods) {
369
383
  a.min_count = Math.min(a.min_count, c.lods.length), a.max_count = Math.max(a.max_count, c.lods.length);
370
- for (let p = 0; p < c.lods.length; p++) {
371
- const _ = c.lods[p];
372
- _.width && (a.lods[p] = a.lods[p] || { min_height: 1 / 0, max_height: 0 }, a.lods[p].min_height = Math.min(a.lods[p].min_height, _.height), a.lods[p].max_height = Math.max(a.lods[p].max_height, _.height));
384
+ for (let m = 0; m < c.lods.length; m++) {
385
+ const w = c.lods[m];
386
+ w.width && (a.lods[m] = a.lods[m] || { min_height: 1 / 0, max_height: 0 }, a.lods[m].min_height = Math.min(a.lods[m].min_height, w.height), a.lods[m].max_height = Math.max(a.lods[m].max_height, w.height));
373
387
  }
374
388
  }
375
389
  }
@@ -382,28 +396,28 @@ class y {
382
396
  */
383
397
  static hasLODLevelAvailable(t, e) {
384
398
  if (Array.isArray(t)) {
385
- for (const r of t)
386
- if (this.hasLODLevelAvailable(r, e)) return !0;
399
+ for (const i of t)
400
+ if (this.hasLODLevelAvailable(i, e)) return !0;
387
401
  return !1;
388
402
  }
389
403
  if (t.isMaterial === !0) {
390
- for (const r of Object.keys(t)) {
391
- const o = t[r];
404
+ for (const i of Object.keys(t)) {
405
+ const o = t[i];
392
406
  if (o && o.isTexture && this.hasLODLevelAvailable(o, e))
393
407
  return !0;
394
408
  }
395
409
  return !1;
396
410
  } else if (t.isGroup === !0) {
397
- for (const r of t.children)
398
- if (r.isMesh === !0 && this.hasLODLevelAvailable(r, e))
411
+ for (const i of t.children)
412
+ if (i.isMesh === !0 && this.hasLODLevelAvailable(i, e))
399
413
  return !0;
400
414
  }
401
- let s, n;
415
+ let s, r;
402
416
  if (t.isMesh ? s = t.geometry : (t.isBufferGeometry || t.isTexture) && (s = t), s && s?.userData?.LODS) {
403
- const r = s.userData.LODS;
404
- if (n = this.lodInfos.get(r.key), e === void 0) return n != null;
405
- if (n)
406
- return Array.isArray(n.lods) ? e < n.lods.length : e === 0;
417
+ const i = s.userData.LODS;
418
+ if (r = this.lodInfos.get(i.key), e === void 0) return r != null;
419
+ if (r)
420
+ return Array.isArray(r.lods) ? e < r.lods.length : e === 0;
407
421
  }
408
422
  return !1;
409
423
  }
@@ -423,20 +437,20 @@ class y {
423
437
  */
424
438
  static assignMeshLOD(t, e) {
425
439
  if (!t) return Promise.resolve(null);
426
- if (t instanceof q || t.isMesh === !0) {
427
- const s = t.geometry, n = this.getAssignedLODInformation(s);
428
- if (!n)
440
+ if (t instanceof X || t.isMesh === !0) {
441
+ const s = t.geometry, r = this.getAssignedLODInformation(s);
442
+ if (!r)
429
443
  return Promise.resolve(null);
430
- for (const r of U)
431
- r.onBeforeGetLODMesh?.(t, e);
432
- return t["LOD:requested level"] = e, y.getOrLoadLOD(s, e).then((r) => {
433
- if (Array.isArray(r)) {
434
- const o = n.index || 0;
435
- r = r[o];
444
+ for (const i of z)
445
+ i.onBeforeGetLODMesh?.(t, e);
446
+ return t["LOD:requested level"] = e, y.getOrLoadLOD(s, e).then((i) => {
447
+ if (Array.isArray(i)) {
448
+ const o = r.index || 0;
449
+ i = i[o];
436
450
  }
437
- return t["LOD:requested level"] === e && (delete t["LOD:requested level"], r && s != r && (r?.isBufferGeometry ? t.geometry = r : g && console.error("Invalid LOD geometry", r))), r;
438
- }).catch((r) => (console.error("Error loading mesh LOD", t, r), null));
439
- } else g && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
451
+ return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i : f && console.error("Invalid LOD geometry", i))), i;
452
+ }).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
453
+ } else f && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
440
454
  return Promise.resolve(null);
441
455
  }
442
456
  static assignTextureLOD(t, e = 0) {
@@ -444,14 +458,14 @@ class y {
444
458
  if (t.isMesh === !0) {
445
459
  const s = t;
446
460
  if (Array.isArray(s.material)) {
447
- const n = new Array();
448
- for (const r of s.material) {
449
- const o = this.assignTextureLOD(r, e);
450
- n.push(o);
461
+ const r = new Array();
462
+ for (const i of s.material) {
463
+ const o = this.assignTextureLOD(i, e);
464
+ r.push(o);
451
465
  }
452
- return Promise.all(n).then((r) => {
466
+ return Promise.all(r).then((i) => {
453
467
  const o = new Array();
454
- for (const l of r)
468
+ for (const l of i)
455
469
  Array.isArray(l) && o.push(...l);
456
470
  return o;
457
471
  });
@@ -459,14 +473,14 @@ class y {
459
473
  return this.assignTextureLOD(s.material, e);
460
474
  }
461
475
  if (t.isMaterial === !0) {
462
- const s = t, n = [], r = new Array();
476
+ const s = t, r = [], i = new Array();
463
477
  if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
464
478
  const o = s;
465
479
  for (const l of Object.keys(o.uniforms)) {
466
480
  const a = o.uniforms[l].value;
467
481
  if (a?.isTexture === !0) {
468
482
  const u = this.assignTextureLODForSlot(a, e, s, l).then((c) => (c && o.uniforms[l].value != c && (o.uniforms[l].value = c, o.uniformsNeedUpdate = !0), c));
469
- n.push(u), r.push(l);
483
+ r.push(u), i.push(l);
470
484
  }
471
485
  }
472
486
  } else
@@ -474,58 +488,58 @@ class y {
474
488
  const l = s[o];
475
489
  if (l?.isTexture === !0) {
476
490
  const a = this.assignTextureLODForSlot(l, e, s, o);
477
- n.push(a), r.push(o);
491
+ r.push(a), i.push(o);
478
492
  }
479
493
  }
480
- return Promise.all(n).then((o) => {
494
+ return Promise.all(r).then((o) => {
481
495
  const l = new Array();
482
496
  for (let a = 0; a < o.length; a++) {
483
- const u = o[a], c = r[a];
497
+ const u = o[a], c = i[a];
484
498
  u && u.isTexture === !0 ? l.push({ material: s, slot: c, texture: u, level: e }) : l.push({ material: s, slot: c, texture: null, level: e });
485
499
  }
486
500
  return l;
487
501
  });
488
502
  }
489
- if (t instanceof E || t.isTexture === !0) {
503
+ if (t instanceof F || t.isTexture === !0) {
490
504
  const s = t;
491
505
  return this.assignTextureLODForSlot(s, e, null, null);
492
506
  }
493
507
  return Promise.resolve(null);
494
508
  }
495
509
  // #region INTERNAL
496
- static assignTextureLODForSlot(t, e, s, n) {
497
- return t?.isTexture !== !0 ? Promise.resolve(null) : n === "glyphMap" ? Promise.resolve(t) : y.getOrLoadLOD(t, e).then((r) => {
498
- if (Array.isArray(r))
510
+ static assignTextureLODForSlot(t, e, s, r) {
511
+ return t?.isTexture !== !0 ? Promise.resolve(null) : r === "glyphMap" ? Promise.resolve(t) : y.getOrLoadLOD(t, e).then((i) => {
512
+ if (Array.isArray(i))
499
513
  return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), null;
500
- if (r?.isTexture === !0) {
501
- if (r != t && s && n) {
502
- const o = s[n];
503
- if (o && !g) {
514
+ if (i?.isTexture === !0) {
515
+ if (i != t && s && r) {
516
+ const o = s[r];
517
+ if (o && !f) {
504
518
  const l = this.getAssignedLODInformation(o);
505
519
  if (l && l?.level < e)
506
- return g === "verbose" && console.warn("Assigned texture level is already higher: ", l.level, e, s, o, r), null;
520
+ return f === "verbose" && console.warn("Assigned texture level is already higher: ", l.level, e, s, o, i), i && i !== o && ((f || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${l.level})`, i.uuid), i.dispose()), null;
507
521
  }
508
- if (ft && r.mipmaps) {
509
- const l = r.mipmaps.length;
510
- r.mipmaps.length = Math.min(r.mipmaps.length, 3), l !== r.mipmaps.length && g && console.debug(`Reduced mipmap count from ${l} to ${r.mipmaps.length} for ${r.uuid}: ${r.image?.width}x${r.image?.height}.`);
522
+ if (this.trackTextureUsage(i), o && o !== i && this.untrackTextureUsage(o) && (f || K)) {
523
+ const a = this.getAssignedLODInformation(o);
524
+ console.log(`[gltf-progressive] Disposed old texture LOD ${a?.level ?? "?"} ${e} for ${s.name || s.type}.${r}`, o.uuid);
511
525
  }
512
- s[n] = r;
526
+ s[r] = i;
513
527
  }
514
- return r;
515
- } else g == "verbose" && console.warn("No LOD found for", t, e);
528
+ return i;
529
+ } else f == "verbose" && console.warn("No LOD found for", t, e);
516
530
  return null;
517
- }).catch((r) => (console.error("Error loading LOD", t, r), null));
531
+ }).catch((i) => (console.error("Error loading LOD", t, i), null));
518
532
  }
519
533
  parser;
520
534
  url;
521
535
  constructor(t) {
522
536
  const e = t.options.path;
523
- g && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
537
+ f && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
524
538
  }
525
539
  _isLoadingMesh;
526
540
  loadMesh = (t) => {
527
541
  if (this._isLoadingMesh) return null;
528
- const e = this.parser.json.meshes[t]?.extensions?.[F];
542
+ const e = this.parser.json.meshes[t]?.extensions?.[W];
529
543
  return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && y.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
530
544
  };
531
545
  // private _isLoadingTexture;
@@ -543,30 +557,30 @@ class y {
543
557
  // });
544
558
  // }
545
559
  afterRoot(t) {
546
- return g && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
560
+ return f && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
547
561
  if (e?.extensions) {
548
- const n = e?.extensions[F];
549
- if (n) {
550
- if (!n.lods) {
551
- g && console.warn("Texture has no LODs", n);
562
+ const r = e?.extensions[W];
563
+ if (r) {
564
+ if (!r.lods) {
565
+ f && console.warn("Texture has no LODs", r);
552
566
  return;
553
567
  }
554
- let r = !1;
568
+ let i = !1;
555
569
  for (const o of this.parser.associations.keys())
556
- o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (r = !0, y.registerTexture(this.url, o, n.lods?.length, s, n));
557
- r || this.parser.getDependency("texture", s).then((o) => {
558
- o && y.registerTexture(this.url, o, n.lods?.length, s, n);
570
+ o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (i = !0, y.registerTexture(this.url, o, r.lods?.length, s, r));
571
+ i || this.parser.getDependency("texture", s).then((o) => {
572
+ o && y.registerTexture(this.url, o, r.lods?.length, s, r);
559
573
  });
560
574
  }
561
575
  }
562
576
  }), this.parser.json.meshes?.forEach((e, s) => {
563
577
  if (e?.extensions) {
564
- const n = e?.extensions[F];
565
- if (n && n.lods) {
566
- for (const r of this.parser.associations.keys())
567
- if (r.isMesh) {
568
- const o = this.parser.associations.get(r);
569
- o?.meshes === s && y.registerMesh(this.url, n.guid, r, n.lods.length, o.primitives, n);
578
+ const r = e?.extensions[W];
579
+ if (r && r.lods) {
580
+ for (const i of this.parser.associations.keys())
581
+ if (i.isMesh) {
582
+ const o = this.parser.associations.get(i);
583
+ o?.meshes === s && y.registerMesh(this.url, r.guid, i, r.lods.length, o.primitives, r);
570
584
  }
571
585
  }
572
586
  }
@@ -575,174 +589,288 @@ class y {
575
589
  /**
576
590
  * Register a texture with LOD information
577
591
  */
578
- static registerTexture = (t, e, s, n, r) => {
592
+ static registerTexture = (t, e, s, r, i) => {
579
593
  if (!e) {
580
- g && console.error("!! gltf-progressive: Called register texture without texture");
594
+ f && console.error("!! gltf-progressive: Called register texture without texture");
581
595
  return;
582
596
  }
583
- if (g) {
597
+ if (f) {
584
598
  const l = e.image?.width || e.source?.data?.width || 0, a = e.image?.height || e.source?.data?.height || 0;
585
- console.log(`> gltf-progressive: register texture[${n}] "${e.name || e.uuid}", Current: ${l}x${a}, Max: ${r.lods[0]?.width}x${r.lods[0]?.height}, uuid: ${e.uuid}`, r, e);
599
+ console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${l}x${a}, Max: ${i.lods[0]?.width}x${i.lods[0]?.height}, uuid: ${e.uuid}`, i, e);
586
600
  }
587
- e.source && (e.source[le] = r);
588
- const o = r.guid;
589
- y.assignLODInformation(t, e, o, s, n), y.lodInfos.set(o, r), y.lowresCache.set(o, e);
601
+ e.source && (e.source[ue] = i);
602
+ const o = i.guid;
603
+ y.assignLODInformation(t, e, o, s, r), y.lodInfos.set(o, i), y.lowresCache.set(o, new WeakRef(e));
590
604
  };
591
605
  /**
592
606
  * Register a mesh with LOD information
593
607
  */
594
- static registerMesh = (t, e, s, n, r, o) => {
608
+ static registerMesh = (t, e, s, r, i, o) => {
595
609
  const l = s.geometry;
596
610
  if (!l) {
597
- g && console.warn("gltf-progressive: Register mesh without geometry");
611
+ f && console.warn("gltf-progressive: Register mesh without geometry");
598
612
  return;
599
613
  }
600
- l.userData || (l.userData = {}), g && console.log("> Progressive: register mesh " + s.name, { index: r, uuid: s.uuid }, o, s), y.assignLODInformation(t, l, e, n, r), y.lodInfos.set(e, o);
601
- let a = y.lowresCache.get(e);
602
- a ? a.push(s.geometry) : a = [s.geometry], y.lowresCache.set(e, a), n > 0 && !Z(s) && nt(s, l);
603
- for (const u of U)
604
- u.onRegisteredNewMesh?.(s, o);
614
+ l.userData || (l.userData = {}), f && console.log("> Progressive: register mesh " + s.name, { index: i, uuid: s.uuid }, o, s), y.assignLODInformation(t, l, e, r, i), y.lodInfos.set(e, o);
615
+ let u = y.lowresCache.get(e)?.deref();
616
+ u ? u.push(s.geometry) : u = [s.geometry], y.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && at(s, l);
617
+ for (const c of z)
618
+ c.onRegisteredNewMesh?.(s, o);
605
619
  };
620
+ /**
621
+ * Dispose cached resources to free memory.
622
+ * Call this when a model is removed from the scene to allow garbage collection of its LOD resources.
623
+ * Calls three.js `.dispose()` on cached Textures and BufferGeometries to free GPU memory.
624
+ * Also clears reference counts for disposed textures.
625
+ * @param guid Optional GUID to dispose resources for a specific model. If omitted, all cached resources are cleared.
626
+ */
627
+ static dispose(t) {
628
+ if (t) {
629
+ this.lodInfos.delete(t);
630
+ const e = this.lowresCache.get(t);
631
+ if (e) {
632
+ const s = e.deref();
633
+ if (s) {
634
+ if (s.isTexture) {
635
+ const r = s;
636
+ this.textureRefCounts.delete(r.uuid), r.dispose();
637
+ } else if (Array.isArray(s))
638
+ for (const r of s) r.dispose();
639
+ }
640
+ this.lowresCache.delete(t);
641
+ }
642
+ for (const [s, r] of this.cache)
643
+ s.includes(t) && (this._disposeCacheEntry(r), this.cache.delete(s));
644
+ } else {
645
+ this.lodInfos.clear();
646
+ for (const [, e] of this.lowresCache) {
647
+ const s = e.deref();
648
+ if (s) {
649
+ if (s.isTexture) {
650
+ const r = s;
651
+ this.textureRefCounts.delete(r.uuid), r.dispose();
652
+ } else if (Array.isArray(s))
653
+ for (const r of s) r.dispose();
654
+ }
655
+ }
656
+ this.lowresCache.clear();
657
+ for (const [, e] of this.cache)
658
+ this._disposeCacheEntry(e);
659
+ this.cache.clear(), this.textureRefCounts.clear();
660
+ }
661
+ }
662
+ /** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
663
+ static _disposeCacheEntry(t) {
664
+ if (t instanceof WeakRef) {
665
+ const e = t.deref();
666
+ e && (e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose());
667
+ } else
668
+ t.then((e) => {
669
+ if (e)
670
+ if (Array.isArray(e))
671
+ for (const s of e) s.dispose();
672
+ else
673
+ e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose();
674
+ }).catch(() => {
675
+ });
676
+ }
606
677
  /** A map of key = asset uuid and value = LOD information */
607
678
  static lodInfos = /* @__PURE__ */ new Map();
608
- /** cache of already loaded mesh lods */
609
- static previouslyLoaded = /* @__PURE__ */ new Map();
610
- /** this contains the geometry/textures that were originally loaded */
679
+ /** cache of already loaded mesh lods. Uses WeakRef for single resources to allow garbage collection when unused. */
680
+ static cache = /* @__PURE__ */ new Map();
681
+ /** this contains the geometry/textures that were originally loaded. Uses WeakRef to allow garbage collection when unused. */
611
682
  static lowresCache = /* @__PURE__ */ new Map();
683
+ /** Reference counting for textures to track usage across multiple materials/objects */
684
+ static textureRefCounts = /* @__PURE__ */ new Map();
685
+ /**
686
+ * FinalizationRegistry to automatically clean up `previouslyLoaded` cache entries
687
+ * when their associated three.js resources are garbage collected by the browser.
688
+ * The held value is the cache key string used in `previouslyLoaded`.
689
+ */
690
+ static _resourceRegistry = new FinalizationRegistry((t) => {
691
+ const e = y.cache.get(t);
692
+ (f || K) && console.debug(`[gltf-progressive] Memory: Resource GC'd
693
+ ${t}`), e instanceof WeakRef && (e.deref() || (y.cache.delete(t), (f || K) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
694
+ });
695
+ /**
696
+ * Track texture usage by incrementing reference count
697
+ */
698
+ static trackTextureUsage(t) {
699
+ const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
700
+ this.textureRefCounts.set(e, s + 1), f === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
701
+ }
702
+ /**
703
+ * Untrack texture usage by decrementing reference count.
704
+ * Automatically disposes the texture when reference count reaches zero.
705
+ * @returns true if the texture was disposed, false otherwise
706
+ */
707
+ static untrackTextureUsage(t) {
708
+ const e = t.uuid, s = this.textureRefCounts.get(e);
709
+ if (!s)
710
+ return (f === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
711
+ const r = s - 1;
712
+ if (r <= 0)
713
+ return this.textureRefCounts.delete(e), (f || K) && i("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
714
+ return this.textureRefCounts.set(e, r), f === "verbose" && i("[gltf-progressive] Memory: Untrack texture", r), !1;
715
+ function i(o, l) {
716
+ let a = t.image?.width || t.source?.data?.width || 0, u = t.image?.height || t.source?.data?.height || 0;
717
+ const c = a && u ? `${a}x${u}` : "N/A";
718
+ let m = "N/A";
719
+ a && u && (m = `~${(it(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${c} (${m}), refCount: ${s} → ${l}
720
+ ${e}`);
721
+ }
722
+ }
612
723
  static workers = [];
613
724
  static _workersIndex = 0;
614
725
  static async getOrLoadLOD(t, e) {
615
- const s = g == "verbose", n = this.getAssignedLODInformation(t);
616
- if (!n)
617
- return g && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
618
- const r = n?.key;
726
+ const s = f == "verbose", r = this.getAssignedLODInformation(t);
727
+ if (!r)
728
+ return f && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
729
+ const i = r?.key;
619
730
  let o;
620
731
  if (t.isTexture === !0) {
621
732
  const a = t;
622
- a.source && a.source[le] && (o = a.source[le]);
733
+ a.source && a.source[ue] && (o = a.source[ue]);
623
734
  }
624
- if (o || (o = y.lodInfos.get(r)), !o)
625
- g && console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`, t.type, y.lodInfos);
735
+ if (o || (o = y.lodInfos.get(i)), !o)
736
+ f && console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`, t.type, y.lodInfos);
626
737
  else {
627
738
  if (e > 0) {
628
739
  let c = !1;
629
- const p = Array.isArray(o.lods);
630
- if (p && e >= o.lods.length ? c = !0 : p || (c = !0), c)
631
- return this.lowresCache.get(r);
740
+ const m = Array.isArray(o.lods);
741
+ if (m && e >= o.lods.length ? c = !0 : m || (c = !0), c) {
742
+ const w = this.lowresCache.get(i);
743
+ if (w) {
744
+ const _ = w.deref();
745
+ if (_) return _;
746
+ this.lowresCache.delete(i), f && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${i}`);
747
+ }
748
+ return null;
749
+ }
632
750
  }
633
751
  const a = Array.isArray(o.lods) ? o.lods[e]?.path : o.lods;
634
752
  if (!a)
635
- return g && !o["missing:uri"] && (o["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, o)), null;
636
- const u = tt(n.url, a);
753
+ return f && !o["missing:uri"] && (o["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, o)), null;
754
+ const u = st(r.url, a);
637
755
  if (u.endsWith(".glb") || u.endsWith(".gltf")) {
638
756
  if (!o.guid)
639
757
  return console.warn("missing pointer for glb/gltf texture", o), null;
640
- const c = u + "_" + o.guid, p = await this.queue.slot(u), _ = this.previouslyLoaded.get(c);
641
- if (_ !== void 0) {
642
- s && console.log(`LOD ${e} was already loading/loaded: ${c}`);
643
- let d = await _.catch((O) => (console.error(`Error loading LOD ${e} from ${u}
644
- `, O), null)), x = !1;
645
- if (d == null || (d instanceof E && t instanceof E ? d.image?.data || d.source?.data ? d = this.copySettings(t, d) : (x = !0, this.previouslyLoaded.delete(c)) : d instanceof J && t instanceof J && (d.attributes.position?.array || (x = !0, this.previouslyLoaded.delete(c)))), !x)
646
- return d;
647
- }
648
- if (!p.use)
649
- return g && console.log(`LOD ${e} was aborted: ${u}`), null;
650
- const v = o, I = new Promise(async (d, x) => {
651
- if (ct) {
652
- const m = await (await ut({})).load(u);
653
- if (m.textures.length > 0)
654
- for (const f of m.textures) {
655
- let h = f.texture;
656
- return y.assignLODInformation(n.url, h, r, e, void 0), t instanceof E && (h = this.copySettings(t, h)), h && (h.guid = v.guid), d(h);
758
+ const c = u + "_" + o.guid, m = await this.queue.slot(u), w = this.cache.get(c);
759
+ if (w !== void 0)
760
+ if (s && console.log(`LOD ${e} was already loading/loaded: ${c}`), w instanceof WeakRef) {
761
+ const d = w.deref();
762
+ if (d) {
763
+ let g = d, b = !1;
764
+ if (g instanceof F && t instanceof F ? g.image?.data || g.source?.data ? g = this.copySettings(t, g) : b = !0 : g instanceof V && t instanceof V && (g.attributes.position?.array || (b = !0)), !b)
765
+ return g;
766
+ }
767
+ this.cache.delete(c), f && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${c}`);
768
+ } else {
769
+ let d = await w.catch((b) => (console.error(`Error loading LOD ${e} from ${u}
770
+ `, b), null)), g = !1;
771
+ if (d == null || (d instanceof F && t instanceof F ? d.image?.data || d.source?.data ? d = this.copySettings(t, d) : (g = !0, this.cache.delete(c)) : d instanceof V && t instanceof V && (d.attributes.position?.array || (g = !0, this.cache.delete(c)))), !g)
772
+ return d;
773
+ }
774
+ if (!m.use)
775
+ return f && console.log(`LOD ${e} was aborted: ${u}`), null;
776
+ const _ = o, k = new Promise(async (d, g) => {
777
+ if (gt) {
778
+ const x = await (await ft({})).load(u);
779
+ if (x.textures.length > 0)
780
+ for (const h of x.textures) {
781
+ let p = h.texture;
782
+ return y.assignLODInformation(r.url, p, i, e, void 0), t instanceof F && (p = this.copySettings(t, p)), p && (p.guid = _.guid), d(p);
657
783
  }
658
- if (m.geometries.length > 0) {
659
- const f = new Array();
660
- for (const h of m.geometries) {
661
- const M = h.geometry;
662
- y.assignLODInformation(n.url, M, r, e, h.primitiveIndex), f.push(M);
784
+ if (x.geometries.length > 0) {
785
+ const h = new Array();
786
+ for (const p of x.geometries) {
787
+ const O = p.geometry;
788
+ y.assignLODInformation(r.url, O, i, e, p.primitiveIndex), h.push(O);
663
789
  }
664
- return d(f);
790
+ return d(h);
665
791
  }
666
792
  return d(null);
667
793
  }
668
- const O = new ye();
669
- Se(O), g && (await new Promise((w) => setTimeout(w, 1e3)), s && console.warn("Start loading (delayed) " + u, v.guid));
794
+ const b = new xe();
795
+ Pe(b), f && (await new Promise((L) => setTimeout(L, 1e3)), s && console.warn("Start loading (delayed) " + u, _.guid));
670
796
  let B = u;
671
- if (v && Array.isArray(v.lods)) {
672
- const w = v.lods[e];
673
- w.hash && (B += "?v=" + w.hash);
797
+ if (_ && Array.isArray(_.lods)) {
798
+ const L = _.lods[e];
799
+ L.hash && (B += "?v=" + L.hash);
674
800
  }
675
- const b = await O.loadAsync(B).catch((w) => (console.error(`Error loading LOD ${e} from ${u}
676
- `, w), d(null)));
677
- if (!b)
801
+ const D = await b.loadAsync(B).catch((L) => (console.error(`Error loading LOD ${e} from ${u}
802
+ `, L), d(null)));
803
+ if (!D)
678
804
  return d(null);
679
- const z = b.parser;
680
- s && console.log("Loading finished " + u, v.guid);
681
- let S = 0;
682
- if (b.parser.json.textures) {
683
- let w = !1;
684
- for (const m of b.parser.json.textures) {
685
- if (m?.extensions) {
686
- const f = m?.extensions[F];
687
- if (f?.guid && f.guid === v.guid) {
688
- w = !0;
805
+ const q = D.parser;
806
+ s && console.log("Loading finished " + u, _.guid);
807
+ let P = 0;
808
+ if (D.parser.json.textures) {
809
+ let L = !1;
810
+ for (const x of D.parser.json.textures) {
811
+ if (x?.extensions) {
812
+ const h = x?.extensions[W];
813
+ if (h?.guid && h.guid === _.guid) {
814
+ L = !0;
689
815
  break;
690
816
  }
691
817
  }
692
- S++;
818
+ P++;
693
819
  }
694
- if (w) {
695
- let m = await z.getDependency("texture", S);
696
- return m && y.assignLODInformation(n.url, m, r, e, void 0), s && console.log('change "' + t.name + '" → "' + m.name + '"', u, S, m, c), t instanceof E && (m = this.copySettings(t, m)), m && (m.guid = v.guid), d(m);
697
- } else g && console.warn("Could not find texture with guid", v.guid, b.parser.json);
820
+ if (L) {
821
+ let x = await q.getDependency("texture", P);
822
+ return x && y.assignLODInformation(r.url, x, i, e, void 0), s && console.log('change "' + t.name + '" → "' + x.name + '"', u, P, x, c), t instanceof F && (x = this.copySettings(t, x)), x && (x.guid = _.guid), d(x);
823
+ } else f && console.warn("Could not find texture with guid", _.guid, D.parser.json);
698
824
  }
699
- if (S = 0, b.parser.json.meshes) {
700
- let w = !1;
701
- for (const m of b.parser.json.meshes) {
702
- if (m?.extensions) {
703
- const f = m?.extensions[F];
704
- if (f?.guid && f.guid === v.guid) {
705
- w = !0;
825
+ if (P = 0, D.parser.json.meshes) {
826
+ let L = !1;
827
+ for (const x of D.parser.json.meshes) {
828
+ if (x?.extensions) {
829
+ const h = x?.extensions[W];
830
+ if (h?.guid && h.guid === _.guid) {
831
+ L = !0;
706
832
  break;
707
833
  }
708
834
  }
709
- S++;
835
+ P++;
710
836
  }
711
- if (w) {
712
- const m = await z.getDependency("mesh", S);
713
- if (s && console.log(`Loaded Mesh "${m.name}"`, u, S, m, c), m.isMesh === !0) {
714
- const f = m.geometry;
715
- return y.assignLODInformation(n.url, f, r, e, 0), d(f);
837
+ if (L) {
838
+ const x = await q.getDependency("mesh", P);
839
+ if (s && console.log(`Loaded Mesh "${x.name}"`, u, P, x, c), x.isMesh === !0) {
840
+ const h = x.geometry;
841
+ return y.assignLODInformation(r.url, h, i, e, 0), d(h);
716
842
  } else {
717
- const f = new Array();
718
- for (let h = 0; h < m.children.length; h++) {
719
- const M = m.children[h];
720
- if (M.isMesh === !0) {
721
- const D = M.geometry;
722
- y.assignLODInformation(n.url, D, r, e, h), f.push(D);
843
+ const h = new Array();
844
+ for (let p = 0; p < x.children.length; p++) {
845
+ const O = x.children[p];
846
+ if (O.isMesh === !0) {
847
+ const S = O.geometry;
848
+ y.assignLODInformation(r.url, S, i, e, p), h.push(S);
723
849
  }
724
850
  }
725
- return d(f);
851
+ return d(h);
726
852
  }
727
- } else g && console.warn("Could not find mesh with guid", v.guid, b.parser.json);
853
+ } else f && console.warn("Could not find mesh with guid", _.guid, D.parser.json);
728
854
  }
729
855
  return d(null);
730
856
  });
731
- return this.previouslyLoaded.set(c, I), p.use(I), await I;
732
- } else if (t instanceof E) {
857
+ this.cache.set(c, k), m.use(k);
858
+ const M = await k;
859
+ return M != null ? M instanceof F ? (this.cache.set(c, new WeakRef(M)), y._resourceRegistry.register(M, c)) : Array.isArray(M) ? this.cache.set(c, Promise.resolve(M)) : this.cache.set(c, Promise.resolve(M)) : this.cache.set(c, Promise.resolve(null)), M;
860
+ } else if (t instanceof F) {
733
861
  s && console.log("Load texture from uri: " + u);
734
- const p = await new ze().loadAsync(u);
735
- return p ? (p.guid = o.guid, p.flipY = !1, p.needsUpdate = !0, p.colorSpace = t.colorSpace, s && console.log(o, p)) : g && console.warn("failed loading", u), p;
862
+ const m = await new Ne().loadAsync(u);
863
+ return m ? (m.guid = o.guid, m.flipY = !1, m.needsUpdate = !0, m.colorSpace = t.colorSpace, s && console.log(o, m)) : f && console.warn("failed loading", u), m;
736
864
  }
737
865
  }
738
866
  return null;
739
867
  }
740
868
  static maxConcurrent = 50;
741
- static queue = new st(y.maxConcurrent, { debug: g != !1 });
742
- static assignLODInformation(t, e, s, n, r) {
869
+ static queue = new rt(y.maxConcurrent, { debug: f != !1 });
870
+ static assignLODInformation(t, e, s, r, i) {
743
871
  if (!e) return;
744
872
  e.userData || (e.userData = {});
745
- const o = new ht(t, s, n, r);
873
+ const o = new pt(t, s, r, i);
746
874
  e.userData.LODS = o, "source" in e && typeof e.source == "object" && (e.source.LODS = o);
747
875
  }
748
876
  static getAssignedLODInformation(t) {
@@ -750,26 +878,26 @@ class y {
750
878
  }
751
879
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
752
880
  static copySettings(t, e) {
753
- return e ? (g === "verbose" && console.debug(`Copy texture settings
881
+ return e ? (f === "verbose" && console.debug(`Copy texture settings
754
882
  `, t.uuid, `
755
883
  `, 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;
756
884
  }
757
885
  }
758
- class ht {
886
+ class pt {
759
887
  url;
760
888
  /** the key to lookup the LOD information */
761
889
  key;
762
890
  level;
763
891
  /** For multi objects (e.g. a group of meshes) this is the index of the object */
764
892
  index;
765
- constructor(t, e, s, n) {
766
- this.url = t, this.key = e, this.level = s, n != null && (this.index = n);
893
+ constructor(t, e, s, r) {
894
+ this.url = t, this.key = e, this.level = s, r != null && (this.index = r);
767
895
  }
768
896
  }
769
- class ue {
770
- static addPromise = (t, e, s, n) => {
771
- n.forEach((r) => {
772
- r.add(t, e, s);
897
+ class ce {
898
+ static addPromise = (t, e, s, r) => {
899
+ r.forEach((i) => {
900
+ i.add(t, e, s);
773
901
  });
774
902
  };
775
903
  ready;
@@ -799,9 +927,9 @@ class ue {
799
927
  _awaiting = [];
800
928
  _maxPromisesPerObject = 1;
801
929
  constructor(t, e) {
802
- const n = Math.max(e.frames ?? 2, 2);
803
- this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture = n, this.ready = new Promise((r) => {
804
- this._resolve = r;
930
+ const r = Math.max(e.frames ?? 2, 2);
931
+ this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture = r, this.ready = new Promise((i) => {
932
+ this._resolve = i;
805
933
  }), this.ready.finally(() => {
806
934
  this._resolved = !0, this._awaiting.length = 0;
807
935
  }), this._signal = e.signal, this._signal?.addEventListener("abort", () => {
@@ -815,18 +943,18 @@ class ue {
815
943
  _seen = /* @__PURE__ */ new WeakMap();
816
944
  add(t, e, s) {
817
945
  if (this._resolved) {
818
- g && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
946
+ f && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
819
947
  return;
820
948
  }
821
949
  if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
822
950
  if (this._maxPromisesPerObject >= 1)
823
951
  if (this._seen.has(e)) {
824
- let n = this._seen.get(e);
825
- if (n >= this._maxPromisesPerObject) {
826
- g && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
952
+ let r = this._seen.get(e);
953
+ if (r >= this._maxPromisesPerObject) {
954
+ f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
827
955
  return;
828
956
  }
829
- this._seen.set(e, n + 1);
957
+ this._seen.set(e, r + 1);
830
958
  } else
831
959
  this._seen.set(e, 1);
832
960
  this._awaiting.push(s), this._addedCount++, s.finally(() => {
@@ -842,22 +970,22 @@ class ue {
842
970
  });
843
971
  }
844
972
  }
845
- const k = X("debugprogressive"), gt = X("noprogressive"), de = Symbol("Needle:LODSManager"), ce = Symbol("Needle:LODState"), W = Symbol("Needle:CurrentLOD"), P = { mesh_lod: -1, texture_lod: -1 };
846
- class L {
973
+ const R = N("debugprogressive"), mt = N("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), U = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), T = { mesh_lod: -1, texture_lod: -1 };
974
+ class v {
847
975
  /**
848
976
  * 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.
849
977
  */
850
978
  static debugDrawLine;
851
979
  /** @internal */
852
980
  static getObjectLODState(t) {
853
- return t[ce];
981
+ return t[fe];
854
982
  }
855
983
  static addPlugin(t) {
856
- U.push(t);
984
+ z.push(t);
857
985
  }
858
986
  static removePlugin(t) {
859
- const e = U.indexOf(t);
860
- e >= 0 && U.splice(e, 1);
987
+ const e = z.indexOf(t);
988
+ e >= 0 && z.splice(e, 1);
861
989
  }
862
990
  /**
863
991
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -867,7 +995,7 @@ class L {
867
995
  static get(t, e) {
868
996
  if (t[de])
869
997
  return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[de];
870
- const s = new L(t, {
998
+ const s = new v(t, {
871
999
  engine: "unknown",
872
1000
  ...e
873
1001
  });
@@ -875,10 +1003,10 @@ class L {
875
1003
  }
876
1004
  renderer;
877
1005
  context;
878
- projectionScreenMatrix = new _e();
1006
+ projectionScreenMatrix = new Le();
879
1007
  /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
880
1008
  get plugins() {
881
- return U;
1009
+ return z;
882
1010
  }
883
1011
  /**
884
1012
  * Force override the LOD level for all objects (meshes + textures) rendered in the scene
@@ -919,13 +1047,13 @@ class L {
919
1047
  * Call to await LODs loading during the next render cycle.
920
1048
  */
921
1049
  awaitLoading(t) {
922
- const e = this._promiseGroupIds++, s = new ue(this.#r, { ...t });
1050
+ const e = this._promiseGroupIds++, s = new ce(this.#r, { ...t });
923
1051
  this._newPromiseGroups.push(s);
924
- const n = performance.now();
1052
+ const r = performance.now();
925
1053
  return s.ready.finally(() => {
926
- const r = this._newPromiseGroups.indexOf(s);
927
- r >= 0 && (this._newPromiseGroups.splice(r, 1), Le() && performance.measure("LODsManager:awaitLoading", {
928
- start: n,
1054
+ const i = this._newPromiseGroups.indexOf(s);
1055
+ i >= 0 && (this._newPromiseGroups.splice(i, 1), ve() && performance.measure("LODsManager:awaitLoading", {
1056
+ start: r,
929
1057
  detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
930
1058
  }));
931
1059
  }), s.ready;
@@ -950,10 +1078,10 @@ class L {
950
1078
  this.renderer = t, this.context = { ...e };
951
1079
  }
952
1080
  #t;
953
- #o = new Ee();
1081
+ #o = new qe();
954
1082
  #r = 0;
955
- #n = 0;
956
1083
  #i = 0;
1084
+ #n = 0;
957
1085
  #s = 0;
958
1086
  _fpsBuffer = [60, 60, 60, 60, 60];
959
1087
  /**
@@ -965,11 +1093,11 @@ class L {
965
1093
  let t = 0;
966
1094
  this.#t = this.renderer.render;
967
1095
  const e = this;
968
- xe(this.renderer), this.renderer.render = function(s, n) {
969
- const r = e.renderer.getRenderTarget();
970
- (r == null || "isXRRenderTarget" in r && r.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((l, a) => l + a) / e._fpsBuffer.length, k && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
1096
+ we(this.renderer), this.renderer.render = function(s, r) {
1097
+ const i = e.renderer.getRenderTarget();
1098
+ (i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#o.getDelta(), e.#n += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((l, a) => l + a) / e._fpsBuffer.length, R && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
971
1099
  const o = t++;
972
- e.#t.call(this, s, n), e.onAfterRender(s, n, o);
1100
+ e.#t.call(this, s, r), e.onAfterRender(s, r, o);
973
1101
  };
974
1102
  }
975
1103
  disable() {
@@ -980,14 +1108,14 @@ class L {
980
1108
  }
981
1109
  onAfterRender(t, e, s) {
982
1110
  if (this.pause) return;
983
- const r = this.renderer.renderLists.get(t, 0).opaque;
1111
+ const i = this.renderer.renderLists.get(t, 0).opaque;
984
1112
  let o = !0;
985
- if (r.length === 1) {
986
- const l = r[0].material;
1113
+ if (i.length === 1) {
1114
+ const l = i[0].material;
987
1115
  (l.name === "EffectMaterial" || l.name === "CopyShader") && (o = !1);
988
1116
  }
989
1117
  if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
990
- if (gt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, k && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, k && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
1118
+ if (mt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, R && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, R && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
991
1119
  return;
992
1120
  this.internalUpdate(t, e), this._postprocessPromiseGroups();
993
1121
  }
@@ -996,12 +1124,12 @@ class L {
996
1124
  * Update LODs in a scene
997
1125
  */
998
1126
  internalUpdate(t, e) {
999
- const s = this.renderer.renderLists.get(t, 0), n = s.opaque;
1127
+ const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
1000
1128
  this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
1001
- const r = this.targetTriangleDensity;
1002
- for (const a of n) {
1129
+ const i = this.targetTriangleDensity;
1130
+ for (const a of r) {
1003
1131
  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")) {
1004
- k && (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)));
1132
+ R && (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", a, a.material.name, a.material.type)));
1005
1133
  continue;
1006
1134
  }
1007
1135
  switch (a.material.type) {
@@ -1013,38 +1141,38 @@ class L {
1013
1141
  case "MeshDepthMaterial":
1014
1142
  continue;
1015
1143
  }
1016
- if (k === "color" && a.material && !a.object.progressive_debug_color) {
1144
+ if (R === "color" && a.material && !a.object.progressive_debug_color) {
1017
1145
  a.object.progressive_debug_color = !0;
1018
- const c = Math.random() * 16777215, p = new Ne({ color: c });
1019
- a.object.material = p;
1146
+ const c = Math.random() * 16777215, m = new Ee({ color: c });
1147
+ a.object.material = m;
1020
1148
  }
1021
1149
  const u = a.object;
1022
- (u instanceof q || u.isMesh) && this.updateLODs(t, e, u, r);
1150
+ (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1023
1151
  }
1024
1152
  const o = s.transparent;
1025
1153
  for (const a of o) {
1026
1154
  const u = a.object;
1027
- (u instanceof q || u.isMesh) && this.updateLODs(t, e, u, r);
1155
+ (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1028
1156
  }
1029
1157
  const l = s.transmissive;
1030
1158
  for (const a of l) {
1031
1159
  const u = a.object;
1032
- (u instanceof q || u.isMesh) && this.updateLODs(t, e, u, r);
1160
+ (u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
1033
1161
  }
1034
1162
  }
1035
1163
  /** Update the LOD levels for the renderer. */
1036
- updateLODs(t, e, s, n) {
1164
+ updateLODs(t, e, s, r) {
1037
1165
  s.userData || (s.userData = {});
1038
- let r = s[ce];
1039
- if (r || (r = new pt(), s[ce] = r), r.frames++ < 2)
1166
+ let i = s[fe];
1167
+ if (i || (i = new yt(), s[fe] = i), i.frames++ < 2)
1040
1168
  return;
1041
- for (const l of U)
1169
+ for (const l of z)
1042
1170
  l.onBeforeUpdateLOD?.(this.renderer, t, e, s);
1043
- const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : N;
1044
- o >= 0 ? (P.mesh_lod = o, P.texture_lod = o) : (this.calculateLodLevel(e, s, r, n, P), P.mesh_lod = Math.round(P.mesh_lod), P.texture_lod = Math.round(P.texture_lod)), P.mesh_lod >= 0 && this.loadProgressiveMeshes(s, P.mesh_lod), s.material && P.texture_lod >= 0 && this.loadProgressiveTextures(s.material, P.texture_lod, o), g && s.material && !s.isGizmo && Ie(s.material);
1045
- for (const l of U)
1046
- l.onAfterUpdatedLOD?.(this.renderer, t, e, s, P);
1047
- r.lastLodLevel_Mesh = P.mesh_lod, r.lastLodLevel_Texture = P.texture_lod;
1171
+ const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : E;
1172
+ o >= 0 ? (T.mesh_lod = o, T.texture_lod = o) : (this.calculateLodLevel(e, s, i, r, T), T.mesh_lod = Math.round(T.mesh_lod), T.texture_lod = Math.round(T.texture_lod)), T.mesh_lod >= 0 && this.loadProgressiveMeshes(s, T.mesh_lod), s.material && T.texture_lod >= 0 && this.loadProgressiveTextures(s.material, T.texture_lod, o), f && s.material && !s.isGizmo && ke(s.material);
1173
+ for (const l of z)
1174
+ l.onAfterUpdatedLOD?.(this.renderer, t, e, s, T);
1175
+ i.lastLodLevel_Mesh = T.mesh_lod, i.lastLodLevel_Texture = T.texture_lod;
1048
1176
  }
1049
1177
  /** Load progressive textures for the given material
1050
1178
  * @param material the material to load the textures for
@@ -1054,17 +1182,17 @@ class L {
1054
1182
  loadProgressiveTextures(t, e, s) {
1055
1183
  if (!t) return;
1056
1184
  if (Array.isArray(t)) {
1057
- for (const r of t)
1058
- this.loadProgressiveTextures(r, e);
1185
+ for (const i of t)
1186
+ this.loadProgressiveTextures(i, e);
1059
1187
  return;
1060
1188
  }
1061
- let n = !1;
1062
- if ((t[W] === void 0 || e < t[W]) && (n = !0), s !== void 0 && s >= 0 && (n = t[W] != s, e = s), n) {
1063
- t[W] = e;
1064
- const r = y.assignTextureLOD(t, e).then((o) => {
1189
+ let r = !1;
1190
+ if ((t[U] === void 0 || e < t[U]) && (r = !0), s !== void 0 && s >= 0 && (r = t[U] != s, e = s), r) {
1191
+ t[U] = e;
1192
+ const i = y.assignTextureLOD(t, e).then((o) => {
1065
1193
  this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
1066
1194
  });
1067
- ue.addPromise("texture", t, r, this._newPromiseGroups);
1195
+ ce.addPromise("texture", t, i, this._newPromiseGroups);
1068
1196
  }
1069
1197
  }
1070
1198
  /** Load progressive meshes for the given mesh
@@ -1075,20 +1203,20 @@ class L {
1075
1203
  */
1076
1204
  loadProgressiveMeshes(t, e) {
1077
1205
  if (!t) return Promise.resolve(null);
1078
- let s = t[W] !== e;
1079
- const n = t["DEBUG:LOD"];
1080
- if (n != null && (s = t[W] != n, e = n), s) {
1081
- t[W] = e;
1082
- const r = t.geometry, o = y.assignMeshLOD(t, e).then((l) => (l && t[W] == e && r != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), l));
1083
- return ue.addPromise("mesh", t, o, this._newPromiseGroups), o;
1206
+ let s = t[U] !== e;
1207
+ const r = t["DEBUG:LOD"];
1208
+ if (r != null && (s = t[U] != r, e = r), s) {
1209
+ t[U] = e;
1210
+ const i = t.geometry, o = y.assignMeshLOD(t, e).then((l) => (l && t[U] == e && i != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), l));
1211
+ return ce.addPromise("mesh", t, o, this._newPromiseGroups), o;
1084
1212
  }
1085
1213
  return Promise.resolve(null);
1086
1214
  }
1087
1215
  // private testIfLODLevelsAreAvailable() {
1088
- _sphere = new De();
1089
- _tempBox = new he();
1090
- _tempBox2 = new he();
1091
- tempMatrix = new _e();
1216
+ _sphere = new Oe();
1217
+ _tempBox = new ge();
1218
+ _tempBox2 = new ge();
1219
+ tempMatrix = new Le();
1092
1220
  _tempWorldPosition = new A();
1093
1221
  _tempBoxSize = new A();
1094
1222
  _tempBox2Size = new A();
@@ -1098,120 +1226,120 @@ class L {
1098
1226
  static corner3 = new A();
1099
1227
  static _tempPtInside = new A();
1100
1228
  static isInside(t, e) {
1101
- const s = t.min, n = t.max, r = (s.x + n.x) * 0.5, o = (s.y + n.y) * 0.5;
1102
- return this._tempPtInside.set(r, o, s.z).applyMatrix4(e).z < 0;
1229
+ const s = t.min, r = t.max, i = (s.x + r.x) * 0.5, o = (s.y + r.y) * 0.5;
1230
+ return this._tempPtInside.set(i, o, s.z).applyMatrix4(e).z < 0;
1103
1231
  }
1104
1232
  static skinnedMeshBoundsFrameOffsetCounter = 0;
1105
- static $skinnedMeshBoundsOffset = Symbol("gltf-progressive-skinnedMeshBoundsOffset");
1233
+ static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
1106
1234
  // #region calculateLodLevel
1107
- calculateLodLevel(t, e, s, n, r) {
1235
+ calculateLodLevel(t, e, s, r, i) {
1108
1236
  if (!e) {
1109
- r.mesh_lod = -1, r.texture_lod = -1;
1237
+ i.mesh_lod = -1, i.texture_lod = -1;
1110
1238
  return;
1111
1239
  }
1112
1240
  if (!t) {
1113
- r.mesh_lod = -1, r.texture_lod = -1;
1241
+ i.mesh_lod = -1, i.texture_lod = -1;
1114
1242
  return;
1115
1243
  }
1116
1244
  let l = 10 + 1, a = !1;
1117
- if (k && e["DEBUG:LOD"] != null)
1245
+ if (R && e["DEBUG:LOD"] != null)
1118
1246
  return e["DEBUG:LOD"];
1119
- const u = y.getMeshLODExtension(e.geometry)?.lods, c = y.getPrimitiveIndex(e.geometry), p = u && u.length > 0, _ = y.getMaterialMinMaxLODsCount(e.material), v = _.min_count !== 1 / 0 && _.min_count >= 0 && _.max_count >= 0;
1120
- if (!p && !v) {
1121
- r.mesh_lod = 0, r.texture_lod = 0;
1247
+ const u = y.getMeshLODExtension(e.geometry)?.lods, c = y.getPrimitiveIndex(e.geometry), m = u && u.length > 0, w = y.getMaterialMinMaxLODsCount(e.material), _ = w.min_count !== 1 / 0 && w.min_count >= 0 && w.max_count >= 0;
1248
+ if (!m && !_) {
1249
+ i.mesh_lod = 0, i.texture_lod = 0;
1122
1250
  return;
1123
1251
  }
1124
- p || (a = !0, l = 0);
1125
- const I = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1126
- let G = e.geometry.boundingBox;
1252
+ m || (a = !0, l = 0);
1253
+ const k = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
1254
+ let M = e.geometry.boundingBox;
1127
1255
  if (e.type === "SkinnedMesh") {
1128
1256
  const d = e;
1129
1257
  if (!d.boundingBox)
1130
1258
  d.computeBoundingBox();
1131
1259
  else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
1132
- if (!d[L.$skinnedMeshBoundsOffset]) {
1133
- const O = L.skinnedMeshBoundsFrameOffsetCounter++;
1134
- d[L.$skinnedMeshBoundsOffset] = O;
1260
+ if (!d[v.$skinnedMeshBoundsOffset]) {
1261
+ const b = v.skinnedMeshBoundsFrameOffsetCounter++;
1262
+ d[v.$skinnedMeshBoundsOffset] = b;
1135
1263
  }
1136
- const x = d[L.$skinnedMeshBoundsOffset];
1137
- if ((s.frames + x) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1138
- const O = Z(d), B = d.geometry;
1139
- O && (d.geometry = O), d.computeBoundingBox(), d.geometry = B;
1264
+ const g = d[v.$skinnedMeshBoundsOffset];
1265
+ if ((s.frames + g) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
1266
+ const b = ee(d), B = d.geometry;
1267
+ b && (d.geometry = b), d.computeBoundingBox(), d.geometry = B;
1140
1268
  }
1141
1269
  }
1142
- G = d.boundingBox;
1270
+ M = d.boundingBox;
1143
1271
  }
1144
- if (G) {
1272
+ if (M) {
1145
1273
  const d = t;
1146
1274
  if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
1147
1275
  this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
1148
- const f = t.getWorldPosition(this._tempWorldPosition);
1149
- if (this._sphere.containsPoint(f)) {
1150
- r.mesh_lod = 0, r.texture_lod = 0;
1276
+ const h = t.getWorldPosition(this._tempWorldPosition);
1277
+ if (this._sphere.containsPoint(h)) {
1278
+ i.mesh_lod = 0, i.texture_lod = 0;
1151
1279
  return;
1152
1280
  }
1153
1281
  }
1154
- if (this._tempBox.copy(G), this._tempBox.applyMatrix4(e.matrixWorld), d.isPerspectiveCamera && L.isInside(this._tempBox, this.projectionScreenMatrix)) {
1155
- r.mesh_lod = 0, r.texture_lod = 0;
1282
+ if (this._tempBox.copy(M), this._tempBox.applyMatrix4(e.matrixWorld), d.isPerspectiveCamera && v.isInside(this._tempBox, this.projectionScreenMatrix)) {
1283
+ i.mesh_lod = 0, i.texture_lod = 0;
1156
1284
  return;
1157
1285
  }
1158
1286
  if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && d.isPerspectiveCamera && d.fov > 70) {
1159
- const f = this._tempBox.min, h = this._tempBox.max;
1160
- let M = f.x, D = f.y, $ = h.x, j = h.y;
1161
- const ee = 2, oe = 1.5, te = (f.x + h.x) * 0.5, se = (f.y + h.y) * 0.5;
1162
- M = (M - te) * ee + te, D = (D - se) * ee + se, $ = ($ - te) * ee + te, j = (j - se) * ee + se;
1163
- const Re = M < 0 && $ > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(h.x)), Be = D < 0 && j > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(h.y)), ie = Math.max(Re, Be);
1164
- s.lastCentrality = (oe - ie) * (oe - ie) * (oe - ie);
1287
+ const h = this._tempBox.min, p = this._tempBox.max;
1288
+ let O = h.x, S = h.y, G = p.x, Y = p.y;
1289
+ const te = 2, ne = 1.5, se = (h.x + p.x) * 0.5, re = (h.y + p.y) * 0.5;
1290
+ O = (O - se) * te + se, S = (S - re) * te + re, G = (G - se) * te + se, Y = (Y - re) * te + re;
1291
+ const $e = O < 0 && G > 0 ? 0 : Math.min(Math.abs(h.x), Math.abs(p.x)), Be = S < 0 && Y > 0 ? 0 : Math.min(Math.abs(h.y), Math.abs(p.y)), ae = Math.max($e, Be);
1292
+ s.lastCentrality = (ne - ae) * (ne - ae) * (ne - ae);
1165
1293
  } else
1166
1294
  s.lastCentrality = 1;
1167
- const x = this._tempBox.getSize(this._tempBoxSize);
1168
- x.multiplyScalar(0.5), screen.availHeight > 0 && I > 0 && x.multiplyScalar(I / screen.availHeight), t.isPerspectiveCamera ? x.x *= t.aspect : t.isOrthographicCamera;
1169
- const O = t.matrixWorldInverse, B = this._tempBox2;
1170
- B.copy(G), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(O);
1171
- const b = B.getSize(this._tempBox2Size), z = Math.max(b.x, b.y);
1172
- if (Math.max(x.x, x.y) != 0 && z != 0 && (x.z = b.z / Math.max(b.x, b.y) * Math.max(x.x, x.y)), s.lastScreenCoverage = Math.max(x.x, x.y, x.z), s.lastScreenspaceVolume.copy(x), s.lastScreenCoverage *= s.lastCentrality, k && L.debugDrawLine) {
1173
- const f = this.tempMatrix.copy(this.projectionScreenMatrix);
1174
- f.invert();
1175
- const h = L.corner0, M = L.corner1, D = L.corner2, $ = L.corner3;
1176
- h.copy(this._tempBox.min), M.copy(this._tempBox.max), M.x = h.x, D.copy(this._tempBox.max), D.y = h.y, $.copy(this._tempBox.max);
1177
- const j = (h.z + $.z) * 0.5;
1178
- h.z = M.z = D.z = $.z = j, h.applyMatrix4(f), M.applyMatrix4(f), D.applyMatrix4(f), $.applyMatrix4(f), L.debugDrawLine(h, M, 255), L.debugDrawLine(h, D, 255), L.debugDrawLine(M, $, 255), L.debugDrawLine(D, $, 255);
1295
+ const g = this._tempBox.getSize(this._tempBoxSize);
1296
+ g.multiplyScalar(0.5), screen.availHeight > 0 && k > 0 && g.multiplyScalar(k / screen.availHeight), t.isPerspectiveCamera ? g.x *= t.aspect : t.isOrthographicCamera;
1297
+ const b = t.matrixWorldInverse, B = this._tempBox2;
1298
+ B.copy(M), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(b);
1299
+ const D = B.getSize(this._tempBox2Size), q = Math.max(D.x, D.y);
1300
+ if (Math.max(g.x, g.y) != 0 && q != 0 && (g.z = D.z / Math.max(D.x, D.y) * Math.max(g.x, g.y)), s.lastScreenCoverage = Math.max(g.x, g.y, g.z), s.lastScreenspaceVolume.copy(g), s.lastScreenCoverage *= s.lastCentrality, R && v.debugDrawLine) {
1301
+ const h = this.tempMatrix.copy(this.projectionScreenMatrix);
1302
+ h.invert();
1303
+ const p = v.corner0, O = v.corner1, S = v.corner2, G = v.corner3;
1304
+ p.copy(this._tempBox.min), O.copy(this._tempBox.max), O.x = p.x, S.copy(this._tempBox.max), S.y = p.y, G.copy(this._tempBox.max);
1305
+ const Y = (p.z + G.z) * 0.5;
1306
+ p.z = O.z = S.z = G.z = Y, p.applyMatrix4(h), O.applyMatrix4(h), S.applyMatrix4(h), G.applyMatrix4(h), v.debugDrawLine(p, O, 255), v.debugDrawLine(p, S, 255), v.debugDrawLine(O, G, 255), v.debugDrawLine(S, G, 255);
1179
1307
  }
1180
- let w = 999;
1308
+ let L = 999;
1181
1309
  if (u && s.lastScreenCoverage > 0)
1182
- for (let f = 0; f < u.length; f++) {
1183
- const h = u[f], D = (h.densities?.[c] || h.density || 1e-5) / s.lastScreenCoverage;
1184
- if (c > 0 && Le() && !h.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), D < n) {
1185
- w = f;
1310
+ for (let h = 0; h < u.length; h++) {
1311
+ const p = u[h], S = (p.densities?.[c] || p.density || 1e-5) / s.lastScreenCoverage;
1312
+ if (c > 0 && ve() && !p.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), S < r) {
1313
+ L = h;
1186
1314
  break;
1187
1315
  }
1188
1316
  }
1189
- w < l && (l = w, a = !0);
1317
+ L < l && (l = L, a = !0);
1190
1318
  }
1191
- if (a ? r.mesh_lod = l : r.mesh_lod = s.lastLodLevel_Mesh, k && r.mesh_lod != s.lastLodLevel_Mesh) {
1192
- const x = u?.[r.mesh_lod];
1193
- x && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (density: ${x.densities?.[c].toFixed(0)}) | ${e.name}`);
1319
+ if (a ? i.mesh_lod = l : i.mesh_lod = s.lastLodLevel_Mesh, R && i.mesh_lod != s.lastLodLevel_Mesh) {
1320
+ const g = u?.[i.mesh_lod];
1321
+ g && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${g.densities?.[c].toFixed(0)}) | ${e.name}`);
1194
1322
  }
1195
- if (v) {
1323
+ if (_) {
1196
1324
  const d = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
1197
1325
  if (s.lastLodLevel_Texture < 0) {
1198
- if (r.texture_lod = _.max_count - 1, k) {
1199
- const x = _.lods[_.max_count - 1];
1200
- k && console.log(`First Texture LOD ${r.texture_lod} (${x.max_height}px) - ${e.name}`);
1326
+ if (i.texture_lod = w.max_count - 1, R) {
1327
+ const g = w.lods[w.max_count - 1];
1328
+ R && console.log(`First Texture LOD ${i.texture_lod} (${g.max_height}px) - ${e.name}`);
1201
1329
  }
1202
1330
  } else {
1203
- const x = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1204
- let O = s.lastScreenCoverage * 4;
1205
- this.context?.engine === "model-viewer" && (O *= 1.5);
1206
- const b = I / window.devicePixelRatio * O;
1207
- let z = !1;
1208
- for (let S = _.lods.length - 1; S >= 0; S--) {
1209
- const w = _.lods[S];
1210
- if (!(d && w.max_height >= 2048) && !(Ae() && w.max_height > 4096) && (w.max_height > b || !z && S === 0)) {
1211
- if (z = !0, r.texture_lod = S, k && r.texture_lod < s.lastLodLevel_Texture) {
1212
- const m = w.max_height;
1213
- console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${m}px
1214
- Screensize: ${b.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${x.toFixed(1)}
1331
+ const g = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1332
+ let b = s.lastScreenCoverage * 4;
1333
+ this.context?.engine === "model-viewer" && (b *= 1.5);
1334
+ const D = k / window.devicePixelRatio * b;
1335
+ let q = !1;
1336
+ for (let P = w.lods.length - 1; P >= 0; P--) {
1337
+ const L = w.lods[P];
1338
+ if (!(d && L.max_height >= 2048) && !(Ae() && L.max_height > 4096) && (L.max_height > D || !q && P === 0)) {
1339
+ if (q = !0, i.texture_lod = P, R && i.texture_lod < s.lastLodLevel_Texture) {
1340
+ const x = L.max_height;
1341
+ console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${x}px
1342
+ Screensize: ${D.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
1215
1343
  ${e.name}`);
1216
1344
  }
1217
1345
  break;
@@ -1219,10 +1347,10 @@ ${e.name}`);
1219
1347
  }
1220
1348
  }
1221
1349
  } else
1222
- r.texture_lod = 0;
1350
+ i.texture_lod = 0;
1223
1351
  }
1224
1352
  }
1225
- class pt {
1353
+ class yt {
1226
1354
  frames = 0;
1227
1355
  lastLodLevel_Mesh = -1;
1228
1356
  lastLodLevel_Texture = -1;
@@ -1230,75 +1358,75 @@ class pt {
1230
1358
  lastScreenspaceVolume = new A();
1231
1359
  lastCentrality = 0;
1232
1360
  }
1233
- const ve = Symbol("NEEDLE_mesh_lod"), re = Symbol("NEEDLE_texture_lod");
1234
- let fe = null;
1235
- function ke() {
1236
- const i = mt();
1237
- i && (i.mapURLs(function(t) {
1238
- return be(), t;
1239
- }), be(), fe?.disconnect(), fe = new MutationObserver((t) => {
1361
+ const be = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
1362
+ let he = null;
1363
+ function Re() {
1364
+ const n = xt();
1365
+ n && (n.mapURLs(function(t) {
1366
+ return Me(), t;
1367
+ }), Me(), he?.disconnect(), he = new MutationObserver((t) => {
1240
1368
  t.forEach((e) => {
1241
1369
  e.addedNodes.forEach((s) => {
1242
- s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ce(s);
1370
+ s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ie(s);
1243
1371
  });
1244
1372
  });
1245
- }), fe.observe(document, { childList: !0, subtree: !0 }));
1373
+ }), he.observe(document, { childList: !0, subtree: !0 }));
1246
1374
  }
1247
- function mt() {
1375
+ function xt() {
1248
1376
  if (typeof customElements > "u") return null;
1249
- const i = customElements.get("model-viewer");
1250
- return i || (customElements.whenDefined("model-viewer").then(() => {
1251
- console.debug("[gltf-progressive] model-viewer defined"), ke();
1377
+ const n = customElements.get("model-viewer");
1378
+ return n || (customElements.whenDefined("model-viewer").then(() => {
1379
+ console.debug("[gltf-progressive] model-viewer defined"), Re();
1252
1380
  }), null);
1253
1381
  }
1254
- function be() {
1382
+ function Me() {
1255
1383
  if (typeof document > "u") return;
1256
1384
  document.querySelectorAll("model-viewer").forEach((t) => {
1257
- Ce(t);
1385
+ Ie(t);
1258
1386
  });
1259
1387
  }
1260
- const Me = /* @__PURE__ */ new WeakSet();
1261
- let yt = 0;
1262
- function Ce(i) {
1263
- if (!i || Me.has(i))
1388
+ const De = /* @__PURE__ */ new WeakSet();
1389
+ let wt = 0;
1390
+ function Ie(n) {
1391
+ if (!n || De.has(n))
1264
1392
  return null;
1265
- Me.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++yt + `
1266
- `, i.getAttribute("src"));
1393
+ De.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
1394
+ `, n.getAttribute("src"));
1267
1395
  let t = null, e = null, s = null;
1268
- for (let n = i; n != null; n = Object.getPrototypeOf(n)) {
1269
- const r = Object.getOwnPropertySymbols(n), o = r.find((u) => u.toString() == "Symbol(renderer)"), l = r.find((u) => u.toString() == "Symbol(scene)"), a = r.find((u) => u.toString() == "Symbol(needsRender)");
1270
- !t && o != null && (t = i[o].threeRenderer), !e && l != null && (e = i[l]), !s && a != null && (s = i[a]);
1396
+ for (let r = n; r != null; r = Object.getPrototypeOf(r)) {
1397
+ const i = Object.getOwnPropertySymbols(r), o = i.find((u) => u.toString() == "Symbol(renderer)"), l = i.find((u) => u.toString() == "Symbol(scene)"), a = i.find((u) => u.toString() == "Symbol(needsRender)");
1398
+ !t && o != null && (t = n[o].threeRenderer), !e && l != null && (e = n[l]), !s && a != null && (s = n[a]);
1271
1399
  }
1272
1400
  if (t && e) {
1273
- let n = function() {
1401
+ let r = function() {
1274
1402
  if (s) {
1275
1403
  let o = 0, l = setInterval(() => {
1276
1404
  if (o++ > 5) {
1277
1405
  clearInterval(l);
1278
1406
  return;
1279
1407
  }
1280
- s?.call(i);
1408
+ s?.call(n);
1281
1409
  }, 300);
1282
1410
  }
1283
1411
  };
1284
1412
  console.debug("[gltf-progressive] setup model-viewer");
1285
- const r = L.get(t, { engine: "model-viewer" });
1286
- return L.addPlugin(new xt()), r.enable(), r.addEventListener("changed", () => {
1287
- s?.call(i);
1288
- }), i.addEventListener("model-visibility", (o) => {
1289
- o.detail.visible && s?.call(i);
1290
- }), i.addEventListener("load", () => {
1291
- n();
1413
+ const i = v.get(t, { engine: "model-viewer" });
1414
+ return v.addPlugin(new _t()), i.enable(), i.addEventListener("changed", () => {
1415
+ s?.call(n);
1416
+ }), n.addEventListener("model-visibility", (o) => {
1417
+ o.detail.visible && s?.call(n);
1418
+ }), n.addEventListener("load", () => {
1419
+ r();
1292
1420
  }), () => {
1293
- r.disable();
1421
+ i.disable();
1294
1422
  };
1295
1423
  }
1296
1424
  return null;
1297
1425
  }
1298
- class xt {
1426
+ class _t {
1299
1427
  _didWarnAboutMissingUrl = !1;
1300
- onBeforeUpdateLOD(t, e, s, n) {
1301
- this.tryParseMeshLOD(e, n), this.tryParseTextureLOD(e, n);
1428
+ onBeforeUpdateLOD(t, e, s, r) {
1429
+ this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
1302
1430
  }
1303
1431
  getUrl(t) {
1304
1432
  if (!t)
@@ -1313,27 +1441,27 @@ class xt {
1313
1441
  return t.element;
1314
1442
  }
1315
1443
  tryParseTextureLOD(t, e) {
1316
- if (e[re] == !0) return;
1317
- e[re] = !0;
1318
- const s = this.tryGetCurrentGLTF(t), n = this.tryGetCurrentModelViewer(t), r = this.getUrl(n);
1319
- if (r && s && e.material) {
1444
+ if (e[ie] == !0) return;
1445
+ e[ie] = !0;
1446
+ const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
1447
+ if (i && s && e.material) {
1320
1448
  let o = function(a) {
1321
- if (a[re] == !0) return;
1322
- a[re] = !0, a.userData && (a.userData.LOD = -1);
1449
+ if (a[ie] == !0) return;
1450
+ a[ie] = !0, a.userData && (a.userData.LOD = -1);
1323
1451
  const u = Object.keys(a);
1324
1452
  for (let c = 0; c < u.length; c++) {
1325
- const p = u[c], _ = a[p];
1326
- if (_?.isTexture === !0) {
1327
- const v = _.userData?.associations?.textures;
1328
- if (v == null) continue;
1329
- const I = s.parser.json.textures[v];
1330
- if (!I) {
1331
- console.warn("Texture data not found for texture index " + v);
1453
+ const m = u[c], w = a[m];
1454
+ if (w?.isTexture === !0) {
1455
+ const _ = w.userData?.associations?.textures;
1456
+ if (_ == null) continue;
1457
+ const k = s.parser.json.textures[_];
1458
+ if (!k) {
1459
+ console.warn("Texture data not found for texture index " + _);
1332
1460
  continue;
1333
1461
  }
1334
- if (I?.extensions?.[F]) {
1335
- const G = I.extensions[F];
1336
- G && r && y.registerTexture(r, _, G.lods.length, v, G);
1462
+ if (k?.extensions?.[W]) {
1463
+ const M = k.extensions[W];
1464
+ M && i && y.registerTexture(i, w, M.lods.length, _, M);
1337
1465
  }
1338
1466
  }
1339
1467
  }
@@ -1344,70 +1472,70 @@ class xt {
1344
1472
  }
1345
1473
  }
1346
1474
  tryParseMeshLOD(t, e) {
1347
- if (e[ve] == !0) return;
1348
- e[ve] = !0;
1349
- const s = this.tryGetCurrentModelViewer(t), n = this.getUrl(s);
1350
- if (!n)
1475
+ if (e[be] == !0) return;
1476
+ e[be] = !0;
1477
+ const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
1478
+ if (!r)
1351
1479
  return;
1352
- const r = e.userData?.gltfExtensions?.[F];
1353
- if (r && n) {
1480
+ const i = e.userData?.gltfExtensions?.[W];
1481
+ if (i && r) {
1354
1482
  const o = e.uuid;
1355
- y.registerMesh(n, o, e, 0, r.lods.length, r);
1483
+ y.registerMesh(r, o, e, 0, i.lods.length, i);
1356
1484
  }
1357
1485
  }
1358
1486
  }
1359
- function wt(...i) {
1360
- let t, e, s, n;
1361
- switch (i.length) {
1487
+ function Lt(...n) {
1488
+ let t, e, s, r;
1489
+ switch (n.length) {
1362
1490
  case 2:
1363
- [s, e] = i, n = {};
1491
+ [s, e] = n, r = {};
1364
1492
  break;
1365
1493
  case 3:
1366
- [s, e, n] = i;
1494
+ [s, e, r] = n;
1367
1495
  break;
1368
1496
  case 4:
1369
- [t, e, s, n] = i;
1497
+ [t, e, s, r] = n;
1370
1498
  break;
1371
1499
  default:
1372
1500
  throw new Error("Invalid arguments");
1373
1501
  }
1374
- xe(e), Se(s), Te(s, {
1502
+ we(e), Pe(s), Ce(s, {
1375
1503
  progressive: !0,
1376
- ...n?.hints
1504
+ ...r?.hints
1377
1505
  }), s.register((o) => new y(o));
1378
- const r = L.get(e);
1379
- return n?.enableLODsManager !== !1 && r.enable(), r;
1506
+ const i = v.get(e);
1507
+ return r?.enableLODsManager !== !1 && i.enable(), i;
1380
1508
  }
1381
- ke();
1382
- if (!rt) {
1383
- const i = {
1509
+ Re();
1510
+ if (!nt) {
1511
+ const n = {
1384
1512
  gltfProgressive: {
1385
- useNeedleProgressive: wt,
1386
- LODsManager: L,
1387
- configureLoader: Te,
1388
- getRaycastMesh: Z,
1389
- useRaycastMeshes: ot
1513
+ useNeedleProgressive: Lt,
1514
+ LODsManager: v,
1515
+ configureLoader: Ce,
1516
+ getRaycastMesh: ee,
1517
+ useRaycastMeshes: lt
1390
1518
  }
1391
1519
  };
1392
1520
  if (!globalThis.Needle)
1393
- globalThis.Needle = i;
1521
+ globalThis.Needle = n;
1394
1522
  else
1395
- for (const t in i)
1396
- globalThis.Needle[t] = i[t];
1523
+ for (const t in n)
1524
+ globalThis.Needle[t] = n[t];
1397
1525
  }
1398
1526
  export {
1399
- F as EXTENSION_NAME,
1400
- L as LODsManager,
1527
+ W as EXTENSION_NAME,
1528
+ v as LODsManager,
1401
1529
  y as NEEDLE_progressive,
1402
- je as VERSION,
1403
- Se as addDracoAndKTX2Loaders,
1404
- Te as configureLoader,
1405
- xe as createLoaders,
1406
- Z as getRaycastMesh,
1407
- ke as patchModelViewer,
1408
- nt as registerRaycastMesh,
1409
- Qe as setDracoDecoderLocation,
1410
- Je as setKTX2TranscoderLocation,
1411
- wt as useNeedleProgressive,
1412
- ot as useRaycastMeshes
1530
+ Ke as VERSION,
1531
+ Pe as addDracoAndKTX2Loaders,
1532
+ Ce as configureLoader,
1533
+ we as createLoaders,
1534
+ ee as getRaycastMesh,
1535
+ Re as patchModelViewer,
1536
+ at as registerRaycastMesh,
1537
+ Je as setDracoDecoderLocation,
1538
+ Ze as setKTX2TranscoderLocation,
1539
+ Lt as useNeedleProgressive,
1540
+ lt as useRaycastMeshes
1413
1541
  };