@needle-tools/gltf-progressive 1.2.3-alpha → 1.2.3-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/gltf-progressive.js +84 -81
- package/gltf-progressive.min.js +5 -5
- package/gltf-progressive.umd.cjs +5 -5
- package/lib/extension.js +4 -4
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.2.3-alpha.2] - 2023-06-27
|
|
8
|
+
- Fix: error caused by parser associations containing `undefined` value
|
|
9
|
+
|
|
10
|
+
## [1.2.3-alpha.1] - 2023-06-25
|
|
11
|
+
- Internal: rename `setRaycastMesh` to `registerRaycastMesh`
|
|
12
|
+
|
|
7
13
|
## [1.2.3-alpha] - 2023-06-24
|
|
8
14
|
- Change: automatically change LOD update interval based on framerate
|
|
9
15
|
|
package/gltf-progressive.js
CHANGED
|
@@ -96,8 +96,8 @@ if (L) {
|
|
|
96
96
|
const n = i[s];
|
|
97
97
|
if (n != null) {
|
|
98
98
|
if (n.isBufferGeometry === !0) {
|
|
99
|
-
const l = S.getMeshLODInformation(n),
|
|
100
|
-
i["DEBUG:LOD"] = t, S.assignMeshLOD(i,
|
|
99
|
+
const l = S.getMeshLODInformation(n), f = l ? Math.min(t, l.lods.length) : 0;
|
|
100
|
+
i["DEBUG:LOD"] = t, S.assignMeshLOD(i, f), l && (e = Math.max(e, l.lods.length - 1));
|
|
101
101
|
} else if (i.isMaterial === !0) {
|
|
102
102
|
i["DEBUG:LOD"] = t, S.assignTextureLOD(i, t);
|
|
103
103
|
break;
|
|
@@ -161,8 +161,8 @@ const O = class {
|
|
|
161
161
|
if (L === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
|
|
162
162
|
const n = t;
|
|
163
163
|
for (const l of Object.keys(n.uniforms)) {
|
|
164
|
-
const
|
|
165
|
-
(
|
|
164
|
+
const f = n.uniforms[l].value;
|
|
165
|
+
(f == null ? void 0 : f.isTexture) === !0 && s(f, e);
|
|
166
166
|
}
|
|
167
167
|
} else if (t.isMaterial)
|
|
168
168
|
for (const n of Object.keys(t)) {
|
|
@@ -171,14 +171,14 @@ const O = class {
|
|
|
171
171
|
}
|
|
172
172
|
return t[o] = e, e;
|
|
173
173
|
function s(n, l) {
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
l.min_count = Math.min(l.min_count,
|
|
179
|
-
for (let M = 0; M <
|
|
180
|
-
const
|
|
181
|
-
|
|
174
|
+
const f = r.getAssignedLODInformation(n);
|
|
175
|
+
if (f) {
|
|
176
|
+
const c = r.lodInfos.get(f.key);
|
|
177
|
+
if (c && c.lods) {
|
|
178
|
+
l.min_count = Math.min(l.min_count, c.lods.length), l.max_count = Math.max(l.max_count, c.lods.length);
|
|
179
|
+
for (let M = 0; M < c.lods.length; M++) {
|
|
180
|
+
const u = c.lods[M];
|
|
181
|
+
u.width && (l.lods[M] = l.lods[M] || { min_height: 1 / 0, max_height: 0 }, l.lods[M].min_height = Math.min(l.lods[M].min_height, u.height), l.lods[M].max_height = Math.max(l.lods[M].max_height, u.height));
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
}
|
|
@@ -274,8 +274,8 @@ const O = class {
|
|
|
274
274
|
for (const n of Object.keys(s.uniforms)) {
|
|
275
275
|
const l = s.uniforms[n].value;
|
|
276
276
|
if ((l == null ? void 0 : l.isTexture) === !0) {
|
|
277
|
-
const
|
|
278
|
-
o.push(
|
|
277
|
+
const f = this.assignTextureLODForSlot(l, e, r, n);
|
|
278
|
+
o.push(f), i.push(n);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
} else
|
|
@@ -289,8 +289,8 @@ const O = class {
|
|
|
289
289
|
return Promise.all(o).then((s) => {
|
|
290
290
|
const n = new Array();
|
|
291
291
|
for (let l = 0; l < s.length; l++) {
|
|
292
|
-
const
|
|
293
|
-
|
|
292
|
+
const f = s[l], c = i[l];
|
|
293
|
+
f && f.isTexture === !0 ? n.push({ material: r, slot: c, texture: f, level: e }) : n.push({ material: r, slot: c, texture: null, level: e });
|
|
294
294
|
}
|
|
295
295
|
return n;
|
|
296
296
|
});
|
|
@@ -339,11 +339,14 @@ const O = class {
|
|
|
339
339
|
return;
|
|
340
340
|
}
|
|
341
341
|
let l = !1;
|
|
342
|
-
for (const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
342
|
+
for (const f of this.parser.associations.keys())
|
|
343
|
+
if (f.isTexture === !0) {
|
|
344
|
+
const c = this.parser.associations.get(f);
|
|
345
|
+
(c == null ? void 0 : c.textures) === i && (l = !0, O.registerTexture(this.url, f, (s = n.lods) == null ? void 0 : s.length, i, n));
|
|
346
|
+
}
|
|
347
|
+
l || this.parser.getDependency("texture", i).then((f) => {
|
|
348
|
+
var c;
|
|
349
|
+
f && O.registerTexture(this.url, f, (c = n.lods) == null ? void 0 : c.length, i, n);
|
|
347
350
|
});
|
|
348
351
|
}
|
|
349
352
|
}
|
|
@@ -354,14 +357,14 @@ const O = class {
|
|
|
354
357
|
for (const n of this.parser.associations.keys())
|
|
355
358
|
if (n.isMesh) {
|
|
356
359
|
const l = this.parser.associations.get(n);
|
|
357
|
-
l.meshes === i && O.registerMesh(this.url, s.guid, n, s.lods.length, l.primitives, s);
|
|
360
|
+
(l == null ? void 0 : l.meshes) === i && O.registerMesh(this.url, s.guid, n, s.lods.length, l.primitives, s);
|
|
358
361
|
}
|
|
359
362
|
}
|
|
360
363
|
}
|
|
361
364
|
}), null;
|
|
362
365
|
}
|
|
363
366
|
static async getOrLoadLOD(t, e) {
|
|
364
|
-
var n, l,
|
|
367
|
+
var n, l, f, c;
|
|
365
368
|
const r = L == "verbose", o = t.userData.LODS;
|
|
366
369
|
if (!o)
|
|
367
370
|
return null;
|
|
@@ -381,32 +384,32 @@ const O = class {
|
|
|
381
384
|
const M = Array.isArray(s.lods) ? (n = s.lods[e]) == null ? void 0 : n.path : s.lods;
|
|
382
385
|
if (!M)
|
|
383
386
|
return L && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, s)), null;
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
387
|
+
const u = Ze(o.url, M);
|
|
388
|
+
if (u.endsWith(".glb") || u.endsWith(".gltf")) {
|
|
386
389
|
if (!s.guid)
|
|
387
390
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
388
|
-
const y =
|
|
391
|
+
const y = u + "_" + s.guid, v = this.previouslyLoaded.get(y);
|
|
389
392
|
if (v !== void 0) {
|
|
390
393
|
r && console.log(`LOD ${e} was already loading/loaded: ${y}`);
|
|
391
|
-
let p = await v.catch((Y) => (console.error(`Error loading LOD ${e} from ${
|
|
394
|
+
let p = await v.catch((Y) => (console.error(`Error loading LOD ${e} from ${u}
|
|
392
395
|
`, Y), null)), D = !1;
|
|
393
|
-
if (p == null || (p instanceof ee && t instanceof ee ? (l = p.image) != null && l.data || (
|
|
396
|
+
if (p == null || (p instanceof ee && t instanceof ee ? (l = p.image) != null && l.data || (f = p.source) != null && f.data ? p = this.copySettings(t, p) : (D = !0, this.previouslyLoaded.delete(y)) : p instanceof de && t instanceof de && ((c = p.attributes.position) != null && c.array || (D = !0, this.previouslyLoaded.delete(y)))), !D)
|
|
394
397
|
return p;
|
|
395
398
|
}
|
|
396
399
|
const x = s, R = new Promise(async (p, D) => {
|
|
397
400
|
const Y = new Ye();
|
|
398
|
-
Ie(Y), L && (await new Promise((b) => setTimeout(b, 1e3)), r && console.warn("Start loading (delayed) " +
|
|
399
|
-
let G =
|
|
401
|
+
Ie(Y), L && (await new Promise((b) => setTimeout(b, 1e3)), r && console.warn("Start loading (delayed) " + u, x.guid));
|
|
402
|
+
let G = u;
|
|
400
403
|
if (x && Array.isArray(x.lods)) {
|
|
401
404
|
const b = x.lods[e];
|
|
402
405
|
b.hash && (G += "?v=" + b.hash);
|
|
403
406
|
}
|
|
404
|
-
const _ = await Y.loadAsync(G).catch((b) => (console.error(`Error loading LOD ${e} from ${
|
|
407
|
+
const _ = await Y.loadAsync(G).catch((b) => (console.error(`Error loading LOD ${e} from ${u}
|
|
405
408
|
`, b), null));
|
|
406
409
|
if (!_)
|
|
407
410
|
return null;
|
|
408
411
|
const K = _.parser;
|
|
409
|
-
r && console.log("Loading finished " +
|
|
412
|
+
r && console.log("Loading finished " + u, x.guid);
|
|
410
413
|
let F = 0;
|
|
411
414
|
if (_.parser.json.textures) {
|
|
412
415
|
let b = !1;
|
|
@@ -422,7 +425,7 @@ const O = class {
|
|
|
422
425
|
}
|
|
423
426
|
if (b) {
|
|
424
427
|
let g = await K.getDependency("texture", F);
|
|
425
|
-
return g && O.assignLODInformation(o.url, g, i, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + g.name + '"',
|
|
428
|
+
return g && O.assignLODInformation(o.url, g, i, e, void 0, void 0), r && console.log('change "' + t.name + '" → "' + g.name + '"', u, F, g, y), t instanceof ee && (g = this.copySettings(t, g)), g && (g.guid = x.guid), p(g);
|
|
426
429
|
} else
|
|
427
430
|
L && console.warn("Could not find texture with guid", x.guid, _.parser.json);
|
|
428
431
|
}
|
|
@@ -440,7 +443,7 @@ const O = class {
|
|
|
440
443
|
}
|
|
441
444
|
if (b) {
|
|
442
445
|
const g = await K.getDependency("mesh", F), h = x;
|
|
443
|
-
if (r && console.log(`Loaded Mesh "${g.name}"`,
|
|
446
|
+
if (r && console.log(`Loaded Mesh "${g.name}"`, u, F, g, y), g.isMesh === !0) {
|
|
444
447
|
const w = g.geometry;
|
|
445
448
|
return O.assignLODInformation(o.url, w, i, e, void 0, h.density), p(w);
|
|
446
449
|
} else {
|
|
@@ -461,9 +464,9 @@ const O = class {
|
|
|
461
464
|
});
|
|
462
465
|
return this.previouslyLoaded.set(y, R), await R;
|
|
463
466
|
} else if (t instanceof ee) {
|
|
464
|
-
r && console.log("Load texture from uri: " +
|
|
465
|
-
const v = await new Ue().loadAsync(
|
|
466
|
-
return v ? (v.guid = s.guid, v.flipY = !1, v.needsUpdate = !0, v.colorSpace = t.colorSpace, r && console.log(s, v)) : L && console.warn("failed loading",
|
|
467
|
+
r && console.log("Load texture from uri: " + u);
|
|
468
|
+
const v = await new Ue().loadAsync(u);
|
|
469
|
+
return v ? (v.guid = s.guid, v.flipY = !1, v.needsUpdate = !0, v.colorSpace = t.colorSpace, r && console.log(s, v)) : L && console.warn("failed loading", u), v;
|
|
467
470
|
}
|
|
468
471
|
} else
|
|
469
472
|
L && console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`, t.type);
|
|
@@ -503,7 +506,7 @@ d(S, "registerTexture", (t, e, r, o, i) => {
|
|
|
503
506
|
* Register a mesh with LOD information
|
|
504
507
|
*/
|
|
505
508
|
d(S, "registerMesh", (t, e, r, o, i, s) => {
|
|
506
|
-
var
|
|
509
|
+
var f;
|
|
507
510
|
L && console.log("> Progressive: register mesh", i, r.name, s, r.uuid, r);
|
|
508
511
|
const n = r.geometry;
|
|
509
512
|
if (!n) {
|
|
@@ -513,8 +516,8 @@ d(S, "registerMesh", (t, e, r, o, i, s) => {
|
|
|
513
516
|
n.userData || (n.userData = {}), O.assignLODInformation(t, n, e, o, i, s.density), O.lodInfos.set(e, s);
|
|
514
517
|
let l = O.lowresCache.get(e);
|
|
515
518
|
l ? l.push(r.geometry) : l = [r.geometry], O.lowresCache.set(e, l), o > 0 && !Oe(r) && et(r, n);
|
|
516
|
-
for (const
|
|
517
|
-
(
|
|
519
|
+
for (const c of X)
|
|
520
|
+
(f = c.onRegisteredNewMesh) == null || f.call(c, r, s);
|
|
518
521
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
519
522
|
d(S, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
520
523
|
d(S, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
@@ -616,7 +619,7 @@ const E = class {
|
|
|
616
619
|
$(this, U, this.renderer.render);
|
|
617
620
|
const e = this;
|
|
618
621
|
ke(this.renderer), this.renderer.render = function(r, o) {
|
|
619
|
-
e.renderer.getRenderTarget() == null && (t = 0, $(e, Q, m(e, Q) + 1), $(e, Z, m(e, ge).getDelta()), $(e, pe, m(e, pe) + m(e, Z)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, Z)), $(e, W, e._fpsBuffer.reduce((l,
|
|
622
|
+
e.renderer.getRenderTarget() == null && (t = 0, $(e, Q, m(e, Q) + 1), $(e, Z, m(e, ge).getDelta()), $(e, pe, m(e, pe) + m(e, Z)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, Z)), $(e, W, e._fpsBuffer.reduce((l, f) => l + f) / e._fpsBuffer.length), B && m(e, Q) % 30 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
|
|
620
623
|
const s = m(e, Q), n = t++;
|
|
621
624
|
e.onBeforeRender(r, o, n, s), m(e, U).call(this, r, o), e.onAfterRender(r, o, n, s);
|
|
622
625
|
};
|
|
@@ -627,26 +630,26 @@ const E = class {
|
|
|
627
630
|
onBeforeRender(t, e, r, o) {
|
|
628
631
|
}
|
|
629
632
|
onAfterRender(t, e, r, o) {
|
|
630
|
-
var l,
|
|
633
|
+
var l, f;
|
|
631
634
|
if (this.pause)
|
|
632
635
|
return;
|
|
633
636
|
const i = this.renderer.renderLists.get(t, 0), s = i.opaque;
|
|
634
637
|
let n = !0;
|
|
635
638
|
if (s.length === 1) {
|
|
636
|
-
const
|
|
637
|
-
(
|
|
639
|
+
const c = s[0].material;
|
|
640
|
+
(c.name === "EffectMaterial" || c.name === "CopyShader") && (n = !1);
|
|
638
641
|
}
|
|
639
642
|
if ((e.parent && e.parent.type === "CubeCamera" || r >= 1 && e.type === "OrthographicCamera") && (n = !1), n) {
|
|
640
643
|
if (st || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? ($(this, C, m(this, C) + 1), B && console.warn("↓ Reducing LOD updates", m(this, C), m(this, W).toFixed(0))) : m(this, W) >= 80 && m(this, C) > 1 && ($(this, C, m(this, C) - 1), B && console.warn("↑ Increasing LOD updates", m(this, C), m(this, W).toFixed(0))) : $(this, C, this.updateInterval), m(this, C) > 0 && o % m(this, C) != 0))
|
|
641
644
|
return;
|
|
642
645
|
this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
643
|
-
const
|
|
644
|
-
for (const
|
|
645
|
-
if (
|
|
646
|
-
B && (
|
|
646
|
+
const c = this.targetTriangleDensity;
|
|
647
|
+
for (const u of s) {
|
|
648
|
+
if (u.material && (((l = u.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((f = u.geometry) == null ? void 0 : f.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
|
|
649
|
+
B && (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)));
|
|
647
650
|
continue;
|
|
648
651
|
}
|
|
649
|
-
switch (
|
|
652
|
+
switch (u.material.type) {
|
|
650
653
|
case "LineBasicMaterial":
|
|
651
654
|
case "LineDashedMaterial":
|
|
652
655
|
case "PointsMaterial":
|
|
@@ -655,38 +658,38 @@ const E = class {
|
|
|
655
658
|
case "MeshDepthMaterial":
|
|
656
659
|
continue;
|
|
657
660
|
}
|
|
658
|
-
if (B === "color" &&
|
|
659
|
-
|
|
661
|
+
if (B === "color" && u.material && !u.object.progressive_debug_color) {
|
|
662
|
+
u.object.progressive_debug_color = !0;
|
|
660
663
|
const v = Math.random() * 16777215, x = new qe({ color: v });
|
|
661
|
-
|
|
664
|
+
u.object.material = x;
|
|
662
665
|
}
|
|
663
|
-
const y =
|
|
664
|
-
(y instanceof J || y.isMesh) && this.updateLODs(t, e, y,
|
|
666
|
+
const y = u.object;
|
|
667
|
+
(y instanceof J || y.isMesh) && this.updateLODs(t, e, y, c, o);
|
|
665
668
|
}
|
|
666
669
|
const M = i.transparent;
|
|
667
|
-
for (const
|
|
668
|
-
const y =
|
|
669
|
-
(y instanceof J || y.isMesh) && this.updateLODs(t, e, y,
|
|
670
|
+
for (const u of M) {
|
|
671
|
+
const y = u.object;
|
|
672
|
+
(y instanceof J || y.isMesh) && this.updateLODs(t, e, y, c, o);
|
|
670
673
|
}
|
|
671
674
|
}
|
|
672
675
|
}
|
|
673
676
|
/** Update the LOD levels for the renderer. */
|
|
674
677
|
updateLODs(t, e, r, o, i) {
|
|
675
|
-
var l,
|
|
678
|
+
var l, f;
|
|
676
679
|
r.userData || (r.userData = {});
|
|
677
680
|
let s = r[Me];
|
|
678
681
|
if (s || (s = new it(), r[Me] = s), s.frames++ < 2)
|
|
679
682
|
return;
|
|
680
|
-
for (const
|
|
681
|
-
(l =
|
|
683
|
+
for (const c of X)
|
|
684
|
+
(l = c.onBeforeUpdateLOD) == null || l.call(c, this.renderer, t, e, r);
|
|
682
685
|
this.calculateLodLevel(e, r, s, o, k), k.mesh_lod = Math.round(k.mesh_lod), k.texture_lod = Math.round(k.texture_lod), k.mesh_lod >= 0 && this.loadProgressiveMeshes(r, k.mesh_lod);
|
|
683
686
|
let n = k.texture_lod;
|
|
684
687
|
if (r.material && n >= 0) {
|
|
685
|
-
const
|
|
686
|
-
|
|
688
|
+
const c = r["DEBUG:LOD"];
|
|
689
|
+
c != null && (n = c), this.loadProgressiveTextures(r.material, n);
|
|
687
690
|
}
|
|
688
|
-
for (const
|
|
689
|
-
(
|
|
691
|
+
for (const c of X)
|
|
692
|
+
(f = c.onAfterUpdatedLOD) == null || f.call(c, this.renderer, t, e, r, k);
|
|
690
693
|
s.lastLodLevel_Mesh = k.mesh_lod, s.lastLodLevel_Texture = k.texture_lod;
|
|
691
694
|
}
|
|
692
695
|
/** Load progressive textures for the given material
|
|
@@ -740,7 +743,7 @@ const E = class {
|
|
|
740
743
|
let n = 10 + 1, l = !1;
|
|
741
744
|
if (B && e["DEBUG:LOD"] != null)
|
|
742
745
|
return e["DEBUG:LOD"];
|
|
743
|
-
const
|
|
746
|
+
const f = S.getMeshLODInformation(e.geometry), c = f == null ? void 0 : f.lods, M = c && c.length > 0, u = S.getMaterialMinMaxLODsCount(e.material), y = (u == null ? void 0 : u.min_count) != 1 / 0 && u.min_count > 0 && u.max_count > 0;
|
|
744
747
|
if (!M && !y) {
|
|
745
748
|
i.mesh_lod = 0, i.texture_lod = 0;
|
|
746
749
|
return;
|
|
@@ -792,9 +795,9 @@ const E = class {
|
|
|
792
795
|
w.z = T.z = A.z = P.z = j, w.applyMatrix4(h), T.applyMatrix4(h), A.applyMatrix4(h), P.applyMatrix4(h), E.debugDrawLine(w, T, 255), E.debugDrawLine(w, A, 255), E.debugDrawLine(T, P, 255), E.debugDrawLine(A, P, 255);
|
|
793
796
|
}
|
|
794
797
|
let b = 999;
|
|
795
|
-
if (
|
|
796
|
-
for (let h = 0; h <
|
|
797
|
-
if (
|
|
798
|
+
if (c && r.lastScreenCoverage > 0) {
|
|
799
|
+
for (let h = 0; h < c.length; h++)
|
|
800
|
+
if (c[h].density / r.lastScreenCoverage < o) {
|
|
798
801
|
b = h;
|
|
799
802
|
break;
|
|
800
803
|
}
|
|
@@ -802,13 +805,13 @@ const E = class {
|
|
|
802
805
|
b < n && (n = b, l = !0);
|
|
803
806
|
}
|
|
804
807
|
if (l ? i.mesh_lod = n : i.mesh_lod = r.lastLodLevel_Mesh, B && i.mesh_lod != r.lastLodLevel_Mesh) {
|
|
805
|
-
const D =
|
|
808
|
+
const D = c == null ? void 0 : c[i.mesh_lod];
|
|
806
809
|
D && console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${i.mesh_lod} (${D.density.toFixed(0)}) - ${e.name}`);
|
|
807
810
|
}
|
|
808
811
|
if (y)
|
|
809
812
|
if (r.lastLodLevel_Texture < 0) {
|
|
810
|
-
if (i.texture_lod =
|
|
811
|
-
const p =
|
|
813
|
+
if (i.texture_lod = u.max_count - 1, B) {
|
|
814
|
+
const p = u.lods[u.max_count - 1];
|
|
812
815
|
B && console.log(`First Texture LOD ${i.texture_lod} (${p.max_height}px) - ${e.name}`);
|
|
813
816
|
}
|
|
814
817
|
} else {
|
|
@@ -816,8 +819,8 @@ const E = class {
|
|
|
816
819
|
let D = r.lastScreenCoverage * 2;
|
|
817
820
|
((z = this.context) == null ? void 0 : z.engine) === "model-viewer" && (D *= 2);
|
|
818
821
|
const G = v / window.devicePixelRatio * D;
|
|
819
|
-
for (let _ =
|
|
820
|
-
let K =
|
|
822
|
+
for (let _ = u.lods.length - 1; _ >= 0; _--) {
|
|
823
|
+
let K = u.lods[_];
|
|
821
824
|
if (!(je() && K.max_height > 4096) && K.max_height > G) {
|
|
822
825
|
if (i.texture_lod = _, i.texture_lod < r.lastLodLevel_Texture) {
|
|
823
826
|
const F = K.max_height;
|
|
@@ -881,7 +884,7 @@ function Ge(a) {
|
|
|
881
884
|
`, a.getAttribute("src"));
|
|
882
885
|
let t = null, e = null, r = null;
|
|
883
886
|
for (let o = a; o != null; o = Object.getPrototypeOf(o)) {
|
|
884
|
-
const i = Object.getOwnPropertySymbols(o), s = i.find((
|
|
887
|
+
const i = Object.getOwnPropertySymbols(o), s = i.find((f) => f.toString() == "Symbol(renderer)"), n = i.find((f) => f.toString() == "Symbol(scene)"), l = i.find((f) => f.toString() == "Symbol(needsRender)");
|
|
885
888
|
!t && s != null && (t = a[s].threeRenderer), !e && n != null && (e = a[n]), !r && l != null && (r = a[l]);
|
|
886
889
|
}
|
|
887
890
|
if (t && e) {
|
|
@@ -936,15 +939,15 @@ class at {
|
|
|
936
939
|
const r = this.tryGetCurrentGLTF(t), o = this.tryGetCurrentModelViewer(t), i = this.getUrl(o);
|
|
937
940
|
if (i && r && e.material) {
|
|
938
941
|
let s = function(l) {
|
|
939
|
-
var
|
|
942
|
+
var c, M, u;
|
|
940
943
|
if (l[fe] == !0)
|
|
941
944
|
return;
|
|
942
945
|
l[fe] = !0, l.userData && (l.userData.LOD = -1);
|
|
943
|
-
const
|
|
944
|
-
for (let y = 0; y <
|
|
945
|
-
const v =
|
|
946
|
+
const f = Object.keys(l);
|
|
947
|
+
for (let y = 0; y < f.length; y++) {
|
|
948
|
+
const v = f[y], x = l[v];
|
|
946
949
|
if ((x == null ? void 0 : x.isTexture) === !0) {
|
|
947
|
-
const R = (M = (
|
|
950
|
+
const R = (M = (c = x.userData) == null ? void 0 : c.associations) == null ? void 0 : M.textures;
|
|
948
951
|
if (R == null)
|
|
949
952
|
continue;
|
|
950
953
|
const z = r.parser.json.textures[R];
|
|
@@ -952,7 +955,7 @@ class at {
|
|
|
952
955
|
console.warn("Texture data not found for texture index " + R);
|
|
953
956
|
continue;
|
|
954
957
|
}
|
|
955
|
-
if ((
|
|
958
|
+
if ((u = z == null ? void 0 : z.extensions) != null && u[N]) {
|
|
956
959
|
const p = z.extensions[N];
|
|
957
960
|
p && i && S.registerTexture(i, x, p.lods.length, R, p);
|
|
958
961
|
}
|
|
@@ -997,9 +1000,9 @@ export {
|
|
|
997
1000
|
ke as createLoaders,
|
|
998
1001
|
Oe as getRaycastMesh,
|
|
999
1002
|
Re as patchModelViewer,
|
|
1003
|
+
et as registerRaycastMesh,
|
|
1000
1004
|
gt as setDracoDecoderLocation,
|
|
1001
1005
|
pt as setKTX2TranscoderLocation,
|
|
1002
|
-
et as setRaycastMesh,
|
|
1003
1006
|
mt as useNeedleProgressive,
|
|
1004
1007
|
yt as useRaycastMeshes
|
|
1005
1008
|
};
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var Re=Object.defineProperty,Ge=(t,e,s)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,d=(t,e,s)=>(Ge(t,typeof e!="symbol"?e+"":e,s),s),Oe=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},y=(t,e,s)=>(Oe(t,e,"read from private field"),s?s.call(t):e.get(t)),V=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},G=(t,e,s,o)=>(Oe(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as oe,Mesh as K,Material as Fe,Texture as Y,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as ze,Sphere as Ue,Box3 as Te,Vector3 as F}from"three";import{GLTFLoader as Ve}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ke}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Xe}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let ie="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ie+"draco_decoder.js",{method:"head"}).catch(t=>{ie="./include/draco/",me="./include/ktx2/"});function He(t){ie=t}function Ye(t){me=t}let J,pe,Q;function xe(t){J||(J=new Ke,J.setDecoderPath(ie),J.setDecoderConfig({type:"js"})),Q||(Q=new Xe,Q.setTranscoderPath(me)),pe||(pe=qe),t?Q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ye(t){t.dracoLoader||t.setDRACOLoader(J),t.ktx2Loader||t.setKTX2Loader(Q),t.meshoptDecoder||t.setMeshoptDecoder(pe)}Z("debugprogressive");function Z(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let le;function Qe(){return le!==void 0||(le=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",le)),le}const ve=Symbol("needle:raycast-mesh");function ae(t){return t?.[ve]instanceof oe?t[ve]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ae(t)){const s=et(e);s.userData={isRaycastMesh:!0},t[ve]=s}}function Ze(t=!0){if(t){if(ee)return;const e=ee=K.prototype.raycast;K.prototype.raycast=function(s,o){const r=this,n=ae(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),e.call(this,s,o),i&&(r.geometry=i)}}else{if(!ee)return;K.prototype.raycast=ee,ee=null}}let ee=null;function et(t){const e=new oe;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const N=new Array,j="NEEDLE_progressive",v=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),te=new Map,Me=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,te),te.forEach((r,n)=>{for(const i of r.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=b.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,b.assignMeshLOD(n,a),u&&(s=Math.max(s,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,b.assignTextureLOD(n,e);break}}}}),e>=s&&(e=-1)},e=-1,s=2,o=!1;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(o=!o,Me&&Me.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Ae(t,e,s){var o;if(!v)return;te.has(t)||te.set(t,{keys:[],sourceId:s});const r=te.get(t);((o=r?.keys)==null?void 0:o.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const n=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[j];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=s.getAssignedLODInformation(i);if(u){const a=s.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let p=0;p<a.lods.length;p++){const c=a.lods[p];c.width&&(l.lods[p]=l.lods[p]||{min_height:1/0,max_height:0},l.lods[p].min_height=Math.min(l.lods[p].min_height,c.height),l.lods[p].max_height=Math.max(l.lods[p].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const n=o.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof K||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const n of N)(s=n.onBeforeGetLODMesh)==null||s.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=r.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,v&&Ae(t,"geometry",r.url)):v&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof Fe||t.isMaterial===!0){const s=t,o=[],r=new Array;if(v&&Me.add(s),s.uniforms&&s.isRawShaderMaterial||s.isShaderMaterial===!0){const n=s;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i);o.push(u),r.push(i)}}}else for(const n of Object.keys(s)){const i=s[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,n);o.push(l),r.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof Y||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t){if(s&&o){const n=s[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,n,r),null}s[o]=r}if(v&&o&&s){const n=this.getAssignedLODInformation(t);n&&Ae(s,o,n.url)}}return r}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[j];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())u.isTexture===!0&&this.parser.associations.get(u).textures===r&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,r,i));l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const n=o?.extensions[j];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l.meshes===r&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,n;const i=v=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const p=t;p.source&&p.source[Le]&&(a=p.source[Le])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let f=!1;const S=Array.isArray(a.lods);if(S&&e>=a.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(u)}const p=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!p)return v&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=Je(l.url,p);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let g=await S.catch(E=>(console.error(`Error loading LOD ${e} from ${c}
|
|
2
|
-
`,E),null)),x=!1;if(g==null||(g instanceof Y&&t instanceof Y?(o=g.image)!=null&&o.data||(r=g.source)!=null&&r.data?g=this.copySettings(t,g):(x=!0,this.previouslyLoaded.delete(f)):g instanceof oe&&t instanceof oe&&((n=g.attributes.position)!=null&&n.array||(x=!0,this.previouslyLoaded.delete(f)))),!x)return g}const M=a,A=new Promise(async(g,x)=>{const E=new Ve;
|
|
3
|
-
`,m),null));if(!D)return null;const q=D.parser;i&&console.log("Loading finished "+c,M.guid);let B=0;if(D.parser.json.textures){let m=!1;for(const h of D.parser.json.textures){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){m=!0;break}}B++}if(m){let h=await q.getDependency("texture",B);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,B,h,f),t instanceof Y&&(h=this.copySettings(t,h)),h&&(h.guid=M.guid),g(h)}else
|
|
1
|
+
var Re=Object.defineProperty,Ge=(t,e,s)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,d=(t,e,s)=>(Ge(t,typeof e!="symbol"?e+"":e,s),s),Oe=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},v=(t,e,s)=>(Oe(t,e,"read from private field"),s?s.call(t):e.get(t)),V=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},G=(t,e,s,o)=>(Oe(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as oe,Mesh as K,Material as Fe,Texture as Y,TextureLoader as We,Matrix4 as Se,Frustum as Ne,Clock as $e,MeshStandardMaterial as ze,Sphere as Ue,Box3 as Te,Vector3 as F}from"three";import{GLTFLoader as Ve}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as qe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ke}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Xe}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let ie="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ie+"draco_decoder.js",{method:"head"}).catch(t=>{ie="./include/draco/",me="./include/ktx2/"});function He(t){ie=t}function Ye(t){me=t}let J,pe,Q;function xe(t){J||(J=new Ke,J.setDecoderPath(ie),J.setDecoderConfig({type:"js"})),Q||(Q=new Xe,Q.setTranscoderPath(me)),pe||(pe=qe),t?Q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ve(t){t.dracoLoader||t.setDRACOLoader(J),t.ktx2Loader||t.setKTX2Loader(Q),t.meshoptDecoder||t.setMeshoptDecoder(pe)}Z("debugprogressive");function Z(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let le;function Qe(){return le!==void 0||(le=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",le)),le}const ye=Symbol("needle:raycast-mesh");function ae(t){return t?.[ye]instanceof oe?t[ye]:null}function Ee(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ae(t)){const s=et(e);s.userData={isRaycastMesh:!0},t[ye]=s}}function Ze(t=!0){if(t){if(ee)return;const e=ee=K.prototype.raycast;K.prototype.raycast=function(s,o){const r=this,n=ae(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),e.call(this,s,o),i&&(r.geometry=i)}}else{if(!ee)return;K.prototype.raycast=ee,ee=null}}let ee=null;function et(t){const e=new oe;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const N=new Array,j="NEEDLE_progressive",y=Z("debugprogressive"),Le=Symbol("needle-progressive-texture"),te=new Map,Me=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,te),te.forEach((r,n)=>{for(const i of r.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=b.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,b.assignMeshLOD(n,a),u&&(s=Math.max(s,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,b.assignTextureLOD(n,e);break}}}}),e>=s&&(e=-1)},e=-1,s=2,o=!1;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(o=!o,Me&&Me.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Ae(t,e,s){var o;if(!y)return;te.has(t)||te.set(t,{keys:[],sourceId:s});const r=te.get(t);((o=r?.keys)==null?void 0:o.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const n=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[j];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=s.getAssignedLODInformation(i);if(u){const a=s.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let p=0;p<a.lods.length;p++){const c=a.lods[p];c.width&&(l.lods[p]=l.lods[p]||{min_height:1/0,max_height:0},l.lods[p].min_height=Math.min(l.lods[p].min_height,c.height),l.lods[p].max_height=Math.max(l.lods[p].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const n=o.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof K||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const n of N)(s=n.onBeforeGetLODMesh)==null||s.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=r.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,y&&Ae(t,"geometry",r.url)):y&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else y&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof Fe||t.isMaterial===!0){const s=t,o=[],r=new Array;if(y&&Me.add(s),s.uniforms&&s.isRawShaderMaterial||s.isShaderMaterial===!0){const n=s;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i);o.push(u),r.push(i)}}}else for(const n of Object.keys(s)){const i=s[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,n);o.push(l),r.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof Y||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t){if(s&&o){const n=s[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,n,r),null}s[o]=r}if(y&&o&&s){const n=this.getAssignedLODInformation(t);n&&Ae(s,o,n.url)}}return r}else y=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[j];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===r&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,r,i))}l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const n=o?.extensions[j];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,n;const i=y=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const p=t;p.source&&p.source[Le]&&(a=p.source[Le])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let f=!1;const S=Array.isArray(a.lods);if(S&&e>=a.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(u)}const p=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!p)return y&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=Je(l.url,p);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let g=await S.catch(E=>(console.error(`Error loading LOD ${e} from ${c}
|
|
2
|
+
`,E),null)),x=!1;if(g==null||(g instanceof Y&&t instanceof Y?(o=g.image)!=null&&o.data||(r=g.source)!=null&&r.data?g=this.copySettings(t,g):(x=!0,this.previouslyLoaded.delete(f)):g instanceof oe&&t instanceof oe&&((n=g.attributes.position)!=null&&n.array||(x=!0,this.previouslyLoaded.delete(f)))),!x)return g}const M=a,A=new Promise(async(g,x)=>{const E=new Ve;ve(E),y&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+c,M.guid));let I=c;if(M&&Array.isArray(M.lods)){const m=M.lods[e];m.hash&&(I+="?v="+m.hash)}const D=await E.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${c}
|
|
3
|
+
`,m),null));if(!D)return null;const q=D.parser;i&&console.log("Loading finished "+c,M.guid);let B=0;if(D.parser.json.textures){let m=!1;for(const h of D.parser.json.textures){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){m=!0;break}}B++}if(m){let h=await q.getDependency("texture",B);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,B,h,f),t instanceof Y&&(h=this.copySettings(t,h)),h&&(h.guid=M.guid),g(h)}else y&&console.warn("Could not find texture with guid",M.guid,D.parser.json)}if(B=0,D.parser.json.meshes){let m=!1;for(const h of D.parser.json.meshes){if(h!=null&&h.extensions){const L=h?.extensions[j];if(L!=null&&L.guid&&L.guid===M.guid){m=!0;break}}B++}if(m){const h=await q.getDependency("mesh",B),L=M;if(i&&console.log(`Loaded Mesh "${h.name}"`,c,B,h,f),h.isMesh===!0){const _=h.geometry;return w.assignLODInformation(l.url,_,u,e,void 0,L.density),g(_)}else{const _=new Array;for(let O=0;O<h.children.length;O++){const W=h.children[O];if(W.isMesh===!0){const U=W.geometry;w.assignLODInformation(l.url,U,u,e,O,L.density),_.push(U)}}return g(_)}}else y&&console.warn("Could not find mesh with guid",M.guid,D.parser.json)}return g(null)});return this.previouslyLoaded.set(f,A),await A}else if(t instanceof Y){i&&console.log("Load texture from uri: "+c);const f=await new We().loadAsync(c);return f?(f.guid=a.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(a,f)):y&&console.warn("failed loading",c),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,n){if(!e)return;e.userData||(e.userData={});const i=new tt(t,s,o,r,n);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),y&&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 b=w;d(b,"registerTexture",(t,e,s,o,r)=>{if(v&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const n=r.guid;w.assignLODInformation(t,e,n,s,o,void 0),w.lodInfos.set(n,r),w.lowresCache.set(n,e)}),d(b,"registerMesh",(t,e,s,o,r,n)=>{var i;v&&console.log("> Progressive: register mesh",r,s.name,n,s.uuid,s);const l=s.geometry;if(!l){v&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,r,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),o>0&&!ae(s)&&Ee(s,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,s,n)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class tt{constructor(e,s,o,r,n){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r),n!=null&&(this.density=n)}}const C=Z("debugprogressive"),st=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),X=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var T,$,_e,H,se,ue,z;const P=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new Se),d(this,"cameraFrustrum",new Ne),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval","auto"),V(this,T,1),d(this,"pause",!1),d(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,_e,new $e),V(this,H,0),V(this,se,0),V(this,ue,0),V(this,z,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new Ue),d(this,"_tempBox",new Te),d(this,"_tempBox2",new Te),d(this,"tempMatrix",new Se),d(this,"_tempWorldPosition",new F),d(this,"_tempBoxSize",new F),d(this,"_tempBox2Size",new F),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){N.push(t)}static removePlugin(t){const e=N.indexOf(t);e>=0&&N.splice(e,1)}static get(t,e){if(t[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const s=new P(t,{engine:"unknown",...e});return t[De]=s,s}get plugins(){return N}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(y(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;xe(this.renderer),this.renderer.render=function(s,o){e.renderer.getRenderTarget()==null&&(t=0,G(e,H,y(e,H)+1),G(e,se,y(e,_e).getDelta()),G(e,ue,y(e,ue)+y(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,se)),G(e,z,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),C&&y(e,H)%30===0&&console.log("FPS",Math.round(y(e,z)),"Interval:",y(e,T)));const r=y(e,H),n=t++;e.onBeforeRender(s,o,n,r),y(e,$).call(this,s,o),e.onAfterRender(s,o,n,r)}}disable(){y(this,$)&&(this.renderer.render=y(this,$),G(this,$,void 0))}onBeforeRender(t,e,s,o){}onAfterRender(t,e,s,o){var r,n;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),l=i.opaque;let u=!0;if(l.length===1){const a=l[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(u=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(u=!1),u){if(st||(this.updateInterval==="auto"?y(this,z)<40&&y(this,T)<10?(G(this,T,y(this,T)+1),C&&console.warn("\u2193 Reducing LOD updates",y(this,T),y(this,z).toFixed(0))):y(this,z)>=80&&y(this,T)>1&&(G(this,T,y(this,T)-1),C&&console.warn("\u2191 Increasing LOD updates",y(this,T),y(this,z).toFixed(0))):G(this,T,this.updateInterval),y(this,T)>0&&o%y(this,T)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const a=this.targetTriangleDensity;for(const c of l){if(c.material&&(((r=c.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=c.geometry)==null?void 0:n.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){C&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(C==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const S=Math.random()*16777215,M=new ze({color:S});c.object.material=M}const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}const p=i.transparent;for(const c of p){const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}}}updateLODs(t,e,s,o,r){var n,i;s.userData||(s.userData={});let l=s[we];if(l||(l=new rt,s[we]=l),l.frames++<2)return;for(const a of N)(n=a.onBeforeUpdateLOD)==null||n.call(a,this.renderer,t,e,s);this.calculateLodLevel(e,s,l,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(s,k.mesh_lod);let u=k.texture_lod;if(s.material&&u>=0){const a=s["DEBUG:LOD"];a!=null&&(u=a),this.loadProgressiveTextures(s.material,u)}for(const a of N)(i=a.onAfterUpdatedLOD)==null||i.call(a,this.renderer,t,e,s,k);l.lastLodLevel_Mesh=k.mesh_lod,l.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[X]===void 0||e<t[X])&&(s=!0),s&&(t[X]=e,b.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[X]!==e){t[X]=e;const s=t.geometry;return b.assignMeshLOD(t,e).then(o=>(o&&t[X]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,n=(s.y+o.y)*.5;return this._tempPtInside.set(r,n,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var n,i;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let l=10+1,u=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=b.getMeshLODInformation(e.geometry),p=a?.lods,c=p&&p.length>0,f=b.getMaterialMinMaxLODsCount(e.material),S=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!c&&!S){r.mesh_lod=0,r.texture_lod=0;return}if(c||(u=!0,l=0),!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e))){r.mesh_lod=99,r.texture_lod=99;return}const M=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let A=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const g=e;g.boundingBox||g.computeBoundingBox(),A=g.boundingBox}if(A&&t.isPerspectiveCamera){const g=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 m=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(A),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&g.fov>70){const m=this._tempBox.min,h=this._tempBox.max;let L=m.x,_=m.y,O=h.x,W=h.y;const U=2,he=1.5,re=(m.x+h.x)*.5,ne=(m.y+h.y)*.5;L=(L-re)*U+re,_=(_-ne)*U+ne,O=(O-re)*U+re,W=(W-ne)*U+ne;const ke=L<0&&O>0?0:Math.min(Math.abs(m.x),Math.abs(h.x)),je=_<0&&W>0?0:Math.min(Math.abs(m.y),Math.abs(h.y)),fe=Math.max(ke,je);s.lastCentrality=(he-fe)*(he-fe)*(he-fe)}else s.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&M>0&&x.multiplyScalar(M/screen.availHeight),x.x*=g.aspect;const E=t.matrixWorldInverse,I=this._tempBox2;I.copy(A),I.applyMatrix4(e.matrixWorld),I.applyMatrix4(E);const D=I.getSize(this._tempBox2Size),q=Math.max(D.x,D.y);if(Math.max(x.x,x.y)!=0&&q!=0&&(x.z=D.z/Math.max(D.x,D.y)*Math.max(x.x,x.y)),s.lastScreenCoverage=Math.max(x.x,x.y,x.z),s.lastScreenspaceVolume.copy(x),s.lastScreenCoverage*=s.lastCentrality,C&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const h=P.corner0,L=P.corner1,_=P.corner2,O=P.corner3;h.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=h.x,_.copy(this._tempBox.max),_.y=h.y,O.copy(this._tempBox.max);const W=(h.z+O.z)*.5;h.z=L.z=_.z=O.z=W,h.applyMatrix4(m),L.applyMatrix4(m),_.applyMatrix4(m),O.applyMatrix4(m),P.debugDrawLine(h,L,255),P.debugDrawLine(h,_,255),P.debugDrawLine(L,O,255),P.debugDrawLine(_,O,255)}let B=999;if(p&&s.lastScreenCoverage>0){for(let m=0;m<p.length;m++)if(p[m].density/s.lastScreenCoverage<o){B=m;break}}B<l&&(l=B,u=!0)}if(u?r.mesh_lod=l:r.mesh_lod=s.lastLodLevel_Mesh,C&&r.mesh_lod!=s.lastLodLevel_Mesh){const g=p?.[r.mesh_lod];g&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${g.density.toFixed(0)}) - ${e.name}`)}if(S)if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,C){const g=f.lods[f.max_count-1];C&&console.log(`First Texture LOD ${r.texture_lod} (${g.max_height}px) - ${e.name}`)}}else{const g=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let x=s.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(x*=2);const E=M/window.devicePixelRatio*x;for(let I=f.lods.length-1;I>=0;I--){let D=f.lods[I];if(!(Qe()&&D.max_height>4096)&&D.max_height>E){if(r.texture_lod=I,r.texture_lod<s.lastLodLevel_Texture){const q=D.max_height;C&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${q}px
|
|
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 b=w;d(b,"registerTexture",(t,e,s,o,r)=>{if(y&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const n=r.guid;w.assignLODInformation(t,e,n,s,o,void 0),w.lodInfos.set(n,r),w.lowresCache.set(n,e)}),d(b,"registerMesh",(t,e,s,o,r,n)=>{var i;y&&console.log("> Progressive: register mesh",r,s.name,n,s.uuid,s);const l=s.geometry;if(!l){y&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,r,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),o>0&&!ae(s)&&Ee(s,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,s,n)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class tt{constructor(e,s,o,r,n){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r),n!=null&&(this.density=n)}}const C=Z("debugprogressive"),st=Z("noprogressive"),De=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),X=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var T,$,_e,H,se,ue,z;const P=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new Se),d(this,"cameraFrustrum",new Ne),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval","auto"),V(this,T,1),d(this,"pause",!1),d(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,_e,new $e),V(this,H,0),V(this,se,0),V(this,ue,0),V(this,z,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new Ue),d(this,"_tempBox",new Te),d(this,"_tempBox2",new Te),d(this,"tempMatrix",new Se),d(this,"_tempWorldPosition",new F),d(this,"_tempBoxSize",new F),d(this,"_tempBox2Size",new F),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){N.push(t)}static removePlugin(t){const e=N.indexOf(t);e>=0&&N.splice(e,1)}static get(t,e){if(t[De])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[De];const s=new P(t,{engine:"unknown",...e});return t[De]=s,s}get plugins(){return N}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(v(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;xe(this.renderer),this.renderer.render=function(s,o){e.renderer.getRenderTarget()==null&&(t=0,G(e,H,v(e,H)+1),G(e,se,v(e,_e).getDelta()),G(e,ue,v(e,ue)+v(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,se)),G(e,z,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),C&&v(e,H)%30===0&&console.log("FPS",Math.round(v(e,z)),"Interval:",v(e,T)));const r=v(e,H),n=t++;e.onBeforeRender(s,o,n,r),v(e,$).call(this,s,o),e.onAfterRender(s,o,n,r)}}disable(){v(this,$)&&(this.renderer.render=v(this,$),G(this,$,void 0))}onBeforeRender(t,e,s,o){}onAfterRender(t,e,s,o){var r,n;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),l=i.opaque;let u=!0;if(l.length===1){const a=l[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(u=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(u=!1),u){if(st||(this.updateInterval==="auto"?v(this,z)<40&&v(this,T)<10?(G(this,T,v(this,T)+1),C&&console.warn("\u2193 Reducing LOD updates",v(this,T),v(this,z).toFixed(0))):v(this,z)>=80&&v(this,T)>1&&(G(this,T,v(this,T)-1),C&&console.warn("\u2191 Increasing LOD updates",v(this,T),v(this,z).toFixed(0))):G(this,T,this.updateInterval),v(this,T)>0&&o%v(this,T)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const a=this.targetTriangleDensity;for(const c of l){if(c.material&&(((r=c.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=c.geometry)==null?void 0:n.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){C&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(C==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const S=Math.random()*16777215,M=new ze({color:S});c.object.material=M}const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}const p=i.transparent;for(const c of p){const f=c.object;(f instanceof K||f.isMesh)&&this.updateLODs(t,e,f,a,o)}}}updateLODs(t,e,s,o,r){var n,i;s.userData||(s.userData={});let l=s[we];if(l||(l=new rt,s[we]=l),l.frames++<2)return;for(const a of N)(n=a.onBeforeUpdateLOD)==null||n.call(a,this.renderer,t,e,s);this.calculateLodLevel(e,s,l,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(s,k.mesh_lod);let u=k.texture_lod;if(s.material&&u>=0){const a=s["DEBUG:LOD"];a!=null&&(u=a),this.loadProgressiveTextures(s.material,u)}for(const a of N)(i=a.onAfterUpdatedLOD)==null||i.call(a,this.renderer,t,e,s,k);l.lastLodLevel_Mesh=k.mesh_lod,l.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[X]===void 0||e<t[X])&&(s=!0),s&&(t[X]=e,b.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[X]!==e){t[X]=e;const s=t.geometry;return b.assignMeshLOD(t,e).then(o=>(o&&t[X]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,n=(s.y+o.y)*.5;return this._tempPtInside.set(r,n,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var n,i;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let l=10+1,u=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=b.getMeshLODInformation(e.geometry),p=a?.lods,c=p&&p.length>0,f=b.getMaterialMinMaxLODsCount(e.material),S=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!c&&!S){r.mesh_lod=0,r.texture_lod=0;return}if(c||(u=!0,l=0),!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e))){r.mesh_lod=99,r.texture_lod=99;return}const M=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let A=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const g=e;g.boundingBox||g.computeBoundingBox(),A=g.boundingBox}if(A&&t.isPerspectiveCamera){const g=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 m=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(A),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&g.fov>70){const m=this._tempBox.min,h=this._tempBox.max;let L=m.x,_=m.y,O=h.x,W=h.y;const U=2,he=1.5,re=(m.x+h.x)*.5,ne=(m.y+h.y)*.5;L=(L-re)*U+re,_=(_-ne)*U+ne,O=(O-re)*U+re,W=(W-ne)*U+ne;const ke=L<0&&O>0?0:Math.min(Math.abs(m.x),Math.abs(h.x)),je=_<0&&W>0?0:Math.min(Math.abs(m.y),Math.abs(h.y)),fe=Math.max(ke,je);s.lastCentrality=(he-fe)*(he-fe)*(he-fe)}else s.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&M>0&&x.multiplyScalar(M/screen.availHeight),x.x*=g.aspect;const E=t.matrixWorldInverse,I=this._tempBox2;I.copy(A),I.applyMatrix4(e.matrixWorld),I.applyMatrix4(E);const D=I.getSize(this._tempBox2Size),q=Math.max(D.x,D.y);if(Math.max(x.x,x.y)!=0&&q!=0&&(x.z=D.z/Math.max(D.x,D.y)*Math.max(x.x,x.y)),s.lastScreenCoverage=Math.max(x.x,x.y,x.z),s.lastScreenspaceVolume.copy(x),s.lastScreenCoverage*=s.lastCentrality,C&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const h=P.corner0,L=P.corner1,_=P.corner2,O=P.corner3;h.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=h.x,_.copy(this._tempBox.max),_.y=h.y,O.copy(this._tempBox.max);const W=(h.z+O.z)*.5;h.z=L.z=_.z=O.z=W,h.applyMatrix4(m),L.applyMatrix4(m),_.applyMatrix4(m),O.applyMatrix4(m),P.debugDrawLine(h,L,255),P.debugDrawLine(h,_,255),P.debugDrawLine(L,O,255),P.debugDrawLine(_,O,255)}let B=999;if(p&&s.lastScreenCoverage>0){for(let m=0;m<p.length;m++)if(p[m].density/s.lastScreenCoverage<o){B=m;break}}B<l&&(l=B,u=!0)}if(u?r.mesh_lod=l:r.mesh_lod=s.lastLodLevel_Mesh,C&&r.mesh_lod!=s.lastLodLevel_Mesh){const g=p?.[r.mesh_lod];g&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${g.density.toFixed(0)}) - ${e.name}`)}if(S)if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,C){const g=f.lods[f.max_count-1];C&&console.log(`First Texture LOD ${r.texture_lod} (${g.max_height}px) - ${e.name}`)}}else{const g=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let x=s.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(x*=2);const E=M/window.devicePixelRatio*x;for(let I=f.lods.length-1;I>=0;I--){let D=f.lods[I];if(!(Qe()&&D.max_height>4096)&&D.max_height>E){if(r.texture_lod=I,r.texture_lod<s.lastLodLevel_Texture){const q=D.max_height;C&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${q}px
|
|
6
6
|
Screensize: ${E.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
|
|
7
7
|
${e.name}`)}break}}}else r.texture_lod=0}};let R=P;T=new WeakMap,$=new WeakMap,_e=new WeakMap,H=new WeakMap,se=new WeakMap,ue=new WeakMap,z=new WeakMap,d(R,"debugDrawLine"),d(R,"corner0",new F),d(R,"corner1",new F),d(R,"corner2",new F),d(R,"corner3",new F),d(R,"_tempPtInside",new F);class rt{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new F),d(this,"lastCentrality",0)}}const Ie=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let de=null;function be(){const t=nt();t&&(t.mapURLs(function(e){return Pe(),e}),Pe(),de?.disconnect(),de=new MutationObserver(e=>{e.forEach(s=>{s.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&Ce(o)})})}),de.observe(document,{childList:!0,subtree:!0}))}function nt(){return customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),be()}),null)}function Pe(){document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Be=new WeakSet;let ot=0;function Ce(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ot+`
|
|
8
|
-
`,t.getAttribute("src"));let e=null,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!s&&l!=null&&(s=t[l]),!o&&u!=null&&(o=t[u])}if(e&&s){let r=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=R.get(e,{engine:"model-viewer"});return R.addPlugin(new it),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class it{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[ce]==!0)return;s[ce]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),n=this.getUrl(r);if(n&&o&&s.material){let i=function(u){var a,p,c;if(u[ce]==!0)return;u[ce]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let S=0;S<f.length;S++){const M=f[S],A=u[M];if(A?.isTexture===!0){const g=(p=(a=A.userData)==null?void 0:a.associations)==null?void 0:p.textures;if(g==null)continue;const x=o.parser.json.textures[g];if(!x){console.warn("Texture data not found for texture index "+g);continue}if((c=x?.extensions)!=null&&c[j]){const E=x.extensions[j];E&&n&&b.registerTexture(n,A,E.lods.length,g,E)}}}};const l=s.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Ie]==!0)return;s[Ie]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[j];if(l&&i){const u=s.uuid;b.registerMesh(i,u,s,0,l.lods.length,l)}}}function lt(t,e,s,o){xe(e),
|
|
8
|
+
`,t.getAttribute("src"));let e=null,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!s&&l!=null&&(s=t[l]),!o&&u!=null&&(o=t[u])}if(e&&s){let r=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=R.get(e,{engine:"model-viewer"});return R.addPlugin(new it),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class it{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[ce]==!0)return;s[ce]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),n=this.getUrl(r);if(n&&o&&s.material){let i=function(u){var a,p,c;if(u[ce]==!0)return;u[ce]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let S=0;S<f.length;S++){const M=f[S],A=u[M];if(A?.isTexture===!0){const g=(p=(a=A.userData)==null?void 0:a.associations)==null?void 0:p.textures;if(g==null)continue;const x=o.parser.json.textures[g];if(!x){console.warn("Texture data not found for texture index "+g);continue}if((c=x?.extensions)!=null&&c[j]){const E=x.extensions[j];E&&n&&b.registerTexture(n,A,E.lods.length,g,E)}}}};const l=s.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Ie]==!0)return;s[Ie]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[j];if(l&&i){const u=s.uuid;b.registerMesh(i,u,s,0,l.lods.length,l)}}}function lt(t,e,s,o){xe(e),ve(s),s.register(n=>new b(n,t));const r=R.get(e);return o?.enableLODsManager!==!1&&r.enable(),r}be();export{j as EXTENSION_NAME,R as LODsManager,b as NEEDLE_progressive,ge as VERSION,ve as addDracoAndKTX2Loaders,xe as createLoaders,ae as getRaycastMesh,be as patchModelViewer,Ee as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";var Re=Object.defineProperty;var Ge=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var x=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},$=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let ue="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ve="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ue+"draco_decoder.js",{method:"head"}).catch(a=>{ue="./include/draco/",ve="./include/ktx2/"});function ze(a){ue=a}function Ue(a){ve=a}let re,Le,se;function _e(a){re||(re=new $e.DRACOLoader,re.setDecoderPath(ue),re.setDecoderConfig({type:"js"})),se||(se=new Ne.KTX2Loader,se.setTranscoderPath(ve)),Le||(Le=Ve.MeshoptDecoder),a?se.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Oe(a){a.dracoLoader||a.setDRACOLoader(re),a.ktx2Loader||a.setKTX2Loader(se),a.meshoptDecoder||a.setMeshoptDecoder(Le)}ie("debugprogressive");function ie(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let Z;function qe(){return Z!==void 0||(Z=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ie("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Z)),Z}const Me=Symbol("needle:raycast-mesh");function he(a){return(a==null?void 0:a[Me])instanceof h.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!he(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(ee)return;const t=ee=h.Mesh.prototype.raycast;h.Mesh.prototype.raycast=function(e,r){const i=this,o=he(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),t.call(this,e,r),s&&(i.geometry=s)}}else{if(!ee)return;h.Mesh.prototype.raycast=ee,ee=null}}let ee=null;function Xe(a){const t=new h.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const X=new Array,N="NEEDLE_progressive",M=ie("debugprogressive"),ye=Symbol("needle-progressive-texture"),oe=new Map,De=new Set;if(M){let a=function(){t+=1,console.log("Toggle LOD level",t,oe),oe.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const l=b.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;o["DEBUG:LOD"]=t,b.assignMeshLOD(o,u),l&&(e=Math.max(e,l.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=t,b.assignTextureLOD(o,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,De&&De.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function Te(a,t,e){var i;if(!M)return;oe.has(a)||oe.set(a,{keys:[],sourceId:e});const r=oe.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(t))==!1&&r.keys.push(t)}const S=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,i;if(this._isLoadingMesh)return null;const e=(i=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:i[N];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(o=>{var s;return this._isLoadingMesh=!1,o&&S.registerMesh(this.url,e.guid,o,(s=e.lods)==null?void 0:s.length,void 0,e),o})):null});M&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}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,i="LODS:minmax",o=t[i];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[i]=e,e}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const u=n.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&s(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[i]=e,e;function s(n,l){const u=r.getAssignedLODInformation(n);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){l.min_count=Math.min(l.min_count,f.lods.length),l.max_count=Math.max(l.max_count,f.lods.length);for(let D=0;D<f.lods.length;D++){const c=f.lods[D];c.width&&(l.lods[D]=l.lods[D]||{min_height:1/0,max_height:0},l.lods[D].min_height=Math.min(l.lods[D].min_height,c.height),l.lods[D].max_height=Math.max(l.lods[D].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var o;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 n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,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 r,i;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),e===void 0)return i!=null;if(i)return Array.isArray(i.lods)?e<i.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof h.Mesh||t.isMesh===!0){const i=t.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of X)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?(t.geometry=s,M&&Te(t,"geometry",o.url)):M&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else M&&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 h.Material||t.isMaterial===!0){const r=t,i=[],o=new Array;if(M&&De.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const l=s.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n);i.push(u),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,s);i.push(l),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let l=0;l<s.length;l++){const u=s[l],f=o[l];u&&u.isTexture===!0?n.push({material:r,slot:f,texture:u,level:e}):n.push({material:r,slot:f,texture:null,level:e})}return n})}if(t instanceof h.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=t){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<e)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,s,o),null}r[i]=o}if(M&&i&&r){const s=this.getAssignedLODInformation(t);s&&Te(r,i,s.url)}}return o}else M=="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 M&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const n=i==null?void 0:i.extensions[N];if(n){if(!n.lods){M&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())u.isTexture===!0&&this.parser.associations.get(u).textures===o&&(l=!0,S.registerTexture(this.url,u,(s=n.lods)==null?void 0:s.length,o,n));l||this.parser.getDependency("texture",o).then(u=>{var f;u&&S.registerTexture(this.url,u,(f=n.lods)==null?void 0:f.length,o,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[N];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);l.meshes===o&&S.registerMesh(this.url,s.guid,n,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,f;const r=M=="verbose",i=t.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(t.isTexture===!0){const D=t;D.source&&D.source[ye]&&(s=D.source[ye])}if(s||(s=S.lodInfos.get(o)),s){if(e>0){let m=!1;const _=Array.isArray(s.lods);if(_&&e>=s.lods.length?m=!0:_||(m=!0),m)return this.lowresCache.get(o)}const D=Array.isArray(s.lods)?(n=s.lods[e])==null?void 0:n.path:s.lods;if(!D)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const c=We(i.url,D);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const m=c+"_"+s.guid,_=this.previouslyLoaded.get(m);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let y=await _.catch(Y=>(console.error(`Error loading LOD ${e} from ${c}
|
|
2
|
-
`,Y),null)),w=!1;if(y==null||(y instanceof h.Texture&&t instanceof h.Texture?(l=y.image)!=null&&l.data||(
|
|
3
|
-
`,T),null));if(!O)return null;const q=O.parser;r&&console.log("Loading finished "+
|
|
1
|
+
"use strict";var Re=Object.defineProperty;var Ge=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(Ge(a,typeof t!="symbol"?t+"":t,e),e),be=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var x=(a,t,e)=>(be(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},$=(a,t,e,r)=>(be(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),Fe=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),$e=require("three/examples/jsm/loaders/DRACOLoader.js"),Ne=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let ue="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",_e="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ue+"draco_decoder.js",{method:"head"}).catch(a=>{ue="./include/draco/",_e="./include/ktx2/"});function ze(a){ue=a}function Ue(a){_e=a}let re,Le,se;function ve(a){re||(re=new $e.DRACOLoader,re.setDecoderPath(ue),re.setDecoderConfig({type:"js"})),se||(se=new Ne.KTX2Loader,se.setTranscoderPath(_e)),Le||(Le=Ve.MeshoptDecoder),a?se.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Oe(a){a.dracoLoader||a.setDRACOLoader(re),a.ktx2Loader||a.setKTX2Loader(se),a.meshoptDecoder||a.setMeshoptDecoder(Le)}ie("debugprogressive");function ie(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let Z;function qe(){return Z!==void 0||(Z=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ie("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Z)),Z}const Me=Symbol("needle:raycast-mesh");function he(a){return(a==null?void 0:a[Me])instanceof h.BufferGeometry?a[Me]:null}function Ce(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!he(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(ee)return;const t=ee=h.Mesh.prototype.raycast;h.Mesh.prototype.raycast=function(e,r){const i=this,o=he(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),t.call(this,e,r),s&&(i.geometry=s)}}else{if(!ee)return;h.Mesh.prototype.raycast=ee,ee=null}}let ee=null;function Xe(a){const t=new h.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const X=new Array,N="NEEDLE_progressive",M=ie("debugprogressive"),ye=Symbol("needle-progressive-texture"),oe=new Map,De=new Set;if(M){let a=function(){t+=1,console.log("Toggle LOD level",t,oe),oe.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const l=b.getMeshLODInformation(n),f=l?Math.min(t,l.lods.length):0;o["DEBUG:LOD"]=t,b.assignMeshLOD(o,f),l&&(e=Math.max(e,l.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=t,b.assignTextureLOD(o,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,De&&De.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function Te(a,t,e){var i;if(!M)return;oe.has(a)||oe.set(a,{keys:[],sourceId:e});const r=oe.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(t))==!1&&r.keys.push(t)}const S=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,i;if(this._isLoadingMesh)return null;const e=(i=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:i[N];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(o=>{var s;return this._isLoadingMesh=!1,o&&S.registerMesh(this.url,e.guid,o,(s=e.lods)==null?void 0:s.length,void 0,e),o})):null});M&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}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,i="LODS:minmax",o=t[i];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[i]=e,e}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const f=n.uniforms[l].value;(f==null?void 0:f.isTexture)===!0&&s(f,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[i]=e,e;function s(n,l){const f=r.getAssignedLODInformation(n);if(f){const c=r.lodInfos.get(f.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let D=0;D<c.lods.length;D++){const u=c.lods[D];u.width&&(l.lods[D]=l.lods[D]||{min_height:1/0,max_height:0},l.lods[D].min_height=Math.min(l.lods[D].min_height,u.height),l.lods[D].max_height=Math.max(l.lods[D].max_height,u.height))}}}}}static hasLODLevelAvailable(t,e){var o;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 n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,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 r,i;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),e===void 0)return i!=null;if(i)return Array.isArray(i.lods)?e<i.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof h.Mesh||t.isMesh===!0){const i=t.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of X)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?(t.geometry=s,M&&Te(t,"geometry",o.url)):M&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else M&&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 h.Material||t.isMaterial===!0){const r=t,i=[],o=new Array;if(M&&De.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const l=s.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const f=this.assignTextureLODForSlot(l,e,r,n);i.push(f),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,s);i.push(l),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let l=0;l<s.length;l++){const f=s[l],c=o[l];f&&f.isTexture===!0?n.push({material:r,slot:c,texture:f,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof h.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=t){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<e)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,s,o),null}r[i]=o}if(M&&i&&r){const s=this.getAssignedLODInformation(t);s&&Te(r,i,s.url)}}return o}else M=="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 M&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const n=i==null?void 0:i.extensions[N];if(n){if(!n.lods){M&&console.warn("Texture has no LODs",n);return}let l=!1;for(const f of this.parser.associations.keys())if(f.isTexture===!0){const c=this.parser.associations.get(f);(c==null?void 0:c.textures)===o&&(l=!0,S.registerTexture(this.url,f,(s=n.lods)==null?void 0:s.length,o,n))}l||this.parser.getDependency("texture",o).then(f=>{var c;f&&S.registerTexture(this.url,f,(c=n.lods)==null?void 0:c.length,o,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[N];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);(l==null?void 0:l.meshes)===o&&S.registerMesh(this.url,s.guid,n,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var n,l,f,c;const r=M=="verbose",i=t.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(t.isTexture===!0){const D=t;D.source&&D.source[ye]&&(s=D.source[ye])}if(s||(s=S.lodInfos.get(o)),s){if(e>0){let m=!1;const v=Array.isArray(s.lods);if(v&&e>=s.lods.length?m=!0:v||(m=!0),m)return this.lowresCache.get(o)}const D=Array.isArray(s.lods)?(n=s.lods[e])==null?void 0:n.path:s.lods;if(!D)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const u=We(i.url,D);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const m=u+"_"+s.guid,v=this.previouslyLoaded.get(m);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let y=await v.catch(Y=>(console.error(`Error loading LOD ${e} from ${u}
|
|
2
|
+
`,Y),null)),w=!1;if(y==null||(y instanceof h.Texture&&t instanceof h.Texture?(l=y.image)!=null&&l.data||(f=y.source)!=null&&f.data?y=this.copySettings(t,y):(w=!0,this.previouslyLoaded.delete(m)):y instanceof h.BufferGeometry&&t instanceof h.BufferGeometry&&((c=y.attributes.position)!=null&&c.array||(w=!0,this.previouslyLoaded.delete(m)))),!w)return y}const L=s,G=new Promise(async(y,w)=>{const Y=new Fe.GLTFLoader;Oe(Y),M&&(await new Promise(T=>setTimeout(T,1e3)),r&&console.warn("Start loading (delayed) "+u,L.guid));let F=u;if(L&&Array.isArray(L.lods)){const T=L.lods[e];T.hash&&(F+="?v="+T.hash)}const O=await Y.loadAsync(F).catch(T=>(console.error(`Error loading LOD ${e} from ${u}
|
|
3
|
+
`,T),null));if(!O)return null;const q=O.parser;r&&console.log("Loading finished "+u,L.guid);let V=0;if(O.parser.json.textures){let T=!1;for(const p of O.parser.json.textures){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[N];if(g!=null&&g.guid&&g.guid===L.guid){T=!0;break}}V++}if(T){let p=await q.getDependency("texture",V);return p&&S.assignLODInformation(i.url,p,o,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+p.name+'"',u,V,p,m),t instanceof h.Texture&&(p=this.copySettings(t,p)),p&&(p.guid=L.guid),y(p)}else M&&console.warn("Could not find texture with guid",L.guid,O.parser.json)}if(V=0,O.parser.json.meshes){let T=!1;for(const p of O.parser.json.meshes){if(p!=null&&p.extensions){const g=p==null?void 0:p.extensions[N];if(g!=null&&g.guid&&g.guid===L.guid){T=!0;break}}V++}if(T){const p=await q.getDependency("mesh",V),g=L;if(r&&console.log(`Loaded Mesh "${p.name}"`,u,V,p,m),p.isMesh===!0){const _=p.geometry;return S.assignLODInformation(i.url,_,o,e,void 0,g.density),y(_)}else{const _=new Array;for(let A=0;A<p.children.length;A++){const E=p.children[A];if(E.isMesh===!0){const P=E.geometry;S.assignLODInformation(i.url,P,o,e,A,g.density),_.push(P)}}return y(_)}}else M&&console.warn("Could not find mesh with guid",L.guid,O.parser.json)}return y(null)});return this.previouslyLoaded.set(m,G),await G}else if(t instanceof h.Texture){r&&console.log("Load texture from uri: "+u);const v=await new h.TextureLoader().loadAsync(u);return v?(v.guid=s.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(s,v)):M&&console.warn("failed loading",u),v}}else M&&console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,i,o,s){if(!e)return;e.userData||(e.userData={});const n=new Ye(t,r,i,o,s);e.userData.LODS=n}static getAssignedLODInformation(t){var e;return((e=t==null?void 0:t.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),M&&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 b=S;d(b,"registerTexture",(t,e,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,o),!e){M&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=o);const s=o.guid;S.assignLODInformation(t,e,s,r,i,void 0),S.lodInfos.set(s,o),S.lowresCache.set(s,e)}),d(b,"registerMesh",(t,e,r,i,o,s)=>{var u;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),S.assignLODInformation(t,n,e,i,o,s.density),S.lodInfos.set(e,s);let l=S.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(e,l),i>0&&!he(r)&&Ce(r,n);for(const f of X)(u=f.onRegisteredNewMesh)==null||u.call(f,r,s)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class Ye{constructor(t,e,r,i,o){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const k=ie("debugprogressive"),He=ie("noprogressive"),me=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1};var B,U,fe,j,J,de,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new h.Matrix4);d(this,"cameraFrustrum",new h.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"_lodchangedlisteners",[]);K(this,U,void 0);K(this,fe,new h.Clock);K(this,j,0);K(this,J,0);K(this,de,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new h.Sphere);d(this,"_tempBox",new h.Box3);d(this,"_tempBox2",new h.Box3);d(this,"tempMatrix",new h.Matrix4);d(this,"_tempWorldPosition",new h.Vector3);d(this,"_tempBoxSize",new h.Vector3);d(this,"_tempBox2Size",new h.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[xe]}static addPlugin(t){X.push(t)}static removePlugin(t){const e=X.indexOf(t);e>=0&&X.splice(e,1)}static get(t,e){if(t[me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[me];const r=new C(t,{engine:"unknown",...e});return t[me]=r,r}get plugins(){return X}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(x(this,U))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;$(this,U,this.renderer.render);const e=this;_e(this.renderer),this.renderer.render=function(r,i){e.renderer.getRenderTarget()==null&&(t=0,$(e,j,x(e,j)+1),$(e,J,x(e,fe).getDelta()),$(e,de,x(e,de)+x(e,J)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,J)),$(e,W,e._fpsBuffer.reduce((l,u)=>l+u)/e._fpsBuffer.length),k&&x(e,j)%30===0&&console.log("FPS",Math.round(x(e,W)),"Interval:",x(e,B)));const s=x(e,j),n=t++;e.onBeforeRender(r,i,n,s),x(e,U).call(this,r,i),e.onAfterRender(r,i,n,s)}}disable(){x(this,U)&&(this.renderer.render=x(this,U),$(this,U,void 0))}onBeforeRender(t,e,r,i){}onAfterRender(t,e,r,i){var l,u;if(this.pause)return;const o=this.renderer.renderLists.get(t,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((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(n=!1),n){if(He||(this.updateInterval==="auto"?x(this,W)<40&&x(this,B)<10?($(this,B,x(this,B)+1),k&&console.warn("↓ Reducing LOD updates",x(this,B),x(this,W).toFixed(0))):x(this,W)>=80&&x(this,B)>1&&($(this,B,x(this,B)-1),k&&console.warn("↑ Increasing LOD updates",x(this,B),x(this,W).toFixed(0))):$(this,B,this.updateInterval),x(this,B)>0&&i%x(this,B)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const c of s){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){k&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const _=Math.random()*16777215,L=new h.MeshStandardMaterial({color:_});c.object.material=L}const m=c.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,f,i)}const D=o.transparent;for(const c of D){const m=c.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,f,i)}}}updateLODs(t,e,r,i,o){var l,u;r.userData||(r.userData={});let s=r[xe];if(s||(s=new je,r[xe]=s),s.frames++<2)return;for(const f of X)(l=f.onBeforeUpdateLOD)==null||l.call(f,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,i,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let n=R.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 X)(u=f.onAfterUpdatedLOD)==null||u.call(f,this.renderer,t,e,r,R);s.lastLodLevel_Mesh=R.mesh_lod,s.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return b.assignMeshLOD(t,e).then(i=>(i&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(o=>o({type:"mesh",level:e,object:t})),i))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,i=t.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,i,o){var G,z;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=b.getMeshLODInformation(e.geometry),f=u==null?void 0:u.lods,D=f&&f.length>0,c=b.getMaterialMinMaxLODsCount(e.material),m=(c==null?void 0:c.min_count)!=1/0&&c.min_count>0&&c.max_count>0;if(!D&&!m){o.mesh_lod=0,o.texture_lod=0;return}if(D||(l=!0,n=0),!((G=this.cameraFrustrum)!=null&&G.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const _=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let L=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;y.boundingBox||y.computeBoundingBox(),L=y.boundingBox}if(L&&t.isPerspectiveCamera){const y=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(L),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const g=this._tempBox.min,v=this._tempBox.max;let A=g.x,E=g.y,P=v.x,Q=v.y;const ne=2,ge=1.5,ae=(g.x+v.x)*.5,le=(g.y+v.y)*.5;A=(A-ae)*ne+ae,E=(E-le)*ne+le,P=(P-ae)*ne+ae,Q=(Q-le)*ne+le;const Ie=A<0&&P>0?0:Math.min(Math.abs(g.x),Math.abs(v.x)),ke=E<0&&Q>0?0:Math.min(Math.abs(g.y),Math.abs(v.y)),pe=Math.max(Ie,ke);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&_>0&&w.multiplyScalar(_/screen.availHeight),w.x*=y.aspect;const Y=t.matrixWorldInverse,F=this._tempBox2;F.copy(L),F.applyMatrix4(e.matrixWorld),F.applyMatrix4(Y);const O=F.getSize(this._tempBox2Size),q=Math.max(O.x,O.y);if(Math.max(w.x,w.y)!=0&&q!=0&&(w.z=O.z/Math.max(O.x,O.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,k&&C.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const v=C.corner0,A=C.corner1,E=C.corner2,P=C.corner3;v.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=v.x,E.copy(this._tempBox.max),E.y=v.y,P.copy(this._tempBox.max);const Q=(v.z+P.z)*.5;v.z=A.z=E.z=P.z=Q,v.applyMatrix4(g),A.applyMatrix4(g),E.applyMatrix4(g),P.applyMatrix4(g),C.debugDrawLine(v,A,255),C.debugDrawLine(v,E,255),C.debugDrawLine(A,P,255),C.debugDrawLine(E,P,255)}let T=999;if(f&&r.lastScreenCoverage>0){for(let g=0;g<f.length;g++)if(f[g].density/r.lastScreenCoverage<i){T=g;break}}T<n&&(n=T,l=!0)}if(l?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,k&&o.mesh_lod!=r.lastLodLevel_Mesh){const w=f==null?void 0:f[o.mesh_lod];w&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${w.density.toFixed(0)}) - ${e.name}`)}if(m)if(r.lastLodLevel_Texture<0){if(o.texture_lod=c.max_count-1,k){const y=c.lods[c.max_count-1];k&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let w=r.lastScreenCoverage*2;((z=this.context)==null?void 0:z.engine)==="model-viewer"&&(w*=2);const F=_/window.devicePixelRatio*w;for(let O=c.lods.length-1;O>=0;O--){let q=c.lods[O];if(!(qe()&&q.max_height>4096)&&q.max_height>F){if(o.texture_lod=O,o.texture_lod<r.lastLodLevel_Texture){const V=q.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${V}px
|
|
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 b=S;d(b,"registerTexture",(t,e,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,o),!e){M&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=o);const s=o.guid;S.assignLODInformation(t,e,s,r,i,void 0),S.lodInfos.set(s,o),S.lowresCache.set(s,e)}),d(b,"registerMesh",(t,e,r,i,o,s)=>{var f;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),S.assignLODInformation(t,n,e,i,o,s.density),S.lodInfos.set(e,s);let l=S.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(e,l),i>0&&!he(r)&&Ce(r,n);for(const c of X)(f=c.onRegisteredNewMesh)==null||f.call(c,r,s)}),d(b,"lodInfos",new Map),d(b,"previouslyLoaded",new Map),d(b,"lowresCache",new Map);class Ye{constructor(t,e,r,i,o){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const k=ie("debugprogressive"),He=ie("noprogressive"),me=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1};var B,U,fe,j,J,de,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new h.Matrix4);d(this,"cameraFrustrum",new h.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"_lodchangedlisteners",[]);K(this,U,void 0);K(this,fe,new h.Clock);K(this,j,0);K(this,J,0);K(this,de,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new h.Sphere);d(this,"_tempBox",new h.Box3);d(this,"_tempBox2",new h.Box3);d(this,"tempMatrix",new h.Matrix4);d(this,"_tempWorldPosition",new h.Vector3);d(this,"_tempBoxSize",new h.Vector3);d(this,"_tempBox2Size",new h.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[xe]}static addPlugin(t){X.push(t)}static removePlugin(t){const e=X.indexOf(t);e>=0&&X.splice(e,1)}static get(t,e){if(t[me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[me];const r=new C(t,{engine:"unknown",...e});return t[me]=r,r}get plugins(){return X}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(x(this,U))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;$(this,U,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,i){e.renderer.getRenderTarget()==null&&(t=0,$(e,j,x(e,j)+1),$(e,J,x(e,fe).getDelta()),$(e,de,x(e,de)+x(e,J)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,J)),$(e,W,e._fpsBuffer.reduce((l,f)=>l+f)/e._fpsBuffer.length),k&&x(e,j)%30===0&&console.log("FPS",Math.round(x(e,W)),"Interval:",x(e,B)));const s=x(e,j),n=t++;e.onBeforeRender(r,i,n,s),x(e,U).call(this,r,i),e.onAfterRender(r,i,n,s)}}disable(){x(this,U)&&(this.renderer.render=x(this,U),$(this,U,void 0))}onBeforeRender(t,e,r,i){}onAfterRender(t,e,r,i){var l,f;if(this.pause)return;const o=this.renderer.renderLists.get(t,0),s=o.opaque;let n=!0;if(s.length===1){const c=s[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(n=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(n=!1),n){if(He||(this.updateInterval==="auto"?x(this,W)<40&&x(this,B)<10?($(this,B,x(this,B)+1),k&&console.warn("↓ Reducing LOD updates",x(this,B),x(this,W).toFixed(0))):x(this,W)>=80&&x(this,B)>1&&($(this,B,x(this,B)-1),k&&console.warn("↑ Increasing LOD updates",x(this,B),x(this,W).toFixed(0))):$(this,B,this.updateInterval),x(this,B)>0&&i%x(this,B)!=0))return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of s){if(u.material&&(((l=u.geometry)==null?void 0:l.type)==="BoxGeometry"||((f=u.geometry)==null?void 0:f.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){k&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&u.material&&!u.object.progressive_debug_color){u.object.progressive_debug_color=!0;const v=Math.random()*16777215,L=new h.MeshStandardMaterial({color:v});u.object.material=L}const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,i)}const D=o.transparent;for(const u of D){const m=u.object;(m instanceof h.Mesh||m.isMesh)&&this.updateLODs(t,e,m,c,i)}}}updateLODs(t,e,r,i,o){var l,f;r.userData||(r.userData={});let s=r[xe];if(s||(s=new je,r[xe]=s),s.frames++<2)return;for(const c of X)(l=c.onBeforeUpdateLOD)==null||l.call(c,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,i,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let n=R.texture_lod;if(r.material&&n>=0){const c=r["DEBUG:LOD"];c!=null&&(n=c),this.loadProgressiveTextures(r.material,n)}for(const c of X)(f=c.onAfterUpdatedLOD)==null||f.call(c,this.renderer,t,e,r,R);s.lastLodLevel_Mesh=R.mesh_lod,s.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,b.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const r=t.geometry;return b.assignMeshLOD(t,e).then(i=>(i&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(o=>o({type:"mesh",level:e,object:t})),i))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,i=t.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,i,o){var G,z;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const f=b.getMeshLODInformation(e.geometry),c=f==null?void 0:f.lods,D=c&&c.length>0,u=b.getMaterialMinMaxLODsCount(e.material),m=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!D&&!m){o.mesh_lod=0,o.texture_lod=0;return}if(D||(l=!0,n=0),!((G=this.cameraFrustrum)!=null&&G.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let L=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;y.boundingBox||y.computeBoundingBox(),L=y.boundingBox}if(L&&t.isPerspectiveCamera){const y=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(L),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const g=this._tempBox.min,_=this._tempBox.max;let A=g.x,E=g.y,P=_.x,Q=_.y;const ne=2,ge=1.5,ae=(g.x+_.x)*.5,le=(g.y+_.y)*.5;A=(A-ae)*ne+ae,E=(E-le)*ne+le,P=(P-ae)*ne+ae,Q=(Q-le)*ne+le;const Ie=A<0&&P>0?0:Math.min(Math.abs(g.x),Math.abs(_.x)),ke=E<0&&Q>0?0:Math.min(Math.abs(g.y),Math.abs(_.y)),pe=Math.max(Ie,ke);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&v>0&&w.multiplyScalar(v/screen.availHeight),w.x*=y.aspect;const Y=t.matrixWorldInverse,F=this._tempBox2;F.copy(L),F.applyMatrix4(e.matrixWorld),F.applyMatrix4(Y);const O=F.getSize(this._tempBox2Size),q=Math.max(O.x,O.y);if(Math.max(w.x,w.y)!=0&&q!=0&&(w.z=O.z/Math.max(O.x,O.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,k&&C.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const _=C.corner0,A=C.corner1,E=C.corner2,P=C.corner3;_.copy(this._tempBox.min),A.copy(this._tempBox.max),A.x=_.x,E.copy(this._tempBox.max),E.y=_.y,P.copy(this._tempBox.max);const Q=(_.z+P.z)*.5;_.z=A.z=E.z=P.z=Q,_.applyMatrix4(g),A.applyMatrix4(g),E.applyMatrix4(g),P.applyMatrix4(g),C.debugDrawLine(_,A,255),C.debugDrawLine(_,E,255),C.debugDrawLine(A,P,255),C.debugDrawLine(E,P,255)}let T=999;if(c&&r.lastScreenCoverage>0){for(let g=0;g<c.length;g++)if(c[g].density/r.lastScreenCoverage<i){T=g;break}}T<n&&(n=T,l=!0)}if(l?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,k&&o.mesh_lod!=r.lastLodLevel_Mesh){const w=c==null?void 0:c[o.mesh_lod];w&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${w.density.toFixed(0)}) - ${e.name}`)}if(m)if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,k){const y=u.lods[u.max_count-1];k&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let w=r.lastScreenCoverage*2;((z=this.context)==null?void 0:z.engine)==="model-viewer"&&(w*=2);const F=v/window.devicePixelRatio*w;for(let O=u.lods.length-1;O>=0;O--){let q=u.lods[O];if(!(qe()&&q.max_height>4096)&&q.max_height>F){if(o.texture_lod=O,o.texture_lod<r.lastLodLevel_Texture){const V=q.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${V}px
|
|
6
6
|
Screensize: ${F.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
|
|
7
7
|
${e.name}`)}break}}}else o.texture_lod=0}};let I=C;B=new WeakMap,U=new WeakMap,fe=new WeakMap,j=new WeakMap,J=new WeakMap,de=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new h.Vector3),d(I,"corner1",new h.Vector3),d(I,"corner2",new h.Vector3),d(I,"corner3",new h.Vector3),d(I,"_tempPtInside",new h.Vector3);class je{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new h.Vector3);d(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let te=null;function Se(){const a=Je();a&&(a.mapURLs(function(t){return Ee(),t}),Ee(),te==null||te.disconnect(),te=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),te.observe(document,{childList:!0,subtree:!0}))}function Je(){const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function Ee(){document.querySelectorAll("model-viewer").forEach(t=>{Be(t)})}const Pe=new WeakSet;let Qe=0;function Be(a){if(!a||Pe.has(a))return null;Pe.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++Qe+`
|
|
8
|
-
`,a.getAttribute("src"));let t=null,e=null,r=null;for(let i=a;i!=null;i=Object.getPrototypeOf(i)){const o=Object.getOwnPropertySymbols(i),s=o.find(
|
|
8
|
+
`,a.getAttribute("src"));let t=null,e=null,r=null;for(let i=a;i!=null;i=Object.getPrototypeOf(i)){const o=Object.getOwnPropertySymbols(i),s=o.find(f=>f.toString()=="Symbol(renderer)"),n=o.find(f=>f.toString()=="Symbol(scene)"),l=o.find(f=>f.toString()=="Symbol(needsRender)");!t&&s!=null&&(t=a[s].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let i=function(){if(r){let s=0,n=setInterval(()=>{if(s++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=I.get(t,{engine:"model-viewer"});return I.addPlugin(new Ze),o.enable(),o.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",s=>{s.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{i()}),()=>{o.disable()}}return null}class Ze{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,r,i){this.tryParseMeshLOD(e,i),this.tryParseTextureLOD(e,i)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[ce]==!0)return;e[ce]=!0;const r=this.tryGetCurrentGLTF(t),i=this.tryGetCurrentModelViewer(t),o=this.getUrl(i);if(o&&r&&e.material){let s=function(l){var c,D,u;if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const f=Object.keys(l);for(let m=0;m<f.length;m++){const v=f[m],L=l[v];if((L==null?void 0:L.isTexture)===!0){const G=(D=(c=L.userData)==null?void 0:c.associations)==null?void 0:D.textures;if(G==null)continue;const z=r.parser.json.textures[G];if(!z){console.warn("Texture data not found for texture index "+G);continue}if((u=z==null?void 0:z.extensions)!=null&&u[N]){const y=z.extensions[N];y&&o&&b.registerTexture(o,L,y.lods.length,G,y)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)s(l);else s(n)}}tryParseMeshLOD(t,e){var s,n;if(e[Ae]==!0)return;e[Ae]=!0;const r=this.tryGetCurrentModelViewer(t),i=this.getUrl(r);if(!i)return;const o=(n=(s=e.userData)==null?void 0:s.gltfExtensions)==null?void 0:n[N];if(o&&i){const l=e.uuid;b.registerMesh(i,l,e,0,o.lods.length,o)}}}function et(a,t,e,r){ve(t),Oe(e),e.register(o=>new b(o,a));const i=I.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}Se();exports.EXTENSION_NAME=N;exports.LODsManager=I;exports.NEEDLE_progressive=b;exports.VERSION=we;exports.addDracoAndKTX2Loaders=Oe;exports.createLoaders=ve;exports.getRaycastMesh=he;exports.patchModelViewer=Se;exports.registerRaycastMesh=Ce;exports.setDracoDecoderLocation=ze;exports.setKTX2TranscoderLocation=Ue;exports.useNeedleProgressive=et;exports.useRaycastMeshes=Ke;
|
package/lib/extension.js
CHANGED
|
@@ -2,7 +2,7 @@ import { BufferGeometry, Material, Mesh, Texture, TextureLoader } from "three";
|
|
|
2
2
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
3
3
|
import { addDracoAndKTX2Loaders } from "./loaders.js";
|
|
4
4
|
import { getParam, resolveUrl } from "./utils.internal.js";
|
|
5
|
-
import { getRaycastMesh,
|
|
5
|
+
import { getRaycastMesh, registerRaycastMesh } from "./utils.js";
|
|
6
6
|
// All of this has to be removed
|
|
7
7
|
// import { getRaycastMesh, setRaycastMesh } from "../../engine_physics.js";
|
|
8
8
|
// import { PromiseAllWithErrors, resolveUrl } from "../../engine_utils.js";
|
|
@@ -438,7 +438,7 @@ export class NEEDLE_progressive {
|
|
|
438
438
|
for (const key of this.parser.associations.keys()) {
|
|
439
439
|
if (key.isTexture === true) {
|
|
440
440
|
const val = this.parser.associations.get(key);
|
|
441
|
-
if (val
|
|
441
|
+
if (val?.textures === index) {
|
|
442
442
|
found = true;
|
|
443
443
|
NEEDLE_progressive.registerTexture(this.url, key, ext.lods?.length, index, ext);
|
|
444
444
|
}
|
|
@@ -463,7 +463,7 @@ export class NEEDLE_progressive {
|
|
|
463
463
|
for (const entry of this.parser.associations.keys()) {
|
|
464
464
|
if (entry.isMesh) {
|
|
465
465
|
const val = this.parser.associations.get(entry);
|
|
466
|
-
if (val
|
|
466
|
+
if (val?.meshes === index) {
|
|
467
467
|
found = true;
|
|
468
468
|
NEEDLE_progressive.registerMesh(this.url, ext.guid, entry, ext.lods.length, val.primitives, ext);
|
|
469
469
|
}
|
|
@@ -526,7 +526,7 @@ export class NEEDLE_progressive {
|
|
|
526
526
|
existing = [mesh.geometry];
|
|
527
527
|
NEEDLE_progressive.lowresCache.set(key, existing);
|
|
528
528
|
if (level > 0 && !getRaycastMesh(mesh)) {
|
|
529
|
-
|
|
529
|
+
registerRaycastMesh(mesh, geometry);
|
|
530
530
|
}
|
|
531
531
|
for (const plugin of plugins) {
|
|
532
532
|
plugin.onRegisteredNewMesh?.(mesh, ext);
|
package/lib/utils.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare function getRaycastMesh(obj: Object3D): BufferGeometry<any> | nul
|
|
|
11
11
|
* @param obj the object to set the raycast mesh for
|
|
12
12
|
* @param geom the raycast mesh
|
|
13
13
|
*/
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function registerRaycastMesh(obj: Object3D, geom: BufferGeometry): void;
|
|
15
15
|
/**
|
|
16
16
|
* Call this method to enable raycasting with the lowpoly raycast meshes (if available) for all meshes in the scene.
|
|
17
17
|
* This is useful for performance optimization when the scene contains high poly meshes that are not visible to the camera.
|
package/lib/utils.js
CHANGED
|
@@ -17,7 +17,7 @@ export function getRaycastMesh(obj) {
|
|
|
17
17
|
* @param obj the object to set the raycast mesh for
|
|
18
18
|
* @param geom the raycast mesh
|
|
19
19
|
*/
|
|
20
|
-
export function
|
|
20
|
+
export function registerRaycastMesh(obj, geom) {
|
|
21
21
|
if (obj.type === "Mesh" || obj.type === "SkinnedMesh") {
|
|
22
22
|
const existing = getRaycastMesh(obj);
|
|
23
23
|
if (!existing) {
|
package/lib/version.js
CHANGED
package/package.json
CHANGED