@needle-tools/gltf-progressive 1.0.0-alpha.13 → 1.0.0-alpha.15

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,57 +1,60 @@
1
- var le = Object.defineProperty;
2
- var ue = (l, e, t) => e in l ? le(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var c = (l, e, t) => (ue(l, typeof e != "symbol" ? e + "" : e, t), t);
4
- import { Mesh as q, BufferGeometry as Y, Material as ce, Texture as I, TextureLoader as fe, Matrix4 as te, Frustum as de, Sphere as ge, Box3 as re, Vector3 as C } from "three";
5
- import { GLTFLoader as he } from "three/examples/jsm/loaders/GLTFLoader.js";
6
- import { MeshoptDecoder as pe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
7
- import { DRACOLoader as ye } from "three/examples/jsm/loaders/DRACOLoader.js";
8
- import { KTX2Loader as me } from "three/examples/jsm/loaders/KTX2Loader.js";
9
- let K = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", j = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
10
- fetch(K + "draco_decoder.js", { method: "head" }).catch((l) => {
11
- K = "./include/draco/", j = "./include/ktx2/";
1
+ var ue = Object.defineProperty;
2
+ var ce = (a, e, t) => e in a ? ue(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
3
+ var c = (a, e, t) => (ce(a, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import { MeshoptDecoder as fe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
5
+ import { DRACOLoader as de } from "three/examples/jsm/loaders/DRACOLoader.js";
6
+ import { KTX2Loader as ge } from "three/examples/jsm/loaders/KTX2Loader.js";
7
+ import { BufferGeometry as K, Mesh as X, Material as he, Texture as U, TextureLoader as pe, Matrix4 as te, Frustum as ye, Sphere as me, Box3 as re, Vector3 as C } from "three";
8
+ import { GLTFLoader as Le } from "three/examples/jsm/loaders/GLTFLoader.js";
9
+ let Y = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", j = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
10
+ fetch(Y + "draco_decoder.js", { method: "head" }).catch((a) => {
11
+ Y = "./include/draco/", j = "./include/ktx2/";
12
12
  });
13
- function _e(l) {
14
- K = l;
13
+ function Re(a) {
14
+ Y = a;
15
15
  }
16
- function Be(l) {
17
- j = l;
16
+ function Ce(a) {
17
+ j = a;
18
18
  }
19
- let U, J, W;
20
- function ne(l) {
21
- U || (U = new ye(), U.setDecoderPath(K), U.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(j)), J || (J = pe), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
19
+ let W, Q, z;
20
+ function oe(a) {
21
+ W || (W = new de(), W.setDecoderPath(Y), W.setDecoderConfig({ type: "js" })), z || (z = new ge(), z.setTranscoderPath(j)), Q || (Q = fe), a ? z.detectSupport(a) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
22
22
  }
23
- function oe(l) {
24
- l.dracoLoader || l.setDRACOLoader(U), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(J);
23
+ function ae(a) {
24
+ a.dracoLoader || a.setDRACOLoader(W), a.ktx2Loader || a.setKTX2Loader(z), a.meshoptDecoder || a.setMeshoptDecoder(Q);
25
25
  }
26
- function ee(l) {
27
- const t = new URL(window.location.href).searchParams.get(l);
26
+ function ee(a) {
27
+ const t = new URL(window.location.href).searchParams.get(a);
28
28
  return t == null || t === "0" || t === "false" ? !1 : t === "" ? !0 : t;
29
29
  }
30
- function Le(l, e) {
31
- if (e === void 0 || e.startsWith("./") || e.startsWith("http") || l === void 0)
30
+ function De(a, e) {
31
+ if (e === void 0 || e.startsWith("./") || e.startsWith("http") || a === void 0)
32
32
  return e;
33
- const t = l.lastIndexOf("/");
33
+ const t = a.lastIndexOf("/");
34
34
  if (t >= 0) {
35
- const r = l.substring(0, t + 1);
35
+ const r = a.substring(0, t + 1);
36
36
  for (; r.endsWith("/") && e.startsWith("/"); )
37
37
  e = e.substring(1);
38
38
  return r + e;
39
39
  }
40
40
  return e;
41
41
  }
42
- const Q = new Array();
43
- function ke(l) {
44
- Q.push(l);
42
+ function xe(a) {
43
+ var e;
44
+ return ((e = a.userData) == null ? void 0 : e["needle:raycast-mesh"]) instanceof K ? a.userData["needle:raycast-mesh"] : null;
45
45
  }
46
- const R = "NEEDLE_progressive", S = ee("debugprogressive"), V = Symbol("needle-progressive-texture"), z = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
46
+ function we(a, e) {
47
+ (a.type === "Mesh" || a.type === "SkinnedMesh") && (a.userData || (a.userData = {}), a.userData["needle:raycast-mesh"] = e);
48
+ }
49
+ const F = new Array(), E = "NEEDLE_progressive", S = ee("debugprogressive"), H = Symbol("needle-progressive-texture"), N = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
47
50
  if (S) {
48
- let l = function() {
49
- e += 1, console.log("Toggle LOD level", e, z), z.forEach((i, n) => {
51
+ let a = function() {
52
+ e += 1, console.log("Toggle LOD level", e, N), N.forEach((i, n) => {
50
53
  for (const s of i.keys) {
51
54
  const o = n[s];
52
55
  if (o.isBufferGeometry === !0) {
53
- const a = v.getMeshLODInformation(o), g = a ? Math.min(e, a.lods.length) : 0;
54
- n["DEBUG:LOD"] = e, v.assignMeshLOD(n, g), a && (t = Math.max(t, a.lods.length - 1));
56
+ const l = v.getMeshLODInformation(o), g = l ? Math.min(e, l.lods.length) : 0;
57
+ n["DEBUG:LOD"] = e, v.assignMeshLOD(n, g), l && (t = Math.max(t, l.lods.length - 1));
55
58
  } else if (n.isMaterial === !0) {
56
59
  n["DEBUG:LOD"] = e, v.assignTextureLOD(n, e);
57
60
  break;
@@ -60,17 +63,17 @@ if (S) {
60
63
  }), e >= t && (e = -1);
61
64
  }, e = -1, t = 2, r = !1;
62
65
  window.addEventListener("keyup", (i) => {
63
- i.key === "p" && l(), i.key === "w" && (r = !r, Z && Z.forEach((n) => {
66
+ i.key === "p" && a(), i.key === "w" && (r = !r, Z && Z.forEach((n) => {
64
67
  n.name != "BackgroundCubeMaterial" && "wireframe" in n && (n.wireframe = r);
65
68
  }));
66
69
  });
67
70
  }
68
- function se(l, e, t) {
71
+ function se(a, e, t) {
69
72
  var i;
70
73
  if (!S)
71
74
  return;
72
- z.has(l) || z.set(l, { keys: [], sourceId: t });
73
- const r = z.get(l);
75
+ N.has(a) || N.set(a, { keys: [], sourceId: t });
76
+ const r = N.get(a);
74
77
  ((i = r == null ? void 0 : r.keys) == null ? void 0 : i.includes(e)) == !1 && r.keys.push(e);
75
78
  }
76
79
  const M = class {
@@ -81,7 +84,7 @@ const M = class {
81
84
  }
82
85
  /** The name of the extension */
83
86
  get name() {
84
- return R;
87
+ return E;
85
88
  }
86
89
  static getMeshLODInformation(e) {
87
90
  const t = this.getAssignedLODInformation(e);
@@ -134,11 +137,11 @@ const M = class {
134
137
  var r;
135
138
  if (!e)
136
139
  return Promise.resolve(null);
137
- if (e instanceof q || e.isMesh === !0) {
140
+ if (e instanceof X || e.isMesh === !0) {
138
141
  const i = e.geometry, n = this.getAssignedLODInformation(i);
139
142
  if (!n)
140
143
  return Promise.resolve(null);
141
- for (const s of Q)
144
+ for (const s of F)
142
145
  (r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
143
146
  return e["LOD:requested level"] = t, M.getOrLoadLOD(i, t).then((s) => {
144
147
  if (e["LOD:requested level"] === t) {
@@ -146,7 +149,7 @@ const M = class {
146
149
  const o = n.index || 0;
147
150
  s = s[o];
148
151
  }
149
- s && i != s && s instanceof Y && (e.geometry = s, S && se(e, "geometry", n.url));
152
+ s && i != s && s instanceof K && (e.geometry = s, S && se(e, "geometry", n.url));
150
153
  }
151
154
  return s;
152
155
  }).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
@@ -164,14 +167,14 @@ const M = class {
164
167
  static assignTextureLOD(e, t = 0) {
165
168
  if (!e)
166
169
  return Promise.resolve(null);
167
- if (e instanceof ce || e.isMaterial === !0) {
170
+ if (e instanceof he || e.isMaterial === !0) {
168
171
  const r = e, i = [], n = new Array();
169
172
  if (S && Z.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
170
173
  const s = r;
171
174
  for (const o of Object.keys(s.uniforms)) {
172
- const a = s.uniforms[o].value;
173
- if ((a == null ? void 0 : a.isTexture) === !0) {
174
- const g = this.assignTextureLODForSlot(a, t, r, o);
175
+ const l = s.uniforms[o].value;
176
+ if ((l == null ? void 0 : l.isTexture) === !0) {
177
+ const g = this.assignTextureLODForSlot(l, t, r, o);
175
178
  i.push(g), n.push(o);
176
179
  }
177
180
  }
@@ -179,20 +182,20 @@ const M = class {
179
182
  for (const s of Object.keys(r)) {
180
183
  const o = r[s];
181
184
  if ((o == null ? void 0 : o.isTexture) === !0) {
182
- const a = this.assignTextureLODForSlot(o, t, r, s);
183
- i.push(a), n.push(s);
185
+ const l = this.assignTextureLODForSlot(o, t, r, s);
186
+ i.push(l), n.push(s);
184
187
  }
185
188
  }
186
189
  return Promise.all(i).then((s) => {
187
190
  const o = new Array();
188
- for (let a = 0; a < s.length; a++) {
189
- const g = s[a], f = n[a];
191
+ for (let l = 0; l < s.length; l++) {
192
+ const g = s[l], f = n[l];
190
193
  g && g.isTexture === !0 ? o.push({ material: r, slot: f, texture: g, level: t }) : o.push({ material: r, slot: f, texture: null, level: t });
191
194
  }
192
195
  return o;
193
196
  });
194
197
  }
195
- if (e instanceof I || e.isTexture === !0) {
198
+ if (e instanceof U || e.isTexture === !0) {
196
199
  const r = e;
197
200
  return this.assignTextureLODForSlot(r, t, null, null);
198
201
  }
@@ -217,31 +220,31 @@ const M = class {
217
220
  var t, r;
218
221
  return S && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
219
222
  if (i != null && i.extensions) {
220
- const s = i == null ? void 0 : i.extensions[R];
223
+ const s = i == null ? void 0 : i.extensions[E];
221
224
  if (s) {
222
225
  let o = !1;
223
- for (const a of this.parser.associations.keys())
224
- a.isTexture === !0 && this.parser.associations.get(a).textures === n && (o = !0, M.registerTexture(this.url, a, n, s));
225
- o || this.parser.getDependency("texture", n).then((a) => {
226
- a && M.registerTexture(this.url, a, n, s);
226
+ for (const l of this.parser.associations.keys())
227
+ l.isTexture === !0 && this.parser.associations.get(l).textures === n && (o = !0, M.registerTexture(this.url, l, n, s));
228
+ o || this.parser.getDependency("texture", n).then((l) => {
229
+ l && M.registerTexture(this.url, l, n, s);
227
230
  });
228
231
  }
229
232
  }
230
233
  }), (r = this.parser.json.meshes) == null || r.forEach((i, n) => {
231
234
  if (i != null && i.extensions) {
232
- const s = i == null ? void 0 : i.extensions[R];
235
+ const s = i == null ? void 0 : i.extensions[E];
233
236
  if (s && s.lods) {
234
237
  for (const o of this.parser.associations.keys())
235
238
  if (o.isMesh) {
236
- const a = this.parser.associations.get(o);
237
- a.meshes === n && M.registerMesh(this.url, s.guid, o, s.lods.length, a.primitives, s);
239
+ const l = this.parser.associations.get(o);
240
+ l.meshes === n && M.registerMesh(this.url, s.guid, o, s.lods.length, l.primitives, s);
238
241
  }
239
242
  }
240
243
  }
241
244
  }), null;
242
245
  }
243
246
  static async getOrLoadLOD(e, t) {
244
- var o, a, g;
247
+ var o, l, g;
245
248
  const r = S == "verbose", i = e.userData.LODS;
246
249
  if (!i)
247
250
  return null;
@@ -249,7 +252,7 @@ const M = class {
249
252
  let s;
250
253
  if (e.isTexture === !0) {
251
254
  const f = e;
252
- f.source && f.source[V] && (s = f.source[V]);
255
+ f.source && f.source[H] && (s = f.source[H]);
253
256
  }
254
257
  if (s || (s = M.lodInfos.get(n)), s) {
255
258
  if (t > 0) {
@@ -261,27 +264,27 @@ const M = class {
261
264
  const f = Array.isArray(s.lods) ? s.lods[t].path : s.lods;
262
265
  if (!f)
263
266
  return S && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
264
- const p = Le(i.url, f);
267
+ const p = De(i.url, f);
265
268
  if (p.endsWith(".glb") || p.endsWith(".gltf")) {
266
269
  if (!s.guid)
267
270
  return console.warn("missing pointer for glb/gltf texture", s), null;
268
271
  const u = p + "_" + s.guid, h = this.previouslyLoaded.get(u);
269
272
  if (h !== void 0) {
270
273
  r && console.log(`LOD ${t} was already loading/loaded: ${u}`);
271
- let x = await h.catch((F) => (console.error(`Error loading LOD ${t} from ${p}
272
- `, F), null)), k = !1;
273
- if (x == null || (x instanceof I && e instanceof I ? (o = x.image) != null && o.data || (a = x.source) != null && a.data ? x = this.copySettings(e, x) : (k = !0, this.previouslyLoaded.delete(u)) : x instanceof Y && e instanceof Y && ((g = x.attributes.position) != null && g.array || (k = !0, this.previouslyLoaded.delete(u)))), !k)
274
+ let x = await h.catch((I) => (console.error(`Error loading LOD ${t} from ${p}
275
+ `, I), null)), R = !1;
276
+ if (x == null || (x instanceof U && e instanceof U ? (o = x.image) != null && o.data || (l = x.source) != null && l.data ? x = this.copySettings(e, x) : (R = !0, this.previouslyLoaded.delete(u)) : x instanceof K && e instanceof K && ((g = x.attributes.position) != null && g.array || (R = !0, this.previouslyLoaded.delete(u)))), !R)
274
277
  return x;
275
278
  }
276
- const D = s, A = new Promise(async (x, k) => {
277
- const F = new he();
278
- oe(F), S && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, D.guid));
279
+ const D = s, A = new Promise(async (x, R) => {
280
+ const I = new Le();
281
+ ae(I), S && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, D.guid));
279
282
  let L = p;
280
283
  if (D && Array.isArray(D.lods)) {
281
284
  const m = D.lods[t];
282
285
  m.hash && (L += "?v=" + m.hash);
283
286
  }
284
- const y = await F.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
287
+ const y = await I.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
285
288
  `, m), null));
286
289
  if (!y)
287
290
  return null;
@@ -292,7 +295,7 @@ const M = class {
292
295
  let m = !1;
293
296
  for (const d of y.parser.json.textures) {
294
297
  if (d != null && d.extensions) {
295
- const O = d == null ? void 0 : d.extensions[R];
298
+ const O = d == null ? void 0 : d.extensions[E];
296
299
  if (O != null && O.guid && O.guid === D.guid) {
297
300
  m = !0;
298
301
  break;
@@ -302,14 +305,14 @@ const M = class {
302
305
  }
303
306
  if (m) {
304
307
  let d = await T.getDependency("texture", w);
305
- return r && console.log('change "' + e.name + '" → "' + d.name + '"', p, w, d, u), e instanceof I && (d = this.copySettings(e, d)), d && (d.guid = D.guid), x(d);
308
+ return r && console.log('change "' + e.name + '" → "' + d.name + '"', p, w, d, u), e instanceof U && (d = this.copySettings(e, d)), d && (d.guid = D.guid), x(d);
306
309
  }
307
310
  }
308
311
  if (w = 0, y.parser.json.meshes) {
309
312
  let m = !1;
310
313
  for (const d of y.parser.json.meshes) {
311
314
  if (d != null && d.extensions) {
312
- const O = d == null ? void 0 : d.extensions[R];
315
+ const O = d == null ? void 0 : d.extensions[E];
313
316
  if (O != null && O.guid && O.guid === D.guid) {
314
317
  m = !0;
315
318
  break;
@@ -320,27 +323,27 @@ const M = class {
320
323
  if (m) {
321
324
  const d = await T.getDependency("mesh", w), O = D;
322
325
  if (r && console.log(`Loaded Mesh "${d.name}"`, p, w, d, u), d.isMesh === !0) {
323
- const P = d.geometry;
324
- return M.assignLODInformation(i.url, P, n, t, void 0, O.density), x(P);
326
+ const _ = d.geometry;
327
+ return M.assignLODInformation(i.url, _, n, t, void 0, O.density), x(_);
325
328
  } else {
326
- const P = new Array();
327
- for (let _ = 0; _ < d.children.length; _++) {
328
- const E = d.children[_];
329
- if (E instanceof q) {
330
- const N = E.geometry;
331
- M.assignLODInformation(i.url, N, n, t, _, O.density), P.push(N);
329
+ const _ = new Array();
330
+ for (let k = 0; k < d.children.length; k++) {
331
+ const G = d.children[k];
332
+ if (G instanceof X) {
333
+ const $ = G.geometry;
334
+ M.assignLODInformation(i.url, $, n, t, k, O.density), _.push($);
332
335
  }
333
336
  }
334
- return x(P);
337
+ return x(_);
335
338
  }
336
339
  }
337
340
  }
338
341
  return x(null);
339
342
  });
340
343
  return this.previouslyLoaded.set(u, A), await A;
341
- } else if (e instanceof I) {
344
+ } else if (e instanceof U) {
342
345
  r && console.log("Load texture from uri: " + p);
343
- const h = await new fe().loadAsync(p);
346
+ const h = await new pe().loadAsync(p);
344
347
  return h ? (h.guid = s.guid, h.flipY = !1, h.needsUpdate = !0, h.colorSpace = e.colorSpace, r && console.log(s, h)) : S && console.warn("failed loading", p), h;
345
348
  }
346
349
  } else
@@ -351,7 +354,7 @@ const M = class {
351
354
  if (!t)
352
355
  return;
353
356
  t.userData || (t.userData = {});
354
- const o = new De(e, r, i, n, s);
357
+ const o = new Oe(e, r, i, n, s);
355
358
  t.userData.LODS = o, t.userData.LOD = i;
356
359
  }
357
360
  static getAssignedLODInformation(e) {
@@ -368,7 +371,7 @@ let v = M;
368
371
  * Register a texture with LOD information
369
372
  */
370
373
  c(v, "registerTexture", (e, t, r, i) => {
371
- S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[V] = i);
374
+ S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[H] = i);
372
375
  const n = i.guid;
373
376
  M.assignLODInformation(e, t, n, 0, 0, void 0), M.lodInfos.set(n, i), M.lowresCache.set(n, t);
374
377
  }), /**
@@ -379,15 +382,15 @@ c(v, "registerMesh", (e, t, r, i, n, s) => {
379
382
  S && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
380
383
  const o = r.geometry;
381
384
  o.userData || (o.userData = {}), M.assignLODInformation(e, o, t, i, n, s.density), M.lodInfos.set(t, s);
382
- let a = M.lowresCache.get(t);
383
- a ? a.push(r.geometry) : a = [r.geometry], M.lowresCache.set(t, a);
384
- for (const f of Q)
385
+ let l = M.lowresCache.get(t);
386
+ l ? l.push(r.geometry) : l = [r.geometry], M.lowresCache.set(t, l), i > 0 && !xe(r) && we(r, o);
387
+ for (const f of F)
385
388
  (g = f.onRegisteredNewMesh) == null || g.call(f, r, s);
386
389
  }), /** A map of key = asset uuid and value = LOD information */
387
390
  c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
388
391
  c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
389
392
  c(v, "lowresCache", /* @__PURE__ */ new Map()), c(v, "_copiedTextures", /* @__PURE__ */ new Map());
390
- class De {
393
+ class Oe {
391
394
  constructor(e, t, r, i, n) {
392
395
  c(this, "url");
393
396
  /** the key to lookup the LOD information */
@@ -400,11 +403,17 @@ class De {
400
403
  this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
401
404
  }
402
405
  }
403
- const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
406
+ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:LODSManager"), b = class {
407
+ // readonly plugins: NEEDLE_progressive_plugin[] = [];
404
408
  constructor(e) {
405
409
  c(this, "renderer");
406
410
  c(this, "projectionScreenMatrix", new te());
407
- c(this, "cameraFrustrum", new de());
411
+ c(this, "cameraFrustrum", new ye());
412
+ /**
413
+ * The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
414
+ * @default 200_000
415
+ */
416
+ c(this, "targetTriangleDensity", 2e5);
408
417
  /**
409
418
  * The update interval in frames. If set to 0, the LODs will be updated every frame. If set to 1, the LODs will be updated every second frame, etc.
410
419
  */
@@ -413,11 +422,10 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
413
422
  * If set to true, the LODsManager will not update the LODs.
414
423
  */
415
424
  c(this, "pause", !1);
416
- c(this, "plugins", []);
417
425
  c(this, "_frame", 0);
418
426
  c(this, "_originalRender");
419
427
  // private testIfLODLevelsAreAvailable() {
420
- c(this, "_sphere", new ge());
428
+ c(this, "_sphere", new me());
421
429
  c(this, "_tempBox", new re());
422
430
  c(this, "tempMatrix", new te());
423
431
  c(this, "_tempWorldPosition", new C());
@@ -430,6 +438,21 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
430
438
  var t;
431
439
  return (t = e.userData) == null ? void 0 : t.LOD_state;
432
440
  }
441
+ static addPlugin(e) {
442
+ F.push(e);
443
+ }
444
+ static removePlugin(e) {
445
+ const t = F.indexOf(e);
446
+ t >= 0 && F.splice(t, 1);
447
+ }
448
+ /**
449
+ * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
450
+ * @param renderer The renderer to get the LODsManager for.
451
+ * @returns The LODsManager instance.
452
+ */
453
+ static get(e) {
454
+ return e[ie] ? e[ie] : new b(e);
455
+ }
433
456
  /**
434
457
  * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
435
458
  */
@@ -439,7 +462,7 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
439
462
  let e = 0;
440
463
  this._originalRender = this.renderer.render;
441
464
  const t = this;
442
- ne(this.renderer), this.renderer.render = function(r, i) {
465
+ oe(this.renderer), this.renderer.render = function(r, i) {
443
466
  t.renderer.getRenderTarget() == null && (e = 0, t._frame += 1);
444
467
  const s = t._frame, o = e++;
445
468
  t.onBeforeRender(r, i, o, s), t._originalRender.call(this, r, i), t.onAfterRender(r, i, o, s);
@@ -451,7 +474,7 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
451
474
  onBeforeRender(e, t, r, i) {
452
475
  }
453
476
  onAfterRender(e, t, r, i) {
454
- var a, g;
477
+ var l, g;
455
478
  if (this.pause)
456
479
  return;
457
480
  const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
@@ -461,32 +484,32 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
461
484
  (f.name === "EffectMaterial" || f.name === "CopyShader") && (o = !1);
462
485
  }
463
486
  if (o) {
464
- if (xe || this.updateInterval > 0 && i % this.updateInterval != 0)
487
+ if (Me || this.updateInterval > 0 && i % this.updateInterval != 0)
465
488
  return;
466
489
  this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
467
- const f = 1e5;
490
+ const f = this.targetTriangleDensity;
468
491
  for (const u of s) {
469
- if (u.material && (((a = u.geometry) == null ? void 0 : a.type) === "BoxGeometry" || ((g = u.geometry) == null ? void 0 : g.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
470
- H && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
492
+ if (u.material && (((l = u.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((g = u.geometry) == null ? void 0 : g.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
493
+ J && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
471
494
  continue;
472
495
  }
473
496
  const h = u.object;
474
- (h instanceof q || h.isMesh) && this.updateLODs(e, t, h, f);
497
+ (h instanceof X || h.isMesh) && this.updateLODs(e, t, h, f);
475
498
  }
476
499
  const p = n.transparent;
477
500
  for (const u of p) {
478
501
  const h = u.object;
479
- (h instanceof q || h.isMesh) && this.updateLODs(e, t, h, f);
502
+ (h instanceof X || h.isMesh) && this.updateLODs(e, t, h, f);
480
503
  }
481
504
  }
482
505
  }
483
506
  /** Update the LOD levels for the renderer. */
484
507
  updateLODs(e, t, r, i) {
485
- var a, g;
486
- for (const f of this.plugins)
487
- (a = f.onBeforeUpdateLOD) == null || a.call(f, this.renderer, e, t, r);
508
+ var l, g;
509
+ for (const f of F)
510
+ (l = f.onBeforeUpdateLOD) == null || l.call(f, this.renderer, e, t, r);
488
511
  let n = r.userData.LOD_state;
489
- n || (n = new we(), r.userData.LOD_state = n);
512
+ n || (n = new ve(), r.userData.LOD_state = n);
490
513
  let s = this.calculateLodLevel(t, r, n, i);
491
514
  s = Math.round(s), s >= 0 && this.loadProgressiveMeshes(r, s);
492
515
  let o = 0;
@@ -498,7 +521,7 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
498
521
  else
499
522
  this.loadProgressiveTextures(r.material, o);
500
523
  }
501
- for (const f of this.plugins)
524
+ for (const f of F)
502
525
  (g = f.onAfterUpdatedLOD) == null || g.call(f, this.renderer, e, t, r, s);
503
526
  n.lastLodLevel = s;
504
527
  }
@@ -532,9 +555,9 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
532
555
  return -1;
533
556
  let s = 10 + 1;
534
557
  if (e) {
535
- if (H && t["DEBUG:LOD"] != null)
558
+ if (J && t["DEBUG:LOD"] != null)
536
559
  return t["DEBUG:LOD"];
537
- const a = v.getMeshLODInformation(t.geometry), g = a == null ? void 0 : a.lods;
560
+ const l = v.getMeshLODInformation(t.geometry), g = l == null ? void 0 : l.lods;
538
561
  if (!g || g.length <= 0 || !((o = this.cameraFrustrum) != null && o.intersectsObject(t)))
539
562
  return 99;
540
563
  const f = t.geometry.boundingBox;
@@ -549,18 +572,18 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
549
572
  if (this._tempBox.copy(f), this._tempBox.applyMatrix4(t.matrixWorld), this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
550
573
  const L = this._tempBox.min, y = this._tempBox.max;
551
574
  let T = L.x, w = L.y, m = y.x, d = y.y;
552
- const O = 2, P = 1.5, _ = (L.x + y.x) * 0.5, E = (L.y + y.y) * 0.5;
553
- T = (T - _) * O + _, w = (w - E) * O + E, m = (m - _) * O + _, d = (d - E) * O + E;
554
- const N = T < 0 && m > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(y.x)), ae = w < 0 && d > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(y.y)), X = Math.max(N, ae);
555
- r.lastCentrality = (P - X) * (P - X) * (P - X);
575
+ const O = 2, _ = 1.5, k = (L.x + y.x) * 0.5, G = (L.y + y.y) * 0.5;
576
+ T = (T - k) * O + k, w = (w - G) * O + G, m = (m - k) * O + k, d = (d - G) * O + G;
577
+ const $ = T < 0 && m > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(y.x)), le = w < 0 && d > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(y.y)), V = Math.max($, le);
578
+ r.lastCentrality = (_ - V) * (_ - V) * (_ - V);
556
579
  } else
557
580
  r.lastCentrality = 1;
558
581
  const u = this._tempBox.getSize(this._tempBoxSize);
559
582
  u.multiplyScalar(0.5), screen.availHeight > 0 && u.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), u.x *= p.aspect;
560
583
  const h = e.matrixWorldInverse, D = new re();
561
584
  D.copy(f), D.applyMatrix4(t.matrixWorld), D.applyMatrix4(h);
562
- const A = D.getSize(this._tempBox2Size), G = Math.max(A.x, A.y);
563
- if (Math.max(u.x, u.y) != 0 && G != 0 && (u.z = A.z / Math.max(A.x, A.y) * Math.max(u.x, u.y)), r.lastScreenCoverage = Math.max(u.x, u.y, u.z), r.lastScreenspaceVolume.copy(u), r.lastScreenCoverage *= r.lastCentrality, H && b.debugDrawLine) {
585
+ const A = D.getSize(this._tempBox2Size), B = Math.max(A.x, A.y);
586
+ if (Math.max(u.x, u.y) != 0 && B != 0 && (u.z = A.z / Math.max(A.x, A.y) * Math.max(u.x, u.y)), r.lastScreenCoverage = Math.max(u.x, u.y, u.z), r.lastScreenspaceVolume.copy(u), r.lastScreenCoverage *= r.lastCentrality, J && b.debugDrawLine) {
564
587
  const L = this.tempMatrix.copy(this.projectionScreenMatrix);
565
588
  L.invert();
566
589
  const y = b.corner0, T = b.corner1, w = b.corner2, m = b.corner3;
@@ -568,25 +591,25 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
568
591
  const d = (y.z + m.z) * 0.5;
569
592
  y.z = T.z = w.z = m.z = d, y.applyMatrix4(L), T.applyMatrix4(L), w.applyMatrix4(L), m.applyMatrix4(L), b.debugDrawLine(y, T, 255), b.debugDrawLine(y, w, 255), b.debugDrawLine(T, m, 255), b.debugDrawLine(w, m, 255);
570
593
  }
571
- let k = 999;
594
+ let R = 999;
572
595
  if (g && r.lastScreenCoverage > 0) {
573
596
  for (let L = 0; L < g.length; L++)
574
597
  if (g[L].density / r.lastScreenCoverage < i) {
575
- k = L;
598
+ R = L;
576
599
  break;
577
600
  }
578
601
  }
579
- k < s && (s = k);
602
+ R < s && (s = R);
580
603
  }
581
604
  }
582
605
  return s;
583
606
  }
584
607
  };
585
- let B = b;
608
+ let P = b;
586
609
  /** 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.
587
610
  */
588
- c(B, "debugDrawLine"), c(B, "corner0", new C()), c(B, "corner1", new C()), c(B, "corner2", new C()), c(B, "corner3", new C());
589
- class we {
611
+ c(P, "debugDrawLine"), c(P, "corner0", new C()), c(P, "corner1", new C()), c(P, "corner2", new C()), c(P, "corner3", new C());
612
+ class ve {
590
613
  constructor() {
591
614
  c(this, "lastLodLevel", 0);
592
615
  c(this, "lastScreenCoverage", 0);
@@ -594,19 +617,19 @@ class we {
594
617
  c(this, "lastCentrality", 0);
595
618
  }
596
619
  }
597
- const ie = Symbol("NEEDLE_mesh_lod"), $ = Symbol("NEEDLE_texture_lod");
598
- function Oe(l) {
599
- if (!l)
620
+ const ne = Symbol("NEEDLE_mesh_lod"), q = Symbol("NEEDLE_texture_lod");
621
+ function Se(a) {
622
+ if (!a)
600
623
  return null;
601
624
  let e = null, t = null;
602
- for (let r = l; r != null; r = Object.getPrototypeOf(r)) {
625
+ for (let r = a; r != null; r = Object.getPrototypeOf(r)) {
603
626
  const i = Object.getOwnPropertySymbols(r), n = i.find((o) => o.toString() == "Symbol(renderer)"), s = i.find((o) => o.toString() == "Symbol(scene)");
604
- !e && n != null && (e = l[n].threeRenderer), !t && s != null && (t = l[s]);
627
+ !e && n != null && (e = a[n].threeRenderer), !t && s != null && (t = a[s]);
605
628
  }
606
629
  if (e) {
607
630
  console.log("Adding Needle LODs to modelviewer");
608
- const r = new B(e);
609
- if (r.plugins.push(new Me(l)), r.enable(), t) {
631
+ const r = P.get(e);
632
+ if (P.addPlugin(new Te(a)), r.enable(), t) {
610
633
  const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
611
634
  i && e.render(t, i);
612
635
  }
@@ -616,7 +639,7 @@ function Oe(l) {
616
639
  }
617
640
  return null;
618
641
  }
619
- class Me {
642
+ class Te {
620
643
  constructor(e) {
621
644
  c(this, "modelviewer");
622
645
  c(this, "_didWarnAboutMissingUrl", !1);
@@ -633,23 +656,27 @@ class Me {
633
656
  return e._currentGLTF;
634
657
  }
635
658
  tryParseTextureLOD(e, t) {
636
- if (t[$] == !0)
659
+ if (t[q] == !0)
637
660
  return;
638
- t[$] = !0;
661
+ t[q] = !0;
639
662
  const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
640
663
  if (i && r && t.material) {
641
664
  let n = function(o) {
642
665
  var g, f, p;
643
- if (o[$] == !0)
666
+ if (o[q] == !0)
644
667
  return;
645
- o[$] = !0, o.userData && (o.userData.LOD = -1);
646
- const a = Object.keys(o);
647
- for (let u = 0; u < a.length; u++) {
648
- const h = a[u], D = o[h];
668
+ o[q] = !0, o.userData && (o.userData.LOD = -1);
669
+ const l = Object.keys(o);
670
+ for (let u = 0; u < l.length; u++) {
671
+ const h = l[u], D = o[h];
649
672
  if ((D == null ? void 0 : D.isTexture) === !0) {
650
- const A = (f = (g = D.userData) == null ? void 0 : g.associations) == null ? void 0 : f.textures, G = r.parser.json.textures[A];
651
- if ((p = G.extensions) != null && p[R]) {
652
- const x = G.extensions[R];
673
+ const A = (f = (g = D.userData) == null ? void 0 : g.associations) == null ? void 0 : f.textures, B = r.parser.json.textures[A];
674
+ if (!B) {
675
+ console.warn("Texture data not found for texture index " + A);
676
+ continue;
677
+ }
678
+ if ((p = B == null ? void 0 : B.extensions) != null && p[E]) {
679
+ const x = B.extensions[E];
653
680
  x && i && v.registerTexture(i, D, x.lods.length, x);
654
681
  }
655
682
  }
@@ -665,36 +692,37 @@ class Me {
665
692
  }
666
693
  tryParseMeshLOD(e, t) {
667
694
  var n, s;
668
- if (t[ie] == !0)
695
+ if (t[ne] == !0)
669
696
  return;
670
- t[ie] = !0;
697
+ t[ne] = !0;
671
698
  const r = this.getUrl();
672
699
  if (!r)
673
700
  return;
674
- const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
701
+ const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[E];
675
702
  if (i && r) {
676
703
  const o = t.uuid;
677
704
  v.registerMesh(r, o, t, 0, i.lods.length, i);
678
705
  }
679
706
  }
680
707
  }
681
- function Ce(l, e, t, r) {
682
- ne(e), oe(t), t.register((n) => new v(n, l));
683
- const i = new B(e);
708
+ function Ee(a, e, t, r) {
709
+ oe(e), ae(t), t.register((n) => new v(n, a));
710
+ const i = P.get(e);
684
711
  return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
685
712
  }
686
713
  document.addEventListener("DOMContentLoaded", () => {
687
- Oe(document.querySelector("model-viewer"));
714
+ Se(document.querySelector("model-viewer"));
688
715
  });
689
716
  export {
690
- R as EXTENSION_NAME,
691
- B as LODsManager,
717
+ E as EXTENSION_NAME,
718
+ P as LODsManager,
692
719
  v as NEEDLE_progressive,
693
- oe as addDracoAndKTX2Loaders,
694
- ne as createLoaders,
695
- Oe as patchModelViewer,
696
- ke as registerPlugin,
697
- _e as setDracoDecoderLocation,
698
- Be as setKTX2TranscoderLocation,
699
- Ce as useNeedleProgressive
720
+ ae as addDracoAndKTX2Loaders,
721
+ oe as createLoaders,
722
+ xe as getRaycastMesh,
723
+ Se as patchModelViewer,
724
+ Re as setDracoDecoderLocation,
725
+ Ce as setKTX2TranscoderLocation,
726
+ we as setRaycastMesh,
727
+ Ee as useNeedleProgressive
700
728
  };