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

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.
package/CHANGELOG.md CHANGED
@@ -4,7 +4,11 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [1.0.0-alpha.15] - 2023-05-24
7
+ ## [1.0.0-alpha.16] - 2023-05-29
8
+ - fix: LODs manager now clamps to LOD 0 if the near plane is inside the bounds
9
+ - change: Ignore certain material in lods update loop
10
+
11
+ ## [1.0.0-alpha.15] - 2023-05-25
8
12
  - add: `getRaycastMesh` method
9
13
  - add: LODsManager does now expose `targetTriangleDensity`. The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
10
14
  - change: create LODsManager via `LODsManager.get(renderer)`
@@ -1,27 +1,27 @@
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);
1
+ var ce = Object.defineProperty;
2
+ var ue = (a, e, t) => e in a ? ce(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
3
+ var u = (a, e, t) => (ue(a, typeof e != "symbol" ? e + "" : e, t), t);
4
4
  import { MeshoptDecoder as fe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
5
5
  import { DRACOLoader as de } from "three/examples/jsm/loaders/DRACOLoader.js";
6
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";
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 k } from "three";
8
8
  import { GLTFLoader as Le } from "three/examples/jsm/loaders/GLTFLoader.js";
9
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
10
  fetch(Y + "draco_decoder.js", { method: "head" }).catch((a) => {
11
11
  Y = "./include/draco/", j = "./include/ktx2/";
12
12
  });
13
- function Re(a) {
13
+ function Ce(a) {
14
14
  Y = a;
15
15
  }
16
- function Ce(a) {
16
+ function Re(a) {
17
17
  j = a;
18
18
  }
19
- let W, Q, z;
19
+ let z, Q, W;
20
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");
21
+ z || (z = new de(), z.setDecoderPath(Y), z.setDecoderConfig({ type: "js" })), W || (W = new ge(), W.setTranscoderPath(j)), Q || (Q = fe), a ? W.detectSupport(a) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
22
22
  }
23
23
  function ae(a) {
24
- a.dracoLoader || a.setDRACOLoader(W), a.ktx2Loader || a.setKTX2Loader(z), a.meshoptDecoder || a.setMeshoptDecoder(Q);
24
+ a.dracoLoader || a.setDRACOLoader(z), a.ktx2Loader || a.setKTX2Loader(W), a.meshoptDecoder || a.setMeshoptDecoder(Q);
25
25
  }
26
26
  function ee(a) {
27
27
  const t = new URL(window.location.href).searchParams.get(a);
@@ -46,17 +46,17 @@ function xe(a) {
46
46
  function we(a, e) {
47
47
  (a.type === "Mesh" || a.type === "SkinnedMesh") && (a.userData || (a.userData = {}), a.userData["needle:raycast-mesh"] = e);
48
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();
50
- if (S) {
49
+ const G = new Array(), E = "NEEDLE_progressive", v = ee("debugprogressive"), H = Symbol("needle-progressive-texture"), N = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
50
+ if (v) {
51
51
  let a = function() {
52
52
  e += 1, console.log("Toggle LOD level", e, N), N.forEach((i, n) => {
53
53
  for (const s of i.keys) {
54
54
  const o = n[s];
55
55
  if (o.isBufferGeometry === !0) {
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));
56
+ const l = S.getMeshLODInformation(o), g = l ? Math.min(e, l.lods.length) : 0;
57
+ n["DEBUG:LOD"] = e, S.assignMeshLOD(n, g), l && (t = Math.max(t, l.lods.length - 1));
58
58
  } else if (n.isMaterial === !0) {
59
- n["DEBUG:LOD"] = e, v.assignTextureLOD(n, e);
59
+ n["DEBUG:LOD"] = e, S.assignTextureLOD(n, e);
60
60
  break;
61
61
  }
62
62
  }
@@ -70,17 +70,17 @@ if (S) {
70
70
  }
71
71
  function se(a, e, t) {
72
72
  var i;
73
- if (!S)
73
+ if (!v)
74
74
  return;
75
75
  N.has(a) || N.set(a, { keys: [], sourceId: t });
76
76
  const r = N.get(a);
77
77
  ((i = r == null ? void 0 : r.keys) == null ? void 0 : i.includes(e)) == !1 && r.keys.push(e);
78
78
  }
79
- const M = class {
79
+ const O = class {
80
80
  constructor(e, t) {
81
- c(this, "parser");
82
- c(this, "url");
83
- S && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
81
+ u(this, "parser");
82
+ u(this, "url");
83
+ v && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
84
84
  }
85
85
  /** The name of the extension */
86
86
  get name() {
@@ -141,20 +141,20 @@ const M = class {
141
141
  const i = e.geometry, n = this.getAssignedLODInformation(i);
142
142
  if (!n)
143
143
  return Promise.resolve(null);
144
- for (const s of F)
144
+ for (const s of G)
145
145
  (r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
146
- return e["LOD:requested level"] = t, M.getOrLoadLOD(i, t).then((s) => {
146
+ return e["LOD:requested level"] = t, O.getOrLoadLOD(i, t).then((s) => {
147
147
  if (e["LOD:requested level"] === t) {
148
148
  if (delete e["LOD:requested level"], Array.isArray(s)) {
149
149
  const o = n.index || 0;
150
150
  s = s[o];
151
151
  }
152
- s && i != s && s instanceof K && (e.geometry = s, S && se(e, "geometry", n.url));
152
+ s && i != s && s instanceof K && (e.geometry = s, v && se(e, "geometry", n.url));
153
153
  }
154
154
  return s;
155
155
  }).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
156
156
  } else
157
- S && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
157
+ v && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
158
158
  return Promise.resolve(null);
159
159
  }
160
160
  /** Load a different resolution of a texture (if available)
@@ -169,7 +169,7 @@ const M = class {
169
169
  return Promise.resolve(null);
170
170
  if (e instanceof he || e.isMaterial === !0) {
171
171
  const r = e, i = [], n = new Array();
172
- if (S && Z.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
172
+ if (v && Z.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
173
173
  const s = r;
174
174
  for (const o of Object.keys(s.uniforms)) {
175
175
  const l = s.uniforms[o].value;
@@ -202,31 +202,31 @@ const M = class {
202
202
  return Promise.resolve(null);
203
203
  }
204
204
  static assignTextureLODForSlot(e, t, r, i) {
205
- return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) : M.getOrLoadLOD(e, t).then((n) => {
205
+ return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) : O.getOrLoadLOD(e, t).then((n) => {
206
206
  if (Array.isArray(n))
207
207
  return null;
208
208
  if ((n == null ? void 0 : n.isTexture) === !0) {
209
- if (n != e && (r && i && (r[i] = n), S && i && r)) {
209
+ if (n != e && (r && i && (r[i] = n), v && i && r)) {
210
210
  const s = this.getAssignedLODInformation(e);
211
211
  s && se(r, i, s.url);
212
212
  }
213
213
  return n;
214
214
  } else
215
- S == "verbose" && console.warn("No LOD found for", e, t);
215
+ v == "verbose" && console.warn("No LOD found for", e, t);
216
216
  return null;
217
217
  }).catch((n) => (console.error("Error loading LOD", e, n), null));
218
218
  }
219
219
  afterRoot(e) {
220
220
  var t, r;
221
- return S && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
221
+ return v && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
222
222
  if (i != null && i.extensions) {
223
223
  const s = i == null ? void 0 : i.extensions[E];
224
224
  if (s) {
225
225
  let o = !1;
226
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));
227
+ l.isTexture === !0 && this.parser.associations.get(l).textures === n && (o = !0, O.registerTexture(this.url, l, n, s));
228
228
  o || this.parser.getDependency("texture", n).then((l) => {
229
- l && M.registerTexture(this.url, l, n, s);
229
+ l && O.registerTexture(this.url, l, n, s);
230
230
  });
231
231
  }
232
232
  }
@@ -237,7 +237,7 @@ const M = class {
237
237
  for (const o of this.parser.associations.keys())
238
238
  if (o.isMesh) {
239
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);
240
+ l.meshes === n && O.registerMesh(this.url, s.guid, o, s.lods.length, l.primitives, s);
241
241
  }
242
242
  }
243
243
  }
@@ -245,7 +245,7 @@ const M = class {
245
245
  }
246
246
  static async getOrLoadLOD(e, t) {
247
247
  var o, l, g;
248
- const r = S == "verbose", i = e.userData.LODS;
248
+ const r = v == "verbose", i = e.userData.LODS;
249
249
  if (!i)
250
250
  return null;
251
251
  const n = i == null ? void 0 : i.key;
@@ -254,49 +254,49 @@ const M = class {
254
254
  const f = e;
255
255
  f.source && f.source[H] && (s = f.source[H]);
256
256
  }
257
- if (s || (s = M.lodInfos.get(n)), s) {
257
+ if (s || (s = O.lodInfos.get(n)), s) {
258
258
  if (t > 0) {
259
- let u = !1;
259
+ let c = !1;
260
260
  const h = Array.isArray(s.lods);
261
- if (h && t >= s.lods.length ? u = !0 : h || (u = !0), u)
261
+ if (h && t >= s.lods.length ? c = !0 : h || (c = !0), c)
262
262
  return this.lowresCache.get(n);
263
263
  }
264
264
  const f = Array.isArray(s.lods) ? s.lods[t].path : s.lods;
265
265
  if (!f)
266
- return S && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
266
+ return v && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
267
267
  const p = De(i.url, f);
268
268
  if (p.endsWith(".glb") || p.endsWith(".gltf")) {
269
269
  if (!s.guid)
270
270
  return console.warn("missing pointer for glb/gltf texture", s), null;
271
- const u = p + "_" + s.guid, h = this.previouslyLoaded.get(u);
271
+ const c = p + "_" + s.guid, h = this.previouslyLoaded.get(c);
272
272
  if (h !== void 0) {
273
- r && console.log(`LOD ${t} was already loading/loaded: ${u}`);
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)
273
+ r && console.log(`LOD ${t} was already loading/loaded: ${c}`);
274
+ let x = await h.catch((F) => (console.error(`Error loading LOD ${t} from ${p}
275
+ `, F), 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(c)) : x instanceof K && e instanceof K && ((g = x.attributes.position) != null && g.array || (R = !0, this.previouslyLoaded.delete(c)))), !R)
277
277
  return x;
278
278
  }
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));
282
- let L = p;
283
- if (D && Array.isArray(D.lods)) {
284
- const m = D.lods[t];
285
- m.hash && (L += "?v=" + m.hash);
279
+ const L = s, A = new Promise(async (x, R) => {
280
+ const F = new Le();
281
+ ae(F), v && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, L.guid));
282
+ let D = p;
283
+ if (L && Array.isArray(L.lods)) {
284
+ const m = L.lods[t];
285
+ m.hash && (D += "?v=" + m.hash);
286
286
  }
287
- const y = await I.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
287
+ const y = await F.loadAsync(D).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
288
288
  `, m), null));
289
289
  if (!y)
290
290
  return null;
291
291
  const T = y.parser;
292
- r && console.log("Loading finished " + p, D.guid);
292
+ r && console.log("Loading finished " + p, L.guid);
293
293
  let w = 0;
294
294
  if (y.parser.json.textures) {
295
295
  let m = !1;
296
296
  for (const d of y.parser.json.textures) {
297
297
  if (d != null && d.extensions) {
298
- const O = d == null ? void 0 : d.extensions[E];
299
- if (O != null && O.guid && O.guid === D.guid) {
298
+ const M = d == null ? void 0 : d.extensions[E];
299
+ if (M != null && M.guid && M.guid === L.guid) {
300
300
  m = !0;
301
301
  break;
302
302
  }
@@ -305,15 +305,16 @@ const M = class {
305
305
  }
306
306
  if (m) {
307
307
  let d = await T.getDependency("texture", w);
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);
309
- }
308
+ return d && O.assignLODInformation(i.url, d, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + d.name + '"', p, w, d, c), e instanceof U && (d = this.copySettings(e, d)), d && (d.guid = L.guid), x(d);
309
+ } else
310
+ v && console.warn("Could not find texture with guid", L.guid);
310
311
  }
311
312
  if (w = 0, y.parser.json.meshes) {
312
313
  let m = !1;
313
314
  for (const d of y.parser.json.meshes) {
314
315
  if (d != null && d.extensions) {
315
- const O = d == null ? void 0 : d.extensions[E];
316
- if (O != null && O.guid && O.guid === D.guid) {
316
+ const M = d == null ? void 0 : d.extensions[E];
317
+ if (M != null && M.guid && M.guid === L.guid) {
317
318
  m = !0;
318
319
  break;
319
320
  }
@@ -321,17 +322,17 @@ const M = class {
321
322
  w++;
322
323
  }
323
324
  if (m) {
324
- const d = await T.getDependency("mesh", w), O = D;
325
- if (r && console.log(`Loaded Mesh "${d.name}"`, p, w, d, u), d.isMesh === !0) {
325
+ const d = await T.getDependency("mesh", w), M = L;
326
+ if (r && console.log(`Loaded Mesh "${d.name}"`, p, w, d, c), d.isMesh === !0) {
326
327
  const _ = d.geometry;
327
- return M.assignLODInformation(i.url, _, n, t, void 0, O.density), x(_);
328
+ return O.assignLODInformation(i.url, _, n, t, void 0, M.density), x(_);
328
329
  } else {
329
330
  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($);
331
+ for (let B = 0; B < d.children.length; B++) {
332
+ const I = d.children[B];
333
+ if (I instanceof X) {
334
+ const $ = I.geometry;
335
+ O.assignLODInformation(i.url, $, n, t, B, M.density), _.push($);
335
336
  }
336
337
  }
337
338
  return x(_);
@@ -340,14 +341,14 @@ const M = class {
340
341
  }
341
342
  return x(null);
342
343
  });
343
- return this.previouslyLoaded.set(u, A), await A;
344
+ return this.previouslyLoaded.set(c, A), await A;
344
345
  } else if (e instanceof U) {
345
346
  r && console.log("Load texture from uri: " + p);
346
347
  const h = await new pe().loadAsync(p);
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;
348
+ return h ? (h.guid = s.guid, h.flipY = !1, h.needsUpdate = !0, h.colorSpace = e.colorSpace, r && console.log(s, h)) : v && console.warn("failed loading", p), h;
348
349
  }
349
350
  } else
350
- S && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
351
+ v && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
351
352
  return null;
352
353
  }
353
354
  static assignLODInformation(e, t, r, i, n, s) {
@@ -366,71 +367,72 @@ const M = class {
366
367
  return r || (t = t.clone(), this._copiedTextures.set(e, t), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t.magFilter = e.magFilter, t.minFilter = e.minFilter, t.wrapS = e.wrapS, t.wrapT = e.wrapT, t.flipY = e.flipY, t.anisotropy = e.anisotropy, t.generateMipmaps = e.generateMipmaps, t);
367
368
  }
368
369
  };
369
- let v = M;
370
+ let S = O;
370
371
  /**
371
372
  * Register a texture with LOD information
372
373
  */
373
- c(v, "registerTexture", (e, t, r, i) => {
374
- S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[H] = i);
374
+ u(S, "registerTexture", (e, t, r, i) => {
375
+ v && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[H] = i);
375
376
  const n = i.guid;
376
- M.assignLODInformation(e, t, n, 0, 0, void 0), M.lodInfos.set(n, i), M.lowresCache.set(n, t);
377
+ O.assignLODInformation(e, t, n, 0, 0, void 0), O.lodInfos.set(n, i), O.lowresCache.set(n, t);
377
378
  }), /**
378
379
  * Register a mesh with LOD information
379
380
  */
380
- c(v, "registerMesh", (e, t, r, i, n, s) => {
381
+ u(S, "registerMesh", (e, t, r, i, n, s) => {
381
382
  var g;
382
- S && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
383
+ v && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
383
384
  const o = r.geometry;
384
- o.userData || (o.userData = {}), M.assignLODInformation(e, o, t, i, n, s.density), M.lodInfos.set(t, s);
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
+ o.userData || (o.userData = {}), O.assignLODInformation(e, o, t, i, n, s.density), O.lodInfos.set(t, s);
386
+ let l = O.lowresCache.get(t);
387
+ l ? l.push(r.geometry) : l = [r.geometry], O.lowresCache.set(t, l), i > 0 && !xe(r) && we(r, o);
388
+ for (const f of G)
388
389
  (g = f.onRegisteredNewMesh) == null || g.call(f, r, s);
389
390
  }), /** A map of key = asset uuid and value = LOD information */
390
- c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
391
- c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
392
- c(v, "lowresCache", /* @__PURE__ */ new Map()), c(v, "_copiedTextures", /* @__PURE__ */ new Map());
391
+ u(S, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
392
+ u(S, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
393
+ u(S, "lowresCache", /* @__PURE__ */ new Map()), u(S, "_copiedTextures", /* @__PURE__ */ new Map());
393
394
  class Oe {
394
395
  constructor(e, t, r, i, n) {
395
- c(this, "url");
396
+ u(this, "url");
396
397
  /** the key to lookup the LOD information */
397
- c(this, "key");
398
- c(this, "level");
398
+ u(this, "key");
399
+ u(this, "level");
399
400
  /** For multi objects (e.g. a group of meshes) this is the index of the object */
400
- c(this, "index");
401
+ u(this, "index");
401
402
  /** the mesh density */
402
- c(this, "density");
403
+ u(this, "density");
403
404
  this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
404
405
  }
405
406
  }
406
- const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:LODSManager"), b = class {
407
+ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:LODSManager"), P = class {
407
408
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
408
409
  constructor(e) {
409
- c(this, "renderer");
410
- c(this, "projectionScreenMatrix", new te());
411
- c(this, "cameraFrustrum", new ye());
410
+ u(this, "renderer");
411
+ u(this, "projectionScreenMatrix", new te());
412
+ u(this, "cameraFrustrum", new ye());
412
413
  /**
413
414
  * The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
414
415
  * @default 200_000
415
416
  */
416
- c(this, "targetTriangleDensity", 2e5);
417
+ u(this, "targetTriangleDensity", 2e5);
417
418
  /**
418
419
  * 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.
419
420
  */
420
- c(this, "updateInterval", 0);
421
+ u(this, "updateInterval", 0);
421
422
  /**
422
423
  * If set to true, the LODsManager will not update the LODs.
423
424
  */
424
- c(this, "pause", !1);
425
- c(this, "_frame", 0);
426
- c(this, "_originalRender");
425
+ u(this, "pause", !1);
426
+ u(this, "_frame", 0);
427
+ u(this, "_originalRender");
427
428
  // private testIfLODLevelsAreAvailable() {
428
- c(this, "_sphere", new me());
429
- c(this, "_tempBox", new re());
430
- c(this, "tempMatrix", new te());
431
- c(this, "_tempWorldPosition", new C());
432
- c(this, "_tempBoxSize", new C());
433
- c(this, "_tempBox2Size", new C());
429
+ u(this, "_sphere", new me());
430
+ u(this, "_tempBox", new re());
431
+ u(this, "_tempBox2", new re());
432
+ u(this, "tempMatrix", new te());
433
+ u(this, "_tempWorldPosition", new k());
434
+ u(this, "_tempBoxSize", new k());
435
+ u(this, "_tempBox2Size", new k());
434
436
  this.renderer = e;
435
437
  }
436
438
  /** @internal */
@@ -439,11 +441,11 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
439
441
  return (t = e.userData) == null ? void 0 : t.LOD_state;
440
442
  }
441
443
  static addPlugin(e) {
442
- F.push(e);
444
+ G.push(e);
443
445
  }
444
446
  static removePlugin(e) {
445
- const t = F.indexOf(e);
446
- t >= 0 && F.splice(t, 1);
447
+ const t = G.indexOf(e);
448
+ t >= 0 && G.splice(t, 1);
447
449
  }
448
450
  /**
449
451
  * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
@@ -451,7 +453,7 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
451
453
  * @returns The LODsManager instance.
452
454
  */
453
455
  static get(e) {
454
- return e[ie] ? e[ie] : new b(e);
456
+ return e[ie] ? e[ie] : new P(e);
455
457
  }
456
458
  /**
457
459
  * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
@@ -488,17 +490,26 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
488
490
  return;
489
491
  this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
490
492
  const f = this.targetTriangleDensity;
491
- for (const u of s) {
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)));
493
+ for (const c of s) {
494
+ if (c.material && (((l = c.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((g = c.geometry) == null ? void 0 : g.type) === "BufferGeometry") && (c.material.name === "SphericalGaussianBlur" || c.material.name == "BackgroundCubeMaterial" || c.material.name === "CubemapFromEquirect" || c.material.name === "EquirectangularToCubeUV")) {
495
+ J && (c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", c, c.material.name, c.material.type)));
494
496
  continue;
495
497
  }
496
- const h = u.object;
498
+ switch (c.material.type) {
499
+ case "LineBasicMaterial":
500
+ case "LineDashedMaterial":
501
+ case "PointsMaterial":
502
+ case "ShadowMaterial":
503
+ case "MeshDistanceMaterial":
504
+ case "MeshDepthMaterial":
505
+ continue;
506
+ }
507
+ const h = c.object;
497
508
  (h instanceof X || h.isMesh) && this.updateLODs(e, t, h, f);
498
509
  }
499
510
  const p = n.transparent;
500
- for (const u of p) {
501
- const h = u.object;
511
+ for (const c of p) {
512
+ const h = c.object;
502
513
  (h instanceof X || h.isMesh) && this.updateLODs(e, t, h, f);
503
514
  }
504
515
  }
@@ -506,7 +517,7 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
506
517
  /** Update the LOD levels for the renderer. */
507
518
  updateLODs(e, t, r, i) {
508
519
  var l, g;
509
- for (const f of F)
520
+ for (const f of G)
510
521
  (l = f.onBeforeUpdateLOD) == null || l.call(f, this.renderer, e, t, r);
511
522
  let n = r.userData.LOD_state;
512
523
  n || (n = new ve(), r.userData.LOD_state = n);
@@ -521,7 +532,7 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
521
532
  else
522
533
  this.loadProgressiveTextures(r.material, o);
523
534
  }
524
- for (const f of F)
535
+ for (const f of G)
525
536
  (g = f.onAfterUpdatedLOD) == null || g.call(f, this.renderer, e, t, r, s);
526
537
  n.lastLodLevel = s;
527
538
  }
@@ -531,7 +542,7 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
531
542
  * @returns Promise with true if the LOD was loaded, false if not
532
543
  */
533
544
  loadProgressiveTextures(e, t) {
534
- return e && e.userData && e.userData.LOD !== t ? (e.userData.LOD = t, v.assignTextureLOD(e, t)) : Promise.resolve(null);
545
+ return e && e.userData && e.userData.LOD !== t ? (e.userData.LOD = t, S.assignTextureLOD(e, t)) : Promise.resolve(null);
535
546
  }
536
547
  /** Load progressive meshes for the given mesh
537
548
  * @param mesh the mesh to load the LOD for
@@ -545,10 +556,14 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
545
556
  if (e.userData || (e.userData = {}), e.userData.LOD !== t) {
546
557
  e.userData.LOD = t;
547
558
  const r = e.geometry;
548
- return v.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
559
+ return S.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
549
560
  }
550
561
  return Promise.resolve(null);
551
562
  }
563
+ static isInside(e, t) {
564
+ const r = e.min, i = e.max, n = (r.x + i.x) * 0.5, s = (r.y + i.y) * 0.5;
565
+ return this._tempPtInside.set(n, s, r.z).applyMatrix4(t).z < 0;
566
+ }
552
567
  calculateLodLevel(e, t, r, i) {
553
568
  var o;
554
569
  if (!t)
@@ -557,45 +572,49 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
557
572
  if (e) {
558
573
  if (J && t["DEBUG:LOD"] != null)
559
574
  return t["DEBUG:LOD"];
560
- const l = v.getMeshLODInformation(t.geometry), g = l == null ? void 0 : l.lods;
561
- if (!g || g.length <= 0 || !((o = this.cameraFrustrum) != null && o.intersectsObject(t)))
575
+ const l = S.getMeshLODInformation(t.geometry), g = l == null ? void 0 : l.lods;
576
+ if (!g || g.length <= 0)
577
+ return 0;
578
+ if (!((o = this.cameraFrustrum) != null && o.intersectsObject(t)))
562
579
  return 99;
563
580
  const f = t.geometry.boundingBox;
564
581
  if (f && e.isPerspectiveCamera) {
565
582
  const p = e;
566
583
  if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
567
584
  this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
568
- const L = e.getWorldPosition(this._tempWorldPosition);
569
- if (this._sphere.containsPoint(L))
585
+ const D = e.getWorldPosition(this._tempWorldPosition);
586
+ if (this._sphere.containsPoint(D))
570
587
  return 0;
571
588
  }
572
- if (this._tempBox.copy(f), this._tempBox.applyMatrix4(t.matrixWorld), this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
573
- const L = this._tempBox.min, y = this._tempBox.max;
574
- let T = L.x, w = L.y, m = y.x, d = y.y;
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);
589
+ if (this._tempBox.copy(f), this._tempBox.applyMatrix4(t.matrixWorld), P.isInside(this._tempBox, this.projectionScreenMatrix))
590
+ return 0;
591
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
592
+ const D = this._tempBox.min, y = this._tempBox.max;
593
+ let T = D.x, w = D.y, m = y.x, d = y.y;
594
+ const M = 2, _ = 1.5, B = (D.x + y.x) * 0.5, I = (D.y + y.y) * 0.5;
595
+ T = (T - B) * M + B, w = (w - I) * M + I, m = (m - B) * M + B, d = (d - I) * M + I;
596
+ const $ = T < 0 && m > 0 ? 0 : Math.min(Math.abs(D.x), Math.abs(y.x)), le = w < 0 && d > 0 ? 0 : Math.min(Math.abs(D.y), Math.abs(y.y)), V = Math.max($, le);
578
597
  r.lastCentrality = (_ - V) * (_ - V) * (_ - V);
579
598
  } else
580
599
  r.lastCentrality = 1;
581
- const u = this._tempBox.getSize(this._tempBoxSize);
582
- u.multiplyScalar(0.5), screen.availHeight > 0 && u.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), u.x *= p.aspect;
583
- const h = e.matrixWorldInverse, D = new re();
584
- D.copy(f), D.applyMatrix4(t.matrixWorld), D.applyMatrix4(h);
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) {
587
- const L = this.tempMatrix.copy(this.projectionScreenMatrix);
588
- L.invert();
589
- const y = b.corner0, T = b.corner1, w = b.corner2, m = b.corner3;
600
+ const c = this._tempBox.getSize(this._tempBoxSize);
601
+ c.multiplyScalar(0.5), screen.availHeight > 0 && c.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), c.x *= p.aspect;
602
+ const h = e.matrixWorldInverse, L = this._tempBox2;
603
+ L.copy(f), L.applyMatrix4(t.matrixWorld), L.applyMatrix4(h);
604
+ const A = L.getSize(this._tempBox2Size), C = Math.max(A.x, A.y);
605
+ if (Math.max(c.x, c.y) != 0 && C != 0 && (c.z = A.z / Math.max(A.x, A.y) * Math.max(c.x, c.y)), r.lastScreenCoverage = Math.max(c.x, c.y, c.z), r.lastScreenspaceVolume.copy(c), r.lastScreenCoverage *= r.lastCentrality, J && P.debugDrawLine) {
606
+ const D = this.tempMatrix.copy(this.projectionScreenMatrix);
607
+ D.invert();
608
+ const y = P.corner0, T = P.corner1, w = P.corner2, m = P.corner3;
590
609
  y.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = y.x, w.copy(this._tempBox.max), w.y = y.y, m.copy(this._tempBox.max);
591
610
  const d = (y.z + m.z) * 0.5;
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);
611
+ y.z = T.z = w.z = m.z = d, y.applyMatrix4(D), T.applyMatrix4(D), w.applyMatrix4(D), m.applyMatrix4(D), P.debugDrawLine(y, T, 255), P.debugDrawLine(y, w, 255), P.debugDrawLine(T, m, 255), P.debugDrawLine(w, m, 255);
593
612
  }
594
613
  let R = 999;
595
614
  if (g && r.lastScreenCoverage > 0) {
596
- for (let L = 0; L < g.length; L++)
597
- if (g[L].density / r.lastScreenCoverage < i) {
598
- R = L;
615
+ for (let D = 0; D < g.length; D++)
616
+ if (g[D].density / r.lastScreenCoverage < i) {
617
+ R = D;
599
618
  break;
600
619
  }
601
620
  }
@@ -605,16 +624,16 @@ const J = ee("debugprogressive"), Me = ee("noprogressive"), ie = Symbol("Needle:
605
624
  return s;
606
625
  }
607
626
  };
608
- let P = b;
627
+ let b = P;
609
628
  /** 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.
610
629
  */
611
- c(P, "debugDrawLine"), c(P, "corner0", new C()), c(P, "corner1", new C()), c(P, "corner2", new C()), c(P, "corner3", new C());
630
+ u(b, "debugDrawLine"), u(b, "corner0", new k()), u(b, "corner1", new k()), u(b, "corner2", new k()), u(b, "corner3", new k()), u(b, "_tempPtInside", new k());
612
631
  class ve {
613
632
  constructor() {
614
- c(this, "lastLodLevel", 0);
615
- c(this, "lastScreenCoverage", 0);
616
- c(this, "lastScreenspaceVolume", new C());
617
- c(this, "lastCentrality", 0);
633
+ u(this, "lastLodLevel", 0);
634
+ u(this, "lastScreenCoverage", 0);
635
+ u(this, "lastScreenspaceVolume", new k());
636
+ u(this, "lastCentrality", 0);
618
637
  }
619
638
  }
620
639
  const ne = Symbol("NEEDLE_mesh_lod"), q = Symbol("NEEDLE_texture_lod");
@@ -628,8 +647,8 @@ function Se(a) {
628
647
  }
629
648
  if (e) {
630
649
  console.log("Adding Needle LODs to modelviewer");
631
- const r = P.get(e);
632
- if (P.addPlugin(new Te(a)), r.enable(), t) {
650
+ const r = b.get(e);
651
+ if (b.addPlugin(new Te(a)), r.enable(), t) {
633
652
  const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
634
653
  i && e.render(t, i);
635
654
  }
@@ -641,8 +660,8 @@ function Se(a) {
641
660
  }
642
661
  class Te {
643
662
  constructor(e) {
644
- c(this, "modelviewer");
645
- c(this, "_didWarnAboutMissingUrl", !1);
663
+ u(this, "modelviewer");
664
+ u(this, "_didWarnAboutMissingUrl", !1);
646
665
  this.modelviewer = e;
647
666
  }
648
667
  onBeforeUpdateLOD(e, t, r, i) {
@@ -667,17 +686,17 @@ class Te {
667
686
  return;
668
687
  o[q] = !0, o.userData && (o.userData.LOD = -1);
669
688
  const l = Object.keys(o);
670
- for (let u = 0; u < l.length; u++) {
671
- const h = l[u], D = o[h];
672
- if ((D == null ? void 0 : D.isTexture) === !0) {
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) {
689
+ for (let c = 0; c < l.length; c++) {
690
+ const h = l[c], L = o[h];
691
+ if ((L == null ? void 0 : L.isTexture) === !0) {
692
+ const A = (f = (g = L.userData) == null ? void 0 : g.associations) == null ? void 0 : f.textures, C = r.parser.json.textures[A];
693
+ if (!C) {
675
694
  console.warn("Texture data not found for texture index " + A);
676
695
  continue;
677
696
  }
678
- if ((p = B == null ? void 0 : B.extensions) != null && p[E]) {
679
- const x = B.extensions[E];
680
- x && i && v.registerTexture(i, D, x.lods.length, x);
697
+ if ((p = C == null ? void 0 : C.extensions) != null && p[E]) {
698
+ const x = C.extensions[E];
699
+ x && i && S.registerTexture(i, L, x.lods.length, x);
681
700
  }
682
701
  }
683
702
  }
@@ -701,13 +720,13 @@ class Te {
701
720
  const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[E];
702
721
  if (i && r) {
703
722
  const o = t.uuid;
704
- v.registerMesh(r, o, t, 0, i.lods.length, i);
723
+ S.registerMesh(r, o, t, 0, i.lods.length, i);
705
724
  }
706
725
  }
707
726
  }
708
727
  function Ee(a, e, t, r) {
709
- oe(e), ae(t), t.register((n) => new v(n, a));
710
- const i = P.get(e);
728
+ oe(e), ae(t), t.register((n) => new S(n, a));
729
+ const i = b.get(e);
711
730
  return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
712
731
  }
713
732
  document.addEventListener("DOMContentLoaded", () => {
@@ -715,14 +734,14 @@ document.addEventListener("DOMContentLoaded", () => {
715
734
  });
716
735
  export {
717
736
  E as EXTENSION_NAME,
718
- P as LODsManager,
719
- v as NEEDLE_progressive,
737
+ b as LODsManager,
738
+ S as NEEDLE_progressive,
720
739
  ae as addDracoAndKTX2Loaders,
721
740
  oe as createLoaders,
722
741
  xe as getRaycastMesh,
723
742
  Se as patchModelViewer,
724
- Re as setDracoDecoderLocation,
725
- Ce as setKTX2TranscoderLocation,
743
+ Ce as setDracoDecoderLocation,
744
+ Re as setKTX2TranscoderLocation,
726
745
  we as setRaycastMesh,
727
746
  Ee as useNeedleProgressive
728
747
  };
@@ -1,3 +1,3 @@
1
- var le=Object.defineProperty,ue=(r,e,t)=>e in r?le(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,c=(r,e,t)=>(ue(r,typeof e!="symbol"?e+"":e,t),t);import{MeshoptDecoder as ce}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as de}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as he}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as U,Mesh as z,Material as fe,Texture as C,TextureLoader as ge,Matrix4 as ee,Frustum as me,Sphere as pe,Box3 as re,Vector3 as I}from"three";import{GLTFLoader as ye}from"three/examples/jsm/loaders/GLTFLoader.js";let $="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",V="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch($+"draco_decoder.js",{method:"head"}).catch(r=>{$="./include/draco/",V="./include/ktx2/"});function De(r){$=r}function xe(r){V=r}let G,X,N;function K(r){G||(G=new de,G.setDecoderPath($),G.setDecoderConfig({type:"js"})),N||(N=new he,N.setTranscoderPath(V)),X||(X=ce),r?N.detectSupport(r):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function H(r){r.dracoLoader||r.setDRACOLoader(G),r.ktx2Loader||r.setKTX2Loader(N),r.meshoptDecoder||r.setMeshoptDecoder(X)}function Y(r){const e=new URL(window.location.href).searchParams.get(r);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Le(r,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||r===void 0)return e;const t=r.lastIndexOf("/");if(t>=0){const o=r.substring(0,t+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}function te(r){var e;return((e=r.userData)==null?void 0:e["needle:raycast-mesh"])instanceof U?r.userData["needle:raycast-mesh"]:null}function se(r,e){(r.type==="Mesh"||r.type==="SkinnedMesh")&&(r.userData||(r.userData={}),r.userData["needle:raycast-mesh"]=e)}const R=new Array,P="NEEDLE_progressive",v=Y("debugprogressive"),J=Symbol("needle-progressive-texture"),F=new Map,Q=new Set;if(v){let r=function(){e+=1,console.log("Toggle LOD level",e,F),F.forEach((n,s)=>{for(const a of n.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=w.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,d),l&&(t=Math.max(t,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,o=!1;window.addEventListener("keyup",n=>{n.key==="p"&&r(),n.key==="w"&&(o=!o,Q&&Q.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=o)}))})}function oe(r,e,t){var o;if(!v)return;F.has(r)||F.set(r,{keys:[],sourceId:t});const n=F.get(r);((o=n?.keys)==null?void 0:o.includes(e))==!1&&n.keys.push(e)}const O=class{constructor(r,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=r,this.url=e}get name(){return P}static getMeshLODInformation(r){const e=this.getAssignedLODInformation(r);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(r,e){var t;if(r.isMaterial===!0){for(const s of Object.keys(r)){const a=r[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(r.isGroup===!0){for(const s of r.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let o,n;if(r.isMesh?o=r.geometry:(r.isBufferGeometry||r.isTexture)&&(o=r),o&&(t=o?.userData)!=null&&t.LODS){const s=o.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(r,e){var t;if(!r)return Promise.resolve(null);if(r instanceof z||r.isMesh===!0){const o=r.geometry,n=this.getAssignedLODInformation(o);if(!n)return Promise.resolve(null);for(const s of R)(t=s.onBeforeGetLODMesh)==null||t.call(s,r,e);return r["LOD:requested level"]=e,O.getOrLoadLOD(o,e).then(s=>{if(r["LOD:requested level"]===e){if(delete r["LOD:requested level"],Array.isArray(s)){const a=n.index||0;s=s[a]}s&&o!=s&&s instanceof U&&(r.geometry=s,v&&oe(r,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",r,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",r);return Promise.resolve(null)}static assignTextureLOD(r,e=0){if(!r)return Promise.resolve(null);if(r instanceof fe||r.isMaterial===!0){const t=r,o=[],n=new Array;if(v&&Q.add(t),t.uniforms&&t.isRawShaderMaterial||t.isShaderMaterial===!0){const s=t;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,t,a);o.push(l),n.push(a)}}}else for(const s of Object.keys(t)){const a=t[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,t,s);o.push(i),n.push(s)}}return Promise.all(o).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=n[i];l&&l.isTexture===!0?a.push({material:t,slot:d,texture:l,level:e}):a.push({material:t,slot:d,texture:null,level:e})}return a})}if(r instanceof C||r.isTexture===!0){const t=r;return this.assignTextureLODForSlot(t,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(r,e,t,o){return r?.isTexture!==!0?Promise.resolve(null):O.getOrLoadLOD(r,e).then(n=>{if(Array.isArray(n))return null;if(n?.isTexture===!0){if(n!=r&&(t&&o&&(t[o]=n),v&&o&&t)){const s=this.getAssignedLODInformation(r);s&&oe(t,o,s.url)}return n}else v=="verbose"&&console.warn("No LOD found for",r,e);return null}).catch(n=>(console.error("Error loading LOD",r,n),null))}afterRoot(r){var e,t;return v&&console.log("AFTER",this.url,r),(e=this.parser.json.textures)==null||e.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===n&&(a=!0,O.registerTexture(this.url,i,n,s));a||this.parser.getDependency("texture",n).then(i=>{i&&O.registerTexture(this.url,i,n,s)})}}}),(t=this.parser.json.meshes)==null||t.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===n&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(r,e){var t,o,n;const s=v=="verbose",a=r.userData.LODS;if(!a)return null;const i=a?.key;let l;if(r.isTexture===!0){const d=r;d.source&&d.source[J]&&(l=d.source[J])}if(l||(l=O.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=Le(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
2
- `,m),null)),f=!1;if(y==null||(y instanceof C&&r instanceof C?(t=y.image)!=null&&t.data||(o=y.source)!=null&&o.data?y=this.copySettings(r,y):(f=!0,this.previouslyLoaded.delete(u)):y instanceof U&&r instanceof U&&((n=y.attributes.position)!=null&&n.array||(f=!0,this.previouslyLoaded.delete(u)))),!f)return y}const D=l,A=new Promise(async(y,f)=>{const m=new ye;H(m),v&&(await new Promise(L=>setTimeout(L,1e3)),s&&console.warn("Start loading (delayed) "+h,D.guid));let b=h;if(D&&Array.isArray(D.lods)){const L=D.lods[e];L.hash&&(b+="?v="+L.hash)}const x=await m.loadAsync(b).catch(L=>(console.error(`Error loading LOD ${e} from ${h}
3
- `,L),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,D.guid);let T=0;if(x.parser.json.textures){let L=!1;for(const g of x.parser.json.textures){if(g!=null&&g.extensions){const M=g?.extensions[P];if(M!=null&&M.guid&&M.guid===D.guid){L=!0;break}}T++}if(L){let g=await S.getDependency("texture",T);return s&&console.log('change "'+r.name+'" \u2192 "'+g.name+'"',h,T,g,u),r instanceof C&&(g=this.copySettings(r,g)),g&&(g.guid=D.guid),y(g)}}if(T=0,x.parser.json.meshes){let L=!1;for(const g of x.parser.json.meshes){if(g!=null&&g.extensions){const M=g?.extensions[P];if(M!=null&&M.guid&&M.guid===D.guid){L=!0;break}}T++}if(L){const g=await S.getDependency("mesh",T),M=D;if(s&&console.log(`Loaded Mesh "${g.name}"`,h,T,g,u),g.isMesh===!0){const E=g.geometry;return O.assignLODInformation(a.url,E,i,e,void 0,M.density),y(E)}else{const E=new Array;for(let k=0;k<g.children.length;k++){const W=g.children[k];if(W instanceof z){const j=W.geometry;O.assignLODInformation(a.url,j,i,e,k,M.density),E.push(j)}}return y(E)}}}return y(null)});return this.previouslyLoaded.set(u,A),await A}else if(r instanceof C){s&&console.log("Load texture from uri: "+h);const u=await new ge().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=r.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${r.name}`,r.type);return null}static assignLODInformation(r,e,t,o,n,s){if(!e)return;e.userData||(e.userData={});const a=new ve(r,t,o,n,s);e.userData.LODS=a,e.userData.LOD=o}static getAssignedLODInformation(r){var e;return((e=r?.userData)==null?void 0:e.LODS)||null}static copySettings(r,e){return this._copiedTextures.get(r)||(e=e.clone(),this._copiedTextures.set(r,e),e.offset=r.offset,e.repeat=r.repeat,e.colorSpace=r.colorSpace,e.magFilter=r.magFilter,e.minFilter=r.minFilter,e.wrapS=r.wrapS,e.wrapT=r.wrapT,e.flipY=r.flipY,e.anisotropy=r.anisotropy,e.generateMipmaps=r.generateMipmaps,e)}};let w=O;c(w,"registerTexture",(r,e,t,o)=>{v&&console.log("> Progressive: register texture",t,e.name,e.uuid,e,o),e.source&&(e.source[J]=o);const n=o.guid;O.assignLODInformation(r,e,n,0,0,void 0),O.lodInfos.set(n,o),O.lowresCache.set(n,e)}),c(w,"registerMesh",(r,e,t,o,n,s)=>{var a;v&&console.log("> Progressive: register mesh",n,t.name,s,t.uuid,t);const i=t.geometry;i.userData||(i.userData={}),O.assignLODInformation(r,i,e,o,n,s.density),O.lodInfos.set(e,s);let l=O.lowresCache.get(e);l?l.push(t.geometry):l=[t.geometry],O.lowresCache.set(e,l),o>0&&!te(t)&&se(t,i);for(const d of R)(a=d.onRegisteredNewMesh)==null||a.call(d,t,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map),c(w,"_copiedTextures",new Map);class ve{constructor(e,t,o,n,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=t,this.level=o,n!=null&&(this.index=n),s!=null&&(this.density=s)}}const Z=Y("debugprogressive"),Oe=Y("noprogressive"),ne=Symbol("Needle:LODSManager"),_=class{constructor(r){c(this,"renderer"),c(this,"projectionScreenMatrix",new ee),c(this,"cameraFrustrum",new me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new pe),c(this,"_tempBox",new re),c(this,"tempMatrix",new ee),c(this,"_tempWorldPosition",new I),c(this,"_tempBoxSize",new I),c(this,"_tempBox2Size",new I),this.renderer=r}static getObjectLODState(r){var e;return(e=r.userData)==null?void 0:e.LOD_state}static addPlugin(r){R.push(r)}static removePlugin(r){const e=R.indexOf(r);e>=0&&R.splice(e,1)}static get(r){return r[ne]?r[ne]:new _(r)}enable(){if(this._originalRender)return;let r=0;this._originalRender=this.renderer.render;const e=this;K(this.renderer),this.renderer.render=function(t,o){e.renderer.getRenderTarget()==null&&(r=0,e._frame+=1);const n=e._frame,s=r++;e.onBeforeRender(t,o,s,n),e._originalRender.call(this,t,o),e.onAfterRender(t,o,s,n)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(r,e,t,o){}onAfterRender(r,e,t,o){var n,s;if(this.pause)return;const a=this.renderer.renderLists.get(r,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(Oe||this.updateInterval>0&&o%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const u of i){if(u.material&&(((n=u.geometry)==null?void 0:n.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){Z&&(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)));continue}const p=u.object;(p instanceof z||p.isMesh)&&this.updateLODs(r,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof z||p.isMesh)&&this.updateLODs(r,e,p,d)}}}updateLODs(r,e,t,o){var n,s;for(const d of R)(n=d.onBeforeUpdateLOD)==null||n.call(d,this.renderer,r,e,t);let a=t.userData.LOD_state;a||(a=new we,t.userData.LOD_state=a);let i=this.calculateLodLevel(e,t,a,o);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(t,i);let l=0;if(t.material){const d=t["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(t.material))for(const h of t.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(t.material,l)}for(const d of R)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,r,e,t,i);a.lastLodLevel=i}loadProgressiveTextures(r,e){return r&&r.userData&&r.userData.LOD!==e?(r.userData.LOD=e,w.assignTextureLOD(r,e)):Promise.resolve(null)}loadProgressiveMeshes(r,e){if(!r)return Promise.resolve(null);if(r.userData||(r.userData={}),r.userData.LOD!==e){r.userData.LOD=e;const t=r.geometry;return w.assignMeshLOD(r,e).then(o=>(o&&r.userData.LOD==e&&t!=r.geometry,o))}return Promise.resolve(null)}calculateLodLevel(r,e,t,o){var n;if(!e)return-1;let s=10+1;if(r){if(Z&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=w.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&r.isPerspectiveCamera){const d=r;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=r.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let b=f.x,x=f.y,S=m.x,T=m.y;const L=2,g=1.5,M=(f.x+m.x)*.5,E=(f.y+m.y)*.5;b=(b-M)*L+M,x=(x-E)*L+E,S=(S-M)*L+M,T=(T-E)*L+E;const k=b<0&&S>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),W=x<0&&T>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),j=Math.max(k,W);t.lastCentrality=(g-j)*(g-j)*(g-j)}else t.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=r.matrixWorldInverse,p=new re;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const D=p.getSize(this._tempBox2Size),A=Math.max(D.x,D.y);if(Math.max(h.x,h.y)!=0&&A!=0&&(h.z=D.z/Math.max(D.x,D.y)*Math.max(h.x,h.y)),t.lastScreenCoverage=Math.max(h.x,h.y,h.z),t.lastScreenspaceVolume.copy(h),t.lastScreenCoverage*=t.lastCentrality,Z&&_.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=_.corner0,b=_.corner1,x=_.corner2,S=_.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const T=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=T,m.applyMatrix4(f),b.applyMatrix4(f),x.applyMatrix4(f),S.applyMatrix4(f),_.debugDrawLine(m,b,255),_.debugDrawLine(m,x,255),_.debugDrawLine(b,S,255),_.debugDrawLine(x,S,255)}let y=999;if(i&&t.lastScreenCoverage>0){for(let f=0;f<i.length;f++)if(i[f].density/t.lastScreenCoverage<o){y=f;break}}y<s&&(s=y)}}return s}};let B=_;c(B,"debugDrawLine"),c(B,"corner0",new I),c(B,"corner1",new I),c(B,"corner2",new I),c(B,"corner3",new I);class we{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new I),c(this,"lastCentrality",0)}}const ie=Symbol("NEEDLE_mesh_lod"),q=Symbol("NEEDLE_texture_lod");function ae(r){if(!r)return null;let e=null,t=null;for(let o=r;o!=null;o=Object.getPrototypeOf(o)){const n=Object.getOwnPropertySymbols(o),s=n.find(i=>i.toString()=="Symbol(renderer)"),a=n.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=r[s].threeRenderer),!t&&a!=null&&(t=r[a])}if(e){console.log("Adding Needle LODs to modelviewer");const o=B.get(e);if(B.addPlugin(new Me(r)),o.enable(),t){const n=t.camera||t.traverse(s=>s.type=="PerspectiveCamera")[0];n&&e.render(t,n)}return()=>{o.disable()}}return null}class Me{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,t,o,n){this.tryParseMeshLOD(t,n),this.tryParseTextureLOD(t,n)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[q]==!0)return;t[q]=!0;const o=this.tryGetCurrentGLTF(e),n=this.getUrl();if(n&&o&&t.material){let s=function(i){var l,d,h;if(i[q]==!0)return;i[q]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const D=u[p],A=i[D];if(A?.isTexture===!0){const y=(d=(l=A.userData)==null?void 0:l.associations)==null?void 0:d.textures,f=o.parser.json.textures[y];if(!f){console.warn("Texture data not found for texture index "+y);continue}if((h=f?.extensions)!=null&&h[P]){const m=f.extensions[P];m&&n&&w.registerTexture(n,A,m.lods.length,m)}}}};const a=t.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,t){var o,n;if(t[ie]==!0)return;t[ie]=!0;const s=this.getUrl();if(!s)return;const a=(n=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:n[P];if(a&&s){const i=t.uuid;w.registerMesh(s,i,t,0,a.lods.length,a)}}}function be(r,e,t,o){K(e),H(t),t.register(s=>new w(s,r));const n=B.get(e);return o?.enableLODsManager!==!1&&n.enable(),n}document.addEventListener("DOMContentLoaded",()=>{ae(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,B as LODsManager,w as NEEDLE_progressive,H as addDracoAndKTX2Loaders,K as createLoaders,te as getRaycastMesh,ae as patchModelViewer,De as setDracoDecoderLocation,xe as setKTX2TranscoderLocation,se as setRaycastMesh,be as useNeedleProgressive};
1
+ var le=Object.defineProperty,ue=(t,e,r)=>e in t?le(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ue(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as ce}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as de}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as he}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as z,Mesh as U,Material as fe,Texture as k,TextureLoader as ge,Matrix4 as ee,Frustum as me,Sphere as pe,Box3 as te,Vector3 as B}from"three";import{GLTFLoader as ye}from"three/examples/jsm/loaders/GLTFLoader.js";let $="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",V="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch($+"draco_decoder.js",{method:"head"}).catch(t=>{$="./include/draco/",V="./include/ktx2/"});function De(t){$=t}function xe(t){V=t}let G,X,N;function K(t){G||(G=new de,G.setDecoderPath($),G.setDecoderConfig({type:"js"})),N||(N=new he,N.setTranscoderPath(V)),X||(X=ce),t?N.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function H(t){t.dracoLoader||t.setDRACOLoader(G),t.ktx2Loader||t.setKTX2Loader(N),t.meshoptDecoder||t.setMeshoptDecoder(X)}function Y(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Le(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}function re(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof z?t.userData["needle:raycast-mesh"]:null}function se(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const R=new Array,I="NEEDLE_progressive",v=Y("debugprogressive"),J=Symbol("needle-progressive-texture"),F=new Map,Q=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,F),F.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=O.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,O.assignMeshLOD(s,d),l&&(r=Math.max(r,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,O.assignTextureLOD(s,e);break}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",o=>{o.key==="p"&&t(),o.key==="w"&&(n=!n,Q&&Q.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ne(t,e,r){var n;if(!v)return;F.has(t)||F.set(t,{keys:[],sourceId:r});const o=F.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const M=class{constructor(t,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return I}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(t,e){var r;if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let n,o;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const s=n.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof U||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of R)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const a=o.index||0;s=s[a]}s&&n!=s&&s instanceof z&&(t.geometry=s,v&&ne(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof fe||t.isMaterial===!0){const r=t,n=[],o=new Array;if(v&&Q.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,a);n.push(l),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,r,s);n.push(i),o.push(s)}}return Promise.all(n).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=o[i];l&&l.isTexture===!0?a.push({material:r,slot:d,texture:l,level:e}):a.push({material:r,slot:d,texture:null,level:e})}return a})}if(t instanceof k||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):M.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t&&(r&&n&&(r[n]=o),v&&n&&r)){const s=this.getAssignedLODInformation(t);s&&ne(r,n,s.url)}return o}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[I];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,M.registerTexture(this.url,i,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&M.registerTexture(this.url,i,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[I];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===o&&M.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o;const s=v=="verbose",a=t.userData.LODS;if(!a)return null;const i=a?.key;let l;if(t.isTexture===!0){const d=t;d.source&&d.source[J]&&(l=d.source[J])}if(l||(l=M.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=Le(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
2
+ `,m),null)),g=!1;if(y==null||(y instanceof k&&t instanceof k?(r=y.image)!=null&&r.data||(n=y.source)!=null&&n.data?y=this.copySettings(t,y):(g=!0,this.previouslyLoaded.delete(u)):y instanceof z&&t instanceof z&&((o=y.attributes.position)!=null&&o.array||(g=!0,this.previouslyLoaded.delete(u)))),!g)return y}const D=l,P=new Promise(async(y,g)=>{const m=new ye;H(m),v&&(await new Promise(L=>setTimeout(L,1e3)),s&&console.warn("Start loading (delayed) "+h,D.guid));let b=h;if(D&&Array.isArray(D.lods)){const L=D.lods[e];L.hash&&(b+="?v="+L.hash)}const x=await m.loadAsync(b).catch(L=>(console.error(`Error loading LOD ${e} from ${h}
3
+ `,L),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,D.guid);let _=0;if(x.parser.json.textures){let L=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){let f=await S.getDependency("texture",_);return f&&M.assignLODInformation(a.url,f,i,e,void 0,void 0),s&&console.log('change "'+t.name+'" \u2192 "'+f.name+'"',h,_,f,u),t instanceof k&&(f=this.copySettings(t,f)),f&&(f.guid=D.guid),y(f)}else v&&console.warn("Could not find texture with guid",D.guid)}if(_=0,x.parser.json.meshes){let L=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){const f=await S.getDependency("mesh",_),w=D;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,_,f,u),f.isMesh===!0){const E=f.geometry;return M.assignLODInformation(a.url,E,i,e,void 0,w.density),y(E)}else{const E=new Array;for(let C=0;C<f.children.length;C++){const W=f.children[C];if(W instanceof U){const j=W.geometry;M.assignLODInformation(a.url,j,i,e,C,w.density),E.push(j)}}return y(E)}}}return y(null)});return this.previouslyLoaded.set(u,P),await P}else if(t instanceof k){s&&console.log("Load texture from uri: "+h);const u=await new ge().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new ve(t,r,n,o,s);e.userData.LODS=a,e.userData.LOD=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return this._copiedTextures.get(t)||(e=e.clone(),this._copiedTextures.set(t,e),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.generateMipmaps=t.generateMipmaps,e)}};let O=M;c(O,"registerTexture",(t,e,r,n)=>{v&&console.log("> Progressive: register texture",r,e.name,e.uuid,e,n),e.source&&(e.source[J]=n);const o=n.guid;M.assignLODInformation(t,e,o,0,0,void 0),M.lodInfos.set(o,n),M.lowresCache.set(o,e)}),c(O,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let l=M.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],M.lowresCache.set(e,l),n>0&&!re(r)&&se(r,i);for(const d of R)(a=d.onRegisteredNewMesh)==null||a.call(d,r,s)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"lowresCache",new Map),c(O,"_copiedTextures",new Map);class ve{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const Z=Y("debugprogressive"),Me=Y("noprogressive"),oe=Symbol("Needle:LODSManager"),T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ee),c(this,"cameraFrustrum",new me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new pe),c(this,"_tempBox",new te),c(this,"_tempBox2",new te),c(this,"tempMatrix",new ee),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[oe]?t[oe]:new T(t)}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;K(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(Me||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const u of i){if(u.material&&(((o=u.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){Z&&(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)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}}}updateLODs(t,e,r,n){var o,s;for(const d of R)(o=d.onBeforeUpdateLOD)==null||o.call(d,this.renderer,t,e,r);let a=r.userData.LOD_state;a||(a=new Oe,r.userData.LOD_state=a);let i=this.calculateLodLevel(e,r,a,n);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(r,i);let l=0;if(r.material){const d=r["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(r.material))for(const h of r.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(r.material,l)}for(const d of R)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,t,e,r,i);a.lastLodLevel=i}loadProgressiveTextures(t,e){return t&&t.userData&&t.userData.LOD!==e?(t.userData.LOD=e,O.assignTextureLOD(t,e)):Promise.resolve(null)}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n){var o;if(!e)return-1;let s=10+1;if(t){if(Z&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&t.isPerspectiveCamera){const d=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const L=2,f=1.5,w=(g.x+m.x)*.5,E=(g.y+m.y)*.5;b=(b-w)*L+w,x=(x-E)*L+E,S=(S-w)*L+w,_=(_-E)*L+E;const C=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(C,W);r.lastCentrality=(f-j)*(f-j)*(f-j)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=t.matrixWorldInverse,p=this._tempBox2;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const D=p.getSize(this._tempBox2Size),P=Math.max(D.x,D.y);if(Math.max(h.x,h.y)!=0&&P!=0&&(h.z=D.z/Math.max(D.x,D.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,Z&&T.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=T.corner0,b=T.corner1,x=T.corner2,S=T.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),T.debugDrawLine(m,b,255),T.debugDrawLine(m,x,255),T.debugDrawLine(b,S,255),T.debugDrawLine(x,S,255)}let y=999;if(i&&r.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/r.lastScreenCoverage<n){y=g;break}}y<s&&(s=y)}}return s}};let A=T;c(A,"debugDrawLine"),c(A,"corner0",new B),c(A,"corner1",new B),c(A,"corner2",new B),c(A,"corner3",new B),c(A,"_tempPtInside",new B);class Oe{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const ie=Symbol("NEEDLE_mesh_lod"),q=Symbol("NEEDLE_texture_lod");function ae(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=A.get(e);if(A.addPlugin(new we(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class we{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[q]==!0)return;r[q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var l,d,h;if(i[q]==!0)return;i[q]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const D=u[p],P=i[D];if(P?.isTexture===!0){const y=(d=(l=P.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=n.parser.json.textures[y];if(!g){console.warn("Texture data not found for texture index "+y);continue}if((h=g?.extensions)!=null&&h[I]){const m=g.extensions[I];m&&o&&O.registerTexture(o,P,m.lods.length,m)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[ie]==!0)return;r[ie]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[I];if(a&&s){const i=r.uuid;O.registerMesh(s,i,r,0,a.lods.length,a)}}}function be(t,e,r,n){K(e),H(r),r.register(s=>new O(s,t));const o=A.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ae(document.querySelector("model-viewer"))});export{I as EXTENSION_NAME,A as LODsManager,O as NEEDLE_progressive,H as addDracoAndKTX2Loaders,K as createLoaders,re as getRaycastMesh,ae as patchModelViewer,De as setDracoDecoderLocation,xe as setKTX2TranscoderLocation,se as setRaycastMesh,be as useNeedleProgressive};
@@ -1,3 +1,3 @@
1
- "use strict";var ae=Object.defineProperty;var le=(a,e,t)=>e in a?ae(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var u=(a,e,t)=>(le(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("three/examples/jsm/libs/meshopt_decoder.module.js"),ue=require("three/examples/jsm/loaders/DRACOLoader.js"),fe=require("three/examples/jsm/loaders/KTX2Loader.js"),h=require("three"),de=require("three/examples/jsm/loaders/GLTFLoader.js");let q="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(q+"draco_decoder.js",{method:"head"}).catch(a=>{q="./include/draco/",J="./include/ktx2/"});function ge(a){q=a}function he(a){J=a}let N,Y,U;function Q(a){N||(N=new ue.DRACOLoader,N.setDecoderPath(q),N.setDecoderConfig({type:"js"})),U||(U=new fe.KTX2Loader,U.setTranscoderPath(J)),Y||(Y=ce.MeshoptDecoder),a?U.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(a){a.dracoLoader||a.setDRACOLoader(N),a.ktx2Loader||a.setKTX2Loader(U),a.meshoptDecoder||a.setMeshoptDecoder(Y)}function j(a){const t=new URL(window.location.href).searchParams.get(a);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function pe(a,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||a===void 0)return e;const t=a.lastIndexOf("/");if(t>=0){const r=a.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}function se(a){var e;return((e=a.userData)==null?void 0:e["needle:raycast-mesh"])instanceof h.BufferGeometry?a.userData["needle:raycast-mesh"]:null}function ie(a,e){(a.type==="Mesh"||a.type==="SkinnedMesh")&&(a.userData||(a.userData={}),a.userData["needle:raycast-mesh"]=e)}const F=new Array,R="NEEDLE_progressive",T=j("debugprogressive"),$=Symbol("needle-progressive-texture"),W=new Map,H=new Set;if(T){let a=function(){e+=1,console.log("Toggle LOD level",e,W),W.forEach((i,n)=>{for(const s of i.keys){const o=n[s];if(o.isBufferGeometry===!0){const l=M.getMeshLODInformation(o),g=l?Math.min(e,l.lods.length):0;n["DEBUG:LOD"]=e,M.assignMeshLOD(n,g),l&&(t=Math.max(t,l.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,M.assignTextureLOD(n,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,H&&H.forEach(n=>{n.name!="BackgroundCubeMaterial"&&"wireframe"in n&&(n.wireframe=r)}))})}function ee(a,e,t){var i;if(!T)return;W.has(a)||W.set(a,{keys:[],sourceId:t});const r=W.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const S=class{constructor(e,t){u(this,"parser");u(this,"url");T&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return R}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static hasLODLevelAvailable(e,t){var n;if(e.isMaterial===!0){for(const s of Object.keys(e)){const o=e[s];if(o.isTexture&&this.hasLODLevelAvailable(o,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(n=r==null?void 0:r.userData)!=null&&n.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof h.Mesh||e.isMesh===!0){const i=e.geometry,n=this.getAssignedLODInformation(i);if(!n)return Promise.resolve(null);for(const s of F)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,S.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const o=n.index||0;s=s[o]}s&&i!=s&&s instanceof h.BufferGeometry&&(e.geometry=s,T&&ee(e,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else T&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof h.Material||e.isMaterial===!0){const r=e,i=[],n=new Array;if(T&&H.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const o of Object.keys(s.uniforms)){const l=s.uniforms[o].value;if((l==null?void 0:l.isTexture)===!0){const g=this.assignTextureLODForSlot(l,t,r,o);i.push(g),n.push(o)}}}else for(const s of Object.keys(r)){const o=r[s];if((o==null?void 0:o.isTexture)===!0){const l=this.assignTextureLODForSlot(o,t,r,s);i.push(l),n.push(s)}}return Promise.all(i).then(s=>{const o=new Array;for(let l=0;l<s.length;l++){const g=s[l],f=n[l];g&&g.isTexture===!0?o.push({material:r,slot:f,texture:g,level:t}):o.push({material:r,slot:f,texture:null,level:t})}return o})}if(e instanceof h.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):S.getOrLoadLOD(e,t).then(n=>{if(Array.isArray(n))return null;if((n==null?void 0:n.isTexture)===!0){if(n!=e&&(r&&i&&(r[i]=n),T&&i&&r)){const s=this.getAssignedLODInformation(e);s&&ee(r,i,s.url)}return n}else T=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(n=>(console.error("Error loading LOD",e,n),null))}afterRoot(e){var t,r;return T&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s){let o=!1;for(const l of this.parser.associations.keys())l.isTexture===!0&&this.parser.associations.get(l).textures===n&&(o=!0,S.registerTexture(this.url,l,n,s));o||this.parser.getDependency("texture",n).then(l=>{l&&S.registerTexture(this.url,l,n,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s&&s.lods){for(const o of this.parser.associations.keys())if(o.isMesh){const l=this.parser.associations.get(o);l.meshes===n&&S.registerMesh(this.url,s.guid,o,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var o,l,g;const r=T=="verbose",i=e.userData.LODS;if(!i)return null;const n=i==null?void 0:i.key;let s;if(e.isTexture===!0){const f=e;f.source&&f.source[$]&&(s=f.source[$])}if(s||(s=S.lodInfos.get(n)),s){if(t>0){let c=!1;const p=Array.isArray(s.lods);if(p&&t>=s.lods.length?c=!0:p||(c=!0),c)return this.lowresCache.get(n)}const f=Array.isArray(s.lods)?s.lods[t].path:s.lods;if(!f)return T&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const y=pe(i.url,f);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const c=y+"_"+s.guid,p=this.previouslyLoaded.get(c);if(p!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${c}`);let O=await p.catch(I=>(console.error(`Error loading LOD ${t} from ${y}
2
- `,I),null)),C=!1;if(O==null||(O instanceof h.Texture&&e instanceof h.Texture?(o=O.image)!=null&&o.data||(l=O.source)!=null&&l.data?O=this.copySettings(e,O):(C=!0,this.previouslyLoaded.delete(c)):O instanceof h.BufferGeometry&&e instanceof h.BufferGeometry&&((g=O.attributes.position)!=null&&g.array||(C=!0,this.previouslyLoaded.delete(c)))),!C)return O}const x=s,P=new Promise(async(O,C)=>{const I=new de.GLTFLoader;Z(I),T&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+y,x.guid));let D=y;if(x&&Array.isArray(x.lods)){const L=x.lods[t];L.hash&&(D+="?v="+L.hash)}const m=await I.loadAsync(D).catch(L=>(console.error(`Error loading LOD ${t} from ${y}
3
- `,L),null));if(!m)return null;const A=m.parser;r&&console.log("Loading finished "+y,x.guid);let w=0;if(m.parser.json.textures){let L=!1;for(const d of m.parser.json.textures){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[R];if(v!=null&&v.guid&&v.guid===x.guid){L=!0;break}}w++}if(L){let d=await A.getDependency("texture",w);return r&&console.log('change "'+e.name+'" → "'+d.name+'"',y,w,d,c),e instanceof h.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=x.guid),O(d)}}if(w=0,m.parser.json.meshes){let L=!1;for(const d of m.parser.json.meshes){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[R];if(v!=null&&v.guid&&v.guid===x.guid){L=!0;break}}w++}if(L){const d=await A.getDependency("mesh",w),v=x;if(r&&console.log(`Loaded Mesh "${d.name}"`,y,w,d,c),d.isMesh===!0){const B=d.geometry;return S.assignLODInformation(i.url,B,n,t,void 0,v.density),O(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const G=d.children[E];if(G instanceof h.Mesh){const z=G.geometry;S.assignLODInformation(i.url,z,n,t,E,v.density),B.push(z)}}return O(B)}}}return O(null)});return this.previouslyLoaded.set(c,P),await P}else if(e instanceof h.Texture){r&&console.log("Load texture from uri: "+y);const p=await new h.TextureLoader().loadAsync(y);return p?(p.guid=s.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=e.colorSpace,r&&console.log(s,p)):T&&console.warn("failed loading",y),p}}else T&&console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,n,s){if(!t)return;t.userData||(t.userData={});const o=new ye(e,r,i,n,s);t.userData.LODS=o,t.userData.LOD=i}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){const r=this._copiedTextures.get(e);return r||(t=t.clone(),this._copiedTextures.set(e,t),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.generateMipmaps=e.generateMipmaps,t)}};let M=S;u(M,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[$]=i);const n=i.guid;S.assignLODInformation(e,t,n,0,0,void 0),S.lodInfos.set(n,i),S.lowresCache.set(n,t)}),u(M,"registerMesh",(e,t,r,i,n,s)=>{var g;T&&console.log("> Progressive: register mesh",n,r.name,s,r.uuid,r);const o=r.geometry;o.userData||(o.userData={}),S.assignLODInformation(e,o,t,i,n,s.density),S.lodInfos.set(t,s);let l=S.lowresCache.get(t);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(t,l),i>0&&!se(r)&&ie(r,o);for(const f of F)(g=f.onRegisteredNewMesh)==null||g.call(f,r,s)}),u(M,"lodInfos",new Map),u(M,"previouslyLoaded",new Map),u(M,"lowresCache",new Map),u(M,"_copiedTextures",new Map);class ye{constructor(e,t,r,i,n){u(this,"url");u(this,"key");u(this,"level");u(this,"index");u(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),n!=null&&(this.density=n)}}const K=j("debugprogressive"),me=j("noprogressive"),te=Symbol("Needle:LODSManager"),b=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new h.Matrix4);u(this,"cameraFrustrum",new h.Frustum);u(this,"targetTriangleDensity",2e5);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"_frame",0);u(this,"_originalRender");u(this,"_sphere",new h.Sphere);u(this,"_tempBox",new h.Box3);u(this,"tempMatrix",new h.Matrix4);u(this,"_tempWorldPosition",new h.Vector3);u(this,"_tempBoxSize",new h.Vector3);u(this,"_tempBox2Size",new h.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){F.push(e)}static removePlugin(e){const t=F.indexOf(e);t>=0&&F.splice(t,1)}static get(e){return e[te]?e[te]:new b(e)}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;Q(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,o=e++;t.onBeforeRender(r,i,o,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,o,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var l,g;if(this.pause)return;const n=this.renderer.renderLists.get(e,0),s=n.opaque;let o=!0;if(s.length===1){const f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(o=!1)}if(o){if(me||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const c of s){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((g=c.geometry)==null?void 0:g.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){K&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}const p=c.object;(p instanceof h.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}const y=n.transparent;for(const c of y){const p=c.object;(p instanceof h.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}}}updateLODs(e,t,r,i){var l,g;for(const f of F)(l=f.onBeforeUpdateLOD)==null||l.call(f,this.renderer,e,t,r);let n=r.userData.LOD_state;n||(n=new Le,r.userData.LOD_state=n);let s=this.calculateLodLevel(t,r,n,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let o=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(o=f),Array.isArray(r.material))for(const y of r.material)this.loadProgressiveTextures(y,o);else this.loadProgressiveTextures(r.material,o)}for(const f of F)(g=f.onAfterUpdatedLOD)==null||g.call(f,this.renderer,e,t,r,s);n.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,M.assignTextureLOD(e,t)):Promise.resolve(null)}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return M.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}calculateLodLevel(e,t,r,i){var o;if(!t)return-1;let s=10+1;if(e){if(K&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const l=M.getMeshLODInformation(t.geometry),g=l==null?void 0:l.lods;if(!g||g.length<=0||!((o=this.cameraFrustrum)!=null&&o.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const y=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const D=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(D))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const D=this._tempBox.min,m=this._tempBox.max;let A=D.x,w=D.y,L=m.x,d=m.y;const v=2,B=1.5,E=(D.x+m.x)*.5,G=(D.y+m.y)*.5;A=(A-E)*v+E,w=(w-G)*v+G,L=(L-E)*v+E,d=(d-G)*v+G;const z=A<0&&L>0?0:Math.min(Math.abs(D.x),Math.abs(m.x)),oe=w<0&&d>0?0:Math.min(Math.abs(D.y),Math.abs(m.y)),X=Math.max(z,oe);r.lastCentrality=(B-X)*(B-X)*(B-X)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&c.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),c.x*=y.aspect;const p=e.matrixWorldInverse,x=new h.Box3;x.copy(f),x.applyMatrix4(t.matrixWorld),x.applyMatrix4(p);const P=x.getSize(this._tempBox2Size),k=Math.max(P.x,P.y);if(Math.max(c.x,c.y)!=0&&k!=0&&(c.z=P.z/Math.max(P.x,P.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,K&&b.debugDrawLine){const D=this.tempMatrix.copy(this.projectionScreenMatrix);D.invert();const m=b.corner0,A=b.corner1,w=b.corner2,L=b.corner3;m.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=m.x,w.copy(this._tempBox.max),w.y=m.y,L.copy(this._tempBox.max);const d=(m.z+L.z)*.5;m.z=A.z=w.z=L.z=d,m.applyMatrix4(D),A.applyMatrix4(D),w.applyMatrix4(D),L.applyMatrix4(D),b.debugDrawLine(m,A,255),b.debugDrawLine(m,w,255),b.debugDrawLine(A,L,255),b.debugDrawLine(w,L,255)}let C=999;if(g&&r.lastScreenCoverage>0){for(let D=0;D<g.length;D++)if(g[D].density/r.lastScreenCoverage<i){C=D;break}}C<s&&(s=C)}}return s}};let _=b;u(_,"debugDrawLine"),u(_,"corner0",new h.Vector3),u(_,"corner1",new h.Vector3),u(_,"corner2",new h.Vector3),u(_,"corner3",new h.Vector3);class Le{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new h.Vector3);u(this,"lastCentrality",0)}}const re=Symbol("NEEDLE_mesh_lod"),V=Symbol("NEEDLE_texture_lod");function ne(a){if(!a)return null;let e=null,t=null;for(let r=a;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),n=i.find(o=>o.toString()=="Symbol(renderer)"),s=i.find(o=>o.toString()=="Symbol(scene)");!e&&n!=null&&(e=a[n].threeRenderer),!t&&s!=null&&(t=a[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=_.get(e);if(_.addPlugin(new De(a)),r.enable(),t){const i=t.camera||t.traverse(n=>n.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class De{constructor(e){u(this,"modelviewer");u(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[V]==!0)return;t[V]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let n=function(o){var g,f,y;if(o[V]==!0)return;o[V]=!0,o.userData&&(o.userData.LOD=-1);const l=Object.keys(o);for(let c=0;c<l.length;c++){const p=l[c],x=o[p];if((x==null?void 0:x.isTexture)===!0){const P=(f=(g=x.userData)==null?void 0:g.associations)==null?void 0:f.textures,k=r.parser.json.textures[P];if(!k){console.warn("Texture data not found for texture index "+P);continue}if((y=k==null?void 0:k.extensions)!=null&&y[R]){const O=k.extensions[R];O&&i&&M.registerTexture(i,x,O.lods.length,O)}}}};const s=t.material;if(Array.isArray(s))for(const o of s)n(o);else n(s)}}tryParseMeshLOD(e,t){var n,s;if(t[re]==!0)return;t[re]=!0;const r=this.getUrl();if(!r)return;const i=(s=(n=t.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(i&&r){const o=t.uuid;M.registerMesh(r,o,t,0,i.lods.length,i)}}}function xe(a,e,t,r){Q(e),Z(t),t.register(n=>new M(n,a));const i=_.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ne(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=_;exports.NEEDLE_progressive=M;exports.addDracoAndKTX2Loaders=Z;exports.createLoaders=Q;exports.getRaycastMesh=se;exports.patchModelViewer=ne;exports.setDracoDecoderLocation=ge;exports.setKTX2TranscoderLocation=he;exports.setRaycastMesh=ie;exports.useNeedleProgressive=xe;
1
+ "use strict";var ae=Object.defineProperty;var le=(a,e,t)=>e in a?ae(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var u=(a,e,t)=>(le(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("three/examples/jsm/libs/meshopt_decoder.module.js"),ue=require("three/examples/jsm/loaders/DRACOLoader.js"),fe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),de=require("three/examples/jsm/loaders/GLTFLoader.js");let q="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(q+"draco_decoder.js",{method:"head"}).catch(a=>{q="./include/draco/",J="./include/ktx2/"});function ge(a){q=a}function he(a){J=a}let N,Y,U;function Q(a){N||(N=new ue.DRACOLoader,N.setDecoderPath(q),N.setDecoderConfig({type:"js"})),U||(U=new fe.KTX2Loader,U.setTranscoderPath(J)),Y||(Y=ce.MeshoptDecoder),a?U.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(a){a.dracoLoader||a.setDRACOLoader(N),a.ktx2Loader||a.setKTX2Loader(U),a.meshoptDecoder||a.setMeshoptDecoder(Y)}function j(a){const t=new URL(window.location.href).searchParams.get(a);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function pe(a,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||a===void 0)return e;const t=a.lastIndexOf("/");if(t>=0){const r=a.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}function se(a){var e;return((e=a.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?a.userData["needle:raycast-mesh"]:null}function ie(a,e){(a.type==="Mesh"||a.type==="SkinnedMesh")&&(a.userData||(a.userData={}),a.userData["needle:raycast-mesh"]=e)}const I=new Array,R="NEEDLE_progressive",T=j("debugprogressive"),$=Symbol("needle-progressive-texture"),z=new Map,H=new Set;if(T){let a=function(){e+=1,console.log("Toggle LOD level",e,z),z.forEach((i,n)=>{for(const s of i.keys){const o=n[s];if(o.isBufferGeometry===!0){const l=v.getMeshLODInformation(o),h=l?Math.min(e,l.lods.length):0;n["DEBUG:LOD"]=e,v.assignMeshLOD(n,h),l&&(t=Math.max(t,l.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,v.assignTextureLOD(n,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,H&&H.forEach(n=>{n.name!="BackgroundCubeMaterial"&&"wireframe"in n&&(n.wireframe=r)}))})}function ee(a,e,t){var i;if(!T)return;z.has(a)||z.set(a,{keys:[],sourceId:t});const r=z.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const O=class{constructor(e,t){u(this,"parser");u(this,"url");T&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return R}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static hasLODLevelAvailable(e,t){var n;if(e.isMaterial===!0){for(const s of Object.keys(e)){const o=e[s];if(o.isTexture&&this.hasLODLevelAvailable(o,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(n=r==null?void 0:r.userData)!=null&&n.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof g.Mesh||e.isMesh===!0){const i=e.geometry,n=this.getAssignedLODInformation(i);if(!n)return Promise.resolve(null);for(const s of I)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,O.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const o=n.index||0;s=s[o]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,T&&ee(e,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else T&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof g.Material||e.isMaterial===!0){const r=e,i=[],n=new Array;if(T&&H.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const o of Object.keys(s.uniforms)){const l=s.uniforms[o].value;if((l==null?void 0:l.isTexture)===!0){const h=this.assignTextureLODForSlot(l,t,r,o);i.push(h),n.push(o)}}}else for(const s of Object.keys(r)){const o=r[s];if((o==null?void 0:o.isTexture)===!0){const l=this.assignTextureLODForSlot(o,t,r,s);i.push(l),n.push(s)}}return Promise.all(i).then(s=>{const o=new Array;for(let l=0;l<s.length;l++){const h=s[l],f=n[l];h&&h.isTexture===!0?o.push({material:r,slot:f,texture:h,level:t}):o.push({material:r,slot:f,texture:null,level:t})}return o})}if(e instanceof g.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):O.getOrLoadLOD(e,t).then(n=>{if(Array.isArray(n))return null;if((n==null?void 0:n.isTexture)===!0){if(n!=e&&(r&&i&&(r[i]=n),T&&i&&r)){const s=this.getAssignedLODInformation(e);s&&ee(r,i,s.url)}return n}else T=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(n=>(console.error("Error loading LOD",e,n),null))}afterRoot(e){var t,r;return T&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s){let o=!1;for(const l of this.parser.associations.keys())l.isTexture===!0&&this.parser.associations.get(l).textures===n&&(o=!0,O.registerTexture(this.url,l,n,s));o||this.parser.getDependency("texture",n).then(l=>{l&&O.registerTexture(this.url,l,n,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s&&s.lods){for(const o of this.parser.associations.keys())if(o.isMesh){const l=this.parser.associations.get(o);l.meshes===n&&O.registerMesh(this.url,s.guid,o,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var o,l,h;const r=T=="verbose",i=e.userData.LODS;if(!i)return null;const n=i==null?void 0:i.key;let s;if(e.isTexture===!0){const f=e;f.source&&f.source[$]&&(s=f.source[$])}if(s||(s=O.lodInfos.get(n)),s){if(t>0){let c=!1;const p=Array.isArray(s.lods);if(p&&t>=s.lods.length?c=!0:p||(c=!0),c)return this.lowresCache.get(n)}const f=Array.isArray(s.lods)?s.lods[t].path:s.lods;if(!f)return T&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const y=pe(i.url,f);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const c=y+"_"+s.guid,p=this.previouslyLoaded.get(c);if(p!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${c}`);let M=await p.catch(F=>(console.error(`Error loading LOD ${t} from ${y}
2
+ `,F),null)),k=!1;if(M==null||(M instanceof g.Texture&&e instanceof g.Texture?(o=M.image)!=null&&o.data||(l=M.source)!=null&&l.data?M=this.copySettings(e,M):(k=!0,this.previouslyLoaded.delete(c)):M instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((h=M.attributes.position)!=null&&h.array||(k=!0,this.previouslyLoaded.delete(c)))),!k)return M}const D=s,b=new Promise(async(M,k)=>{const F=new de.GLTFLoader;Z(F),T&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+y,D.guid));let x=y;if(D&&Array.isArray(D.lods)){const L=D.lods[t];L.hash&&(x+="?v="+L.hash)}const m=await F.loadAsync(x).catch(L=>(console.error(`Error loading LOD ${t} from ${y}
3
+ `,L),null));if(!m)return null;const P=m.parser;r&&console.log("Loading finished "+y,D.guid);let w=0;if(m.parser.json.textures){let L=!1;for(const d of m.parser.json.textures){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){let d=await P.getDependency("texture",w);return d&&O.assignLODInformation(i.url,d,n,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+d.name+'"',y,w,d,c),e instanceof g.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=D.guid),M(d)}else T&&console.warn("Could not find texture with guid",D.guid)}if(w=0,m.parser.json.meshes){let L=!1;for(const d of m.parser.json.meshes){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){const d=await P.getDependency("mesh",w),S=D;if(r&&console.log(`Loaded Mesh "${d.name}"`,y,w,d,c),d.isMesh===!0){const B=d.geometry;return O.assignLODInformation(i.url,B,n,t,void 0,S.density),M(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const G=d.children[E];if(G instanceof g.Mesh){const W=G.geometry;O.assignLODInformation(i.url,W,n,t,E,S.density),B.push(W)}}return M(B)}}}return M(null)});return this.previouslyLoaded.set(c,b),await b}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+y);const p=await new g.TextureLoader().loadAsync(y);return p?(p.guid=s.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=e.colorSpace,r&&console.log(s,p)):T&&console.warn("failed loading",y),p}}else T&&console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,n,s){if(!t)return;t.userData||(t.userData={});const o=new ye(e,r,i,n,s);t.userData.LODS=o,t.userData.LOD=i}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){const r=this._copiedTextures.get(e);return r||(t=t.clone(),this._copiedTextures.set(e,t),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.generateMipmaps=e.generateMipmaps,t)}};let v=O;u(v,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[$]=i);const n=i.guid;O.assignLODInformation(e,t,n,0,0,void 0),O.lodInfos.set(n,i),O.lowresCache.set(n,t)}),u(v,"registerMesh",(e,t,r,i,n,s)=>{var h;T&&console.log("> Progressive: register mesh",n,r.name,s,r.uuid,r);const o=r.geometry;o.userData||(o.userData={}),O.assignLODInformation(e,o,t,i,n,s.density),O.lodInfos.set(t,s);let l=O.lowresCache.get(t);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(t,l),i>0&&!se(r)&&ie(r,o);for(const f of I)(h=f.onRegisteredNewMesh)==null||h.call(f,r,s)}),u(v,"lodInfos",new Map),u(v,"previouslyLoaded",new Map),u(v,"lowresCache",new Map),u(v,"_copiedTextures",new Map);class ye{constructor(e,t,r,i,n){u(this,"url");u(this,"key");u(this,"level");u(this,"index");u(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),n!=null&&(this.density=n)}}const K=j("debugprogressive"),me=j("noprogressive"),te=Symbol("Needle:LODSManager"),A=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new g.Matrix4);u(this,"cameraFrustrum",new g.Frustum);u(this,"targetTriangleDensity",2e5);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"_frame",0);u(this,"_originalRender");u(this,"_sphere",new g.Sphere);u(this,"_tempBox",new g.Box3);u(this,"_tempBox2",new g.Box3);u(this,"tempMatrix",new g.Matrix4);u(this,"_tempWorldPosition",new g.Vector3);u(this,"_tempBoxSize",new g.Vector3);u(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[te]?e[te]:new A(e)}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;Q(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,o=e++;t.onBeforeRender(r,i,o,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,o,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var l,h;if(this.pause)return;const n=this.renderer.renderLists.get(e,0),s=n.opaque;let o=!0;if(s.length===1){const f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(o=!1)}if(o){if(me||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const c of s){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((h=c.geometry)==null?void 0:h.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){K&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}const y=n.transparent;for(const c of y){const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}}}updateLODs(e,t,r,i){var l,h;for(const f of I)(l=f.onBeforeUpdateLOD)==null||l.call(f,this.renderer,e,t,r);let n=r.userData.LOD_state;n||(n=new Le,r.userData.LOD_state=n);let s=this.calculateLodLevel(t,r,n,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let o=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(o=f),Array.isArray(r.material))for(const y of r.material)this.loadProgressiveTextures(y,o);else this.loadProgressiveTextures(r.material,o)}for(const f of I)(h=f.onAfterUpdatedLOD)==null||h.call(f,this.renderer,e,t,r,s);n.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,v.assignTextureLOD(e,t)):Promise.resolve(null)}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return v.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,n=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(n,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i){var o;if(!t)return-1;let s=10+1;if(e){if(K&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const l=v.getMeshLODInformation(t.geometry),h=l==null?void 0:l.lods;if(!h||h.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const y=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const x=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),A.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const x=this._tempBox.min,m=this._tempBox.max;let P=x.x,w=x.y,L=m.x,d=m.y;const S=2,B=1.5,E=(x.x+m.x)*.5,G=(x.y+m.y)*.5;P=(P-E)*S+E,w=(w-G)*S+G,L=(L-E)*S+E,d=(d-G)*S+G;const W=P<0&&L>0?0:Math.min(Math.abs(x.x),Math.abs(m.x)),oe=w<0&&d>0?0:Math.min(Math.abs(x.y),Math.abs(m.y)),X=Math.max(W,oe);r.lastCentrality=(B-X)*(B-X)*(B-X)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&c.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),c.x*=y.aspect;const p=e.matrixWorldInverse,D=this._tempBox2;D.copy(f),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(p);const b=D.getSize(this._tempBox2Size),C=Math.max(b.x,b.y);if(Math.max(c.x,c.y)!=0&&C!=0&&(c.z=b.z/Math.max(b.x,b.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,K&&A.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const m=A.corner0,P=A.corner1,w=A.corner2,L=A.corner3;m.copy(this._tempBox.min),P.copy(this._tempBox.max),P.x=m.x,w.copy(this._tempBox.max),w.y=m.y,L.copy(this._tempBox.max);const d=(m.z+L.z)*.5;m.z=P.z=w.z=L.z=d,m.applyMatrix4(x),P.applyMatrix4(x),w.applyMatrix4(x),L.applyMatrix4(x),A.debugDrawLine(m,P,255),A.debugDrawLine(m,w,255),A.debugDrawLine(P,L,255),A.debugDrawLine(w,L,255)}let k=999;if(h&&r.lastScreenCoverage>0){for(let x=0;x<h.length;x++)if(h[x].density/r.lastScreenCoverage<i){k=x;break}}k<s&&(s=k)}}return s}};let _=A;u(_,"debugDrawLine"),u(_,"corner0",new g.Vector3),u(_,"corner1",new g.Vector3),u(_,"corner2",new g.Vector3),u(_,"corner3",new g.Vector3),u(_,"_tempPtInside",new g.Vector3);class Le{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new g.Vector3);u(this,"lastCentrality",0)}}const re=Symbol("NEEDLE_mesh_lod"),V=Symbol("NEEDLE_texture_lod");function ne(a){if(!a)return null;let e=null,t=null;for(let r=a;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),n=i.find(o=>o.toString()=="Symbol(renderer)"),s=i.find(o=>o.toString()=="Symbol(scene)");!e&&n!=null&&(e=a[n].threeRenderer),!t&&s!=null&&(t=a[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=_.get(e);if(_.addPlugin(new De(a)),r.enable(),t){const i=t.camera||t.traverse(n=>n.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class De{constructor(e){u(this,"modelviewer");u(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[V]==!0)return;t[V]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let n=function(o){var h,f,y;if(o[V]==!0)return;o[V]=!0,o.userData&&(o.userData.LOD=-1);const l=Object.keys(o);for(let c=0;c<l.length;c++){const p=l[c],D=o[p];if((D==null?void 0:D.isTexture)===!0){const b=(f=(h=D.userData)==null?void 0:h.associations)==null?void 0:f.textures,C=r.parser.json.textures[b];if(!C){console.warn("Texture data not found for texture index "+b);continue}if((y=C==null?void 0:C.extensions)!=null&&y[R]){const M=C.extensions[R];M&&i&&v.registerTexture(i,D,M.lods.length,M)}}}};const s=t.material;if(Array.isArray(s))for(const o of s)n(o);else n(s)}}tryParseMeshLOD(e,t){var n,s;if(t[re]==!0)return;t[re]=!0;const r=this.getUrl();if(!r)return;const i=(s=(n=t.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(i&&r){const o=t.uuid;v.registerMesh(r,o,t,0,i.lods.length,i)}}}function xe(a,e,t,r){Q(e),Z(t),t.register(n=>new v(n,a));const i=_.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ne(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=_;exports.NEEDLE_progressive=v;exports.addDracoAndKTX2Loaders=Z;exports.createLoaders=Q;exports.getRaycastMesh=se;exports.patchModelViewer=ne;exports.setDracoDecoderLocation=ge;exports.setKTX2TranscoderLocation=he;exports.setRaycastMesh=ie;exports.useNeedleProgressive=xe;
package/lib/extension.js CHANGED
@@ -540,6 +540,9 @@ export class NEEDLE_progressive {
540
540
  }
541
541
  if (found) {
542
542
  let tex = await parser.getDependency("texture", index);
543
+ if (tex) {
544
+ NEEDLE_progressive.assignLODInformation(LOD.url, tex, LODKEY, level, undefined, undefined);
545
+ }
543
546
  if (debugverbose)
544
547
  console.log("change \"" + current.name + "\" → \"" + tex.name + "\"", lod_url, index, tex, KEY);
545
548
  if (current instanceof Texture)
@@ -549,6 +552,9 @@ export class NEEDLE_progressive {
549
552
  }
550
553
  return resolve(tex);
551
554
  }
555
+ else if (debug) {
556
+ console.warn("Could not find texture with guid", ext.guid);
557
+ }
552
558
  }
553
559
  index = 0;
554
560
  if (gltf.parser.json.meshes) {
@@ -86,6 +86,7 @@ export declare class LODsManager {
86
86
  private loadProgressiveMeshes;
87
87
  private readonly _sphere;
88
88
  private readonly _tempBox;
89
+ private readonly _tempBox2;
89
90
  private readonly tempMatrix;
90
91
  private readonly _tempWorldPosition;
91
92
  private readonly _tempBoxSize;
@@ -94,6 +95,8 @@ export declare class LODsManager {
94
95
  private static corner1;
95
96
  private static corner2;
96
97
  private static corner3;
98
+ private static readonly _tempPtInside;
99
+ private static isInside;
97
100
  private calculateLodLevel;
98
101
  }
99
102
  declare class LOD_state {
@@ -169,6 +169,15 @@ export class LODsManager {
169
169
  continue;
170
170
  }
171
171
  }
172
+ switch (entry.material.type) {
173
+ case "LineBasicMaterial":
174
+ case "LineDashedMaterial":
175
+ case "PointsMaterial":
176
+ case "ShadowMaterial":
177
+ case "MeshDistanceMaterial":
178
+ case "MeshDepthMaterial":
179
+ continue;
180
+ }
172
181
  const object = entry.object;
173
182
  if (object instanceof Mesh || (object.isMesh)) {
174
183
  this.updateLODs(scene, camera, object, desiredDensity);
@@ -267,6 +276,7 @@ export class LODsManager {
267
276
  // private testIfLODLevelsAreAvailable() {
268
277
  _sphere = new Sphere();
269
278
  _tempBox = new Box3();
279
+ _tempBox2 = new Box3();
270
280
  tempMatrix = new Matrix4();
271
281
  _tempWorldPosition = new Vector3();
272
282
  _tempBoxSize = new Vector3();
@@ -275,6 +285,15 @@ export class LODsManager {
275
285
  static corner1 = new Vector3();
276
286
  static corner2 = new Vector3();
277
287
  static corner3 = new Vector3();
288
+ static _tempPtInside = new Vector3();
289
+ static isInside(box, matrix) {
290
+ const min = box.min;
291
+ const max = box.max;
292
+ const centerx = (min.x + max.x) * 0.5;
293
+ const centery = (min.y + max.y) * 0.5;
294
+ const pt1 = this._tempPtInside.set(centerx, centery, min.z).applyMatrix4(matrix);
295
+ return pt1.z < 0;
296
+ }
278
297
  calculateLodLevel(camera, mesh, state, desiredDensity) {
279
298
  if (!mesh)
280
299
  return -1;
@@ -292,8 +311,10 @@ export class LODsManager {
292
311
  const lodsInfo = NEEDLE_progressive.getMeshLODInformation(mesh.geometry);
293
312
  const lods = lodsInfo?.lods;
294
313
  // We can skip all this if we dont have any LOD information - we can ask the progressive extension for that
314
+ // But if the MESH has no LODs we might still have materials that do - we would need to check that
315
+ // Until we properly check if an object has *any* LODs we do return the best quality for now
295
316
  if (!lods || lods.length <= 0) {
296
- return 99;
317
+ return 0;
297
318
  }
298
319
  if (!this.cameraFrustrum?.intersectsObject(mesh)) {
299
320
  // console.log("Mesh not visible");
@@ -306,8 +327,8 @@ export class LODsManager {
306
327
  // the object is not visible by the camera
307
328
  return 99;
308
329
  }
309
- const box = mesh.geometry.boundingBox;
310
- if (box && camera.isPerspectiveCamera) {
330
+ const boundingBox = mesh.geometry.boundingBox;
331
+ if (boundingBox && camera.isPerspectiveCamera) {
311
332
  const cam = camera;
312
333
  // hack: if the mesh has vertex colors, has less than 100 vertices we always select the highest LOD
313
334
  if (mesh.geometry.attributes.color && mesh.geometry.attributes.color.count < 100) {
@@ -321,7 +342,7 @@ export class LODsManager {
321
342
  }
322
343
  }
323
344
  // calculate size on screen
324
- this._tempBox.copy(box);
345
+ this._tempBox.copy(boundingBox);
325
346
  this._tempBox.applyMatrix4(mesh.matrixWorld);
326
347
  // Converting into projection space has the disadvantage that objects further to the side
327
348
  // will have a much larger coverage, especially with high-field-of-view situations like in VR.
@@ -330,6 +351,9 @@ export class LODsManager {
330
351
  // High distortions would lead to lower LOD levels.
331
352
  // "Centrality" of the calculated screen-space bounding box could be a factor here –
332
353
  // what's the distance of the bounding box to the center of the screen?
354
+ if (LODsManager.isInside(this._tempBox, this.projectionScreenMatrix)) {
355
+ return 0;
356
+ }
333
357
  this._tempBox.applyMatrix4(this.projectionScreenMatrix);
334
358
  // TODO might need to be adjusted for cameras that are rendered during an XR session but are
335
359
  // actually not XR cameras (e.g. a render texture)
@@ -365,8 +389,8 @@ export class LODsManager {
365
389
  boxSize.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight); // correct for size of context on screen
366
390
  boxSize.x *= cam.aspect;
367
391
  const matView = camera.matrixWorldInverse;
368
- const box2 = new Box3();
369
- box2.copy(box);
392
+ const box2 = this._tempBox2;
393
+ box2.copy(boundingBox);
370
394
  box2.applyMatrix4(mesh.matrixWorld);
371
395
  box2.applyMatrix4(matView);
372
396
  const boxSize2 = box2.getSize(this._tempBox2Size);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "1.0.0-alpha.15",
3
+ "version": "1.0.0-alpha.16",
4
4
  "description": "three.js support for loading glTF or GLB files that contain progressive loading data",
5
5
  "homepage": "https://needle.tools",
6
6
  "author": {