@needle-tools/gltf-progressive 3.4.0-next.a9f46ea → 3.4.0-next.ed30751

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