@needle-tools/gltf-progressive 1.2.0-alpha → 1.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,8 @@ var ge = Object.defineProperty;
2
2
  var pe = (l, e, t) => e in l ? ge(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
3
  var c = (l, e, t) => (pe(l, typeof e != "symbol" ? e + "" : e, t), t);
4
4
  import { MeshoptDecoder as ye } from "three/examples/jsm/libs/meshopt_decoder.module.js";
5
- import { DRACOLoader as me } from "three/examples/jsm/loaders/DRACOLoader.js";
6
- import { KTX2Loader as Le } from "three/examples/jsm/loaders/KTX2Loader.js";
5
+ import { DRACOLoader as Le } from "three/examples/jsm/loaders/DRACOLoader.js";
6
+ import { KTX2Loader as me } from "three/examples/jsm/loaders/KTX2Loader.js";
7
7
  import { BufferGeometry as V, Mesh as H, Material as xe, Texture as U, TextureLoader as De, Matrix4 as ne, Frustum as Me, Sphere as Oe, Box3 as oe, Vector3 as k } from "three";
8
8
  import { GLTFLoader as we } from "three/examples/jsm/loaders/GLTFLoader.js";
9
9
  let J = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", se = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
@@ -18,7 +18,7 @@ function ze(l) {
18
18
  }
19
19
  let N, te, W;
20
20
  function ue(l) {
21
- N || (N = new me(), N.setDecoderPath(J), N.setDecoderConfig({ type: "js" })), W || (W = new Le(), W.setTranscoderPath(se)), te || (te = ye), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
21
+ N || (N = new Le(), N.setDecoderPath(J), N.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(se)), te || (te = ye), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
22
22
  }
23
23
  function fe(l) {
24
24
  l.dracoLoader || l.setDRACOLoader(N), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(te);
@@ -53,8 +53,8 @@ if (w) {
53
53
  for (const s of i.keys) {
54
54
  const o = n[s];
55
55
  if (o.isBufferGeometry === !0) {
56
- const a = v.getMeshLODInformation(o), f = a ? Math.min(e, a.lods.length) : 0;
57
- n["DEBUG:LOD"] = e, v.assignMeshLOD(n, f), a && (t = Math.max(t, a.lods.length - 1));
56
+ const a = v.getMeshLODInformation(o), h = a ? Math.min(e, a.lods.length) : 0;
57
+ n["DEBUG:LOD"] = e, v.assignMeshLOD(n, h), a && (t = Math.max(t, a.lods.length - 1));
58
58
  } else if (n.isMaterial === !0) {
59
59
  n["DEBUG:LOD"] = e, v.assignTextureLOD(n, e);
60
60
  break;
@@ -99,44 +99,43 @@ const _ = class {
99
99
  return t != null && t.key ? this.lodInfos.get(t.key) : null;
100
100
  }
101
101
  static getMaterialMinMaxLODsCount(e, t) {
102
- const r = "LODS:minmax", i = e[r];
103
- if (i != null)
104
- return i;
102
+ const r = this, i = "LODS:minmax", n = e[i];
103
+ if (n != null)
104
+ return n;
105
105
  if (t || (t = {
106
106
  min_count: 1 / 0,
107
107
  max_count: 0,
108
108
  lods: []
109
109
  }), Array.isArray(e)) {
110
- for (const s of e)
111
- this.getMaterialMinMaxLODsCount(s, t);
112
- return e[r] = t, t;
110
+ for (const o of e)
111
+ this.getMaterialMinMaxLODsCount(o, t);
112
+ return e[i] = t, t;
113
113
  }
114
- w === "verbose" && console.log("getMaterialMinMaxLODsCount", e);
115
- const n = (s) => {
116
- const o = this.getAssignedLODInformation(s);
117
- if (o) {
118
- const a = this.lodInfos.get(o.key);
119
- if (a && a.lods) {
120
- t.min_count = Math.min(t.min_count, a.lods.length), t.max_count = Math.max(t.max_count, a.lods.length);
121
- for (let f = 0; f < a.lods.length; f++) {
122
- const h = a.lods[f];
123
- h.width && (t.lods[f] = t.lods[f] || { min_height: 1 / 0, max_height: 0 }, t.lods[f].min_height = Math.min(t.lods[f].min_height, h.height), t.lods[f].max_height = Math.max(t.lods[f].max_height, h.height));
124
- }
125
- }
126
- }
127
- };
128
- if (e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
129
- const s = e;
130
- for (const o of Object.keys(s.uniforms)) {
131
- const a = s.uniforms[o].value;
132
- (a == null ? void 0 : a.isTexture) === !0 && n(a);
114
+ if (w === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
115
+ const o = e;
116
+ for (const a of Object.keys(o.uniforms)) {
117
+ const h = o.uniforms[a].value;
118
+ (h == null ? void 0 : h.isTexture) === !0 && s(h, t);
133
119
  }
134
120
  } else if (e.isMaterial)
135
- for (const s of Object.keys(e)) {
136
- const o = e[s];
137
- (o == null ? void 0 : o.isTexture) === !0 && n(o);
121
+ for (const o of Object.keys(e)) {
122
+ const a = e[o];
123
+ (a == null ? void 0 : a.isTexture) === !0 && s(a, t);
138
124
  }
139
- return e[r] = t, t;
125
+ return e[i] = t, t;
126
+ function s(o, a) {
127
+ const h = r.getAssignedLODInformation(o);
128
+ if (h) {
129
+ const d = r.lodInfos.get(h.key);
130
+ if (d && d.lods) {
131
+ a.min_count = Math.min(a.min_count, d.lods.length), a.max_count = Math.max(a.max_count, d.lods.length);
132
+ for (let g = 0; g < d.lods.length; g++) {
133
+ const f = d.lods[g];
134
+ f.width && (a.lods[g] = a.lods[g] || { min_height: 1 / 0, max_height: 0 }, a.lods[g].min_height = Math.min(a.lods[g].min_height, f.height), a.lods[g].max_height = Math.max(a.lods[g].max_height, f.height));
135
+ }
136
+ }
137
+ }
138
+ }
140
139
  }
141
140
  /** Check if a LOD level is available for a mesh or a texture
142
141
  * @param obj the mesh or texture to check
@@ -228,8 +227,8 @@ const _ = class {
228
227
  for (const o of Object.keys(s.uniforms)) {
229
228
  const a = s.uniforms[o].value;
230
229
  if ((a == null ? void 0 : a.isTexture) === !0) {
231
- const f = this.assignTextureLODForSlot(a, t, r, o);
232
- i.push(f), n.push(o);
230
+ const h = this.assignTextureLODForSlot(a, t, r, o);
231
+ i.push(h), n.push(o);
233
232
  }
234
233
  }
235
234
  } else
@@ -243,8 +242,8 @@ const _ = class {
243
242
  return Promise.all(i).then((s) => {
244
243
  const o = new Array();
245
244
  for (let a = 0; a < s.length; a++) {
246
- const f = s[a], h = n[a];
247
- f && f.isTexture === !0 ? o.push({ material: r, slot: h, texture: f, level: t }) : o.push({ material: r, slot: h, texture: null, level: t });
245
+ const h = s[a], d = n[a];
246
+ h && h.isTexture === !0 ? o.push({ material: r, slot: d, texture: h, level: t }) : o.push({ material: r, slot: d, texture: null, level: t });
248
247
  }
249
248
  return o;
250
249
  });
@@ -309,95 +308,95 @@ const _ = class {
309
308
  }), null;
310
309
  }
311
310
  static async getOrLoadLOD(e, t) {
312
- var o, a, f, h;
311
+ var o, a, h, d;
313
312
  const r = w == "verbose", i = e.userData.LODS;
314
313
  if (!i)
315
314
  return null;
316
315
  const n = i == null ? void 0 : i.key;
317
316
  let s;
318
317
  if (e.isTexture === !0) {
319
- const x = e;
320
- x.source && x.source[ee] && (s = x.source[ee]);
318
+ const g = e;
319
+ g.source && g.source[ee] && (s = g.source[ee]);
321
320
  }
322
321
  if (s || (s = _.lodInfos.get(n)), s) {
323
322
  if (t > 0) {
324
- let y = !1;
323
+ let L = !1;
325
324
  const D = Array.isArray(s.lods);
326
- if (D && t >= s.lods.length ? y = !0 : D || (y = !0), y)
325
+ if (D && t >= s.lods.length ? L = !0 : D || (L = !0), L)
327
326
  return this.lowresCache.get(n);
328
327
  }
329
- const x = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
330
- if (!x)
328
+ const g = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
329
+ if (!g)
331
330
  return w && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
332
- const d = _e(i.url, x);
333
- if (d.endsWith(".glb") || d.endsWith(".gltf")) {
331
+ const f = _e(i.url, g);
332
+ if (f.endsWith(".glb") || f.endsWith(".gltf")) {
334
333
  if (!s.guid)
335
334
  return console.warn("missing pointer for glb/gltf texture", s), null;
336
- const y = d + "_" + s.guid, D = this.previouslyLoaded.get(y);
335
+ const L = f + "_" + s.guid, D = this.previouslyLoaded.get(L);
337
336
  if (D !== void 0) {
338
- r && console.log(`LOD ${t} was already loading/loaded: ${y}`);
339
- let m = await D.catch((G) => (console.error(`Error loading LOD ${t} from ${d}
337
+ r && console.log(`LOD ${t} was already loading/loaded: ${L}`);
338
+ let m = await D.catch((G) => (console.error(`Error loading LOD ${t} from ${f}
340
339
  `, G), null)), T = !1;
341
- if (m == null || (m instanceof U && e instanceof U ? (a = m.image) != null && a.data || (f = m.source) != null && f.data ? m = this.copySettings(e, m) : (T = !0, this.previouslyLoaded.delete(y)) : m instanceof V && e instanceof V && ((h = m.attributes.position) != null && h.array || (T = !0, this.previouslyLoaded.delete(y)))), !T)
340
+ if (m == null || (m instanceof U && e instanceof U ? (a = m.image) != null && a.data || (h = m.source) != null && h.data ? m = this.copySettings(e, m) : (T = !0, this.previouslyLoaded.delete(L)) : m instanceof V && e instanceof V && ((d = m.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(L)))), !T)
342
341
  return m;
343
342
  }
344
343
  const M = s, O = new Promise(async (m, T) => {
345
344
  const G = new we();
346
- fe(G), w && (await new Promise((g) => setTimeout(g, 1e3)), r && console.warn("Start loading (delayed) " + d, M.guid));
347
- let Q = d;
345
+ fe(G), w && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, M.guid));
346
+ let Q = f;
348
347
  if (M && Array.isArray(M.lods)) {
349
- const g = M.lods[t];
350
- g.hash && (Q += "?v=" + g.hash);
348
+ const p = M.lods[t];
349
+ p.hash && (Q += "?v=" + p.hash);
351
350
  }
352
- const E = await G.loadAsync(Q).catch((g) => (console.error(`Error loading LOD ${t} from ${d}
353
- `, g), null));
351
+ const E = await G.loadAsync(Q).catch((p) => (console.error(`Error loading LOD ${t} from ${f}
352
+ `, p), null));
354
353
  if (!E)
355
354
  return null;
356
355
  const Z = E.parser;
357
- r && console.log("Loading finished " + d, M.guid);
358
- let p = 0;
356
+ r && console.log("Loading finished " + f, M.guid);
357
+ let y = 0;
359
358
  if (E.parser.json.textures) {
360
- let g = !1;
359
+ let p = !1;
361
360
  for (const u of E.parser.json.textures) {
362
361
  if (u != null && u.extensions) {
363
- const L = u == null ? void 0 : u.extensions[R];
364
- if (L != null && L.guid && L.guid === M.guid) {
365
- g = !0;
362
+ const x = u == null ? void 0 : u.extensions[R];
363
+ if (x != null && x.guid && x.guid === M.guid) {
364
+ p = !0;
366
365
  break;
367
366
  }
368
367
  }
369
- p++;
368
+ y++;
370
369
  }
371
- if (g) {
372
- let u = await Z.getDependency("texture", p);
373
- return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', d, p, u, y), e instanceof U && (u = this.copySettings(e, u)), u && (u.guid = M.guid), m(u);
370
+ if (p) {
371
+ let u = await Z.getDependency("texture", y);
372
+ return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, y, u, L), e instanceof U && (u = this.copySettings(e, u)), u && (u.guid = M.guid), m(u);
374
373
  } else
375
374
  w && console.warn("Could not find texture with guid", M.guid);
376
375
  }
377
- if (p = 0, E.parser.json.meshes) {
378
- let g = !1;
376
+ if (y = 0, E.parser.json.meshes) {
377
+ let p = !1;
379
378
  for (const u of E.parser.json.meshes) {
380
379
  if (u != null && u.extensions) {
381
- const L = u == null ? void 0 : u.extensions[R];
382
- if (L != null && L.guid && L.guid === M.guid) {
383
- g = !0;
380
+ const x = u == null ? void 0 : u.extensions[R];
381
+ if (x != null && x.guid && x.guid === M.guid) {
382
+ p = !0;
384
383
  break;
385
384
  }
386
385
  }
387
- p++;
386
+ y++;
388
387
  }
389
- if (g) {
390
- const u = await Z.getDependency("mesh", p), L = M;
391
- if (r && console.log(`Loaded Mesh "${u.name}"`, d, p, u, y), u.isMesh === !0) {
388
+ if (p) {
389
+ const u = await Z.getDependency("mesh", y), x = M;
390
+ if (r && console.log(`Loaded Mesh "${u.name}"`, f, y, u, L), u.isMesh === !0) {
392
391
  const S = u.geometry;
393
- return _.assignLODInformation(i.url, S, n, t, void 0, L.density), m(S);
392
+ return _.assignLODInformation(i.url, S, n, t, void 0, x.density), m(S);
394
393
  } else {
395
394
  const S = new Array();
396
395
  for (let C = 0; C < u.children.length; C++) {
397
396
  const F = u.children[C];
398
397
  if (F instanceof H) {
399
398
  const z = F.geometry;
400
- _.assignLODInformation(i.url, z, n, t, C, L.density), S.push(z);
399
+ _.assignLODInformation(i.url, z, n, t, C, x.density), S.push(z);
401
400
  }
402
401
  }
403
402
  return m(S);
@@ -406,11 +405,11 @@ const _ = class {
406
405
  }
407
406
  return m(null);
408
407
  });
409
- return this.previouslyLoaded.set(y, O), await O;
408
+ return this.previouslyLoaded.set(L, O), await O;
410
409
  } else if (e instanceof U) {
411
- r && console.log("Load texture from uri: " + d);
412
- const D = await new De().loadAsync(d);
413
- return D ? (D.guid = s.guid, D.flipY = !1, D.needsUpdate = !0, D.colorSpace = e.colorSpace, r && console.log(s, D)) : w && console.warn("failed loading", d), D;
410
+ r && console.log("Load texture from uri: " + f);
411
+ const D = await new De().loadAsync(f);
412
+ return D ? (D.guid = s.guid, D.flipY = !1, D.needsUpdate = !0, D.colorSpace = e.colorSpace, r && console.log(s, D)) : w && console.warn("failed loading", f), D;
414
413
  }
415
414
  } else
416
415
  w && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
@@ -446,14 +445,14 @@ c(v, "registerTexture", (e, t, r, i, n) => {
446
445
  * Register a mesh with LOD information
447
446
  */
448
447
  c(v, "registerMesh", (e, t, r, i, n, s) => {
449
- var f;
448
+ var h;
450
449
  w && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
451
450
  const o = r.geometry;
452
451
  o.userData || (o.userData = {}), _.assignLODInformation(e, o, t, i, n, s.density), _.lodInfos.set(t, s);
453
452
  let a = _.lowresCache.get(t);
454
453
  a ? a.push(r.geometry) : a = [r.geometry], _.lowresCache.set(t, a), i > 0 && !ve(r) && Se(r, o);
455
- for (const h of I)
456
- (f = h.onRegisteredNewMesh) == null || f.call(h, r, s);
454
+ for (const d of I)
455
+ (h = d.onRegisteredNewMesh) == null || h.call(d, r, s);
457
456
  }), /** A map of key = asset uuid and value = LOD information */
458
457
  c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
459
458
  c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
@@ -547,26 +546,26 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
547
546
  onBeforeRender(e, t, r, i) {
548
547
  }
549
548
  onAfterRender(e, t, r, i) {
550
- var a, f;
549
+ var a, h;
551
550
  if (this.pause)
552
551
  return;
553
552
  const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
554
553
  let o = !0;
555
554
  if (s.length === 1) {
556
- const h = s[0].material;
557
- (h.name === "EffectMaterial" || h.name === "CopyShader") && (o = !1);
555
+ const d = s[0].material;
556
+ (d.name === "EffectMaterial" || d.name === "CopyShader") && (o = !1);
558
557
  }
559
558
  if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
560
559
  if (Ae || this.updateInterval > 0 && i % this.updateInterval != 0)
561
560
  return;
562
561
  this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
563
- const h = this.targetTriangleDensity;
564
- for (const d of s) {
565
- if (d.material && (((a = d.geometry) == null ? void 0 : a.type) === "BoxGeometry" || ((f = d.geometry) == null ? void 0 : f.type) === "BufferGeometry") && (d.material.name === "SphericalGaussianBlur" || d.material.name == "BackgroundCubeMaterial" || d.material.name === "CubemapFromEquirect" || d.material.name === "EquirectangularToCubeUV")) {
566
- $ && (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)));
562
+ const d = this.targetTriangleDensity;
563
+ for (const f of s) {
564
+ 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")) {
565
+ $ && (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)));
567
566
  continue;
568
567
  }
569
- switch (d.material.type) {
568
+ switch (f.material.type) {
570
569
  case "LineBasicMaterial":
571
570
  case "LineDashedMaterial":
572
571
  case "PointsMaterial":
@@ -575,32 +574,32 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
575
574
  case "MeshDepthMaterial":
576
575
  continue;
577
576
  }
578
- const y = d.object;
579
- (y instanceof H || y.isMesh) && this.updateLODs(e, t, y, h, i);
577
+ const L = f.object;
578
+ (L instanceof H || L.isMesh) && this.updateLODs(e, t, L, d, i);
580
579
  }
581
- const x = n.transparent;
582
- for (const d of x) {
583
- const y = d.object;
584
- (y instanceof H || y.isMesh) && this.updateLODs(e, t, y, h, i);
580
+ const g = n.transparent;
581
+ for (const f of g) {
582
+ const L = f.object;
583
+ (L instanceof H || L.isMesh) && this.updateLODs(e, t, L, d, i);
585
584
  }
586
585
  }
587
586
  }
588
587
  /** Update the LOD levels for the renderer. */
589
588
  updateLODs(e, t, r, i, n) {
590
- var a, f;
589
+ var a, h;
591
590
  let s = r.userData.LOD_state;
592
591
  if (s || (s = new be(), r.userData.LOD_state = s), s.frames++ < 2)
593
592
  return;
594
- for (const h of I)
595
- (a = h.onBeforeUpdateLOD) == null || a.call(h, this.renderer, e, t, r);
593
+ for (const d of I)
594
+ (a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
596
595
  this.calculateLodLevel(t, r, s, i, b), b.mesh_lod = Math.round(b.mesh_lod), b.texture_lod = Math.round(b.texture_lod), b.mesh_lod >= 0 && this.loadProgressiveMeshes(r, b.mesh_lod);
597
596
  let o = b.texture_lod;
598
597
  if (r.material && o >= 0) {
599
- const h = r["DEBUG:LOD"];
600
- h != null && (o = h), this.loadProgressiveTextures(r.material, o);
598
+ const d = r["DEBUG:LOD"];
599
+ d != null && (o = d), this.loadProgressiveTextures(r.material, o);
601
600
  }
602
- for (const h of I)
603
- (f = h.onAfterUpdatedLOD) == null || f.call(h, this.renderer, e, t, r, b);
601
+ for (const d of I)
602
+ (h = d.onAfterUpdatedLOD) == null || h.call(d, this.renderer, e, t, r, b);
604
603
  s.lastLodLevel_Mesh = b.mesh_lod, s.lastLodLevel_Texture = b.texture_lod;
605
604
  }
606
605
  /** Load progressive textures for the given material
@@ -653,72 +652,72 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
653
652
  let o = 10 + 1;
654
653
  if ($ && t["DEBUG:LOD"] != null)
655
654
  return t["DEBUG:LOD"];
656
- const a = v.getMeshLODInformation(t.geometry), f = a == null ? void 0 : a.lods, h = f && f.length > 0, x = v.getMaterialMinMaxLODsCount(t.material), d = (x == null ? void 0 : x.min_count) != 1 / 0 && x.min_count > 0 && x.max_count > 0;
657
- if (!h && !d) {
655
+ const a = v.getMeshLODInformation(t.geometry), h = a == null ? void 0 : a.lods, d = h && h.length > 0, g = v.getMaterialMinMaxLODsCount(t.material), f = (g == null ? void 0 : g.min_count) != 1 / 0 && g.min_count > 0 && g.max_count > 0;
656
+ if (!d && !f) {
658
657
  n.mesh_lod = 0, n.texture_lod = 0;
659
658
  return;
660
659
  }
661
- if (h || (o = 0), !((D = this.cameraFrustrum) != null && D.intersectsObject(t))) {
660
+ if (d || (o = 0), !((D = this.cameraFrustrum) != null && D.intersectsObject(t))) {
662
661
  n.mesh_lod = 99, n.texture_lod = 99;
663
662
  return;
664
663
  }
665
- const y = t.geometry.boundingBox;
666
- if (y && e.isPerspectiveCamera) {
664
+ const L = t.geometry.boundingBox;
665
+ if (L && e.isPerspectiveCamera) {
667
666
  const M = e;
668
667
  if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
669
668
  this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
670
- const p = e.getWorldPosition(this._tempWorldPosition);
671
- if (this._sphere.containsPoint(p)) {
669
+ const y = e.getWorldPosition(this._tempWorldPosition);
670
+ if (this._sphere.containsPoint(y)) {
672
671
  n.mesh_lod = 0, n.texture_lod = 0;
673
672
  return;
674
673
  }
675
674
  }
676
- if (this._tempBox.copy(y), this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
675
+ if (this._tempBox.copy(L), this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
677
676
  n.mesh_lod = 0, n.texture_lod = 0;
678
677
  return;
679
678
  }
680
679
  if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && M.fov > 70) {
681
- const p = this._tempBox.min, g = this._tempBox.max;
682
- let u = p.x, L = p.y, S = g.x, C = g.y;
683
- const F = 2, z = 1.5, q = (p.x + g.x) * 0.5, X = (p.y + g.y) * 0.5;
684
- u = (u - q) * F + q, L = (L - X) * F + X, S = (S - q) * F + q, C = (C - X) * F + X;
685
- const de = u < 0 && S > 0 ? 0 : Math.min(Math.abs(p.x), Math.abs(g.x)), he = L < 0 && C > 0 ? 0 : Math.min(Math.abs(p.y), Math.abs(g.y)), j = Math.max(de, he);
680
+ const y = this._tempBox.min, p = this._tempBox.max;
681
+ let u = y.x, x = y.y, S = p.x, C = p.y;
682
+ const F = 2, z = 1.5, q = (y.x + p.x) * 0.5, X = (y.y + p.y) * 0.5;
683
+ u = (u - q) * F + q, x = (x - X) * F + X, S = (S - q) * F + q, C = (C - X) * F + X;
684
+ const de = u < 0 && S > 0 ? 0 : Math.min(Math.abs(y.x), Math.abs(p.x)), he = x < 0 && C > 0 ? 0 : Math.min(Math.abs(y.y), Math.abs(p.y)), j = Math.max(de, he);
686
685
  r.lastCentrality = (z - j) * (z - j) * (z - j);
687
686
  } else
688
687
  r.lastCentrality = 1;
689
688
  const O = this._tempBox.getSize(this._tempBoxSize);
690
689
  O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= M.aspect;
691
690
  const B = e.matrixWorldInverse, m = this._tempBox2;
692
- m.copy(y), m.applyMatrix4(t.matrixWorld), m.applyMatrix4(B);
691
+ m.copy(L), m.applyMatrix4(t.matrixWorld), m.applyMatrix4(B);
693
692
  const T = m.getSize(this._tempBox2Size), G = Math.max(T.x, T.y);
694
693
  if (Math.max(O.x, O.y) != 0 && G != 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, $ && A.debugDrawLine) {
695
- const p = this.tempMatrix.copy(this.projectionScreenMatrix);
696
- p.invert();
697
- const g = A.corner0, u = A.corner1, L = A.corner2, S = A.corner3;
698
- g.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = g.x, L.copy(this._tempBox.max), L.y = g.y, S.copy(this._tempBox.max);
699
- const C = (g.z + S.z) * 0.5;
700
- g.z = u.z = L.z = S.z = C, g.applyMatrix4(p), u.applyMatrix4(p), L.applyMatrix4(p), S.applyMatrix4(p), A.debugDrawLine(g, u, 255), A.debugDrawLine(g, L, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(L, S, 255);
694
+ const y = this.tempMatrix.copy(this.projectionScreenMatrix);
695
+ y.invert();
696
+ const p = A.corner0, u = A.corner1, x = A.corner2, S = A.corner3;
697
+ p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x, x.copy(this._tempBox.max), x.y = p.y, S.copy(this._tempBox.max);
698
+ const C = (p.z + S.z) * 0.5;
699
+ p.z = u.z = x.z = S.z = C, p.applyMatrix4(y), u.applyMatrix4(y), x.applyMatrix4(y), S.applyMatrix4(y), A.debugDrawLine(p, u, 255), A.debugDrawLine(p, x, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(x, S, 255);
701
700
  }
702
701
  let E = 999;
703
- if (f && r.lastScreenCoverage > 0) {
704
- for (let p = 0; p < f.length; p++)
705
- if (f[p].density / r.lastScreenCoverage < i) {
706
- E = p;
702
+ if (h && r.lastScreenCoverage > 0) {
703
+ for (let y = 0; y < h.length; y++)
704
+ if (h[y].density / r.lastScreenCoverage < i) {
705
+ E = y;
707
706
  break;
708
707
  }
709
708
  }
710
709
  E < o && (o = E);
711
710
  }
712
- if (n.mesh_lod = o, d)
711
+ if (n.mesh_lod = o, f)
713
712
  if (r.lastLodLevel_Texture < 0) {
714
- if (n.texture_lod = x.max_count - 1, $) {
715
- const M = x.lods[x.max_count - 1];
713
+ if (n.texture_lod = g.max_count - 1, $) {
714
+ const M = g.lods[g.max_count - 1];
716
715
  $ && console.log(`First Texture LOD ${n.texture_lod} (${M.max_height}px) - ${t.name}`);
717
716
  }
718
717
  } else {
719
718
  const M = r.lastScreenCoverage * 1.5, B = this.renderer.domElement.clientHeight / window.devicePixelRatio * M;
720
- for (let m = x.lods.length - 1; m >= 0; m--) {
721
- const T = x.lods[m];
719
+ for (let m = g.lods.length - 1; m >= 0; m--) {
720
+ const T = g.lods[m];
722
721
  if (T.max_height > B) {
723
722
  n.texture_lod = m, n.texture_lod < r.lastLodLevel_Texture && $ && console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${n.texture_lod} (${T.max_height}px: ${(100 * r.lastScreenCoverage).toFixed(2)} % = ${B.toFixed(0)}px) - ${t.name}`);
724
723
  break;
@@ -788,20 +787,20 @@ class Ee {
788
787
  const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
789
788
  if (i && r && t.material) {
790
789
  let n = function(o) {
791
- var f, h, x;
790
+ var h, d, g;
792
791
  if (o[Y] == !0)
793
792
  return;
794
793
  o[Y] = !0, o.userData && (o.userData.LOD = -1);
795
794
  const a = Object.keys(o);
796
- for (let d = 0; d < a.length; d++) {
797
- const y = a[d], D = o[y];
795
+ for (let f = 0; f < a.length; f++) {
796
+ const L = a[f], D = o[L];
798
797
  if ((D == null ? void 0 : D.isTexture) === !0) {
799
- const M = (h = (f = D.userData) == null ? void 0 : f.associations) == null ? void 0 : h.textures, O = r.parser.json.textures[M];
798
+ const M = (d = (h = D.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[M];
800
799
  if (!O) {
801
800
  console.warn("Texture data not found for texture index " + M);
802
801
  continue;
803
802
  }
804
- if ((x = O == null ? void 0 : O.extensions) != null && x[R]) {
803
+ if ((g = O == null ? void 0 : O.extensions) != null && g[R]) {
805
804
  const B = O.extensions[R];
806
805
  B && i && v.registerTexture(i, D, B.lods.length, M, B);
807
806
  }
@@ -1,5 +1,5 @@
1
- var fe=Object.defineProperty,ge=(t,e,r)=>e in t?fe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ge(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as me}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as xe}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as q,Mesh as V,Material as ye,Texture as $,TextureLoader as Le,Matrix4 as se,Frustum as ve,Sphere as De,Box3 as oe,Vector3 as B}from"three";import{GLTFLoader as Me}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",Y="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",Y="./include/ktx2/"});function Oe(t){X=t}function _e(t){Y=t}let z,J,W;function Q(t){z||(z=new pe,z.setDecoderPath(X),z.setDecoderConfig({type:"js"})),W||(W=new xe,W.setTranscoderPath(Y)),J||(J=me),t?W.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(t){t.dracoLoader||t.setDRACOLoader(z),t.ktx2Loader||t.setKTX2Loader(W),t.meshoptDecoder||t.setMeshoptDecoder(J)}function ee(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function we(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}function ne(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof q?t.userData["needle:raycast-mesh"]:null}function ie(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const k=new Array,P="NEEDLE_progressive",L=ee("debugprogressive"),te=Symbol("needle-progressive-texture"),U=new Map,re=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,U),U.forEach((o,s)=>{for(const i of o.keys){const a=s[i];if(a.isBufferGeometry===!0){const u=_.getMeshLODInformation(a),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,re&&re.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ae(t,e,r){var n;if(!L)return;U.has(t)||U.set(t,{keys:[],sourceId:r});const o=U.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(i=>(this._isLoadingMesh=!1,i&&M.registerMesh(this.url,s.guid,i,s.lods.length,void 0,s),i))):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="LODS:minmax",n=t[r];if(n!=null)return n;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const s of t)this.getMaterialMinMaxLODsCount(s,e);return t[r]=e,e}L==="verbose"&&console.log("getMaterialMinMaxLODsCount",t);const o=s=>{const i=this.getAssignedLODInformation(s);if(i){const a=this.lodInfos.get(i.key);if(a&&a.lods){e.min_count=Math.min(e.min_count,a.lods.length),e.max_count=Math.max(e.max_count,a.lods.length);for(let u=0;u<a.lods.length;u++){const l=a.lods[u];l.width&&(e.lods[u]=e.lods[u]||{min_height:1/0,max_height:0},e.lods[u].min_height=Math.min(e.lods[u].min_height,l.height),e.lods[u].max_height=Math.max(e.lods[u].max_height,l.height))}}}};if(t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const s=t;for(const i of Object.keys(s.uniforms)){const a=s.uniforms[i].value;a?.isTexture===!0&&o(a)}}else if(t.isMaterial)for(const s of Object.keys(t)){const i=t[s];i?.isTexture===!0&&o(i)}return t[r]=e,e}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 i=t[s];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,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 V||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of k)(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 i=o.index||0;s=s[i]}s&&n!=s&&s instanceof q&&(t.geometry=s,L&&ae(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 ye||t.isMaterial===!0){const r=t,n=[],o=new Array;if(L&&re.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const i of Object.keys(s.uniforms)){const a=s.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i);n.push(u),o.push(i)}}}else for(const s of Object.keys(r)){const i=r[s];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,s);n.push(a),o.push(s)}}return Promise.all(n).then(s=>{const i=new Array;for(let a=0;a<s.length;a++){const u=s[a],l=o[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof $||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 i=this.getAssignedLODInformation(s);if(i&&i?.level<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,s,o),null}r[n]=o}if(L&&n&&r){const s=this.getAssignedLODInformation(t);s&&ae(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){let i=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(i=!0,M.registerTexture(this.url,a,s.lods.length,o,s));i||this.parser.getDependency("texture",o).then(a=>{a&&M.registerTexture(this.url,a,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 i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a.meshes===o&&M.registerMesh(this.url,s.guid,i,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const i=L=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const y=t;y.source&&y.source[te]&&(l=y.source[te])}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 y=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!y)return L&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=we(a.url,y);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=h+"_"+l.guid,w=this.previouslyLoaded.get(f);if(w!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let m=await w.catch(G=>(console.error(`Error loading LOD ${e} from ${h}
2
- `,G),null)),b=!1;if(m==null||(m instanceof $&&t instanceof $?(n=m.image)!=null&&n.data||(o=m.source)!=null&&o.data?m=this.copySettings(t,m):(b=!0,this.previouslyLoaded.delete(f)):m instanceof q&&t instanceof q&&((s=m.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return m}const g=l,S=new Promise(async(m,b)=>{const G=new Me;Z(G),L&&(await new Promise(x=>setTimeout(x,1e3)),i&&console.warn("Start loading (delayed) "+h,g.guid));let N=h;if(g&&Array.isArray(g.lods)){const x=g.lods[e];x.hash&&(N+="?v="+x.hash)}const p=await G.loadAsync(N).catch(x=>(console.error(`Error loading LOD ${e} from ${h}
3
- `,x),null));if(!p)return null;const v=p.parser;i&&console.log("Loading finished "+h,g.guid);let D=0;if(p.parser.json.textures){let x=!1;for(const d of p.parser.json.textures){if(d!=null&&d.extensions){const O=d?.extensions[P];if(O!=null&&O.guid&&O.guid===g.guid){x=!0;break}}D++}if(x){let d=await v.getDependency("texture",D);return d&&M.assignLODInformation(a.url,d,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',h,D,d,f),t instanceof $&&(d=this.copySettings(t,d)),d&&(d.guid=g.guid),m(d)}else L&&console.warn("Could not find texture with guid",g.guid)}if(D=0,p.parser.json.meshes){let x=!1;for(const d of p.parser.json.meshes){if(d!=null&&d.extensions){const O=d?.extensions[P];if(O!=null&&O.guid&&O.guid===g.guid){x=!0;break}}D++}if(x){const d=await v.getDependency("mesh",D),O=g;if(i&&console.log(`Loaded Mesh "${d.name}"`,h,D,d,f),d.isMesh===!0){const A=d.geometry;return M.assignLODInformation(a.url,A,u,e,void 0,O.density),m(A)}else{const A=new Array;for(let C=0;C<d.children.length;C++){const j=d.children[C];if(j instanceof V){const R=j.geometry;M.assignLODInformation(a.url,R,u,e,C,O.density),A.push(R)}}return m(A)}}}return m(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof $){i&&console.log("Load texture from uri: "+h);const f=await new Le().loadAsync(h);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(l,f)):L&&console.warn("failed loading",h),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 i=new be(t,r,n,o,s);e.userData.LODS=i,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 fe=Object.defineProperty,ge=(t,e,r)=>e in t?fe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ge(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as me}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as xe}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as q,Mesh as V,Material as ye,Texture as $,TextureLoader as Le,Matrix4 as se,Frustum as ve,Sphere as De,Box3 as oe,Vector3 as B}from"three";import{GLTFLoader as Me}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",Y="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",Y="./include/ktx2/"});function Oe(t){X=t}function _e(t){Y=t}let z,J,W;function Q(t){z||(z=new pe,z.setDecoderPath(X),z.setDecoderConfig({type:"js"})),W||(W=new xe,W.setTranscoderPath(Y)),J||(J=me),t?W.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(t){t.dracoLoader||t.setDRACOLoader(z),t.ktx2Loader||t.setKTX2Loader(W),t.meshoptDecoder||t.setMeshoptDecoder(J)}function ee(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function we(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}function ne(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof q?t.userData["needle:raycast-mesh"]:null}function ie(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const k=new Array,P="NEEDLE_progressive",L=ee("debugprogressive"),te=Symbol("needle-progressive-texture"),U=new Map,re=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,U),U.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,re&&re.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ae(t,e,r){var n;if(!L)return;U.has(t)||U.set(t,{keys:[],sourceId:r});const o=U.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 V||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of k)(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 q&&(t.geometry=s,L&&ae(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 ye||t.isMaterial===!0){const r=t,n=[],o=new Array;if(L&&re.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 $||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&&ae(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){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[te]&&(l=g.source[te])}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=we(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(G=>(console.error(`Error loading LOD ${e} from ${d}
2
+ `,G),null)),b=!1;if(p==null||(p instanceof $&&t instanceof $?(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 q&&t instanceof q&&((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 G=new Me;Z(G),L&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let N=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(N+="?v="+y.hash)}const x=await G.loadAsync(N).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 $&&(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 j=h.children[C];if(j instanceof V){const R=j.geometry;M.assignLODInformation(i.url,R,u,e,C,O.density),A.push(R)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof $){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)):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 be(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
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)=>{L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),e.source&&(e.source[te]=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 i;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const a=r.geometry;a.userData||(a.userData={}),M.assignLODInformation(t,a,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&&!ne(r)&&ie(r,a);for(const l of k)(i=l.onRegisteredNewMesh)==null||i.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class be{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 F=ee("debugprogressive"),Se=ee("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new se),c(this,"cameraFrustrum",new ve),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new De),c(this,"_tempBox",new oe),c(this,"_tempBox2",new oe),c(this,"tempMatrix",new se),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){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t){return t[le]?t[le]:new T(t)}get plugins(){return k}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;Q(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 i=this.renderer.renderLists.get(t,0),a=i.opaque;let u=!0;if(a.length===1){const l=a[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Se||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 h of a){if(h.material&&(((o=h.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=h.geometry)==null?void 0:s.type)==="BufferGeometry")&&(h.material.name==="SphericalGaussianBlur"||h.material.name=="BackgroundCubeMaterial"||h.material.name==="CubemapFromEquirect"||h.material.name==="EquirectangularToCubeUV")){F&&(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",h,h.material.name,h.material.type)));continue}switch(h.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=h.object;(f instanceof V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const y=i.transparent;for(const h of y){const f=h.object;(f instanceof V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,i;let a=r.userData.LOD_state;if(a||(a=new Te,r.userData.LOD_state=a),a.frames++<2)return;for(const l of k)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,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 k)(i=l.onAfterUpdatedLOD)==null||i.call(l,this.renderer,t,e,r,E);a.lastLodLevel_Mesh=E.mesh_lod,a.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 i=10+1;if(F&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=_.getMeshLODInformation(e.geometry),u=a?.lods,l=u&&u.length>0,y=_.getMaterialMinMaxLODsCount(e.material),h=y?.min_count!=1/0&&y.min_count>0&&y.max_count>0;if(!l&&!h){o.mesh_lod=0,o.texture_lod=0;return}if(l||(i=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 p=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(p)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),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 p=this._tempBox.min,v=this._tempBox.max;let D=p.x,x=p.y,d=v.x,O=v.y;const A=2,C=1.5,j=(p.x+v.x)*.5,R=(p.y+v.y)*.5;D=(D-j)*A+j,x=(x-R)*A+R,d=(d-j)*A+j,O=(O-R)*A+R;const de=D<0&&d>0?0:Math.min(Math.abs(p.x),Math.abs(v.x)),he=x<0&&O>0?0:Math.min(Math.abs(p.y),Math.abs(v.y)),H=Math.max(de,he);r.lastCentrality=(C-H)*(C-H)*(C-H)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&g.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),g.x*=w.aspect;const S=t.matrixWorldInverse,m=this._tempBox2;m.copy(f),m.applyMatrix4(e.matrixWorld),m.applyMatrix4(S);const b=m.getSize(this._tempBox2Size),G=Math.max(b.x,b.y);if(Math.max(g.x,g.y)!=0&&G!=0&&(g.z=b.z/Math.max(b.x,b.y)*Math.max(g.x,g.y)),r.lastScreenCoverage=Math.max(g.x,g.y,g.z),r.lastScreenspaceVolume.copy(g),r.lastScreenCoverage*=r.lastCentrality,F&&T.debugDrawLine){const p=this.tempMatrix.copy(this.projectionScreenMatrix);p.invert();const v=T.corner0,D=T.corner1,x=T.corner2,d=T.corner3;v.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=v.x,x.copy(this._tempBox.max),x.y=v.y,d.copy(this._tempBox.max);const O=(v.z+d.z)*.5;v.z=D.z=x.z=d.z=O,v.applyMatrix4(p),D.applyMatrix4(p),x.applyMatrix4(p),d.applyMatrix4(p),T.debugDrawLine(v,D,255),T.debugDrawLine(v,x,255),T.debugDrawLine(D,d,255),T.debugDrawLine(x,d,255)}let N=999;if(u&&r.lastScreenCoverage>0){for(let p=0;p<u.length;p++)if(u[p].density/r.lastScreenCoverage<n){N=p;break}}N<i&&(i=N)}if(o.mesh_lod=i,h)if(r.lastLodLevel_Texture<0){if(o.texture_lod=y.max_count-1,F){const w=y.lods[y.max_count-1];F&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,g=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=y.lods.length-1;S>=0;S--){const m=y.lods[S];if(m.max_height>g){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&F&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${m.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${g.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 Te{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 ue=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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(a=>a.toString()=="Symbol(renderer)"),i=o.find(a=>a.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&i!=null&&(r=t[i])}if(e){console.log("Adding Needle LODs to modelviewer");const n=I.get(e);if(I.addPlugin(new Ee(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 Ee{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[K]==!0)return;r[K]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(a){var u,l,y;if(a[K]==!0)return;a[K]=!0,a.userData&&(a.userData.LOD=-1);const h=Object.keys(a);for(let f=0;f<h.length;f++){const w=h[f],g=a[w];if(g?.isTexture===!0){const S=(l=(u=g.userData)==null?void 0:u.associations)==null?void 0:l.textures,m=n.parser.json.textures[S];if(!m){console.warn("Texture data not found for texture index "+S);continue}if((y=m?.extensions)!=null&&y[P]){const b=m.extensions[P];b&&o&&_.registerTexture(o,g,b.lods.length,S,b)}}}};const i=r.material;if(Array.isArray(i))for(const a of i)s(a);else s(i)}}tryParseMeshLOD(e,r){var n,o;if(r[ue]==!0)return;r[ue]=!0;const s=this.getUrl();if(!s)return;const i=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(i&&s){const a=r.uuid;_.registerMesh(s,a,r,0,i.lods.length,i)}}}function Ae(t,e,r,n){Q(e),Z(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ce(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,Z as addDracoAndKTX2Loaders,Q as createLoaders,ne as getRaycastMesh,ce as patchModelViewer,Oe as setDracoDecoderLocation,_e as setKTX2TranscoderLocation,ie as setRaycastMesh,Ae as useNeedleProgressive};
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)=>{L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),e.source&&(e.source[te]=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;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&&!ne(r)&&ie(r,i);for(const l of k)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class be{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 F=ee("debugprogressive"),Se=ee("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new se),c(this,"cameraFrustrum",new ve),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new De),c(this,"_tempBox",new oe),c(this,"_tempBox2",new oe),c(this,"tempMatrix",new se),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){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t){return t[le]?t[le]:new T(t)}get plugins(){return k}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;Q(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(Se||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")){F&&(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 V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;let i=r.userData.LOD_state;if(i||(i=new Te,r.userData.LOD_state=i),i.frames++<2)return;for(const l of k)(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 k)(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(F&&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),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,j=(x.x+v.x)*.5,R=(x.y+v.y)*.5;D=(D-j)*A+j,y=(y-R)*A+R,h=(h-j)*A+j,O=(O-R)*A+R;const de=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(v.x)),he=y<0&&O>0?0:Math.min(Math.abs(x.y),Math.abs(v.y)),H=Math.max(de,he);r.lastCentrality=(C-H)*(C-H)*(C-H)}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),G=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&G!=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,F&&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 N=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){N=x;break}}N<a&&(a=N)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,F){const w=g.lods[g.max_count-1];F&&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(p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&F&&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 Te{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 ue=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 Ee(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 Ee{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[K]==!0)return;r[K]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[K]==!0)return;i[K]=!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[ue]==!0)return;r[ue]=!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 Ae(t,e,r,n){Q(e),Z(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ce(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,Z as addDracoAndKTX2Loaders,Q as createLoaders,ne as getRaycastMesh,ce as patchModelViewer,Oe as setDracoDecoderLocation,_e as setKTX2TranscoderLocation,ie as setRaycastMesh,Ae as useNeedleProgressive};
@@ -1,5 +1,5 @@
1
- "use strict";var fe=Object.defineProperty;var he=(l,e,t)=>e in l?fe(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(he(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ge=require("three/examples/jsm/libs/meshopt_decoder.module.js"),pe=require("three/examples/jsm/loaders/DRACOLoader.js"),ye=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),Le=require("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(l=>{X="./include/draco/",ee="./include/ktx2/"});function xe(l){X=l}function me(l){ee=l}let $,Z,U;function te(l){$||($=new pe.DRACOLoader,$.setDecoderPath(X),$.setDecoderConfig({type:"js"})),U||(U=new ye.KTX2Loader,U.setTranscoderPath(ee)),Z||(Z=ge.MeshoptDecoder),l?U.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function re(l){l.dracoLoader||l.setDRACOLoader($),l.ktx2Loader||l.setKTX2Loader(U),l.meshoptDecoder||l.setMeshoptDecoder(Z)}function se(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function De(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}function ae(l){var e;return((e=l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function le(l,e){(l.type==="Mesh"||l.type==="SkinnedMesh")&&(l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=e)}const I=new Array,R="NEEDLE_progressive",w=se("debugprogressive"),Q=Symbol("needle-progressive-texture"),W=new Map,j=new Set;if(w){let l=function(){e+=1,console.log("Toggle LOD level",e,W),W.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),d=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,d),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,j&&j.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ie(l,e,t){var i;if(!w)return;W.has(l)||W.set(l,{keys:[],sourceId:t});const r=W.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[R];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});w&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return R}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r="LODS:minmax",i=e[r];if(i!=null)return i;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const s of e)this.getMaterialMinMaxLODsCount(s,t);return e[r]=t,t}w==="verbose"&&console.log("getMaterialMinMaxLODsCount",e);const o=s=>{const n=this.getAssignedLODInformation(s);if(n){const a=this.lodInfos.get(n.key);if(a&&a.lods){t.min_count=Math.min(t.min_count,a.lods.length),t.max_count=Math.max(t.max_count,a.lods.length);for(let d=0;d<a.lods.length;d++){const h=a.lods[d];h.width&&(t.lods[d]=t.lods[d]||{min_height:1/0,max_height:0},t.lods[d].min_height=Math.min(t.lods[d].min_height,h.height),t.lods[d].max_height=Math.max(t.lods[d].max_height,h.height))}}}};if(e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const s=e;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;(a==null?void 0:a.isTexture)===!0&&o(a)}}else if(e.isMaterial)for(const s of Object.keys(e)){const n=e[s];(n==null?void 0:n.isTexture)===!0&&o(n)}return e[r]=t,t}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,w&&ie(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else w&&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(w&&j.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 d=this.assignTextureLODForSlot(a,t,r,n);i.push(d),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 d=s[a],h=o[a];d&&d.isTexture===!0?n.push({material:r,slot:h,texture:d,level:t}):n.push({material:r,slot:h,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 w==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(w&&i&&r){const s=this.getAssignedLODInformation(e);s&&ie(r,i,s.url)}}return o}else w=="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 w&&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[R];if(s){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[R];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,d,h;const r=w=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const D=e;D.source&&D.source[Q]&&(s=D.source[Q])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let L=!1;const M=Array.isArray(s.lods);if(M&&t>=s.lods.length?L=!0:M||(L=!0),L)return this.lowresCache.get(o)}const D=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!D)return w&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const f=De(i.url,D);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const L=f+"_"+s.guid,M=this.previouslyLoaded.get(L);if(M!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${L}`);let x=await M.catch(F=>(console.error(`Error loading LOD ${t} from ${f}
2
- `,F),null)),A=!1;if(x==null||(x instanceof g.Texture&&e instanceof g.Texture?(a=x.image)!=null&&a.data||(d=x.source)!=null&&d.data?x=this.copySettings(e,x):(A=!0,this.previouslyLoaded.delete(L)):x instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((h=x.attributes.position)!=null&&h.array||(A=!0,this.previouslyLoaded.delete(L)))),!A)return x}const O=s,_=new Promise(async(x,A)=>{const F=new Le.GLTFLoader;re(F),w&&(await new Promise(p=>setTimeout(p,1e3)),r&&console.warn("Start loading (delayed) "+f,O.guid));let Y=f;if(O&&Array.isArray(O.lods)){const p=O.lods[t];p.hash&&(Y+="?v="+p.hash)}const B=await F.loadAsync(Y).catch(p=>(console.error(`Error loading LOD ${t} from ${f}
3
- `,p),null));if(!B)return null;const H=B.parser;r&&console.log("Loading finished "+f,O.guid);let y=0;if(B.parser.json.textures){let p=!1;for(const u of B.parser.json.textures){if(u!=null&&u.extensions){const m=u==null?void 0:u.extensions[R];if(m!=null&&m.guid&&m.guid===O.guid){p=!0;break}}y++}if(p){let u=await H.getDependency("texture",y);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,y,u,L),e instanceof g.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=O.guid),x(u)}else w&&console.warn("Could not find texture with guid",O.guid)}if(y=0,B.parser.json.meshes){let p=!1;for(const u of B.parser.json.meshes){if(u!=null&&u.extensions){const m=u==null?void 0:u.extensions[R];if(m!=null&&m.guid&&m.guid===O.guid){p=!0;break}}y++}if(p){const u=await H.getDependency("mesh",y),m=O;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,y,u,L),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,m.density),x(T)}else{const T=new Array;for(let C=0;C<u.children.length;C++){const G=u.children[C];if(G instanceof g.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,C,m.density),T.push(N)}}return x(T)}}}return x(null)});return this.previouslyLoaded.set(L,_),await _}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+f);const M=await new g.TextureLoader().loadAsync(f);return M?(M.guid=s.guid,M.flipY=!1,M.needsUpdate=!0,M.colorSpace=e.colorSpace,r&&console.log(s,M)):w&&console.warn("failed loading",f),M}}else w&&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 Me(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(),w&&console.warn(`Copying texture settings
1
+ "use strict";var fe=Object.defineProperty;var he=(l,e,t)=>e in l?fe(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(he(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ge=require("three/examples/jsm/libs/meshopt_decoder.module.js"),pe=require("three/examples/jsm/loaders/DRACOLoader.js"),ye=require("three/examples/jsm/loaders/KTX2Loader.js"),p=require("three"),Le=require("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(l=>{X="./include/draco/",ee="./include/ktx2/"});function xe(l){X=l}function me(l){ee=l}let $,Z,U;function te(l){$||($=new pe.DRACOLoader,$.setDecoderPath(X),$.setDecoderConfig({type:"js"})),U||(U=new ye.KTX2Loader,U.setTranscoderPath(ee)),Z||(Z=ge.MeshoptDecoder),l?U.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function re(l){l.dracoLoader||l.setDRACOLoader($),l.ktx2Loader||l.setKTX2Loader(U),l.meshoptDecoder||l.setMeshoptDecoder(Z)}function se(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function De(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}function ae(l){var e;return((e=l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof p.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function le(l,e){(l.type==="Mesh"||l.type==="SkinnedMesh")&&(l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=e)}const I=new Array,R="NEEDLE_progressive",w=se("debugprogressive"),Q=Symbol("needle-progressive-texture"),W=new Map,j=new Set;if(w){let l=function(){e+=1,console.log("Toggle LOD level",e,W),W.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,j&&j.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ie(l,e,t){var i;if(!w)return;W.has(l)||W.set(l,{keys:[],sourceId:t});const r=W.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[R];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});w&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return R}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static 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(w==="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 f=r.lodInfos.get(h.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let g=0;g<f.lods.length;g++){const d=f.lods[g];d.width&&(a.lods[g]=a.lods[g]||{min_height:1/0,max_height:0},a.lods[g].min_height=Math.min(a.lods[g].min_height,d.height),a.lods[g].max_height=Math.max(a.lods[g].max_height,d.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 p.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 p.BufferGeometry&&(e.geometry=s,w&&ie(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else w&&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 p.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(w&&j.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],f=o[a];h&&h.isTexture===!0?n.push({material:r,slot:f,texture:h,level:t}):n.push({material:r,slot:f,texture:null,level:t})}return n})}if(e instanceof p.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 w==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(w&&i&&r){const s=this.getAssignedLODInformation(e);s&&ie(r,i,s.url)}}return o}else w=="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 w&&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[R];if(s){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[R];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,f;const r=w=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const g=e;g.source&&g.source[Q]&&(s=g.source[Q])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const M=Array.isArray(s.lods);if(M&&t>=s.lods.length?x=!0:M||(x=!0),x)return this.lowresCache.get(o)}const g=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!g)return w&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const d=De(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=d+"_"+s.guid,M=this.previouslyLoaded.get(x);if(M!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let m=await M.catch(F=>(console.error(`Error loading LOD ${t} from ${d}
2
+ `,F),null)),A=!1;if(m==null||(m instanceof p.Texture&&e instanceof p.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 p.BufferGeometry&&e instanceof p.BufferGeometry&&((f=m.attributes.position)!=null&&f.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return m}const O=s,_=new Promise(async(m,A)=>{const F=new Le.GLTFLoader;re(F),w&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+d,O.guid));let Y=d;if(O&&Array.isArray(O.lods)){const y=O.lods[t];y.hash&&(Y+="?v="+y.hash)}const B=await F.loadAsync(Y).catch(y=>(console.error(`Error loading LOD ${t} from ${d}
3
+ `,y),null));if(!B)return null;const H=B.parser;r&&console.log("Loading finished "+d,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[R];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){let u=await H.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',d,L,u,x),e instanceof p.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=O.guid),m(u)}else w&&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[R];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){const u=await H.getDependency("mesh",L),D=O;if(r&&console.log(`Loaded Mesh "${u.name}"`,d,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 C=0;C<u.children.length;C++){const G=u.children[C];if(G instanceof p.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,C,D.density),T.push(N)}}return m(T)}}}return m(null)});return this.previouslyLoaded.set(x,_),await _}else if(e instanceof p.Texture){r&&console.log("Load texture from uri: "+d);const M=await new p.TextureLoader().loadAsync(d);return M?(M.guid=s.guid,M.flipY=!1,M.needsUpdate=!0,M.colorSpace=e.colorSpace,r&&console.log(s,M)):w&&console.warn("failed loading",d),M}}else w&&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 Me(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(),w&&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)=>{w&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),t.source&&(t.source[Q]=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 d;w&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;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&&!ae(r)&&le(r,n);for(const h of I)(d=h.onRegisteredNewMesh)==null||d.call(h,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Me{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=se("debugprogressive"),Oe=se("noprogressive"),oe=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[oe]?e[oe]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;te(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,d;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const h=s[0].material;(h.name==="EffectMaterial"||h.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Oe||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const h=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((d=f.geometry)==null?void 0:d.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 L=f.object;(L instanceof g.Mesh||L.isMesh)&&this.updateLODs(e,t,L,h,i)}const D=o.transparent;for(const f of D){const L=f.object;(L instanceof g.Mesh||L.isMesh)&&this.updateLODs(e,t,L,h,i)}}}updateLODs(e,t,r,i,o){var a,d;let s=r.userData.LOD_state;if(s||(s=new _e,r.userData.LOD_state=s),s.frames++<2)return;for(const h of I)(a=h.onBeforeUpdateLOD)==null||a.call(h,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 h=r["DEBUG:LOD"];h!=null&&(n=h),this.loadProgressiveTextures(r.material,n)}for(const h of I)(d=h.onAfterUpdatedLOD)==null||d.call(h,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 M;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),d=a==null?void 0:a.lods,h=d&&d.length>0,D=S.getMaterialMinMaxLODsCount(t.material),f=(D==null?void 0:D.min_count)!=1/0&&D.min_count>0&&D.max_count>0;if(!h&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(h||(n=0),!((M=this.cameraFrustrum)!=null&&M.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const L=t.geometry.boundingBox;if(L&&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 y=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(L),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 y=this._tempBox.min,p=this._tempBox.max;let u=y.x,m=y.y,T=p.x,C=p.y;const G=2,N=1.5,V=(y.x+p.x)*.5,q=(y.y+p.y)*.5;u=(u-V)*G+V,m=(m-q)*G+q,T=(T-V)*G+V,C=(C-q)*G+q;const ue=u<0&&T>0?0:Math.min(Math.abs(y.x),Math.abs(p.x)),de=m<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(p.y)),J=Math.max(ue,de);r.lastCentrality=(N-J)*(N-J)*(N-J)}else r.lastCentrality=1;const _=this._tempBox.getSize(this._tempBoxSize);_.multiplyScalar(.5),screen.availHeight>0&&_.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),_.x*=O.aspect;const k=e.matrixWorldInverse,x=this._tempBox2;x.copy(L),x.applyMatrix4(t.matrixWorld),x.applyMatrix4(k);const A=x.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(_.x,_.y)!=0&&F!=0&&(_.z=A.z/Math.max(A.x,A.y)*Math.max(_.x,_.y)),r.lastScreenCoverage=Math.max(_.x,_.y,_.z),r.lastScreenspaceVolume.copy(_),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const p=b.corner0,u=b.corner1,m=b.corner2,T=b.corner3;p.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=p.x,m.copy(this._tempBox.max),m.y=p.y,T.copy(this._tempBox.max);const C=(p.z+T.z)*.5;p.z=u.z=m.z=T.z=C,p.applyMatrix4(y),u.applyMatrix4(y),m.applyMatrix4(y),T.applyMatrix4(y),b.debugDrawLine(p,u,255),b.debugDrawLine(p,m,255),b.debugDrawLine(u,T,255),b.debugDrawLine(m,T,255)}let B=999;if(d&&r.lastScreenCoverage>0){for(let y=0;y<d.length;y++)if(d[y].density/r.lastScreenCoverage<i){B=y;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=D.max_count-1,z){const O=D.lods[D.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 x=D.lods.length-1;x>=0;x--){const A=D.lods[x];if(A.max_height>k){o.texture_lod=x,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 _e{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 ne=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 we(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 we{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[K]==!0)return;t[K]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var d,h,D;if(n[K]==!0)return;n[K]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const L=a[f],M=n[L];if((M==null?void 0:M.isTexture)===!0){const O=(h=(d=M.userData)==null?void 0:d.associations)==null?void 0:h.textures,_=r.parser.json.textures[O];if(!_){console.warn("Texture data not found for texture index "+O);continue}if((D=_==null?void 0:_.extensions)!=null&&D[R]){const k=_.extensions[R];k&&i&&S.registerTexture(i,M,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[ne]==!0)return;t[ne]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function ve(l,e,t,r){te(e),re(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",()=>{ce(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=re;exports.createLoaders=te;exports.getRaycastMesh=ae;exports.patchModelViewer=ce;exports.setDracoDecoderLocation=xe;exports.setKTX2TranscoderLocation=me;exports.setRaycastMesh=le;exports.useNeedleProgressive=ve;
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)=>{w&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),t.source&&(t.source[Q]=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;w&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;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&&!ae(r)&&le(r,n);for(const f of I)(h=f.onRegisteredNewMesh)==null||h.call(f,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Me{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=se("debugprogressive"),Oe=se("noprogressive"),oe=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new p.Matrix4);c(this,"cameraFrustrum",new p.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new p.Sphere);c(this,"_tempBox",new p.Box3);c(this,"_tempBox2",new p.Box3);c(this,"tempMatrix",new p.Matrix4);c(this,"_tempWorldPosition",new p.Vector3);c(this,"_tempBoxSize",new p.Vector3);c(this,"_tempBox2Size",new p.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[oe]?e[oe]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;te(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 f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Oe||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const d of s){if(d.material&&(((a=d.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=d.geometry)==null?void 0:h.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){z&&(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 x=d.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,f,i)}const g=o.transparent;for(const d of g){const x=d.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,f,i)}}}updateLODs(e,t,r,i,o){var a,h;let s=r.userData.LOD_state;if(s||(s=new _e,r.userData.LOD_state=s),s.frames++<2)return;for(const f of I)(a=f.onBeforeUpdateLOD)==null||a.call(f,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 f=r["DEBUG:LOD"];f!=null&&(n=f),this.loadProgressiveTextures(r.material,n)}for(const f of I)(h=f.onAfterUpdatedLOD)==null||h.call(f,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 M;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,f=h&&h.length>0,g=S.getMaterialMinMaxLODsCount(t.material),d=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(f||(n=0),!((M=this.cameraFrustrum)!=null&&M.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),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,C=y.y;const G=2,N=1.5,V=(L.x+y.x)*.5,q=(L.y+y.y)*.5;u=(u-V)*G+V,D=(D-q)*G+q,T=(T-V)*G+V,C=(C-q)*G+q;const ue=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),de=D<0&&C>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),J=Math.max(ue,de);r.lastCentrality=(N-J)*(N-J)*(N-J)}else r.lastCentrality=1;const _=this._tempBox.getSize(this._tempBoxSize);_.multiplyScalar(.5),screen.availHeight>0&&_.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),_.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(_.x,_.y)!=0&&F!=0&&(_.z=A.z/Math.max(A.x,A.y)*Math.max(_.x,_.y)),r.lastScreenCoverage=Math.max(_.x,_.y,_.z),r.lastScreenspaceVolume.copy(_),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 C=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=C,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,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,z){const O=g.lods[g.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=g.lods.length-1;m>=0;m--){const A=g.lods[m];if(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 p.Vector3),c(P,"corner1",new p.Vector3),c(P,"corner2",new p.Vector3),c(P,"corner3",new p.Vector3),c(P,"_tempPtInside",new p.Vector3);class _e{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new p.Vector3);c(this,"lastCentrality",0)}}const ne=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 we(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 we{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[K]==!0)return;t[K]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,f,g;if(n[K]==!0)return;n[K]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let d=0;d<a.length;d++){const x=a[d],M=n[x];if((M==null?void 0:M.isTexture)===!0){const O=(f=(h=M.userData)==null?void 0:h.associations)==null?void 0:f.textures,_=r.parser.json.textures[O];if(!_){console.warn("Texture data not found for texture index "+O);continue}if((g=_==null?void 0:_.extensions)!=null&&g[R]){const k=_.extensions[R];k&&i&&S.registerTexture(i,M,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[ne]==!0)return;t[ne]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function ve(l,e,t,r){te(e),re(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",()=>{ce(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=re;exports.createLoaders=te;exports.getRaycastMesh=ae;exports.patchModelViewer=ce;exports.setDracoDecoderLocation=xe;exports.setKTX2TranscoderLocation=me;exports.setRaycastMesh=le;exports.useNeedleProgressive=ve;
package/lib/extension.js CHANGED
@@ -96,6 +96,7 @@ export class NEEDLE_progressive {
96
96
  return null;
97
97
  }
98
98
  static getMaterialMinMaxLODsCount(material, minmax) {
99
+ const self = this;
99
100
  // we can cache this material min max data because it wont change at runtime
100
101
  const cacheKey = "LODS:minmax";
101
102
  const cached = material[cacheKey];
@@ -117,30 +118,12 @@ export class NEEDLE_progressive {
117
118
  }
118
119
  if (debug === "verbose")
119
120
  console.log("getMaterialMinMaxLODsCount", material);
120
- const processTexture = (tex) => {
121
- const info = this.getAssignedLODInformation(tex);
122
- if (info) {
123
- const model = this.lodInfos.get(info.key);
124
- if (model && model.lods) {
125
- minmax.min_count = Math.min(minmax.min_count, model.lods.length);
126
- minmax.max_count = Math.max(minmax.max_count, model.lods.length);
127
- for (let i = 0; i < model.lods.length; i++) {
128
- const lod = model.lods[i];
129
- if (lod.width) {
130
- minmax.lods[i] = minmax.lods[i] || { min_height: Infinity, max_height: 0 };
131
- minmax.lods[i].min_height = Math.min(minmax.lods[i].min_height, lod.height);
132
- minmax.lods[i].max_height = Math.max(minmax.lods[i].max_height, lod.height);
133
- }
134
- }
135
- }
136
- }
137
- };
138
121
  if (material.type === "ShaderMaterial" || material.type === "RawShaderMaterial") {
139
122
  const mat = material;
140
123
  for (const slot of Object.keys(mat.uniforms)) {
141
124
  const val = mat.uniforms[slot].value;
142
125
  if (val?.isTexture === true) {
143
- processTexture(val);
126
+ processTexture(val, minmax);
144
127
  }
145
128
  }
146
129
  }
@@ -148,12 +131,30 @@ export class NEEDLE_progressive {
148
131
  for (const slot of Object.keys(material)) {
149
132
  const val = material[slot];
150
133
  if (val?.isTexture === true) {
151
- processTexture(val);
134
+ processTexture(val, minmax);
152
135
  }
153
136
  }
154
137
  }
155
138
  material[cacheKey] = minmax;
156
139
  return minmax;
140
+ function processTexture(tex, minmax) {
141
+ const info = self.getAssignedLODInformation(tex);
142
+ if (info) {
143
+ const model = self.lodInfos.get(info.key);
144
+ if (model && model.lods) {
145
+ minmax.min_count = Math.min(minmax.min_count, model.lods.length);
146
+ minmax.max_count = Math.max(minmax.max_count, model.lods.length);
147
+ for (let i = 0; i < model.lods.length; i++) {
148
+ const lod = model.lods[i];
149
+ if (lod.width) {
150
+ minmax.lods[i] = minmax.lods[i] || { min_height: Infinity, max_height: 0 };
151
+ minmax.lods[i].min_height = Math.min(minmax.lods[i].min_height, lod.height);
152
+ minmax.lods[i].max_height = Math.max(minmax.lods[i].max_height, lod.height);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
157
158
  }
158
159
  /** Check if a LOD level is available for a mesh or a texture
159
160
  * @param obj the mesh or texture to check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "1.2.0-alpha",
3
+ "version": "1.2.0-alpha.1",
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": {