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

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.
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "react-typescript",
3
+ "version": "1.0.0",
4
+ "main": "src/index.tsx",
5
+ "dependencies": {
6
+ "@needle-tools/gltf-progressive": "file:../..",
7
+ "react": "^18.0.0",
8
+ "react-dom": "^18.0.0",
9
+ "@react-three/drei": "^9.0.1",
10
+ "@react-three/fiber": "^8.0.6",
11
+ "three": "0.162.0",
12
+ "typescript": "4.7.4"
13
+ },
14
+ "devDependencies": {
15
+ "@types/react": "18.0.15",
16
+ "@types/react-dom": "17.0.0",
17
+ "@types/three": "0.162.0",
18
+ "typescript": "4.1.3",
19
+ "@vitejs/plugin-basic-ssl": "^1.0.1",
20
+ "vite": "<= 4.3.9",
21
+ "@vitejs/plugin-react": "^1.3.0"
22
+ },
23
+ "scripts": {
24
+ "start": "vite --host",
25
+ "build": "react-scripts build",
26
+ "test": "react-scripts test --env=jsdom",
27
+ "eject": "react-scripts eject"
28
+ },
29
+ "browserslist": [
30
+ ">0.2%",
31
+ "not dead",
32
+ "not ie <= 11",
33
+ "not op_mini all"
34
+ ]
35
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "jsx": "react",
4
+ "target": "ESNext",
5
+ "useDefineForClassFields": true,
6
+ "module": "ESNext",
7
+ "lib": ["ESNext", "DOM"],
8
+ "moduleResolution": "Node",
9
+ "strict": true,
10
+ "sourceMap": true,
11
+ "resolveJsonModule": true,
12
+ "esModuleInterop": true,
13
+ "noEmit": true,
14
+ "noUnusedLocals": false,
15
+ "noUnusedParameters": true,
16
+ "noImplicitReturns": true,
17
+ "noImplicitAny": false,
18
+ "experimentalDecorators": true,
19
+ "skipLibCheck": true
20
+ },
21
+ "include": ["./src"]
22
+ }
@@ -0,0 +1,44 @@
1
+ import * as path from 'path';
2
+ import { defineConfig } from 'vite';
3
+ import react from '@vitejs/plugin-react';
4
+ import basicSsl from '@vitejs/plugin-basic-ssl'
5
+
6
+ export default defineConfig(async (command) => {
7
+
8
+
9
+ return {
10
+ base: "./",
11
+ assetsInclude: ['*'],
12
+
13
+ plugins: [
14
+ react(),
15
+ basicSsl(),
16
+ ],
17
+
18
+ server: {
19
+ https: true,
20
+ proxy: { // workaround: specifying a proxy skips HTTP2 which is currently problematic in Vite since it causes session memory timeouts.
21
+ 'https://localhost:3000': 'https://localhost:3000'
22
+ },
23
+ watch: {
24
+ awaitWriteFinish: {
25
+ stabilityThreshold: 500,
26
+ pollInterval: 1000
27
+ },
28
+ },
29
+ strictPort: true,
30
+ port: 3001
31
+ },
32
+ build: {
33
+ outDir: "./dist",
34
+ emptyOutDir: true,
35
+ keepNames: true,
36
+ },
37
+ resolve: {
38
+ alias: {
39
+ 'react': () => path.resolve(__dirname, 'node_modules/react'),
40
+ '@react-three/fiber': () => path.resolve(__dirname, 'node_modules/@react-three/fiber'),
41
+ }
42
+ }
43
+ }
44
+ });
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>My first three.js app</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ }
11
+ </style>
12
+ <script type="importmap">
13
+ {
14
+ "imports": {
15
+ "three": "https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js",
16
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@latest/examples/jsm/",
17
+ "three/examples/": "https://cdn.jsdelivr.net/npm/three@latest/examples/",
18
+ "@needle-engine/gltf-progressive": "https://www.unpkg.com/@needle-tools/gltf-progressive@latest"
19
+ }
20
+ }
21
+ </script>
22
+ </head>
23
+
24
+ <body>
25
+ <script type="module" src="./main.js"></script>
26
+ <button class="show-source">Show Source</button>
27
+ </body>
28
+
29
+
30
+ <style>
31
+ .show-source {
32
+ position: fixed;
33
+ right: 1rem;
34
+ bottom: 1rem;
35
+ z-index: 100;
36
+ border-radius: .5rem;
37
+ border: none;
38
+ padding: .3rem .5rem;
39
+ }
40
+ </style>
41
+ <script>
42
+ document.addEventListener("DOMContentLoaded", () => {
43
+ document.querySelector('.show-source').addEventListener('click', () => {
44
+ const scriptSource = document.querySelector('script[type="module"]').src;
45
+ console.log(scriptSource);
46
+ window.open(scriptSource);
47
+ });
48
+ });
49
+ </script>
50
+
51
+ </html>
@@ -0,0 +1,76 @@
1
+ import * as THREE from 'three';
2
+ import { EXRLoader } from 'three/addons/loaders/EXRLoader.js';
3
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
4
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
5
+ import { useNeedleProgressive, } from "@needle-engine/gltf-progressive"
6
+
7
+ const scene = new THREE.Scene();
8
+ scene.background = new THREE.Color(0x555555);
9
+ const renderer = new THREE.WebGLRenderer();
10
+ renderer.setSize(window.innerWidth, window.innerHeight);
11
+ document.body.appendChild(renderer.domElement);
12
+
13
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
14
+
15
+
16
+ window.addEventListener('resize', () => {
17
+ renderer.setSize(window.innerWidth, window.innerHeight);
18
+ camera.aspect = window.innerWidth / window.innerHeight;
19
+ camera.updateProjectionMatrix();
20
+ });
21
+
22
+ const orbit = new OrbitControls(camera, renderer.domElement);
23
+ orbit.target = new THREE.Vector3(0, .6, 0);
24
+ camera.position.x = -1;
25
+ camera.position.y = 1.5;
26
+ camera.position.z = 1.8;
27
+
28
+ const grid = new THREE.GridHelper(10, 10, 0x444444, 0x666666);
29
+ scene.add(grid);
30
+
31
+ const directionalLight = new THREE.DirectionalLight(0xffffff, .2);
32
+ directionalLight.position.set(1, 1, 0);
33
+ scene.add(directionalLight);
34
+
35
+
36
+ // Animate the scene
37
+ function animate() {
38
+ requestAnimationFrame(animate);
39
+ orbit.update();
40
+ renderer.render(scene, camera);
41
+ }
42
+ animate();
43
+
44
+ const environmentTextureUrl = "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/studio_small_09_1k.exr";
45
+ const pmremGenerator = new THREE.PMREMGenerator(renderer);
46
+ pmremGenerator.compileEquirectangularShader();
47
+ new EXRLoader().load(environmentTextureUrl, texture => {
48
+ const envMap = pmremGenerator.fromEquirectangular(texture).texture;
49
+ scene.environment = envMap;
50
+ texture.dispose();
51
+ pmremGenerator.dispose();
52
+ });
53
+
54
+
55
+
56
+
57
+ // Integrate @needle-tools/gltf-progressive
58
+ // This is the model we want to load
59
+ const url = "https://engine.needle.tools/demos/gltf-progressive/threejs/assets/model.glb";
60
+
61
+ const gltfLoader = new GLTFLoader();
62
+
63
+ /**
64
+ * Call this method to register the progressive loader
65
+ */
66
+ useNeedleProgressive(url, renderer, gltfLoader)
67
+
68
+ // just call the load method as usual
69
+ gltfLoader.load(url, gltf => {
70
+ console.log(gltf)
71
+ scene.add(gltf.scene)
72
+ gltf.scene.position.y += .95;
73
+ })
74
+
75
+
76
+
@@ -1,7 +1,7 @@
1
1
  var le = Object.defineProperty;
2
2
  var ue = (l, e, t) => e in l ? le(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
3
  var c = (l, e, t) => (ue(l, typeof e != "symbol" ? e + "" : e, t), t);
4
- import { Mesh as q, BufferGeometry as V, Material as ce, Texture as U, TextureLoader as fe, Matrix4 as te, Frustum as de, Sphere as ge, Box3 as re, Vector3 as C } from "three";
4
+ import { Mesh as q, BufferGeometry as Y, Material as ce, Texture as I, TextureLoader as fe, Matrix4 as te, Frustum as de, Sphere as ge, Box3 as re, Vector3 as C } from "three";
5
5
  import { GLTFLoader as he } from "three/examples/jsm/loaders/GLTFLoader.js";
6
6
  import { MeshoptDecoder as pe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
7
7
  import { DRACOLoader as ye } from "three/examples/jsm/loaders/DRACOLoader.js";
@@ -16,12 +16,12 @@ function _e(l) {
16
16
  function Be(l) {
17
17
  j = l;
18
18
  }
19
- let F, J, W;
19
+ let U, J, W;
20
20
  function ne(l) {
21
- F || (F = new ye(), F.setDecoderPath(K), F.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(j)), J || (J = pe), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
21
+ U || (U = new ye(), U.setDecoderPath(K), U.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(j)), J || (J = pe), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
22
22
  }
23
23
  function oe(l) {
24
- l.dracoLoader || l.setDRACOLoader(F), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(J);
24
+ l.dracoLoader || l.setDRACOLoader(U), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(J);
25
25
  }
26
26
  function ee(l) {
27
27
  const t = new URL(window.location.href).searchParams.get(l);
@@ -43,7 +43,7 @@ const Q = new Array();
43
43
  function ke(l) {
44
44
  Q.push(l);
45
45
  }
46
- const R = "NEEDLE_progressive", S = ee("debugprogressive"), Y = Symbol("needle-progressive-texture"), z = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
46
+ const R = "NEEDLE_progressive", S = ee("debugprogressive"), V = Symbol("needle-progressive-texture"), z = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
47
47
  if (S) {
48
48
  let l = function() {
49
49
  e += 1, console.log("Toggle LOD level", e, z), z.forEach((i, n) => {
@@ -146,7 +146,7 @@ const M = class {
146
146
  const o = n.index || 0;
147
147
  s = s[o];
148
148
  }
149
- s && i != s && s instanceof V && (e.geometry = s, S && se(e, "geometry", n.url));
149
+ s && i != s && s instanceof Y && (e.geometry = s, S && se(e, "geometry", n.url));
150
150
  }
151
151
  return s;
152
152
  }).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
@@ -192,7 +192,7 @@ const M = class {
192
192
  return o;
193
193
  });
194
194
  }
195
- if (e instanceof U || e.isTexture === !0) {
195
+ if (e instanceof I || e.isTexture === !0) {
196
196
  const r = e;
197
197
  return this.assignTextureLODForSlot(r, t, null, null);
198
198
  }
@@ -249,7 +249,7 @@ const M = class {
249
249
  let s;
250
250
  if (e.isTexture === !0) {
251
251
  const f = e;
252
- f.source && f.source[Y] && (s = f.source[Y]);
252
+ f.source && f.source[V] && (s = f.source[V]);
253
253
  }
254
254
  if (s || (s = M.lodInfos.get(n)), s) {
255
255
  if (t > 0) {
@@ -268,67 +268,67 @@ const M = class {
268
268
  const u = p + "_" + s.guid, h = this.previouslyLoaded.get(u);
269
269
  if (h !== void 0) {
270
270
  r && console.log(`LOD ${t} was already loading/loaded: ${u}`);
271
- let x = await h.catch((I) => (console.error(`Error loading LOD ${t} from ${p}
272
- `, I), null)), k = !1;
273
- if (x == null || (x instanceof U && e instanceof U ? (o = x.image) != null && o.data || (a = x.source) != null && a.data ? x = this.copySettings(e, x) : (k = !0, this.previouslyLoaded.delete(u)) : x instanceof V && e instanceof V && ((g = x.attributes.position) != null && g.array || (k = !0, this.previouslyLoaded.delete(u)))), !k)
271
+ let x = await h.catch((F) => (console.error(`Error loading LOD ${t} from ${p}
272
+ `, F), null)), k = !1;
273
+ if (x == null || (x instanceof I && e instanceof I ? (o = x.image) != null && o.data || (a = x.source) != null && a.data ? x = this.copySettings(e, x) : (k = !0, this.previouslyLoaded.delete(u)) : x instanceof Y && e instanceof Y && ((g = x.attributes.position) != null && g.array || (k = !0, this.previouslyLoaded.delete(u)))), !k)
274
274
  return x;
275
275
  }
276
276
  const D = s, A = new Promise(async (x, k) => {
277
- const I = new he();
278
- oe(I), S && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, D.guid));
277
+ const F = new he();
278
+ oe(F), S && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, D.guid));
279
279
  let L = p;
280
280
  if (D && Array.isArray(D.lods)) {
281
281
  const m = D.lods[t];
282
282
  m.hash && (L += "?v=" + m.hash);
283
283
  }
284
- const y = await I.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
284
+ const y = await F.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
285
285
  `, m), null));
286
286
  if (!y)
287
287
  return null;
288
288
  const T = y.parser;
289
289
  r && console.log("Loading finished " + p, D.guid);
290
- let O = 0;
290
+ let w = 0;
291
291
  if (y.parser.json.textures) {
292
292
  let m = !1;
293
293
  for (const d of y.parser.json.textures) {
294
294
  if (d != null && d.extensions) {
295
- const w = d == null ? void 0 : d.extensions[R];
296
- if (w != null && w.guid && w.guid === D.guid) {
295
+ const O = d == null ? void 0 : d.extensions[R];
296
+ if (O != null && O.guid && O.guid === D.guid) {
297
297
  m = !0;
298
298
  break;
299
299
  }
300
300
  }
301
- O++;
301
+ w++;
302
302
  }
303
303
  if (m) {
304
- let d = await T.getDependency("texture", O);
305
- return r && console.log('change "' + e.name + '" → "' + d.name + '"', p, O, d, u), e instanceof U && (d = this.copySettings(e, d)), d && (d.guid = D.guid), x(d);
304
+ let d = await T.getDependency("texture", w);
305
+ return r && console.log('change "' + e.name + '" → "' + d.name + '"', p, w, d, u), e instanceof I && (d = this.copySettings(e, d)), d && (d.guid = D.guid), x(d);
306
306
  }
307
307
  }
308
- if (O = 0, y.parser.json.meshes) {
308
+ if (w = 0, y.parser.json.meshes) {
309
309
  let m = !1;
310
310
  for (const d of y.parser.json.meshes) {
311
311
  if (d != null && d.extensions) {
312
- const w = d == null ? void 0 : d.extensions[R];
313
- if (w != null && w.guid && w.guid === D.guid) {
312
+ const O = d == null ? void 0 : d.extensions[R];
313
+ if (O != null && O.guid && O.guid === D.guid) {
314
314
  m = !0;
315
315
  break;
316
316
  }
317
317
  }
318
- O++;
318
+ w++;
319
319
  }
320
320
  if (m) {
321
- const d = await T.getDependency("mesh", O), w = D;
322
- if (r && console.log(`Loaded Mesh "${d.name}"`, p, O, d, u), d.isMesh === !0) {
321
+ const d = await T.getDependency("mesh", w), O = D;
322
+ if (r && console.log(`Loaded Mesh "${d.name}"`, p, w, d, u), d.isMesh === !0) {
323
323
  const P = d.geometry;
324
- return M.assignLODInformation(i.url, P, n, t, void 0, w.density), x(P);
324
+ return M.assignLODInformation(i.url, P, n, t, void 0, O.density), x(P);
325
325
  } else {
326
326
  const P = new Array();
327
327
  for (let _ = 0; _ < d.children.length; _++) {
328
328
  const E = d.children[_];
329
329
  if (E instanceof q) {
330
330
  const N = E.geometry;
331
- M.assignLODInformation(i.url, N, n, t, _, w.density), P.push(N);
331
+ M.assignLODInformation(i.url, N, n, t, _, O.density), P.push(N);
332
332
  }
333
333
  }
334
334
  return x(P);
@@ -338,7 +338,7 @@ const M = class {
338
338
  return x(null);
339
339
  });
340
340
  return this.previouslyLoaded.set(u, A), await A;
341
- } else if (e instanceof U) {
341
+ } else if (e instanceof I) {
342
342
  r && console.log("Load texture from uri: " + p);
343
343
  const h = await new fe().loadAsync(p);
344
344
  return h ? (h.guid = s.guid, h.flipY = !1, h.needsUpdate = !0, h.colorSpace = e.colorSpace, r && console.log(s, h)) : S && console.warn("failed loading", p), h;
@@ -360,7 +360,7 @@ const M = class {
360
360
  }
361
361
  static copySettings(e, t) {
362
362
  const r = this._copiedTextures.get(e);
363
- return r || (t = t.clone(), this._copiedTextures.set(e, t), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t);
363
+ return r || (t = t.clone(), this._copiedTextures.set(e, t), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t.magFilter = e.magFilter, t.minFilter = e.minFilter, t.wrapS = e.wrapS, t.wrapT = e.wrapT, t.flipY = e.flipY, t.anisotropy = e.anisotropy, t.generateMipmaps = e.generateMipmaps, t);
364
364
  }
365
365
  };
366
366
  let v = M;
@@ -368,7 +368,7 @@ let v = M;
368
368
  * Register a texture with LOD information
369
369
  */
370
370
  c(v, "registerTexture", (e, t, r, i) => {
371
- S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[Y] = i);
371
+ S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[V] = i);
372
372
  const n = i.guid;
373
373
  M.assignLODInformation(e, t, n, 0, 0, void 0), M.lodInfos.set(n, i), M.lowresCache.set(n, t);
374
374
  }), /**
@@ -486,7 +486,7 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
486
486
  for (const f of this.plugins)
487
487
  (a = f.onBeforeUpdateLOD) == null || a.call(f, this.renderer, e, t, r);
488
488
  let n = r.userData.LOD_state;
489
- n || (n = new Oe(), r.userData.LOD_state = n);
489
+ n || (n = new we(), r.userData.LOD_state = n);
490
490
  let s = this.calculateLodLevel(t, r, n, i);
491
491
  s = Math.round(s), s >= 0 && this.loadProgressiveMeshes(r, s);
492
492
  let o = 0;
@@ -548,10 +548,10 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
548
548
  }
549
549
  if (this._tempBox.copy(f), this._tempBox.applyMatrix4(t.matrixWorld), this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
550
550
  const L = this._tempBox.min, y = this._tempBox.max;
551
- let T = L.x, O = L.y, m = y.x, d = y.y;
552
- const w = 2, P = 1.5, _ = (L.x + y.x) * 0.5, E = (L.y + y.y) * 0.5;
553
- T = (T - _) * w + _, O = (O - E) * w + E, m = (m - _) * w + _, d = (d - E) * w + E;
554
- const N = T < 0 && m > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(y.x)), ae = O < 0 && d > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(y.y)), X = Math.max(N, ae);
551
+ let T = L.x, w = L.y, m = y.x, d = y.y;
552
+ const O = 2, P = 1.5, _ = (L.x + y.x) * 0.5, E = (L.y + y.y) * 0.5;
553
+ T = (T - _) * O + _, w = (w - E) * O + E, m = (m - _) * O + _, d = (d - E) * O + E;
554
+ const N = T < 0 && m > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(y.x)), ae = w < 0 && d > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(y.y)), X = Math.max(N, ae);
555
555
  r.lastCentrality = (P - X) * (P - X) * (P - X);
556
556
  } else
557
557
  r.lastCentrality = 1;
@@ -563,10 +563,10 @@ const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
563
563
  if (Math.max(u.x, u.y) != 0 && G != 0 && (u.z = A.z / Math.max(A.x, A.y) * Math.max(u.x, u.y)), r.lastScreenCoverage = Math.max(u.x, u.y, u.z), r.lastScreenspaceVolume.copy(u), r.lastScreenCoverage *= r.lastCentrality, H && b.debugDrawLine) {
564
564
  const L = this.tempMatrix.copy(this.projectionScreenMatrix);
565
565
  L.invert();
566
- const y = b.corner0, T = b.corner1, O = b.corner2, m = b.corner3;
567
- y.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = y.x, O.copy(this._tempBox.max), O.y = y.y, m.copy(this._tempBox.max);
566
+ const y = b.corner0, T = b.corner1, w = b.corner2, m = b.corner3;
567
+ y.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = y.x, w.copy(this._tempBox.max), w.y = y.y, m.copy(this._tempBox.max);
568
568
  const d = (y.z + m.z) * 0.5;
569
- y.z = T.z = O.z = m.z = d, y.applyMatrix4(L), T.applyMatrix4(L), O.applyMatrix4(L), m.applyMatrix4(L), b.debugDrawLine(y, T, 255), b.debugDrawLine(y, O, 255), b.debugDrawLine(T, m, 255), b.debugDrawLine(O, m, 255);
569
+ y.z = T.z = w.z = m.z = d, y.applyMatrix4(L), T.applyMatrix4(L), w.applyMatrix4(L), m.applyMatrix4(L), b.debugDrawLine(y, T, 255), b.debugDrawLine(y, w, 255), b.debugDrawLine(T, m, 255), b.debugDrawLine(w, m, 255);
570
570
  }
571
571
  let k = 999;
572
572
  if (g && r.lastScreenCoverage > 0) {
@@ -586,7 +586,7 @@ let B = b;
586
586
  /** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
587
587
  */
588
588
  c(B, "debugDrawLine"), c(B, "corner0", new C()), c(B, "corner1", new C()), c(B, "corner2", new C()), c(B, "corner3", new C());
589
- class Oe {
589
+ class we {
590
590
  constructor() {
591
591
  c(this, "lastLodLevel", 0);
592
592
  c(this, "lastScreenCoverage", 0);
@@ -595,7 +595,7 @@ class Oe {
595
595
  }
596
596
  }
597
597
  const ie = Symbol("NEEDLE_mesh_lod"), $ = Symbol("NEEDLE_texture_lod");
598
- function we(l) {
598
+ function Oe(l) {
599
599
  if (!l)
600
600
  return null;
601
601
  let e = null, t = null;
@@ -684,13 +684,15 @@ function Ce(l, e, t, r) {
684
684
  return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
685
685
  }
686
686
  document.addEventListener("DOMContentLoaded", () => {
687
- we(document.querySelector("model-viewer"));
687
+ Oe(document.querySelector("model-viewer"));
688
688
  });
689
689
  export {
690
690
  R as EXTENSION_NAME,
691
691
  B as LODsManager,
692
692
  v as NEEDLE_progressive,
693
- we as patchModelViewer,
693
+ oe as addDracoAndKTX2Loaders,
694
+ ne as createLoaders,
695
+ Oe as patchModelViewer,
694
696
  ke as registerPlugin,
695
697
  _e as setDracoDecoderLocation,
696
698
  Be as setKTX2TranscoderLocation,
@@ -1,3 +1,3 @@
1
- var ne=Object.defineProperty,ie=(r,e,t)=>e in r?ne(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,c=(r,e,t)=>(ie(r,typeof e!="symbol"?e+"":e,t),t);import{Mesh as U,BufferGeometry as $,Material as ae,Texture as C,TextureLoader as le,Matrix4 as Q,Frustum as ue,Sphere as ce,Box3 as Z,Vector3 as B}from"three";import{GLTFLoader as de}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as he}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as fe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ge}from"three/examples/jsm/loaders/KTX2Loader.js";let z="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",q="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(z+"draco_decoder.js",{method:"head"}).catch(r=>{z="./include/draco/",q="./include/ktx2/"});function me(r){z=r}function pe(r){q=r}let R,V,G;function ee(r){R||(R=new fe,R.setDecoderPath(z),R.setDecoderConfig({type:"js"})),G||(G=new ge,G.setTranscoderPath(q)),V||(V=he),r?G.detectSupport(r):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function re(r){r.dracoLoader||r.setDRACOLoader(R),r.ktx2Loader||r.setKTX2Loader(G),r.meshoptDecoder||r.setMeshoptDecoder(V)}function X(r){const e=new URL(window.location.href).searchParams.get(r);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function ye(r,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||r===void 0)return e;const t=r.lastIndexOf("/");if(t>=0){const o=r.substring(0,t+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}const K=new Array;function Le(r){K.push(r)}const P="NEEDLE_progressive",v=X("debugprogressive"),H=Symbol("needle-progressive-texture"),N=new Map,Y=new Set;if(v){let r=function(){e+=1,console.log("Toggle LOD level",e,N),N.forEach((n,s)=>{for(const a of n.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=w.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,d),l&&(t=Math.max(t,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,o=!1;window.addEventListener("keyup",n=>{n.key==="p"&&r(),n.key==="w"&&(o=!o,Y&&Y.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=o)}))})}function te(r,e,t){var o;if(!v)return;N.has(r)||N.set(r,{keys:[],sourceId:t});const n=N.get(r);((o=n?.keys)==null?void 0:o.includes(e))==!1&&n.keys.push(e)}const O=class{constructor(r,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=r,this.url=e}get name(){return P}static getMeshLODInformation(r){const e=this.getAssignedLODInformation(r);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(r,e){var t;if(r.isMaterial===!0){for(const s of Object.keys(r)){const a=r[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(r.isGroup===!0){for(const s of r.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let o,n;if(r.isMesh?o=r.geometry:(r.isBufferGeometry||r.isTexture)&&(o=r),o&&(t=o?.userData)!=null&&t.LODS){const s=o.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(r,e){var t;if(!r)return Promise.resolve(null);if(r instanceof U||r.isMesh===!0){const o=r.geometry,n=this.getAssignedLODInformation(o);if(!n)return Promise.resolve(null);for(const s of K)(t=s.onBeforeGetLODMesh)==null||t.call(s,r,e);return r["LOD:requested level"]=e,O.getOrLoadLOD(o,e).then(s=>{if(r["LOD:requested level"]===e){if(delete r["LOD:requested level"],Array.isArray(s)){const a=n.index||0;s=s[a]}s&&o!=s&&s instanceof $&&(r.geometry=s,v&&te(r,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",r,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",r);return Promise.resolve(null)}static assignTextureLOD(r,e=0){if(!r)return Promise.resolve(null);if(r instanceof ae||r.isMaterial===!0){const t=r,o=[],n=new Array;if(v&&Y.add(t),t.uniforms&&t.isRawShaderMaterial||t.isShaderMaterial===!0){const s=t;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,t,a);o.push(l),n.push(a)}}}else for(const s of Object.keys(t)){const a=t[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,t,s);o.push(i),n.push(s)}}return Promise.all(o).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=n[i];l&&l.isTexture===!0?a.push({material:t,slot:d,texture:l,level:e}):a.push({material:t,slot:d,texture:null,level:e})}return a})}if(r instanceof C||r.isTexture===!0){const t=r;return this.assignTextureLODForSlot(t,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(r,e,t,o){return r?.isTexture!==!0?Promise.resolve(null):O.getOrLoadLOD(r,e).then(n=>{if(Array.isArray(n))return null;if(n?.isTexture===!0){if(n!=r&&(t&&o&&(t[o]=n),v&&o&&t)){const s=this.getAssignedLODInformation(r);s&&te(t,o,s.url)}return n}else v=="verbose"&&console.warn("No LOD found for",r,e);return null}).catch(n=>(console.error("Error loading LOD",r,n),null))}afterRoot(r){var e,t;return v&&console.log("AFTER",this.url,r),(e=this.parser.json.textures)==null||e.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===n&&(a=!0,O.registerTexture(this.url,i,n,s));a||this.parser.getDependency("texture",n).then(i=>{i&&O.registerTexture(this.url,i,n,s)})}}}),(t=this.parser.json.meshes)==null||t.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===n&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(r,e){var t,o,n;const s=v=="verbose",a=r.userData.LODS;if(!a)return null;const i=a?.key;let l;if(r.isTexture===!0){const d=r;d.source&&d.source[H]&&(l=d.source[H])}if(l||(l=O.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=ye(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
2
- `,m),null)),g=!1;if(y==null||(y instanceof C&&r instanceof C?(t=y.image)!=null&&t.data||(o=y.source)!=null&&o.data?y=this.copySettings(r,y):(g=!0,this.previouslyLoaded.delete(u)):y instanceof $&&r instanceof $&&((n=y.attributes.position)!=null&&n.array||(g=!0,this.previouslyLoaded.delete(u)))),!g)return y}const L=l,A=new Promise(async(y,g)=>{const m=new de;re(m),v&&(await new Promise(D=>setTimeout(D,1e3)),s&&console.warn("Start loading (delayed) "+h,L.guid));let b=h;if(L&&Array.isArray(L.lods)){const D=L.lods[e];D.hash&&(b+="?v="+D.hash)}const x=await m.loadAsync(b).catch(D=>(console.error(`Error loading LOD ${e} from ${h}
3
- `,D),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,L.guid);let _=0;if(x.parser.json.textures){let D=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){D=!0;break}}_++}if(D){let f=await S.getDependency("texture",_);return s&&console.log('change "'+r.name+'" \u2192 "'+f.name+'"',h,_,f,u),r instanceof C&&(f=this.copySettings(r,f)),f&&(f.guid=L.guid),y(f)}}if(_=0,x.parser.json.meshes){let D=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){D=!0;break}}_++}if(D){const f=await S.getDependency("mesh",_),M=L;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,_,f,u),f.isMesh===!0){const T=f.geometry;return O.assignLODInformation(a.url,T,i,e,void 0,M.density),y(T)}else{const T=new Array;for(let k=0;k<f.children.length;k++){const W=f.children[k];if(W instanceof U){const j=W.geometry;O.assignLODInformation(a.url,j,i,e,k,M.density),T.push(j)}}return y(T)}}}return y(null)});return this.previouslyLoaded.set(u,A),await A}else if(r instanceof C){s&&console.log("Load texture from uri: "+h);const u=await new le().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=r.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${r.name}`,r.type);return null}static assignLODInformation(r,e,t,o,n,s){if(!e)return;e.userData||(e.userData={});const a=new xe(r,t,o,n,s);e.userData.LODS=a,e.userData.LOD=o}static getAssignedLODInformation(r){var e;return((e=r?.userData)==null?void 0:e.LODS)||null}static copySettings(r,e){return this._copiedTextures.get(r)||(e=e.clone(),this._copiedTextures.set(r,e),e.offset=r.offset,e.repeat=r.repeat,e.colorSpace=r.colorSpace,e)}};let w=O;c(w,"registerTexture",(r,e,t,o)=>{v&&console.log("> Progressive: register texture",t,e.name,e.uuid,e,o),e.source&&(e.source[H]=o);const n=o.guid;O.assignLODInformation(r,e,n,0,0,void 0),O.lodInfos.set(n,o),O.lowresCache.set(n,e)}),c(w,"registerMesh",(r,e,t,o,n,s)=>{var a;v&&console.log("> Progressive: register mesh",n,t.name,s,t.uuid,t);const i=t.geometry;i.userData||(i.userData={}),O.assignLODInformation(r,i,e,o,n,s.density),O.lodInfos.set(e,s);let l=O.lowresCache.get(e);l?l.push(t.geometry):l=[t.geometry],O.lowresCache.set(e,l);for(const d of K)(a=d.onRegisteredNewMesh)==null||a.call(d,t,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map),c(w,"_copiedTextures",new Map);class xe{constructor(e,t,o,n,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=t,this.level=o,n!=null&&(this.index=n),s!=null&&(this.density=s)}}const J=X("debugprogressive"),De=X("noprogressive"),E=class{constructor(r){c(this,"renderer"),c(this,"projectionScreenMatrix",new Q),c(this,"cameraFrustrum",new ue),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"plugins",[]),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new ce),c(this,"_tempBox",new Z),c(this,"tempMatrix",new Q),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=r}static getObjectLODState(r){var e;return(e=r.userData)==null?void 0:e.LOD_state}enable(){if(this._originalRender)return;let r=0;this._originalRender=this.renderer.render;const e=this;ee(this.renderer),this.renderer.render=function(t,o){e.renderer.getRenderTarget()==null&&(r=0,e._frame+=1);const n=e._frame,s=r++;e.onBeforeRender(t,o,s,n),e._originalRender.call(this,t,o),e.onAfterRender(t,o,s,n)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(r,e,t,o){}onAfterRender(r,e,t,o){var n,s;if(this.pause)return;const a=this.renderer.renderLists.get(r,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(De||this.updateInterval>0&&o%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=1e5;for(const u of i){if(u.material&&(((n=u.geometry)==null?void 0:n.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){J&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(r,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(r,e,p,d)}}}updateLODs(r,e,t,o){var n,s;for(const d of this.plugins)(n=d.onBeforeUpdateLOD)==null||n.call(d,this.renderer,r,e,t);let a=t.userData.LOD_state;a||(a=new ve,t.userData.LOD_state=a);let i=this.calculateLodLevel(e,t,a,o);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(t,i);let l=0;if(t.material){const d=t["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(t.material))for(const h of t.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(t.material,l)}for(const d of this.plugins)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,r,e,t,i);a.lastLodLevel=i}loadProgressiveTextures(r,e){return r&&r.userData&&r.userData.LOD!==e?(r.userData.LOD=e,w.assignTextureLOD(r,e)):Promise.resolve(null)}loadProgressiveMeshes(r,e){if(!r)return Promise.resolve(null);if(r.userData||(r.userData={}),r.userData.LOD!==e){r.userData.LOD=e;const t=r.geometry;return w.assignMeshLOD(r,e).then(o=>(o&&r.userData.LOD==e&&t!=r.geometry,o))}return Promise.resolve(null)}calculateLodLevel(r,e,t,o){var n;if(!e)return-1;let s=10+1;if(r){if(J&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=w.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&r.isPerspectiveCamera){const d=r;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=r.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const D=2,f=1.5,M=(g.x+m.x)*.5,T=(g.y+m.y)*.5;b=(b-M)*D+M,x=(x-T)*D+T,S=(S-M)*D+M,_=(_-T)*D+T;const k=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(k,W);t.lastCentrality=(f-j)*(f-j)*(f-j)}else t.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=r.matrixWorldInverse,p=new Z;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const L=p.getSize(this._tempBox2Size),A=Math.max(L.x,L.y);if(Math.max(h.x,h.y)!=0&&A!=0&&(h.z=L.z/Math.max(L.x,L.y)*Math.max(h.x,h.y)),t.lastScreenCoverage=Math.max(h.x,h.y,h.z),t.lastScreenspaceVolume.copy(h),t.lastScreenCoverage*=t.lastCentrality,J&&E.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=E.corner0,b=E.corner1,x=E.corner2,S=E.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),E.debugDrawLine(m,b,255),E.debugDrawLine(m,x,255),E.debugDrawLine(b,S,255),E.debugDrawLine(x,S,255)}let y=999;if(i&&t.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/t.lastScreenCoverage<o){y=g;break}}y<s&&(s=y)}}return s}};let I=E;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B);class ve{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const se=Symbol("NEEDLE_mesh_lod"),F=Symbol("NEEDLE_texture_lod");function oe(r){if(!r)return null;let e=null,t=null;for(let o=r;o!=null;o=Object.getPrototypeOf(o)){const n=Object.getOwnPropertySymbols(o),s=n.find(i=>i.toString()=="Symbol(renderer)"),a=n.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=r[s].threeRenderer),!t&&a!=null&&(t=r[a])}if(e){console.log("Adding Needle LODs to modelviewer");const o=new I(e);if(o.plugins.push(new Oe(r)),o.enable(),t){const n=t.camera||t.traverse(s=>s.type=="PerspectiveCamera")[0];n&&e.render(t,n)}return()=>{o.disable()}}return null}class Oe{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,t,o,n){this.tryParseMeshLOD(t,n),this.tryParseTextureLOD(t,n)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[F]==!0)return;t[F]=!0;const o=this.tryGetCurrentGLTF(e),n=this.getUrl();if(n&&o&&t.material){let s=function(i){var l,d,h;if(i[F]==!0)return;i[F]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const L=u[p],A=i[L];if(A?.isTexture===!0){const y=(d=(l=A.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=o.parser.json.textures[y];if((h=g.extensions)!=null&&h[P]){const m=g.extensions[P];m&&n&&w.registerTexture(n,A,m.lods.length,m)}}}};const a=t.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,t){var o,n;if(t[se]==!0)return;t[se]=!0;const s=this.getUrl();if(!s)return;const a=(n=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:n[P];if(a&&s){const i=t.uuid;w.registerMesh(s,i,t,0,a.lods.length,a)}}}function we(r,e,t,o){ee(e),re(t),t.register(s=>new w(s,r));const n=new I(e);return o?.enableLODsManager!==!1&&n.enable(),n}document.addEventListener("DOMContentLoaded",()=>{oe(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,w as NEEDLE_progressive,oe as patchModelViewer,Le as registerPlugin,me as setDracoDecoderLocation,pe as setKTX2TranscoderLocation,we as useNeedleProgressive};
1
+ var ne=Object.defineProperty,ie=(r,e,t)=>e in r?ne(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,c=(r,e,t)=>(ie(r,typeof e!="symbol"?e+"":e,t),t);import{Mesh as W,BufferGeometry as $,Material as ae,Texture as C,TextureLoader as le,Matrix4 as ee,Frustum as ue,Sphere as ce,Box3 as re,Vector3 as B}from"three";import{GLTFLoader as de}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as he}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as fe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ge}from"three/examples/jsm/loaders/KTX2Loader.js";let U="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",q="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(U+"draco_decoder.js",{method:"head"}).catch(r=>{U="./include/draco/",q="./include/ktx2/"});function me(r){U=r}function pe(r){q=r}let R,V,G;function X(r){R||(R=new fe,R.setDecoderPath(U),R.setDecoderConfig({type:"js"})),G||(G=new ge,G.setTranscoderPath(q)),V||(V=he),r?G.detectSupport(r):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function K(r){r.dracoLoader||r.setDRACOLoader(R),r.ktx2Loader||r.setKTX2Loader(G),r.meshoptDecoder||r.setMeshoptDecoder(V)}function H(r){const e=new URL(window.location.href).searchParams.get(r);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function ye(r,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||r===void 0)return e;const t=r.lastIndexOf("/");if(t>=0){const o=r.substring(0,t+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}const Y=new Array;function Le(r){Y.push(r)}const P="NEEDLE_progressive",v=H("debugprogressive"),J=Symbol("needle-progressive-texture"),N=new Map,Q=new Set;if(v){let r=function(){e+=1,console.log("Toggle LOD level",e,N),N.forEach((n,s)=>{for(const a of n.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=w.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,d),l&&(t=Math.max(t,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,o=!1;window.addEventListener("keyup",n=>{n.key==="p"&&r(),n.key==="w"&&(o=!o,Q&&Q.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=o)}))})}function te(r,e,t){var o;if(!v)return;N.has(r)||N.set(r,{keys:[],sourceId:t});const n=N.get(r);((o=n?.keys)==null?void 0:o.includes(e))==!1&&n.keys.push(e)}const O=class{constructor(r,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=r,this.url=e}get name(){return P}static getMeshLODInformation(r){const e=this.getAssignedLODInformation(r);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(r,e){var t;if(r.isMaterial===!0){for(const s of Object.keys(r)){const a=r[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(r.isGroup===!0){for(const s of r.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let o,n;if(r.isMesh?o=r.geometry:(r.isBufferGeometry||r.isTexture)&&(o=r),o&&(t=o?.userData)!=null&&t.LODS){const s=o.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(r,e){var t;if(!r)return Promise.resolve(null);if(r instanceof W||r.isMesh===!0){const o=r.geometry,n=this.getAssignedLODInformation(o);if(!n)return Promise.resolve(null);for(const s of Y)(t=s.onBeforeGetLODMesh)==null||t.call(s,r,e);return r["LOD:requested level"]=e,O.getOrLoadLOD(o,e).then(s=>{if(r["LOD:requested level"]===e){if(delete r["LOD:requested level"],Array.isArray(s)){const a=n.index||0;s=s[a]}s&&o!=s&&s instanceof $&&(r.geometry=s,v&&te(r,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",r,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",r);return Promise.resolve(null)}static assignTextureLOD(r,e=0){if(!r)return Promise.resolve(null);if(r instanceof ae||r.isMaterial===!0){const t=r,o=[],n=new Array;if(v&&Q.add(t),t.uniforms&&t.isRawShaderMaterial||t.isShaderMaterial===!0){const s=t;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,t,a);o.push(l),n.push(a)}}}else for(const s of Object.keys(t)){const a=t[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,t,s);o.push(i),n.push(s)}}return Promise.all(o).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=n[i];l&&l.isTexture===!0?a.push({material:t,slot:d,texture:l,level:e}):a.push({material:t,slot:d,texture:null,level:e})}return a})}if(r instanceof C||r.isTexture===!0){const t=r;return this.assignTextureLODForSlot(t,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(r,e,t,o){return r?.isTexture!==!0?Promise.resolve(null):O.getOrLoadLOD(r,e).then(n=>{if(Array.isArray(n))return null;if(n?.isTexture===!0){if(n!=r&&(t&&o&&(t[o]=n),v&&o&&t)){const s=this.getAssignedLODInformation(r);s&&te(t,o,s.url)}return n}else v=="verbose"&&console.warn("No LOD found for",r,e);return null}).catch(n=>(console.error("Error loading LOD",r,n),null))}afterRoot(r){var e,t;return v&&console.log("AFTER",this.url,r),(e=this.parser.json.textures)==null||e.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===n&&(a=!0,O.registerTexture(this.url,i,n,s));a||this.parser.getDependency("texture",n).then(i=>{i&&O.registerTexture(this.url,i,n,s)})}}}),(t=this.parser.json.meshes)==null||t.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===n&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(r,e){var t,o,n;const s=v=="verbose",a=r.userData.LODS;if(!a)return null;const i=a?.key;let l;if(r.isTexture===!0){const d=r;d.source&&d.source[J]&&(l=d.source[J])}if(l||(l=O.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=ye(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
2
+ `,m),null)),g=!1;if(y==null||(y instanceof C&&r instanceof C?(t=y.image)!=null&&t.data||(o=y.source)!=null&&o.data?y=this.copySettings(r,y):(g=!0,this.previouslyLoaded.delete(u)):y instanceof $&&r instanceof $&&((n=y.attributes.position)!=null&&n.array||(g=!0,this.previouslyLoaded.delete(u)))),!g)return y}const L=l,A=new Promise(async(y,g)=>{const m=new de;K(m),v&&(await new Promise(x=>setTimeout(x,1e3)),s&&console.warn("Start loading (delayed) "+h,L.guid));let b=h;if(L&&Array.isArray(L.lods)){const x=L.lods[e];x.hash&&(b+="?v="+x.hash)}const D=await m.loadAsync(b).catch(x=>(console.error(`Error loading LOD ${e} from ${h}
3
+ `,x),null));if(!D)return null;const S=D.parser;s&&console.log("Loading finished "+h,L.guid);let T=0;if(D.parser.json.textures){let x=!1;for(const f of D.parser.json.textures){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){x=!0;break}}T++}if(x){let f=await S.getDependency("texture",T);return s&&console.log('change "'+r.name+'" \u2192 "'+f.name+'"',h,T,f,u),r instanceof C&&(f=this.copySettings(r,f)),f&&(f.guid=L.guid),y(f)}}if(T=0,D.parser.json.meshes){let x=!1;for(const f of D.parser.json.meshes){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){x=!0;break}}T++}if(x){const f=await S.getDependency("mesh",T),M=L;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,T,f,u),f.isMesh===!0){const _=f.geometry;return O.assignLODInformation(a.url,_,i,e,void 0,M.density),y(_)}else{const _=new Array;for(let k=0;k<f.children.length;k++){const F=f.children[k];if(F instanceof W){const j=F.geometry;O.assignLODInformation(a.url,j,i,e,k,M.density),_.push(j)}}return y(_)}}}return y(null)});return this.previouslyLoaded.set(u,A),await A}else if(r instanceof C){s&&console.log("Load texture from uri: "+h);const u=await new le().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=r.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${r.name}`,r.type);return null}static assignLODInformation(r,e,t,o,n,s){if(!e)return;e.userData||(e.userData={});const a=new De(r,t,o,n,s);e.userData.LODS=a,e.userData.LOD=o}static getAssignedLODInformation(r){var e;return((e=r?.userData)==null?void 0:e.LODS)||null}static copySettings(r,e){return this._copiedTextures.get(r)||(e=e.clone(),this._copiedTextures.set(r,e),e.offset=r.offset,e.repeat=r.repeat,e.colorSpace=r.colorSpace,e.magFilter=r.magFilter,e.minFilter=r.minFilter,e.wrapS=r.wrapS,e.wrapT=r.wrapT,e.flipY=r.flipY,e.anisotropy=r.anisotropy,e.generateMipmaps=r.generateMipmaps,e)}};let w=O;c(w,"registerTexture",(r,e,t,o)=>{v&&console.log("> Progressive: register texture",t,e.name,e.uuid,e,o),e.source&&(e.source[J]=o);const n=o.guid;O.assignLODInformation(r,e,n,0,0,void 0),O.lodInfos.set(n,o),O.lowresCache.set(n,e)}),c(w,"registerMesh",(r,e,t,o,n,s)=>{var a;v&&console.log("> Progressive: register mesh",n,t.name,s,t.uuid,t);const i=t.geometry;i.userData||(i.userData={}),O.assignLODInformation(r,i,e,o,n,s.density),O.lodInfos.set(e,s);let l=O.lowresCache.get(e);l?l.push(t.geometry):l=[t.geometry],O.lowresCache.set(e,l);for(const d of Y)(a=d.onRegisteredNewMesh)==null||a.call(d,t,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map),c(w,"_copiedTextures",new Map);class De{constructor(e,t,o,n,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=t,this.level=o,n!=null&&(this.index=n),s!=null&&(this.density=s)}}const Z=H("debugprogressive"),xe=H("noprogressive"),E=class{constructor(r){c(this,"renderer"),c(this,"projectionScreenMatrix",new ee),c(this,"cameraFrustrum",new ue),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"plugins",[]),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new ce),c(this,"_tempBox",new re),c(this,"tempMatrix",new ee),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=r}static getObjectLODState(r){var e;return(e=r.userData)==null?void 0:e.LOD_state}enable(){if(this._originalRender)return;let r=0;this._originalRender=this.renderer.render;const e=this;X(this.renderer),this.renderer.render=function(t,o){e.renderer.getRenderTarget()==null&&(r=0,e._frame+=1);const n=e._frame,s=r++;e.onBeforeRender(t,o,s,n),e._originalRender.call(this,t,o),e.onAfterRender(t,o,s,n)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(r,e,t,o){}onAfterRender(r,e,t,o){var n,s;if(this.pause)return;const a=this.renderer.renderLists.get(r,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(xe||this.updateInterval>0&&o%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=1e5;for(const u of i){if(u.material&&(((n=u.geometry)==null?void 0:n.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){Z&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}const p=u.object;(p instanceof W||p.isMesh)&&this.updateLODs(r,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof W||p.isMesh)&&this.updateLODs(r,e,p,d)}}}updateLODs(r,e,t,o){var n,s;for(const d of this.plugins)(n=d.onBeforeUpdateLOD)==null||n.call(d,this.renderer,r,e,t);let a=t.userData.LOD_state;a||(a=new ve,t.userData.LOD_state=a);let i=this.calculateLodLevel(e,t,a,o);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(t,i);let l=0;if(t.material){const d=t["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(t.material))for(const h of t.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(t.material,l)}for(const d of this.plugins)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,r,e,t,i);a.lastLodLevel=i}loadProgressiveTextures(r,e){return r&&r.userData&&r.userData.LOD!==e?(r.userData.LOD=e,w.assignTextureLOD(r,e)):Promise.resolve(null)}loadProgressiveMeshes(r,e){if(!r)return Promise.resolve(null);if(r.userData||(r.userData={}),r.userData.LOD!==e){r.userData.LOD=e;const t=r.geometry;return w.assignMeshLOD(r,e).then(o=>(o&&r.userData.LOD==e&&t!=r.geometry,o))}return Promise.resolve(null)}calculateLodLevel(r,e,t,o){var n;if(!e)return-1;let s=10+1;if(r){if(Z&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=w.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&r.isPerspectiveCamera){const d=r;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=r.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,D=g.y,S=m.x,T=m.y;const x=2,f=1.5,M=(g.x+m.x)*.5,_=(g.y+m.y)*.5;b=(b-M)*x+M,D=(D-_)*x+_,S=(S-M)*x+M,T=(T-_)*x+_;const k=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),F=D<0&&T>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(k,F);t.lastCentrality=(f-j)*(f-j)*(f-j)}else t.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=r.matrixWorldInverse,p=new re;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const L=p.getSize(this._tempBox2Size),A=Math.max(L.x,L.y);if(Math.max(h.x,h.y)!=0&&A!=0&&(h.z=L.z/Math.max(L.x,L.y)*Math.max(h.x,h.y)),t.lastScreenCoverage=Math.max(h.x,h.y,h.z),t.lastScreenspaceVolume.copy(h),t.lastScreenCoverage*=t.lastCentrality,Z&&E.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=E.corner0,b=E.corner1,D=E.corner2,S=E.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,D.copy(this._tempBox.max),D.y=m.y,S.copy(this._tempBox.max);const T=(m.z+S.z)*.5;m.z=b.z=D.z=S.z=T,m.applyMatrix4(g),b.applyMatrix4(g),D.applyMatrix4(g),S.applyMatrix4(g),E.debugDrawLine(m,b,255),E.debugDrawLine(m,D,255),E.debugDrawLine(b,S,255),E.debugDrawLine(D,S,255)}let y=999;if(i&&t.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/t.lastScreenCoverage<o){y=g;break}}y<s&&(s=y)}}return s}};let I=E;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B);class ve{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const se=Symbol("NEEDLE_mesh_lod"),z=Symbol("NEEDLE_texture_lod");function oe(r){if(!r)return null;let e=null,t=null;for(let o=r;o!=null;o=Object.getPrototypeOf(o)){const n=Object.getOwnPropertySymbols(o),s=n.find(i=>i.toString()=="Symbol(renderer)"),a=n.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=r[s].threeRenderer),!t&&a!=null&&(t=r[a])}if(e){console.log("Adding Needle LODs to modelviewer");const o=new I(e);if(o.plugins.push(new Oe(r)),o.enable(),t){const n=t.camera||t.traverse(s=>s.type=="PerspectiveCamera")[0];n&&e.render(t,n)}return()=>{o.disable()}}return null}class Oe{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,t,o,n){this.tryParseMeshLOD(t,n),this.tryParseTextureLOD(t,n)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[z]==!0)return;t[z]=!0;const o=this.tryGetCurrentGLTF(e),n=this.getUrl();if(n&&o&&t.material){let s=function(i){var l,d,h;if(i[z]==!0)return;i[z]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const L=u[p],A=i[L];if(A?.isTexture===!0){const y=(d=(l=A.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=o.parser.json.textures[y];if((h=g.extensions)!=null&&h[P]){const m=g.extensions[P];m&&n&&w.registerTexture(n,A,m.lods.length,m)}}}};const a=t.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,t){var o,n;if(t[se]==!0)return;t[se]=!0;const s=this.getUrl();if(!s)return;const a=(n=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:n[P];if(a&&s){const i=t.uuid;w.registerMesh(s,i,t,0,a.lods.length,a)}}}function we(r,e,t,o){X(e),K(t),t.register(s=>new w(s,r));const n=new I(e);return o?.enableLODsManager!==!1&&n.enable(),n}document.addEventListener("DOMContentLoaded",()=>{oe(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,w as NEEDLE_progressive,K as addDracoAndKTX2Loaders,X as createLoaders,oe as patchModelViewer,Le as registerPlugin,me as setDracoDecoderLocation,pe as setKTX2TranscoderLocation,we as useNeedleProgressive};