@needle-tools/gltf-progressive 1.2.0-alpha.7 → 1.2.0-alpha.8

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,8 +4,9 @@ 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.2.0-alpha.7] - 2023-06-13
7
+ ## [1.2.0-alpha.8] - 2023-06-13
8
8
  - fix: issue where skinned mesh matrix was falsely applied to calculate screen size
9
+ - fix: use bounding box from SkinnedMesh object
9
10
 
10
11
  ## [1.2.0-alpha.6] - 2023-06-12
11
12
  - fix: minor bug where opened glTF has `NEEDLE_progressive` extension but no lods array because the glTF is a LOD variant
@@ -1,6 +1,6 @@
1
- var me = Object.defineProperty;
2
- var xe = (l, e, t) => e in l ? me(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var c = (l, e, t) => (xe(l, typeof e != "symbol" ? e + "" : e, t), t);
1
+ var xe = Object.defineProperty;
2
+ var me = (l, e, t) => e in l ? xe(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
+ var c = (l, e, t) => (me(l, typeof e != "symbol" ? e + "" : e, t), t);
4
4
  import { MeshoptDecoder as Le } 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 Me } from "three/examples/jsm/loaders/KTX2Loader.js";
@@ -76,8 +76,8 @@ function Pe(l) {
76
76
  e.setAttribute(t, l.getAttribute(t));
77
77
  return e.setIndex(l.getIndex()), e;
78
78
  }
79
- const I = new Array(), B = "NEEDLE_progressive", D = j("debugprogressive"), se = Symbol("needle-progressive-texture"), V = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Set();
80
- if (D) {
79
+ const I = new Array(), R = "NEEDLE_progressive", M = j("debugprogressive"), se = Symbol("needle-progressive-texture"), V = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Set();
80
+ if (M) {
81
81
  let l = function() {
82
82
  e += 1, console.log("Toggle LOD level", e, V), V.forEach((i, n) => {
83
83
  for (const s of i.keys) {
@@ -100,7 +100,7 @@ if (D) {
100
100
  }
101
101
  function ue(l, e, t) {
102
102
  var i;
103
- if (!D)
103
+ if (!M)
104
104
  return;
105
105
  V.has(l) || V.set(l, { keys: [], sourceId: t });
106
106
  const r = V.get(l);
@@ -115,14 +115,14 @@ const _ = class {
115
115
  var r, i;
116
116
  if (this._isLoadingMesh)
117
117
  return null;
118
- const t = (i = (r = this.parser.json.meshes[e]) == null ? void 0 : r.extensions) == null ? void 0 : i[B];
118
+ const t = (i = (r = this.parser.json.meshes[e]) == null ? void 0 : r.extensions) == null ? void 0 : i[R];
119
119
  return t ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", e).then((n) => (this._isLoadingMesh = !1, n && _.registerMesh(this.url, t.guid, n, t.lods.length, void 0, t), n))) : null;
120
120
  });
121
- D && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
121
+ M && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
122
122
  }
123
123
  /** The name of the extension */
124
124
  get name() {
125
- return B;
125
+ return R;
126
126
  }
127
127
  static getMeshLODInformation(e) {
128
128
  const t = this.getAssignedLODInformation(e);
@@ -141,7 +141,7 @@ const _ = class {
141
141
  this.getMaterialMinMaxLODsCount(o, t);
142
142
  return e[i] = t, t;
143
143
  }
144
- if (D === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
144
+ if (M === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
145
145
  const o = e;
146
146
  for (const a of Object.keys(o.uniforms)) {
147
147
  const h = o.uniforms[a].value;
@@ -232,12 +232,12 @@ const _ = class {
232
232
  const o = n.index || 0;
233
233
  s = s[o];
234
234
  }
235
- s && i != s && s instanceof Y && (e.geometry = s, D && ue(e, "geometry", n.url));
235
+ s && i != s && s instanceof Y && (e.geometry = s, M && ue(e, "geometry", n.url));
236
236
  }
237
237
  return s;
238
238
  }).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
239
239
  } else
240
- D && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
240
+ M && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
241
241
  return Promise.resolve(null);
242
242
  }
243
243
  /** Load a different resolution of a texture (if available)
@@ -252,7 +252,7 @@ const _ = class {
252
252
  return Promise.resolve(null);
253
253
  if (e instanceof we || e.isMaterial === !0) {
254
254
  const r = e, i = [], n = new Array();
255
- if (D && ne.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
255
+ if (M && ne.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
256
256
  const s = r;
257
257
  for (const o of Object.keys(s.uniforms)) {
258
258
  const a = s.uniforms[o].value;
@@ -295,29 +295,29 @@ const _ = class {
295
295
  if (s) {
296
296
  const o = this.getAssignedLODInformation(s);
297
297
  if (o && (o == null ? void 0 : o.level) < t)
298
- return D === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, t, r, s, n), null;
298
+ return M === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, t, r, s, n), null;
299
299
  }
300
300
  r[i] = n;
301
301
  }
302
- if (D && i && r) {
302
+ if (M && i && r) {
303
303
  const s = this.getAssignedLODInformation(e);
304
304
  s && ue(r, i, s.url);
305
305
  }
306
306
  }
307
307
  return n;
308
308
  } else
309
- D == "verbose" && console.warn("No LOD found for", e, t);
309
+ M == "verbose" && console.warn("No LOD found for", e, t);
310
310
  return null;
311
311
  }).catch((n) => (console.error("Error loading LOD", e, n), null));
312
312
  }
313
313
  afterRoot(e) {
314
314
  var t, r;
315
- return D && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
315
+ return M && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
316
316
  if (i != null && i.extensions) {
317
- const s = i == null ? void 0 : i.extensions[B];
317
+ const s = i == null ? void 0 : i.extensions[R];
318
318
  if (s) {
319
319
  if (!s.lods) {
320
- D && console.warn("Texture has no LODs", s);
320
+ M && console.warn("Texture has no LODs", s);
321
321
  return;
322
322
  }
323
323
  let o = !1;
@@ -330,7 +330,7 @@ const _ = class {
330
330
  }
331
331
  }), (r = this.parser.json.meshes) == null || r.forEach((i, n) => {
332
332
  if (i != null && i.extensions) {
333
- const s = i == null ? void 0 : i.extensions[B];
333
+ const s = i == null ? void 0 : i.extensions[R];
334
334
  if (s && s.lods) {
335
335
  for (const o of this.parser.associations.keys())
336
336
  if (o.isMesh) {
@@ -343,7 +343,7 @@ const _ = class {
343
343
  }
344
344
  static async getOrLoadLOD(e, t) {
345
345
  var o, a, h, d;
346
- const r = D == "verbose", i = e.userData.LODS;
346
+ const r = M == "verbose", i = e.userData.LODS;
347
347
  if (!i)
348
348
  return null;
349
349
  const n = i == null ? void 0 : i.key;
@@ -354,32 +354,32 @@ const _ = class {
354
354
  }
355
355
  if (s || (s = _.lodInfos.get(n)), s) {
356
356
  if (t > 0) {
357
- let m = !1;
358
- const M = Array.isArray(s.lods);
359
- if (M && t >= s.lods.length ? m = !0 : M || (m = !0), m)
357
+ let y = !1;
358
+ const w = Array.isArray(s.lods);
359
+ if (w && t >= s.lods.length ? y = !0 : w || (y = !0), y)
360
360
  return this.lowresCache.get(n);
361
361
  }
362
362
  const g = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
363
363
  if (!g)
364
- return D && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
364
+ return M && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
365
365
  const f = Te(i.url, g);
366
366
  if (f.endsWith(".glb") || f.endsWith(".gltf")) {
367
367
  if (!s.guid)
368
368
  return console.warn("missing pointer for glb/gltf texture", s), null;
369
- const m = f + "_" + s.guid, M = this.previouslyLoaded.get(m);
370
- if (M !== void 0) {
371
- r && console.log(`LOD ${t} was already loading/loaded: ${m}`);
372
- let x = await M.catch((z) => (console.error(`Error loading LOD ${t} from ${f}
369
+ const y = f + "_" + s.guid, w = this.previouslyLoaded.get(y);
370
+ if (w !== void 0) {
371
+ r && console.log(`LOD ${t} was already loading/loaded: ${y}`);
372
+ let L = await w.catch((z) => (console.error(`Error loading LOD ${t} from ${f}
373
373
  `, z), null)), T = !1;
374
- if (x == null || (x instanceof N && e instanceof N ? (a = x.image) != null && a.data || (h = x.source) != null && h.data ? x = this.copySettings(e, x) : (T = !0, this.previouslyLoaded.delete(m)) : x instanceof Y && e instanceof Y && ((d = x.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(m)))), !T)
375
- return x;
374
+ if (L == null || (L instanceof N && e instanceof N ? (a = L.image) != null && a.data || (h = L.source) != null && h.data ? L = this.copySettings(e, L) : (T = !0, this.previouslyLoaded.delete(y)) : L instanceof Y && e instanceof Y && ((d = L.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(y)))), !T)
375
+ return L;
376
376
  }
377
- const w = s, O = new Promise(async (x, T) => {
377
+ const m = s, O = new Promise(async (L, T) => {
378
378
  const z = new Se();
379
- ge(z), D && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, w.guid));
379
+ ge(z), M && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, m.guid));
380
380
  let ee = f;
381
- if (w && Array.isArray(w.lods)) {
382
- const p = w.lods[t];
381
+ if (m && Array.isArray(m.lods)) {
382
+ const p = m.lods[t];
383
383
  p.hash && (ee += "?v=" + p.hash);
384
384
  }
385
385
  const E = await z.loadAsync(ee).catch((p) => (console.error(`Error loading LOD ${t} from ${f}
@@ -387,66 +387,66 @@ const _ = class {
387
387
  if (!E)
388
388
  return null;
389
389
  const te = E.parser;
390
- r && console.log("Loading finished " + f, w.guid);
391
- let y = 0;
390
+ r && console.log("Loading finished " + f, m.guid);
391
+ let x = 0;
392
392
  if (E.parser.json.textures) {
393
393
  let p = !1;
394
394
  for (const u of E.parser.json.textures) {
395
395
  if (u != null && u.extensions) {
396
- const L = u == null ? void 0 : u.extensions[B];
397
- if (L != null && L.guid && L.guid === w.guid) {
396
+ const D = u == null ? void 0 : u.extensions[R];
397
+ if (D != null && D.guid && D.guid === m.guid) {
398
398
  p = !0;
399
399
  break;
400
400
  }
401
401
  }
402
- y++;
402
+ x++;
403
403
  }
404
404
  if (p) {
405
- let u = await te.getDependency("texture", y);
406
- return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, y, u, m), e instanceof N && (u = this.copySettings(e, u)), u && (u.guid = w.guid), x(u);
405
+ let u = await te.getDependency("texture", x);
406
+ return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, x, u, y), e instanceof N && (u = this.copySettings(e, u)), u && (u.guid = m.guid), L(u);
407
407
  } else
408
- D && console.warn("Could not find texture with guid", w.guid);
408
+ M && console.warn("Could not find texture with guid", m.guid);
409
409
  }
410
- if (y = 0, E.parser.json.meshes) {
410
+ if (x = 0, E.parser.json.meshes) {
411
411
  let p = !1;
412
412
  for (const u of E.parser.json.meshes) {
413
413
  if (u != null && u.extensions) {
414
- const L = u == null ? void 0 : u.extensions[B];
415
- if (L != null && L.guid && L.guid === w.guid) {
414
+ const D = u == null ? void 0 : u.extensions[R];
415
+ if (D != null && D.guid && D.guid === m.guid) {
416
416
  p = !0;
417
417
  break;
418
418
  }
419
419
  }
420
- y++;
420
+ x++;
421
421
  }
422
422
  if (p) {
423
- const u = await te.getDependency("mesh", y), L = w;
424
- if (r && console.log(`Loaded Mesh "${u.name}"`, f, y, u, m), u.isMesh === !0) {
423
+ const u = await te.getDependency("mesh", x), D = m;
424
+ if (r && console.log(`Loaded Mesh "${u.name}"`, f, x, u, y), u.isMesh === !0) {
425
425
  const S = u.geometry;
426
- return _.assignLODInformation(i.url, S, n, t, void 0, L.density), x(S);
426
+ return _.assignLODInformation(i.url, S, n, t, void 0, D.density), L(S);
427
427
  } else {
428
428
  const S = new Array();
429
- for (let C = 0; C < u.children.length; C++) {
430
- const G = u.children[C];
429
+ for (let B = 0; B < u.children.length; B++) {
430
+ const G = u.children[B];
431
431
  if (G instanceof F) {
432
432
  const $ = G.geometry;
433
- _.assignLODInformation(i.url, $, n, t, C, L.density), S.push($);
433
+ _.assignLODInformation(i.url, $, n, t, B, D.density), S.push($);
434
434
  }
435
435
  }
436
- return x(S);
436
+ return L(S);
437
437
  }
438
438
  }
439
439
  }
440
- return x(null);
440
+ return L(null);
441
441
  });
442
- return this.previouslyLoaded.set(m, O), await O;
442
+ return this.previouslyLoaded.set(y, O), await O;
443
443
  } else if (e instanceof N) {
444
444
  r && console.log("Load texture from uri: " + f);
445
- const M = await new Oe().loadAsync(f);
446
- return M ? (M.guid = s.guid, M.flipY = !1, M.needsUpdate = !0, M.colorSpace = e.colorSpace, r && console.log(s, M)) : D && console.warn("failed loading", f), M;
445
+ const w = await new Oe().loadAsync(f);
446
+ return w ? (w.guid = s.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = e.colorSpace, r && console.log(s, w)) : M && console.warn("failed loading", f), w;
447
447
  }
448
448
  } else
449
- D && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
449
+ M && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
450
450
  return null;
451
451
  }
452
452
  static assignLODInformation(e, t, r, i, n, s) {
@@ -462,7 +462,7 @@ const _ = class {
462
462
  }
463
463
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
464
464
  static copySettings(e, t) {
465
- return t = t.clone(), D && console.warn(`Copying texture settings
465
+ return t = t.clone(), M && console.warn(`Copying texture settings
466
466
  `, e.uuid, `
467
467
  `, t.uuid), 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.mipmaps || (t.generateMipmaps = e.generateMipmaps), t;
468
468
  }
@@ -472,8 +472,8 @@ let v = _;
472
472
  * Register a texture with LOD information
473
473
  */
474
474
  c(v, "registerTexture", (e, t, r, i, n) => {
475
- if (D && console.log("> Progressive: register texture", i, t.name, t.uuid, t, n), !t) {
476
- D && console.error("gltf-progressive: Register texture without texture");
475
+ if (M && console.log("> Progressive: register texture", i, t.name, t.uuid, t, n), !t) {
476
+ M && console.error("gltf-progressive: Register texture without texture");
477
477
  return;
478
478
  }
479
479
  t.source && (t.source[se] = n);
@@ -484,10 +484,10 @@ c(v, "registerTexture", (e, t, r, i, n) => {
484
484
  */
485
485
  c(v, "registerMesh", (e, t, r, i, n, s) => {
486
486
  var h;
487
- D && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
487
+ M && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
488
488
  const o = r.geometry;
489
489
  if (!o) {
490
- D && console.warn("gltf-progressive: Register mesh without geometry");
490
+ M && console.warn("gltf-progressive: Register mesh without geometry");
491
491
  return;
492
492
  }
493
493
  o.userData || (o.userData = {}), _.assignLODInformation(e, o, t, i, n, s.density), _.lodInfos.set(t, s);
@@ -512,7 +512,7 @@ class Ee {
512
512
  this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
513
513
  }
514
514
  }
515
- const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LODSManager"), b = { mesh_lod: -1, texture_lod: -1 }, A = class {
515
+ const U = j("debugprogressive"), Be = j("noprogressive"), fe = Symbol("Needle:LODSManager"), b = { mesh_lod: -1, texture_lod: -1 }, A = class {
516
516
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
517
517
  constructor(e) {
518
518
  c(this, "renderer");
@@ -598,7 +598,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
598
598
  (d.name === "EffectMaterial" || d.name === "CopyShader") && (o = !1);
599
599
  }
600
600
  if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
601
- if (Ce || this.updateInterval > 0 && i % this.updateInterval != 0)
601
+ if (Be || this.updateInterval > 0 && i % this.updateInterval != 0)
602
602
  return;
603
603
  this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
604
604
  const d = this.targetTriangleDensity;
@@ -616,13 +616,13 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
616
616
  case "MeshDepthMaterial":
617
617
  continue;
618
618
  }
619
- const m = f.object;
620
- (m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d, i);
619
+ const y = f.object;
620
+ (y instanceof F || y.isMesh) && this.updateLODs(e, t, y, d, i);
621
621
  }
622
622
  const g = n.transparent;
623
623
  for (const f of g) {
624
- const m = f.object;
625
- (m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d, i);
624
+ const y = f.object;
625
+ (y instanceof F || y.isMesh) && this.updateLODs(e, t, y, d, i);
626
626
  }
627
627
  }
628
628
  }
@@ -631,7 +631,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
631
631
  var a, h;
632
632
  r.userData || (r.userData = {});
633
633
  let s = r.userData.LOD_state;
634
- if (s || (s = new Re(), r.userData.LOD_state = s), s.frames++ < 2)
634
+ if (s || (s = new Ce(), r.userData.LOD_state = s), s.frames++ < 2)
635
635
  return;
636
636
  for (const d of I)
637
637
  (a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
@@ -683,7 +683,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
683
683
  return this._tempPtInside.set(n, s, r.z).applyMatrix4(t).z < 0;
684
684
  }
685
685
  calculateLodLevel(e, t, r, i, n) {
686
- var M;
686
+ var w;
687
687
  if (!t) {
688
688
  n.mesh_lod = -1, n.texture_lod = -1;
689
689
  return;
@@ -700,52 +700,56 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
700
700
  n.mesh_lod = 0, n.texture_lod = 0;
701
701
  return;
702
702
  }
703
- if (d || (o = 0), !((M = this.cameraFrustrum) != null && M.intersectsObject(t))) {
703
+ if (d || (o = 0), !((w = this.cameraFrustrum) != null && w.intersectsObject(t))) {
704
704
  n.mesh_lod = 99, n.texture_lod = 99;
705
705
  return;
706
706
  }
707
- const m = t.geometry.boundingBox;
708
- if (m && e.isPerspectiveCamera) {
709
- const w = e;
707
+ let y = t.geometry.boundingBox;
708
+ if (t.type === "SkinnedMesh") {
709
+ const m = t;
710
+ m.boundingBox || m.computeBoundingBox(), y = m.boundingBox;
711
+ }
712
+ if (y && e.isPerspectiveCamera) {
713
+ const m = e;
710
714
  if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
711
715
  this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
712
- const y = e.getWorldPosition(this._tempWorldPosition);
713
- if (this._sphere.containsPoint(y)) {
716
+ const x = e.getWorldPosition(this._tempWorldPosition);
717
+ if (this._sphere.containsPoint(x)) {
714
718
  n.mesh_lod = 0, n.texture_lod = 0;
715
719
  return;
716
720
  }
717
721
  }
718
- if (this._tempBox.copy(m), t.type === "SkinnedMesh" ? t.parent && this._tempBox.applyMatrix4(t.parent.matrixWorld) : this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
722
+ if (this._tempBox.copy(y), t.type === "SkinnedMesh" ? t.parent && this._tempBox.applyMatrix4(t.parent.matrixWorld) : this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
719
723
  n.mesh_lod = 0, n.texture_lod = 0;
720
724
  return;
721
725
  }
722
- if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && w.fov > 70) {
723
- const y = this._tempBox.min, p = this._tempBox.max;
724
- let u = y.x, L = y.y, S = p.x, C = p.y;
725
- const G = 2, $ = 1.5, H = (y.x + p.x) * 0.5, J = (y.y + p.y) * 0.5;
726
- u = (u - H) * G + H, L = (L - J) * G + J, S = (S - H) * G + H, C = (C - J) * G + J;
727
- const pe = u < 0 && S > 0 ? 0 : Math.min(Math.abs(y.x), Math.abs(p.x)), ye = L < 0 && C > 0 ? 0 : Math.min(Math.abs(y.y), Math.abs(p.y)), re = Math.max(pe, ye);
726
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && m.fov > 70) {
727
+ const x = this._tempBox.min, p = this._tempBox.max;
728
+ let u = x.x, D = x.y, S = p.x, B = p.y;
729
+ const G = 2, $ = 1.5, H = (x.x + p.x) * 0.5, J = (x.y + p.y) * 0.5;
730
+ u = (u - H) * G + H, D = (D - J) * G + J, S = (S - H) * G + H, B = (B - J) * G + J;
731
+ const pe = u < 0 && S > 0 ? 0 : Math.min(Math.abs(x.x), Math.abs(p.x)), ye = D < 0 && B > 0 ? 0 : Math.min(Math.abs(x.y), Math.abs(p.y)), re = Math.max(pe, ye);
728
732
  r.lastCentrality = ($ - re) * ($ - re) * ($ - re);
729
733
  } else
730
734
  r.lastCentrality = 1;
731
735
  const O = this._tempBox.getSize(this._tempBoxSize);
732
- O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= w.aspect;
733
- const R = e.matrixWorldInverse, x = this._tempBox2;
734
- x.copy(m), x.applyMatrix4(t.matrixWorld), x.applyMatrix4(R);
735
- const T = x.getSize(this._tempBox2Size), z = Math.max(T.x, T.y);
736
+ O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= m.aspect;
737
+ const C = e.matrixWorldInverse, L = this._tempBox2;
738
+ L.copy(y), L.applyMatrix4(t.matrixWorld), L.applyMatrix4(C);
739
+ const T = L.getSize(this._tempBox2Size), z = Math.max(T.x, T.y);
736
740
  if (Math.max(O.x, O.y) != 0 && z != 0 && (O.z = T.z / Math.max(T.x, T.y) * Math.max(O.x, O.y)), r.lastScreenCoverage = Math.max(O.x, O.y, O.z), r.lastScreenspaceVolume.copy(O), r.lastScreenCoverage *= r.lastCentrality, U && A.debugDrawLine) {
737
- const y = this.tempMatrix.copy(this.projectionScreenMatrix);
738
- y.invert();
739
- const p = A.corner0, u = A.corner1, L = A.corner2, S = A.corner3;
740
- p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x, L.copy(this._tempBox.max), L.y = p.y, S.copy(this._tempBox.max);
741
- const C = (p.z + S.z) * 0.5;
742
- p.z = u.z = L.z = S.z = C, p.applyMatrix4(y), u.applyMatrix4(y), L.applyMatrix4(y), S.applyMatrix4(y), A.debugDrawLine(p, u, 255), A.debugDrawLine(p, L, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(L, S, 255);
741
+ const x = this.tempMatrix.copy(this.projectionScreenMatrix);
742
+ x.invert();
743
+ const p = A.corner0, u = A.corner1, D = A.corner2, S = A.corner3;
744
+ p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x, D.copy(this._tempBox.max), D.y = p.y, S.copy(this._tempBox.max);
745
+ const B = (p.z + S.z) * 0.5;
746
+ p.z = u.z = D.z = S.z = B, p.applyMatrix4(x), u.applyMatrix4(x), D.applyMatrix4(x), S.applyMatrix4(x), A.debugDrawLine(p, u, 255), A.debugDrawLine(p, D, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(D, S, 255);
743
747
  }
744
748
  let E = 999;
745
749
  if (h && r.lastScreenCoverage > 0) {
746
- for (let y = 0; y < h.length; y++)
747
- if (h[y].density / r.lastScreenCoverage < i) {
748
- E = y;
750
+ for (let x = 0; x < h.length; x++)
751
+ if (h[x].density / r.lastScreenCoverage < i) {
752
+ E = x;
749
753
  break;
750
754
  }
751
755
  }
@@ -754,15 +758,15 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
754
758
  if (n.mesh_lod = o, f)
755
759
  if (r.lastLodLevel_Texture < 0) {
756
760
  if (n.texture_lod = g.max_count - 1, U) {
757
- const w = g.lods[g.max_count - 1];
758
- U && console.log(`First Texture LOD ${n.texture_lod} (${w.max_height}px) - ${t.name}`);
761
+ const m = g.lods[g.max_count - 1];
762
+ U && console.log(`First Texture LOD ${n.texture_lod} (${m.max_height}px) - ${t.name}`);
759
763
  }
760
764
  } else {
761
- const w = r.lastScreenCoverage * 1.5, R = this.renderer.domElement.clientHeight / window.devicePixelRatio * w;
762
- for (let x = g.lods.length - 1; x >= 0; x--) {
763
- const T = g.lods[x];
764
- if (!(Ae() && T.max_height > 4096) && T.max_height > R) {
765
- n.texture_lod = x, n.texture_lod < r.lastLodLevel_Texture && U && console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${n.texture_lod} (${T.max_height}px: ${(100 * r.lastScreenCoverage).toFixed(2)} % = ${R.toFixed(0)}px) - ${t.name}`);
765
+ const m = r.lastScreenCoverage * 1.5, C = this.renderer.domElement.clientHeight / window.devicePixelRatio * m;
766
+ for (let L = g.lods.length - 1; L >= 0; L--) {
767
+ const T = g.lods[L];
768
+ if (!(Ae() && T.max_height > 4096) && T.max_height > C) {
769
+ n.texture_lod = L, n.texture_lod < r.lastLodLevel_Texture && U && console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${n.texture_lod} (${T.max_height}px: ${(100 * r.lastScreenCoverage).toFixed(2)} % = ${C.toFixed(0)}px) - ${t.name}`);
766
770
  break;
767
771
  }
768
772
  }
@@ -775,7 +779,7 @@ let P = A;
775
779
  /** 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.
776
780
  */
777
781
  c(P, "debugDrawLine"), c(P, "corner0", new k()), c(P, "corner1", new k()), c(P, "corner2", new k()), c(P, "corner3", new k()), c(P, "_tempPtInside", new k());
778
- class Re {
782
+ class Ce {
779
783
  constructor() {
780
784
  c(this, "frames", 0);
781
785
  c(this, "lastLodLevel_Mesh", -1);
@@ -797,7 +801,7 @@ function ke(l) {
797
801
  if (e) {
798
802
  console.log("Adding Needle LODs to modelviewer");
799
803
  const r = P.get(e);
800
- if (P.addPlugin(new Be(l)), r.enable(), t) {
804
+ if (P.addPlugin(new Re(l)), r.enable(), t) {
801
805
  const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
802
806
  i && e.render(t, i);
803
807
  }
@@ -807,7 +811,7 @@ function ke(l) {
807
811
  }
808
812
  return null;
809
813
  }
810
- class Be {
814
+ class Re {
811
815
  constructor(e) {
812
816
  c(this, "modelviewer");
813
817
  c(this, "_didWarnAboutMissingUrl", !1);
@@ -836,16 +840,16 @@ class Be {
836
840
  o[Q] = !0, o.userData && (o.userData.LOD = -1);
837
841
  const a = Object.keys(o);
838
842
  for (let f = 0; f < a.length; f++) {
839
- const m = a[f], M = o[m];
840
- if ((M == null ? void 0 : M.isTexture) === !0) {
841
- const w = (d = (h = M.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[w];
843
+ const y = a[f], w = o[y];
844
+ if ((w == null ? void 0 : w.isTexture) === !0) {
845
+ const m = (d = (h = w.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[m];
842
846
  if (!O) {
843
- console.warn("Texture data not found for texture index " + w);
847
+ console.warn("Texture data not found for texture index " + m);
844
848
  continue;
845
849
  }
846
- if ((g = O == null ? void 0 : O.extensions) != null && g[B]) {
847
- const R = O.extensions[B];
848
- R && i && v.registerTexture(i, M, R.lods.length, w, R);
850
+ if ((g = O == null ? void 0 : O.extensions) != null && g[R]) {
851
+ const C = O.extensions[R];
852
+ C && i && v.registerTexture(i, w, C.lods.length, m, C);
849
853
  }
850
854
  }
851
855
  }
@@ -866,7 +870,7 @@ class Be {
866
870
  const r = this.getUrl();
867
871
  if (!r)
868
872
  return;
869
- const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[B];
873
+ const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
870
874
  if (i && r) {
871
875
  const o = t.uuid;
872
876
  v.registerMesh(r, o, t, 0, i.lods.length, i);
@@ -882,7 +886,7 @@ document.addEventListener("DOMContentLoaded", () => {
882
886
  ke(document.querySelector("model-viewer"));
883
887
  });
884
888
  export {
885
- B as EXTENSION_NAME,
889
+ R as EXTENSION_NAME,
886
890
  P as LODsManager,
887
891
  v as NEEDLE_progressive,
888
892
  ge as addDracoAndKTX2Loaders,
@@ -1,5 +1,5 @@
1
- var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Le}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as $,Mesh as G,Material as ve,Texture as z,TextureLoader as De,Matrix4 as ie,Frustum as Me,Sphere as Oe,Box3 as ae,Vector3 as B}from"three";import{GLTFLoader as _e}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",ee="./include/ktx2/"});function we(t){X=t}function be(t){ee=t}let U,te,q;function re(t){U||(U=new ye,U.setDecoderPath(X),U.setDecoderConfig({type:"js"})),q||(q=new Le,q.setTranscoderPath(ee)),te||(te=xe),t?q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function se(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(q),t.meshoptDecoder||t.setMeshoptDecoder(te)}function H(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Se(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}let Y;function Te(){return Y!==void 0||(Y=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),H("debugprogressive")&&console.log("isMobileDevice",Y)),Y}function J(t){var e;return((e=t?.userData)==null?void 0:e["needle:raycast-mesh"])instanceof $?t.userData["needle:raycast-mesh"]:null}function le(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!J(t)){const r=Ae(e);r.userData={isRaycastMesh:!0},t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=r}}function Ee(t=!0){if(t){if(V)return;const e=V=G.prototype.raycast;G.prototype.raycast=function(r,n){const o=this,s=J(o);let a;s&&o.isMesh&&(a=o.geometry,o.geometry=s),e.call(this,r,n),a&&(o.geometry=a)}}else{if(!V)return;G.prototype.raycast=V,V=null}}let V=null;function Ae(t){const e=new $;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const R=new Array,P="NEEDLE_progressive",L=H("debugprogressive"),oe=Symbol("needle-progressive-texture"),K=new Map,ne=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const u=_.getMeshLODInformation(i),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,_.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,_.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,ne&&ne.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ue(t,e,r){var n;if(!L)return;K.has(t)||K.set(t,{keys:[],sourceId:r});const o=K.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"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,o;if(this._isLoadingMesh)return null;const s=(o=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:o[P];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(a=>(this._isLoadingMesh=!1,a&&M.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),L&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return P}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",o=t[n];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(L==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const i of Object.keys(a.uniforms)){const u=a.uniforms[i].value;u?.isTexture===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const i=t[a];i?.isTexture===!0&&s(i,e)}return t[n]=e,e;function s(a,i){const u=r.getAssignedLODInformation(a);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){i.min_count=Math.min(i.min_count,l.lods.length),i.max_count=Math.max(i.max_count,l.lods.length);for(let g=0;g<l.lods.length;g++){const d=l.lods[g];d.width&&(i.lods[g]=i.lods[g]||{min_height:1/0,max_height:0},i.lods[g].min_height=Math.min(i.lods[g].min_height,d.height),i.lods[g].max_height=Math.max(i.lods[g].max_height,d.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a&&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 G||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 $&&(t.geometry=s,L&&ue(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else L&&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 ve||t.isMaterial===!0){const r=t,n=[],o=new Array;if(L&&ne.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 u=this.assignTextureLODForSlot(i,e,r,a);n.push(u),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 u=s[i],l=o[i];u&&u.isTexture===!0?a.push({material:r,slot:l,texture:u,level:e}):a.push({material:r,slot:l,texture:null,level:e})}return a})}if(t instanceof z||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):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t){if(r&&n){const s=r[n];if(s){const a=this.getAssignedLODInformation(s);if(a&&a?.level<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(L&&n&&r){const s=this.getAssignedLODInformation(t);s&&ue(r,n,s.url)}}return o}else L=="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 L&&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[P];if(s){if(!s.lods){L&&console.warn("Texture has no LODs",s);return}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,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&M.registerTexture(this.url,i,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.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===o&&M.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const a=L=="verbose",i=t.userData.LODS;if(!i)return null;const u=i?.key;let l;if(t.isTexture===!0){const g=t;g.source&&g.source[oe]&&(l=g.source[oe])}if(l||(l=M.lodInfos.get(u)),l){if(e>0){let f=!1;const w=Array.isArray(l.lods);if(w&&e>=l.lods.length?f=!0:w||(f=!0),f)return this.lowresCache.get(u)}const g=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!g)return L&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const d=Se(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=d+"_"+l.guid,w=this.previouslyLoaded.get(f);if(w!==void 0){a&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let p=await w.catch(N=>(console.error(`Error loading LOD ${e} from ${d}
2
- `,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new _e;se(N),L&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let F=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(F+="?v="+y.hash)}const x=await N.loadAsync(F).catch(y=>(console.error(`Error loading LOD ${e} from ${d}
3
- `,y),null));if(!x)return null;const v=x.parser;a&&console.log("Loading finished "+d,m.guid);let D=0;if(x.parser.json.textures){let y=!1;for(const h of x.parser.json.textures){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){let h=await v.getDependency("texture",D);return h&&M.assignLODInformation(i.url,h,u,e,void 0,void 0),a&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',d,D,h,f),t instanceof z&&(h=this.copySettings(t,h)),h&&(h.guid=m.guid),p(h)}else L&&console.warn("Could not find texture with guid",m.guid)}if(D=0,x.parser.json.meshes){let y=!1;for(const h of x.parser.json.meshes){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){const h=await v.getDependency("mesh",D),O=m;if(a&&console.log(`Loaded Mesh "${h.name}"`,d,D,h,f),h.isMesh===!0){const A=h.geometry;return M.assignLODInformation(i.url,A,u,e,void 0,O.density),p(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const k=h.children[C];if(k instanceof G){const j=k.geometry;M.assignLODInformation(i.url,j,u,e,C,O.density),A.push(j)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof z){a&&console.log("Load texture from uri: "+d);const f=await new De().loadAsync(d);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,a&&console.log(l,f)):L&&console.warn("failed loading",d),f}}else L&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new Pe(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 e=e.clone(),L&&console.warn(`Copying texture settings
1
+ var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ve}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as $,Mesh as G,Material as De,Texture as z,TextureLoader as Le,Matrix4 as ie,Frustum as Me,Sphere as Oe,Box3 as ae,Vector3 as I}from"three";import{GLTFLoader as _e}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",ee="./include/ktx2/"});function we(t){X=t}function be(t){ee=t}let U,te,q;function re(t){U||(U=new ye,U.setDecoderPath(X),U.setDecoderConfig({type:"js"})),q||(q=new ve,q.setTranscoderPath(ee)),te||(te=xe),t?q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function se(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(q),t.meshoptDecoder||t.setMeshoptDecoder(te)}function H(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Se(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}let Y;function Te(){return Y!==void 0||(Y=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),H("debugprogressive")&&console.log("isMobileDevice",Y)),Y}function J(t){var e;return((e=t?.userData)==null?void 0:e["needle:raycast-mesh"])instanceof $?t.userData["needle:raycast-mesh"]:null}function le(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!J(t)){const r=Ae(e);r.userData={isRaycastMesh:!0},t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=r}}function Ee(t=!0){if(t){if(V)return;const e=V=G.prototype.raycast;G.prototype.raycast=function(r,n){const o=this,s=J(o);let a;s&&o.isMesh&&(a=o.geometry,o.geometry=s),e.call(this,r,n),a&&(o.geometry=a)}}else{if(!V)return;G.prototype.raycast=V,V=null}}let V=null;function Ae(t){const e=new $;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const R=new Array,P="NEEDLE_progressive",v=H("debugprogressive"),oe=Symbol("needle-progressive-texture"),K=new Map,ne=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const u=w.getMeshLODInformation(i),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.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,ne&&ne.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ue(t,e,r){var n;if(!v)return;K.has(t)||K.set(t,{keys:[],sourceId:r});const o=K.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const O=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,o;if(this._isLoadingMesh)return null;const s=(o=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:o[P];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(a=>(this._isLoadingMesh=!1,a&&O.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return P}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",o=t[n];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const i of Object.keys(a.uniforms)){const u=a.uniforms[i].value;u?.isTexture===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const i=t[a];i?.isTexture===!0&&s(i,e)}return t[n]=e,e;function s(a,i){const u=r.getAssignedLODInformation(a);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){i.min_count=Math.min(i.min_count,l.lods.length),i.max_count=Math.max(i.max_count,l.lods.length);for(let g=0;g<l.lods.length;g++){const d=l.lods[g];d.width&&(i.lods[g]=i.lods[g]||{min_height:1/0,max_height:0},i.lods[g].min_height=Math.min(i.lods[g].min_height,d.height),i.lods[g].max_height=Math.max(i.lods[g].max_height,d.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a&&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 G||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,O.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 $&&(t.geometry=s,v&&ue(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 De||t.isMaterial===!0){const r=t,n=[],o=new Array;if(v&&ne.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 u=this.assignTextureLODForSlot(i,e,r,a);n.push(u),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 u=s[i],l=o[i];u&&u.isTexture===!0?a.push({material:r,slot:l,texture:u,level:e}):a.push({material:r,slot:l,texture:null,level:e})}return a})}if(t instanceof z||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):n==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t){if(r&&n){const s=r[n];if(s){const a=this.getAssignedLODInformation(s);if(a&&a?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(v&&n&&r){const s=this.getAssignedLODInformation(t);s&&ue(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[P];if(s){if(!s.lods){v&&console.warn("Texture has no LODs",s);return}let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,O.registerTexture(this.url,i,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&O.registerTexture(this.url,i,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.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===o&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const a=v=="verbose",i=t.userData.LODS;if(!i)return null;const u=i?.key;let l;if(t.isTexture===!0){const g=t;g.source&&g.source[oe]&&(l=g.source[oe])}if(l||(l=O.lodInfos.get(u)),l){if(e>0){let f=!1;const D=Array.isArray(l.lods);if(D&&e>=l.lods.length?f=!0:D||(f=!0),f)return this.lowresCache.get(u)}const g=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!g)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const d=Se(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=d+"_"+l.guid,D=this.previouslyLoaded.get(f);if(D!==void 0){a&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let p=await D.catch(N=>(console.error(`Error loading LOD ${e} from ${d}
2
+ `,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new _e;se(N),v&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let F=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(F+="?v="+y.hash)}const x=await N.loadAsync(F).catch(y=>(console.error(`Error loading LOD ${e} from ${d}
3
+ `,y),null));if(!x)return null;const L=x.parser;a&&console.log("Loading finished "+d,m.guid);let M=0;if(x.parser.json.textures){let y=!1;for(const h of x.parser.json.textures){if(h!=null&&h.extensions){const _=h?.extensions[P];if(_!=null&&_.guid&&_.guid===m.guid){y=!0;break}}M++}if(y){let h=await L.getDependency("texture",M);return h&&O.assignLODInformation(i.url,h,u,e,void 0,void 0),a&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',d,M,h,f),t instanceof z&&(h=this.copySettings(t,h)),h&&(h.guid=m.guid),p(h)}else v&&console.warn("Could not find texture with guid",m.guid)}if(M=0,x.parser.json.meshes){let y=!1;for(const h of x.parser.json.meshes){if(h!=null&&h.extensions){const _=h?.extensions[P];if(_!=null&&_.guid&&_.guid===m.guid){y=!0;break}}M++}if(y){const h=await L.getDependency("mesh",M),_=m;if(a&&console.log(`Loaded Mesh "${h.name}"`,d,M,h,f),h.isMesh===!0){const A=h.geometry;return O.assignLODInformation(i.url,A,u,e,void 0,_.density),p(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const k=h.children[C];if(k instanceof G){const j=k.geometry;O.assignLODInformation(i.url,j,u,e,C,_.density),A.push(j)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof z){a&&console.log("Load texture from uri: "+d);const f=await new Le().loadAsync(d);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,a&&console.log(l,f)):v&&console.warn("failed loading",d),f}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new Pe(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 e=e.clone(),v&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let _=M;c(_,"registerTexture",(t,e,r,n,o)=>{if(L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;M.assignLODInformation(t,e,s,r,n,void 0),M.lodInfos.set(s,o),M.lowresCache.set(s,e)}),c(_,"registerMesh",(t,e,r,n,o,s)=>{var a;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){L&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class Pe{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 W=H("debugprogressive"),Ie=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),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 Oe),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),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[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(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 u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Ie||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Be,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,_.assignTextureLOD(t,e))}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 _.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,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=_.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=_.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const f=e.geometry.boundingBox;if(f&&t.isPerspectiveCamera){const w=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 x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const x=this._tempBox.min,v=this._tempBox.max;let D=x.x,y=x.y,h=v.x,O=v.y;const A=2,C=1.5,k=(x.x+v.x)*.5,j=(x.y+v.y)*.5;D=(D-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,O=(O-j)*A+j;const fe=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(v.x)),ge=y<0&&O>0?0:Math.min(Math.abs(x.y),Math.abs(v.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=w.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const v=T.corner0,D=T.corner1,y=T.corner2,h=T.corner3;v.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=v.x,y.copy(this._tempBox.max),y.y=v.y,h.copy(this._tempBox.max);const O=(v.z+h.z)*.5;v.z=D.z=y.z=h.z=O,v.applyMatrix4(x),D.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(v,D,255),T.debugDrawLine(v,y,255),T.debugDrawLine(D,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const w=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let I=T;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B),c(I,"_tempPtInside",new B);class Be{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(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=I.get(e);if(I.addPlugin(new Ce(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 Ce{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 u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const w=d[f],m=i[w];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&_.registerTexture(o,m,b.lods.length,S,b)}}}};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[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;_.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
5
+ `,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let w=O;c(w,"registerTexture",(t,e,r,n,o)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;O.assignLODInformation(t,e,s,r,n,void 0),O.lodInfos.set(s,o),O.lowresCache.set(s,e)}),c(w,"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;if(!i){v&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),O.assignLODInformation(t,i,e,n,o,s.density),O.lodInfos.set(e,s);let u=O.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],O.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map);class Pe{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 W=H("debugprogressive"),Be=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),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 Oe),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),c(this,"_tempWorldPosition",new I),c(this,"_tempBoxSize",new I),c(this,"_tempBox2Size",new I),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[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(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 u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Be||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Ie,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,w.assignTextureLOD(t,e))}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 w.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,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=w.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=w.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}let f=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const D=e;D.boundingBox||D.computeBoundingBox(),f=D.boundingBox}if(f&&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 x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&D.fov>70){const x=this._tempBox.min,L=this._tempBox.max;let M=x.x,y=x.y,h=L.x,_=L.y;const A=2,C=1.5,k=(x.x+L.x)*.5,j=(x.y+L.y)*.5;M=(M-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,_=(_-j)*A+j;const fe=M<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(L.x)),ge=y<0&&_>0?0:Math.min(Math.abs(x.y),Math.abs(L.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=D.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const L=T.corner0,M=T.corner1,y=T.corner2,h=T.corner3;L.copy(this._tempBox.min),M.copy(this._tempBox.max),M.x=L.x,y.copy(this._tempBox.max),y.y=L.y,h.copy(this._tempBox.max);const _=(L.z+h.z)*.5;L.z=M.z=y.z=h.z=_,L.applyMatrix4(x),M.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(L,M,255),T.debugDrawLine(L,y,255),T.debugDrawLine(M,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const D=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${D.max_height}px) - ${e.name}`)}}else{const D=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*D;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let B=T;c(B,"debugDrawLine"),c(B,"corner0",new I),c(B,"corner1",new I),c(B,"corner2",new I),c(B,"corner3",new I),c(B,"_tempPtInside",new I);class Ie{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new I),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(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=B.get(e);if(B.addPlugin(new Ce(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 Ce{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 u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const D=d[f],m=i[D];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&w.registerTexture(o,m,b.lods.length,S,b)}}}};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[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;w.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new w(s,t));const o=B.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,B as LODsManager,w as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
@@ -1,5 +1,5 @@
1
- "use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Le=require("three/examples/jsm/loaders/DRACOLoader.js"),xe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),me=require("three/examples/jsm/loaders/GLTFLoader.js");let H="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ie="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(H+"draco_decoder.js",{method:"head"}).catch(l=>{H="./include/draco/",ie="./include/ktx2/"});function De(l){H=l}function Me(l){ie=l}let W,re,V;function oe(l){W||(W=new Le.DRACOLoader,W.setDecoderPath(H),W.setDecoderConfig({type:"js"})),V||(V=new xe.KTX2Loader,V.setTranscoderPath(ie)),re||(re=ye.MeshoptDecoder),l?V.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ne(l){l.dracoLoader||l.setDRACOLoader(W),l.ktx2Loader||l.setKTX2Loader(V),l.meshoptDecoder||l.setMeshoptDecoder(re)}function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function _e(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let $;function Oe(){return $!==void 0||($=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",$)),$}function Q(l){var e;return((e=l==null?void 0:l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function ue(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!Q(l)){const r=ve(e);r.userData={isRaycastMesh:!0},l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=r}}function we(l=!0){if(l){if(U)return;const e=U=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=Q(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!U)return;g.Mesh.prototype.raycast=U,U=null}}let U=null;function ve(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const I=new Array,C="NEEDLE_progressive",M=J("debugprogressive"),te=Symbol("needle-progressive-texture"),q=new Map,se=new Set;if(M){let l=function(){e+=1,console.log("Toggle LOD level",e,q),q.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),h=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,h),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,se&&se.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ae(l,e,t){var i;if(!M)return;q.has(l)||q.set(l,{keys:[],sourceId:t});const r=q.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const v=class{constructor(e,t){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[C];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>(this._isLoadingMesh=!1,o&&v.registerMesh(this.url,t.guid,o,t.lods.length,void 0,t),o))):null});M&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const h=n.uniforms[a].value;(h==null?void 0:h.isTexture)===!0&&s(h,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const h=r.getAssignedLODInformation(n);if(h){const d=r.lodInfos.get(h.key);if(d&&d.lods){a.min_count=Math.min(a.min_count,d.lods.length),a.max_count=Math.max(a.max_count,d.lods.length);for(let p=0;p<d.lods.length;p++){const f=d.lods[p];f.width&&(a.lods[p]=a.lods[p]||{min_height:1/0,max_height:0},a.lods[p].min_height=Math.min(a.lods[p].min_height,f.height),a.lods[p].max_height=Math.max(a.lods[p].max_height,f.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,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&&(o=r==null?void 0:r.userData)!=null&&o.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,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of I)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,v.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,M&&ae(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else M&&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=[],o=new Array;if(M&&se.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const h=this.assignTextureLODForSlot(a,t,r,n);i.push(h),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const h=s[a],d=o[a];h&&h.isTexture===!0?n.push({material:r,slot:d,texture:h,level:t}):n.push({material:r,slot:d,texture:null,level:t})}return n})}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):i==="glyphMap"?Promise.resolve(e):v.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(M&&i&&r){const s=this.getAssignedLODInformation(e);s&&ae(r,i,s.url)}}return o}else M=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return M&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){if(!s.lods){M&&console.warn("Texture has no LODs",s);return}let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,v.registerTexture(this.url,a,s.lods.length,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&v.registerTexture(this.url,a,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&v.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,h,d;const r=M=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const p=e;p.source&&p.source[te]&&(s=p.source[te])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const _=Array.isArray(s.lods);if(_&&t>=s.lods.length?x=!0:_||(x=!0),x)return this.lowresCache.get(o)}const p=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!p)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const f=_e(i.url,p);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=f+"_"+s.guid,_=this.previouslyLoaded.get(x);if(_!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let m=await _.catch(F=>(console.error(`Error loading LOD ${t} from ${f}
2
- `,F),null)),A=!1;if(m==null||(m instanceof g.Texture&&e instanceof g.Texture?(a=m.image)!=null&&a.data||(h=m.source)!=null&&h.data?m=this.copySettings(e,m):(A=!0,this.previouslyLoaded.delete(x)):m instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((d=m.attributes.position)!=null&&d.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return m}const O=s,w=new Promise(async(m,A)=>{const F=new me.GLTFLoader;ne(F),M&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+f,O.guid));let Z=f;if(O&&Array.isArray(O.lods)){const y=O.lods[t];y.hash&&(Z+="?v="+y.hash)}const B=await F.loadAsync(Z).catch(y=>(console.error(`Error loading LOD ${t} from ${f}
3
- `,y),null));if(!B)return null;const j=B.parser;r&&console.log("Loading finished "+f,O.guid);let L=0;if(B.parser.json.textures){let y=!1;for(const u of B.parser.json.textures){if(u!=null&&u.extensions){const D=u==null?void 0:u.extensions[C];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){let u=await j.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,L,u,x),e instanceof g.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=O.guid),m(u)}else M&&console.warn("Could not find texture with guid",O.guid)}if(L=0,B.parser.json.meshes){let y=!1;for(const u of B.parser.json.meshes){if(u!=null&&u.extensions){const D=u==null?void 0:u.extensions[C];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){const u=await j.getDependency("mesh",L),D=O;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,L,u,x),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,D.density),m(T)}else{const T=new Array;for(let R=0;R<u.children.length;R++){const G=u.children[R];if(G instanceof g.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,R,D.density),T.push(N)}}return m(T)}}}return m(null)});return this.previouslyLoaded.set(x,w),await w}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+f);const _=await new g.TextureLoader().loadAsync(f);return _?(_.guid=s.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=e.colorSpace,r&&console.log(s,_)):M&&console.warn("failed loading",f),_}}else M&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new Se(e,r,i,o,s);t.userData.LODS=n,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){return t=t.clone(),M&&console.warn(`Copying texture settings
1
+ "use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),xe=require("three/examples/jsm/loaders/DRACOLoader.js"),Le=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),me=require("three/examples/jsm/loaders/GLTFLoader.js");let H="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ie="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(H+"draco_decoder.js",{method:"head"}).catch(l=>{H="./include/draco/",ie="./include/ktx2/"});function De(l){H=l}function Me(l){ie=l}let W,re,V;function oe(l){W||(W=new xe.DRACOLoader,W.setDecoderPath(H),W.setDecoderConfig({type:"js"})),V||(V=new Le.KTX2Loader,V.setTranscoderPath(ie)),re||(re=ye.MeshoptDecoder),l?V.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ne(l){l.dracoLoader||l.setDRACOLoader(W),l.ktx2Loader||l.setKTX2Loader(V),l.meshoptDecoder||l.setMeshoptDecoder(re)}function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function _e(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let $;function Oe(){return $!==void 0||($=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",$)),$}function Q(l){var e;return((e=l==null?void 0:l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function ue(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!Q(l)){const r=ve(e);r.userData={isRaycastMesh:!0},l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=r}}function we(l=!0){if(l){if(U)return;const e=U=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=Q(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!U)return;g.Mesh.prototype.raycast=U,U=null}}let U=null;function ve(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const I=new Array,C="NEEDLE_progressive",_=J("debugprogressive"),te=Symbol("needle-progressive-texture"),q=new Map,se=new Set;if(_){let l=function(){e+=1,console.log("Toggle LOD level",e,q),q.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),h=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,h),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,se&&se.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ae(l,e,t){var i;if(!_)return;q.has(l)||q.set(l,{keys:[],sourceId:t});const r=q.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const v=class{constructor(e,t){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[C];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>(this._isLoadingMesh=!1,o&&v.registerMesh(this.url,t.guid,o,t.lods.length,void 0,t),o))):null});_&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(_==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const h=n.uniforms[a].value;(h==null?void 0:h.isTexture)===!0&&s(h,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const h=r.getAssignedLODInformation(n);if(h){const d=r.lodInfos.get(h.key);if(d&&d.lods){a.min_count=Math.min(a.min_count,d.lods.length),a.max_count=Math.max(a.max_count,d.lods.length);for(let p=0;p<d.lods.length;p++){const f=d.lods[p];f.width&&(a.lods[p]=a.lods[p]||{min_height:1/0,max_height:0},a.lods[p].min_height=Math.min(a.lods[p].min_height,f.height),a.lods[p].max_height=Math.max(a.lods[p].max_height,f.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,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&&(o=r==null?void 0:r.userData)!=null&&o.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,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of I)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,v.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,_&&ae(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else _&&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=[],o=new Array;if(_&&se.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const h=this.assignTextureLODForSlot(a,t,r,n);i.push(h),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const h=s[a],d=o[a];h&&h.isTexture===!0?n.push({material:r,slot:d,texture:h,level:t}):n.push({material:r,slot:d,texture:null,level:t})}return n})}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):i==="glyphMap"?Promise.resolve(e):v.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return _==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(_&&i&&r){const s=this.getAssignedLODInformation(e);s&&ae(r,i,s.url)}}return o}else _=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return _&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){if(!s.lods){_&&console.warn("Texture has no LODs",s);return}let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,v.registerTexture(this.url,a,s.lods.length,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&v.registerTexture(this.url,a,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&v.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,h,d;const r=_=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const p=e;p.source&&p.source[te]&&(s=p.source[te])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const O=Array.isArray(s.lods);if(O&&t>=s.lods.length?x=!0:O||(x=!0),x)return this.lowresCache.get(o)}const p=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!p)return _&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const f=_e(i.url,p);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=f+"_"+s.guid,O=this.previouslyLoaded.get(x);if(O!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let D=await O.catch(F=>(console.error(`Error loading LOD ${t} from ${f}
2
+ `,F),null)),A=!1;if(D==null||(D instanceof g.Texture&&e instanceof g.Texture?(a=D.image)!=null&&a.data||(h=D.source)!=null&&h.data?D=this.copySettings(e,D):(A=!0,this.previouslyLoaded.delete(x)):D instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((d=D.attributes.position)!=null&&d.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return D}const m=s,w=new Promise(async(D,A)=>{const F=new me.GLTFLoader;ne(F),_&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+f,m.guid));let Z=f;if(m&&Array.isArray(m.lods)){const y=m.lods[t];y.hash&&(Z+="?v="+y.hash)}const B=await F.loadAsync(Z).catch(y=>(console.error(`Error loading LOD ${t} from ${f}
3
+ `,y),null));if(!B)return null;const j=B.parser;r&&console.log("Loading finished "+f,m.guid);let L=0;if(B.parser.json.textures){let y=!1;for(const u of B.parser.json.textures){if(u!=null&&u.extensions){const M=u==null?void 0:u.extensions[C];if(M!=null&&M.guid&&M.guid===m.guid){y=!0;break}}L++}if(y){let u=await j.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,L,u,x),e instanceof g.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=m.guid),D(u)}else _&&console.warn("Could not find texture with guid",m.guid)}if(L=0,B.parser.json.meshes){let y=!1;for(const u of B.parser.json.meshes){if(u!=null&&u.extensions){const M=u==null?void 0:u.extensions[C];if(M!=null&&M.guid&&M.guid===m.guid){y=!0;break}}L++}if(y){const u=await j.getDependency("mesh",L),M=m;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,L,u,x),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,M.density),D(T)}else{const T=new Array;for(let R=0;R<u.children.length;R++){const G=u.children[R];if(G instanceof g.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,R,M.density),T.push(N)}}return D(T)}}}return D(null)});return this.previouslyLoaded.set(x,w),await w}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+f);const O=await new g.TextureLoader().loadAsync(f);return O?(O.guid=s.guid,O.flipY=!1,O.needsUpdate=!0,O.colorSpace=e.colorSpace,r&&console.log(s,O)):_&&console.warn("failed loading",f),O}}else _&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new Se(e,r,i,o,s);t.userData.LODS=n,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){return t=t.clone(),_&&console.warn(`Copying texture settings
4
4
  `,e.uuid,`
5
- `,t.uuid),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.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){M&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),c(S,"registerMesh",(e,t,r,i,o,s)=>{var h;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(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[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const d=s[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new Ae,r.userData.LOD_state=s),s.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let i=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(i=!0),i&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}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 S.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,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var _;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((_=this.cameraFrustrum)!=null&&_.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const x=t.geometry.boundingBox;if(x&&e.isPerspectiveCamera){const O=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 L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&O.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,D=L.y,T=y.x,R=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,D=(D-X)*G+X,T=(T-K)*G+K,R=(R-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=D<0&&R>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&w.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),w.x*=O.aspect;const k=e.matrixWorldInverse,m=this._tempBox2;m.copy(x),m.applyMatrix4(t.matrixWorld),m.applyMatrix4(k);const A=m.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(w.x,w.y)!=0&&F!=0&&(w.z=A.z/Math.max(A.x,A.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,D=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,D.copy(this._tempBox.max),D.y=y.y,T.copy(this._tempBox.max);const R=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=R,y.applyMatrix4(L),u.applyMatrix4(L),D.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,D,255),b.debugDrawLine(u,T,255),b.debugDrawLine(D,T,255)}let B=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<i){B=L;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const O=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${O.max_height}px) - ${t.name}`)}}else{const O=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*O;for(let m=p.lods.length-1;m>=0;m--){const A=p.lods[m];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=m,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(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[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],_=n[x];if((_==null?void 0:_.isTexture)===!0){const O=(d=(h=_.userData)==null?void 0:h.associations)==null?void 0:d.textures,w=r.parser.json.textures[O];if(!w){console.warn("Texture data not found for texture index "+O);continue}if((p=w==null?void 0:w.extensions)!=null&&p[C]){const k=w.extensions[C];k&&i&&S.registerTexture(i,_,k.lods.length,O,k)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const i=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
5
+ `,t.uuid),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.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,i,o)=>{if(_&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){_&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),c(S,"registerMesh",(e,t,r,i,o,s)=>{var h;_&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){_&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(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[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const d=s[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new Ae,r.userData.LOD_state=s),s.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let i=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(i=!0),i&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}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 S.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,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var O;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((O=this.cameraFrustrum)!=null&&O.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}let x=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const m=t;m.boundingBox||m.computeBoundingBox(),x=m.boundingBox}if(x&&e.isPerspectiveCamera){const m=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 L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,M=L.y,T=y.x,R=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,M=(M-X)*G+X,T=(T-K)*G+K,R=(R-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=M<0&&R>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&w.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),w.x*=m.aspect;const k=e.matrixWorldInverse,D=this._tempBox2;D.copy(x),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(k);const A=D.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(w.x,w.y)!=0&&F!=0&&(w.z=A.z/Math.max(A.x,A.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,M=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,M.copy(this._tempBox.max),M.y=y.y,T.copy(this._tempBox.max);const R=(y.z+T.z)*.5;y.z=u.z=M.z=T.z=R,y.applyMatrix4(L),u.applyMatrix4(L),M.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,M,255),b.debugDrawLine(u,T,255),b.debugDrawLine(M,T,255)}let B=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<i){B=L;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const m=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${m.max_height}px) - ${t.name}`)}}else{const m=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*m;for(let D=p.lods.length-1;D>=0;D--){const A=p.lods[D];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=D,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(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[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],O=n[x];if((O==null?void 0:O.isTexture)===!0){const m=(d=(h=O.userData)==null?void 0:h.associations)==null?void 0:d.textures,w=r.parser.json.textures[m];if(!w){console.warn("Texture data not found for texture index "+m);continue}if((p=w==null?void 0:w.extensions)!=null&&p[C]){const k=w.extensions[C];k&&i&&S.registerTexture(i,O,k.lods.length,m,k)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const i=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
@@ -357,7 +357,13 @@ export class LODsManager {
357
357
  result.texture_lod = 99;
358
358
  return;
359
359
  }
360
- const boundingBox = mesh.geometry.boundingBox;
360
+ let boundingBox = mesh.geometry.boundingBox;
361
+ if (mesh.type === "SkinnedMesh") {
362
+ const skinnedMesh = mesh;
363
+ if (!skinnedMesh.boundingBox)
364
+ skinnedMesh.computeBoundingBox();
365
+ boundingBox = skinnedMesh.boundingBox;
366
+ }
361
367
  if (boundingBox && camera.isPerspectiveCamera) {
362
368
  const cam = camera;
363
369
  // hack: if the mesh has vertex colors, has less than 100 vertices we always select the highest LOD
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "1.2.0-alpha.7",
3
+ "version": "1.2.0-alpha.8",
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": {