@needle-tools/gltf-progressive 1.2.10 → 1.2.12
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 +7 -0
- package/gltf-progressive.js +122 -111
- package/gltf-progressive.min.js +6 -6
- package/gltf-progressive.umd.cjs +5 -5
- package/lib/extension.d.ts +3 -1
- package/lib/extension.js +22 -7
- package/lib/loaders.js +9 -3
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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.12] - 2024-09-23
|
|
8
|
+
- Add: `assignTextureLOD` now also accepts mesh as parameter
|
|
9
|
+
- Change: improved `assignTextureLOD` typing
|
|
10
|
+
|
|
11
|
+
## [1.2.11] - 2024-09-11
|
|
12
|
+
- Fix: draco and KTX decoder path handling when gstatic can not be reached and user set path
|
|
13
|
+
|
|
7
14
|
## [1.2.10] - 2024-09-10
|
|
8
15
|
- Fix: loading and assigning texture LOD for ShaderMaterial and RawShaderMaterial
|
|
9
16
|
|
package/gltf-progressive.js
CHANGED
|
@@ -9,37 +9,38 @@ var m = (a, t, e) => (_e(a, t, "read from private field"), e ? e.call(a) : t.get
|
|
|
9
9
|
throw TypeError("Cannot add the same private member more than once");
|
|
10
10
|
t instanceof WeakSet ? t.add(a) : t.set(a, e);
|
|
11
11
|
}, U = (a, t, e, s) => (_e(a, t, "write to private field"), s ? s.call(a, e) : t.set(a, e), e);
|
|
12
|
-
import { BufferGeometry as
|
|
13
|
-
import { GLTFLoader as
|
|
12
|
+
import { BufferGeometry as ge, Mesh as H, Material as ze, Texture as se, TextureLoader as Ve, Matrix4 as Se, Clock as Ne, MeshStandardMaterial as We, Sphere as Xe, Box3 as be, Vector3 as z } from "three";
|
|
13
|
+
import { GLTFLoader as qe } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
14
14
|
import { MeshoptDecoder as Ke } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
15
15
|
import { DRACOLoader as Ye } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
16
16
|
import { KTX2Loader as He } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
17
17
|
const Ce = "";
|
|
18
18
|
globalThis.GLTF_PROGRESSIVE_VERSION = Ce;
|
|
19
19
|
console.debug(`[gltf-progressive] version ${Ce}`);
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
let j = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", ae = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
|
|
21
|
+
const Je = j, Qe = ae;
|
|
22
|
+
fetch(j + "draco_decoder.js", { method: "head" }).catch((a) => {
|
|
23
|
+
j === Je && (j = "./include/draco/"), ae === Qe && (ae = "./include/ktx2/");
|
|
23
24
|
});
|
|
24
|
-
function
|
|
25
|
-
|
|
25
|
+
function gt(a) {
|
|
26
|
+
j = a;
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
28
|
+
function pt(a) {
|
|
29
|
+
ae = a;
|
|
29
30
|
}
|
|
30
|
-
let Q,
|
|
31
|
+
let Q, he, Z;
|
|
31
32
|
function Be(a) {
|
|
32
|
-
return Q || (Q = new Ye(), Q.setDecoderPath(
|
|
33
|
+
return Q || (Q = new Ye(), Q.setDecoderPath(j), Q.setDecoderConfig({ type: "js" })), Z || (Z = new He(), Z.setTranscoderPath(ae)), he || (he = Ke), a ? Z.detectSupport(a) : a !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: Q, ktx2Loader: Z, meshoptDecoder: he };
|
|
33
34
|
}
|
|
34
35
|
function Ie(a) {
|
|
35
|
-
a.dracoLoader || a.setDRACOLoader(Q), a.ktx2Loader || a.setKTX2Loader(Z), a.meshoptDecoder || a.setMeshoptDecoder(
|
|
36
|
+
a.dracoLoader || a.setDRACOLoader(Q), a.ktx2Loader || a.setKTX2Loader(Z), a.meshoptDecoder || a.setMeshoptDecoder(he);
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
-
function
|
|
38
|
+
le("debugprogressive");
|
|
39
|
+
function le(a) {
|
|
39
40
|
const e = new URL(window.location.href).searchParams.get(a);
|
|
40
41
|
return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
+
function Ze(a, t) {
|
|
43
44
|
if (t === void 0 || t.startsWith("./") || t.startsWith("http") || a === void 0)
|
|
44
45
|
return t;
|
|
45
46
|
const e = a.lastIndexOf("/");
|
|
@@ -51,47 +52,47 @@ function Je(a, t) {
|
|
|
51
52
|
}
|
|
52
53
|
return t;
|
|
53
54
|
}
|
|
54
|
-
let
|
|
55
|
-
function
|
|
56
|
-
return
|
|
55
|
+
let re;
|
|
56
|
+
function je() {
|
|
57
|
+
return re !== void 0 || (re = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), le("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", re)), re;
|
|
57
58
|
}
|
|
58
|
-
const
|
|
59
|
-
function
|
|
60
|
-
return (a == null ? void 0 : a[
|
|
59
|
+
const ve = Symbol("needle:raycast-mesh");
|
|
60
|
+
function me(a) {
|
|
61
|
+
return (a == null ? void 0 : a[ve]) instanceof ge ? a[ve] : null;
|
|
61
62
|
}
|
|
62
|
-
function
|
|
63
|
-
if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !
|
|
64
|
-
const s =
|
|
65
|
-
s.userData = { isRaycastMesh: !0 }, a[
|
|
63
|
+
function et(a, t) {
|
|
64
|
+
if ((a.type === "Mesh" || a.type === "SkinnedMesh") && !me(a)) {
|
|
65
|
+
const s = tt(t);
|
|
66
|
+
s.userData = { isRaycastMesh: !0 }, a[ve] = s;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
|
-
function
|
|
69
|
+
function yt(a = !0) {
|
|
69
70
|
if (a) {
|
|
70
|
-
if (
|
|
71
|
+
if (ie)
|
|
71
72
|
return;
|
|
72
|
-
const t =
|
|
73
|
+
const t = ie = H.prototype.raycast;
|
|
73
74
|
H.prototype.raycast = function(e, s) {
|
|
74
|
-
const n = this, r =
|
|
75
|
+
const n = this, r = me(n);
|
|
75
76
|
let i;
|
|
76
77
|
r && n.isMesh && (i = n.geometry, n.geometry = r), t.call(this, e, s), i && (n.geometry = i);
|
|
77
78
|
};
|
|
78
79
|
} else {
|
|
79
|
-
if (!
|
|
80
|
+
if (!ie)
|
|
80
81
|
return;
|
|
81
|
-
H.prototype.raycast =
|
|
82
|
+
H.prototype.raycast = ie, ie = null;
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
let
|
|
85
|
-
function
|
|
86
|
-
const t = new
|
|
85
|
+
let ie = null;
|
|
86
|
+
function tt(a) {
|
|
87
|
+
const t = new ge();
|
|
87
88
|
for (const e in a.attributes)
|
|
88
89
|
t.setAttribute(e, a.getAttribute(e));
|
|
89
90
|
return t.setIndex(a.getIndex()), t;
|
|
90
91
|
}
|
|
91
|
-
const Y = new Array(), V = "NEEDLE_progressive", x =
|
|
92
|
+
const Y = new Array(), V = "NEEDLE_progressive", x = le("debugprogressive"), Me = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), Oe = /* @__PURE__ */ new Set();
|
|
92
93
|
if (x) {
|
|
93
94
|
let a = function() {
|
|
94
|
-
t += 1, console.log("Toggle LOD level", t,
|
|
95
|
+
t += 1, console.log("Toggle LOD level", t, oe), oe.forEach((n, r) => {
|
|
95
96
|
for (const i of n.keys) {
|
|
96
97
|
const o = r[i];
|
|
97
98
|
if (o != null) {
|
|
@@ -107,7 +108,7 @@ if (x) {
|
|
|
107
108
|
}), t >= e && (t = -1);
|
|
108
109
|
}, t = -1, e = 2, s = !1;
|
|
109
110
|
window.addEventListener("keyup", (n) => {
|
|
110
|
-
n.key === "p" && a(), n.key === "w" && (s = !s,
|
|
111
|
+
n.key === "p" && a(), n.key === "w" && (s = !s, Oe && Oe.forEach((r) => {
|
|
111
112
|
r.name != "BackgroundCubeMaterial" && r.glyphMap == null && "wireframe" in r && (r.wireframe = s);
|
|
112
113
|
}));
|
|
113
114
|
});
|
|
@@ -116,8 +117,8 @@ function Te(a, t, e) {
|
|
|
116
117
|
var n;
|
|
117
118
|
if (!x)
|
|
118
119
|
return;
|
|
119
|
-
|
|
120
|
-
const s =
|
|
120
|
+
oe.has(a) || oe.set(a, { keys: [], sourceId: e });
|
|
121
|
+
const s = oe.get(a);
|
|
121
122
|
((n = s == null ? void 0 : s.keys) == null ? void 0 : n.includes(t)) == !1 && s.keys.push(t);
|
|
122
123
|
}
|
|
123
124
|
const v = class {
|
|
@@ -257,19 +258,29 @@ const v = class {
|
|
|
257
258
|
x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
258
259
|
return Promise.resolve(null);
|
|
259
260
|
}
|
|
260
|
-
/** Load a different resolution of a texture (if available)
|
|
261
|
-
* @param context the context
|
|
262
|
-
* @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
|
|
263
|
-
* @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
|
|
264
|
-
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
265
|
-
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
266
|
-
*/
|
|
267
261
|
static assignTextureLOD(t, e = 0) {
|
|
268
262
|
if (!t)
|
|
269
263
|
return Promise.resolve(null);
|
|
264
|
+
if (t.isMesh === !0) {
|
|
265
|
+
const s = t;
|
|
266
|
+
if (Array.isArray(s.material)) {
|
|
267
|
+
const n = new Array();
|
|
268
|
+
for (const r of s.material) {
|
|
269
|
+
const i = this.assignTextureLOD(r, e);
|
|
270
|
+
n.push(i);
|
|
271
|
+
}
|
|
272
|
+
return Promise.all(n).then((r) => {
|
|
273
|
+
const i = new Array();
|
|
274
|
+
for (const o of r)
|
|
275
|
+
Array.isArray(o) && i.push(...o);
|
|
276
|
+
return i;
|
|
277
|
+
});
|
|
278
|
+
} else
|
|
279
|
+
return this.assignTextureLOD(s.material, e);
|
|
280
|
+
}
|
|
270
281
|
if (t instanceof ze || t.isMaterial === !0) {
|
|
271
282
|
const s = t, n = [], r = new Array();
|
|
272
|
-
if (x &&
|
|
283
|
+
if (x && Oe.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
|
273
284
|
const i = s;
|
|
274
285
|
for (const o of Object.keys(i.uniforms)) {
|
|
275
286
|
const l = i.uniforms[o].value;
|
|
@@ -295,7 +306,7 @@ const v = class {
|
|
|
295
306
|
return o;
|
|
296
307
|
});
|
|
297
308
|
}
|
|
298
|
-
if (t instanceof
|
|
309
|
+
if (t instanceof se || t.isTexture === !0) {
|
|
299
310
|
const s = t;
|
|
300
311
|
return this.assignTextureLODForSlot(s, e, null, null);
|
|
301
312
|
}
|
|
@@ -372,7 +383,7 @@ const v = class {
|
|
|
372
383
|
let i;
|
|
373
384
|
if (t.isTexture === !0) {
|
|
374
385
|
const g = t;
|
|
375
|
-
g.source && g.source[
|
|
386
|
+
g.source && g.source[Me] && (i = g.source[Me]);
|
|
376
387
|
}
|
|
377
388
|
if (i || (i = v.lodInfos.get(r)), i) {
|
|
378
389
|
if (e > 0) {
|
|
@@ -384,7 +395,7 @@ const v = class {
|
|
|
384
395
|
const g = Array.isArray(i.lods) ? (o = i.lods[e]) == null ? void 0 : o.path : i.lods;
|
|
385
396
|
if (!g)
|
|
386
397
|
return x && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
|
|
387
|
-
const p =
|
|
398
|
+
const p = Ze(n.url, g);
|
|
388
399
|
if (p.endsWith(".glb") || p.endsWith(".gltf")) {
|
|
389
400
|
if (!i.guid)
|
|
390
401
|
return console.warn("missing pointer for glb/gltf texture", i), null;
|
|
@@ -393,11 +404,11 @@ const v = class {
|
|
|
393
404
|
s && console.log(`LOD ${e} was already loading/loaded: ${M}`);
|
|
394
405
|
let h = await w.catch(($) => (console.error(`Error loading LOD ${e} from ${p}
|
|
395
406
|
`, $), null)), B = !1;
|
|
396
|
-
if (h == null || (h instanceof
|
|
407
|
+
if (h == null || (h instanceof se && t instanceof se ? (l = h.image) != null && l.data || (u = h.source) != null && u.data ? h = this.copySettings(t, h) : (B = !0, this.previouslyLoaded.delete(M)) : h instanceof ge && t instanceof ge && ((c = h.attributes.position) != null && c.array || (B = !0, this.previouslyLoaded.delete(M)))), !B)
|
|
397
408
|
return h;
|
|
398
409
|
}
|
|
399
410
|
const L = i, F = new Promise(async (h, B) => {
|
|
400
|
-
const $ = new
|
|
411
|
+
const $ = new qe();
|
|
401
412
|
Ie($), x && (await new Promise((A) => setTimeout(A, 1e3)), s && console.warn("Start loading (delayed) " + p, L.guid));
|
|
402
413
|
let I = p;
|
|
403
414
|
if (L && Array.isArray(L.lods)) {
|
|
@@ -408,7 +419,7 @@ const v = class {
|
|
|
408
419
|
`, A), null));
|
|
409
420
|
if (!S)
|
|
410
421
|
return null;
|
|
411
|
-
const
|
|
422
|
+
const X = S.parser;
|
|
412
423
|
s && console.log("Loading finished " + p, L.guid);
|
|
413
424
|
let T = 0;
|
|
414
425
|
if (S.parser.json.textures) {
|
|
@@ -424,8 +435,8 @@ const v = class {
|
|
|
424
435
|
T++;
|
|
425
436
|
}
|
|
426
437
|
if (A) {
|
|
427
|
-
let f = await
|
|
428
|
-
return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof
|
|
438
|
+
let f = await X.getDependency("texture", T);
|
|
439
|
+
return f && v.assignLODInformation(n.url, f, r, e, void 0, void 0), s && console.log('change "' + t.name + '" → "' + f.name + '"', p, T, f, M), t instanceof se && (f = this.copySettings(t, f)), f && (f.guid = L.guid), h(f);
|
|
429
440
|
} else
|
|
430
441
|
x && console.warn("Could not find texture with guid", L.guid, S.parser.json);
|
|
431
442
|
}
|
|
@@ -442,7 +453,7 @@ const v = class {
|
|
|
442
453
|
T++;
|
|
443
454
|
}
|
|
444
455
|
if (A) {
|
|
445
|
-
const f = await
|
|
456
|
+
const f = await X.getDependency("mesh", T), y = L;
|
|
446
457
|
if (s && console.log(`Loaded Mesh "${f.name}"`, p, T, f, M), f.isMesh === !0) {
|
|
447
458
|
const O = f.geometry;
|
|
448
459
|
return v.assignLODInformation(n.url, O, r, e, void 0, y.density), h(O);
|
|
@@ -451,8 +462,8 @@ const v = class {
|
|
|
451
462
|
for (let b = 0; b < f.children.length; b++) {
|
|
452
463
|
const E = f.children[b];
|
|
453
464
|
if (E.isMesh === !0) {
|
|
454
|
-
const
|
|
455
|
-
v.assignLODInformation(n.url,
|
|
465
|
+
const q = E.geometry;
|
|
466
|
+
v.assignLODInformation(n.url, q, r, e, b, y.density), O.push(q);
|
|
456
467
|
}
|
|
457
468
|
}
|
|
458
469
|
return h(O);
|
|
@@ -463,7 +474,7 @@ const v = class {
|
|
|
463
474
|
return h(null);
|
|
464
475
|
});
|
|
465
476
|
return this.previouslyLoaded.set(M, F), await F;
|
|
466
|
-
} else if (t instanceof
|
|
477
|
+
} else if (t instanceof se) {
|
|
467
478
|
s && console.log("Load texture from uri: " + p);
|
|
468
479
|
const w = await new Ve().loadAsync(p);
|
|
469
480
|
return w ? (w.guid = i.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = t.colorSpace, s && console.log(i, w)) : x && console.warn("failed loading", p), w;
|
|
@@ -476,7 +487,7 @@ const v = class {
|
|
|
476
487
|
if (!e)
|
|
477
488
|
return;
|
|
478
489
|
e.userData || (e.userData = {});
|
|
479
|
-
const o = new
|
|
490
|
+
const o = new st(t, s, n, r, i);
|
|
480
491
|
e.userData.LODS = o;
|
|
481
492
|
}
|
|
482
493
|
static getAssignedLODInformation(t) {
|
|
@@ -499,7 +510,7 @@ d(_, "registerTexture", (t, e, s, n, r) => {
|
|
|
499
510
|
x && console.error("gltf-progressive: Register texture without texture");
|
|
500
511
|
return;
|
|
501
512
|
}
|
|
502
|
-
e.source && (e.source[
|
|
513
|
+
e.source && (e.source[Me] = r);
|
|
503
514
|
const i = r.guid;
|
|
504
515
|
v.assignLODInformation(t, e, i, s, n, void 0), v.lodInfos.set(i, r), v.lowresCache.set(i, e);
|
|
505
516
|
}), /**
|
|
@@ -515,14 +526,14 @@ d(_, "registerMesh", (t, e, s, n, r, i) => {
|
|
|
515
526
|
}
|
|
516
527
|
o.userData || (o.userData = {}), v.assignLODInformation(t, o, e, n, r, i.density), v.lodInfos.set(e, i);
|
|
517
528
|
let l = v.lowresCache.get(e);
|
|
518
|
-
l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !
|
|
529
|
+
l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !me(s) && et(s, o);
|
|
519
530
|
for (const c of Y)
|
|
520
531
|
(u = c.onRegisteredNewMesh) == null || u.call(c, s, i);
|
|
521
532
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
522
533
|
d(_, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
523
534
|
d(_, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
524
535
|
d(_, "lowresCache", /* @__PURE__ */ new Map());
|
|
525
|
-
class
|
|
536
|
+
class st {
|
|
526
537
|
constructor(t, e, s, n, r) {
|
|
527
538
|
d(this, "url");
|
|
528
539
|
/** the key to lookup the LOD information */
|
|
@@ -535,8 +546,8 @@ class et {
|
|
|
535
546
|
this.url = t, this.key = e, this.level = s, n != null && (this.index = n), r != null && (this.density = r);
|
|
536
547
|
}
|
|
537
548
|
}
|
|
538
|
-
const k =
|
|
539
|
-
var C, N,
|
|
549
|
+
const k = le("debugprogressive"), rt = le("noprogressive"), De = Symbol("Needle:LODSManager"), we = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), R = { mesh_lod: -1, texture_lod: -1 };
|
|
550
|
+
var C, N, pe, ee, te, ye, W;
|
|
540
551
|
const P = class {
|
|
541
552
|
// readonly plugins: NEEDLE_progressive_plugin[] = [];
|
|
542
553
|
constructor(t, e) {
|
|
@@ -567,14 +578,14 @@ const P = class {
|
|
|
567
578
|
d(this, "manual", !1);
|
|
568
579
|
d(this, "_lodchangedlisteners", []);
|
|
569
580
|
K(this, N, void 0);
|
|
570
|
-
K(this,
|
|
571
|
-
K(this, j, 0);
|
|
581
|
+
K(this, pe, new Ne());
|
|
572
582
|
K(this, ee, 0);
|
|
573
|
-
K(this,
|
|
583
|
+
K(this, te, 0);
|
|
584
|
+
K(this, ye, 0);
|
|
574
585
|
K(this, W, 0);
|
|
575
586
|
d(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
|
|
576
587
|
// private testIfLODLevelsAreAvailable() {
|
|
577
|
-
d(this, "_sphere", new
|
|
588
|
+
d(this, "_sphere", new Xe());
|
|
578
589
|
d(this, "_tempBox", new be());
|
|
579
590
|
d(this, "_tempBox2", new be());
|
|
580
591
|
d(this, "tempMatrix", new Se());
|
|
@@ -585,7 +596,7 @@ const P = class {
|
|
|
585
596
|
}
|
|
586
597
|
/** @internal */
|
|
587
598
|
static getObjectLODState(t) {
|
|
588
|
-
return t[
|
|
599
|
+
return t[we];
|
|
589
600
|
}
|
|
590
601
|
static addPlugin(t) {
|
|
591
602
|
Y.push(t);
|
|
@@ -600,13 +611,13 @@ const P = class {
|
|
|
600
611
|
* @returns The LODsManager instance.
|
|
601
612
|
*/
|
|
602
613
|
static get(t, e) {
|
|
603
|
-
if (t[
|
|
604
|
-
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[
|
|
614
|
+
if (t[De])
|
|
615
|
+
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[De];
|
|
605
616
|
const s = new P(t, {
|
|
606
617
|
engine: "unknown",
|
|
607
618
|
...e
|
|
608
619
|
});
|
|
609
|
-
return t[
|
|
620
|
+
return t[De] = s, s;
|
|
610
621
|
}
|
|
611
622
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
612
623
|
get plugins() {
|
|
@@ -633,7 +644,7 @@ const P = class {
|
|
|
633
644
|
const e = this;
|
|
634
645
|
Be(this.renderer), this.renderer.render = function(s, n) {
|
|
635
646
|
const r = e.renderer.getRenderTarget();
|
|
636
|
-
(r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e,
|
|
647
|
+
(r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e, ee, m(e, ee) + 1), U(e, te, m(e, pe).getDelta()), U(e, ye, m(e, ye) + m(e, te)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, te)), U(e, W, e._fpsBuffer.reduce((o, l) => o + l) / e._fpsBuffer.length), k && m(e, ee) % 200 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
|
|
637
648
|
const i = t++;
|
|
638
649
|
m(e, N).call(this, s, n), e.onAfterRender(s, n, i);
|
|
639
650
|
};
|
|
@@ -654,7 +665,7 @@ const P = class {
|
|
|
654
665
|
(o.name === "EffectMaterial" || o.name === "CopyShader") && (i = !1);
|
|
655
666
|
}
|
|
656
667
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
|
|
657
|
-
if (
|
|
668
|
+
if (rt || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? (U(this, C, m(this, C) + 1), k && console.warn("↓ Reducing LOD updates", m(this, C), m(this, W).toFixed(0))) : m(this, W) >= 60 && m(this, C) > 1 && (U(this, C, m(this, C) - 1), k && console.warn("↑ Increasing LOD updates", m(this, C), m(this, W).toFixed(0))) : U(this, C, this.updateInterval), m(this, C) > 0 && m(this, ee) % m(this, C) != 0))
|
|
658
669
|
return;
|
|
659
670
|
this.internalUpdate(t, e);
|
|
660
671
|
}
|
|
@@ -704,8 +715,8 @@ const P = class {
|
|
|
704
715
|
updateLODs(t, e, s, n) {
|
|
705
716
|
var o, l;
|
|
706
717
|
s.userData || (s.userData = {});
|
|
707
|
-
let r = s[
|
|
708
|
-
if (r || (r = new
|
|
718
|
+
let r = s[we];
|
|
719
|
+
if (r || (r = new it(), s[we] = r), r.frames++ < 2)
|
|
709
720
|
return;
|
|
710
721
|
for (const u of Y)
|
|
711
722
|
(o = u.onBeforeUpdateLOD) == null || o.call(u, this.renderer, t, e, s);
|
|
@@ -783,7 +794,7 @@ const P = class {
|
|
|
783
794
|
if (!D.boundingBox)
|
|
784
795
|
D.computeBoundingBox();
|
|
785
796
|
else if (s.frames % 30 === 0) {
|
|
786
|
-
const h =
|
|
797
|
+
const h = me(D), B = D.geometry;
|
|
787
798
|
h && (D.geometry = h), D.computeBoundingBox(), D.geometry = B;
|
|
788
799
|
}
|
|
789
800
|
L = D.boundingBox;
|
|
@@ -804,11 +815,11 @@ const P = class {
|
|
|
804
815
|
}
|
|
805
816
|
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && D.fov > 70) {
|
|
806
817
|
const f = this._tempBox.min, y = this._tempBox.max;
|
|
807
|
-
let O = f.x, b = f.y, E = y.x,
|
|
808
|
-
const
|
|
809
|
-
O = (O -
|
|
810
|
-
const Ge = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), Fe = b < 0 &&
|
|
811
|
-
s.lastCentrality = (
|
|
818
|
+
let O = f.x, b = f.y, E = y.x, q = y.y;
|
|
819
|
+
const ce = 2, xe = 1.5, ue = (f.x + y.x) * 0.5, fe = (f.y + y.y) * 0.5;
|
|
820
|
+
O = (O - ue) * ce + ue, b = (b - fe) * ce + fe, E = (E - ue) * ce + ue, q = (q - fe) * ce + fe;
|
|
821
|
+
const Ge = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), Fe = b < 0 && q > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), Le = Math.max(Ge, Fe);
|
|
822
|
+
s.lastCentrality = (xe - Le) * (xe - Le) * (xe - Le);
|
|
812
823
|
} else
|
|
813
824
|
s.lastCentrality = 1;
|
|
814
825
|
const h = this._tempBox.getSize(this._tempBoxSize);
|
|
@@ -821,8 +832,8 @@ const P = class {
|
|
|
821
832
|
f.invert();
|
|
822
833
|
const y = P.corner0, O = P.corner1, b = P.corner2, E = P.corner3;
|
|
823
834
|
y.copy(this._tempBox.min), O.copy(this._tempBox.max), O.x = y.x, b.copy(this._tempBox.max), b.y = y.y, E.copy(this._tempBox.max);
|
|
824
|
-
const
|
|
825
|
-
y.z = O.z = b.z = E.z =
|
|
835
|
+
const q = (y.z + E.z) * 0.5;
|
|
836
|
+
y.z = O.z = b.z = E.z = q, y.applyMatrix4(f), O.applyMatrix4(f), b.applyMatrix4(f), E.applyMatrix4(f), P.debugDrawLine(y, O, 255), P.debugDrawLine(y, b, 255), P.debugDrawLine(O, E, 255), P.debugDrawLine(b, E, 255);
|
|
826
837
|
}
|
|
827
838
|
let T = 999;
|
|
828
839
|
if (c && s.lastScreenCoverage > 0) {
|
|
@@ -851,10 +862,10 @@ const P = class {
|
|
|
851
862
|
((F = this.context) == null ? void 0 : F.engine) === "model-viewer" && (B *= 2);
|
|
852
863
|
const I = w / window.devicePixelRatio * B;
|
|
853
864
|
for (let S = p.lods.length - 1; S >= 0; S--) {
|
|
854
|
-
let
|
|
855
|
-
if (!(D &&
|
|
865
|
+
let X = p.lods[S];
|
|
866
|
+
if (!(D && X.max_height >= 2048) && !(je() && X.max_height > 4096) && X.max_height > I) {
|
|
856
867
|
if (r.texture_lod = S, r.texture_lod < s.lastLodLevel_Texture) {
|
|
857
|
-
const T =
|
|
868
|
+
const T = X.max_height;
|
|
858
869
|
k && console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${T}px
|
|
859
870
|
Screensize: ${I.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
|
|
860
871
|
${e.name}`);
|
|
@@ -868,10 +879,10 @@ ${e.name}`);
|
|
|
868
879
|
}
|
|
869
880
|
};
|
|
870
881
|
let G = P;
|
|
871
|
-
C = new WeakMap(), N = new WeakMap(),
|
|
882
|
+
C = new WeakMap(), N = new WeakMap(), pe = new WeakMap(), ee = new WeakMap(), te = new WeakMap(), ye = new WeakMap(), W = new WeakMap(), /** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
|
|
872
883
|
*/
|
|
873
884
|
d(G, "debugDrawLine"), d(G, "corner0", new z()), d(G, "corner1", new z()), d(G, "corner2", new z()), d(G, "corner3", new z()), d(G, "_tempPtInside", new z());
|
|
874
|
-
class
|
|
885
|
+
class it {
|
|
875
886
|
constructor() {
|
|
876
887
|
d(this, "frames", 0);
|
|
877
888
|
d(this, "lastLodLevel_Mesh", -1);
|
|
@@ -881,21 +892,21 @@ class st {
|
|
|
881
892
|
d(this, "lastCentrality", 0);
|
|
882
893
|
}
|
|
883
894
|
}
|
|
884
|
-
const Ae = Symbol("NEEDLE_mesh_lod"),
|
|
885
|
-
let
|
|
895
|
+
const Ae = Symbol("NEEDLE_mesh_lod"), de = Symbol("NEEDLE_texture_lod");
|
|
896
|
+
let ne = null;
|
|
886
897
|
function ke() {
|
|
887
|
-
const a =
|
|
898
|
+
const a = nt();
|
|
888
899
|
a && (a.mapURLs(function(t) {
|
|
889
900
|
return Ee(), t;
|
|
890
|
-
}), Ee(),
|
|
901
|
+
}), Ee(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
|
|
891
902
|
t.forEach((e) => {
|
|
892
903
|
e.addedNodes.forEach((s) => {
|
|
893
904
|
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Re(s);
|
|
894
905
|
});
|
|
895
906
|
});
|
|
896
|
-
}),
|
|
907
|
+
}), ne.observe(document, { childList: !0, subtree: !0 }));
|
|
897
908
|
}
|
|
898
|
-
function
|
|
909
|
+
function nt() {
|
|
899
910
|
if (typeof customElements > "u")
|
|
900
911
|
return null;
|
|
901
912
|
const a = customElements.get("model-viewer");
|
|
@@ -911,11 +922,11 @@ function Ee() {
|
|
|
911
922
|
});
|
|
912
923
|
}
|
|
913
924
|
const Pe = /* @__PURE__ */ new WeakSet();
|
|
914
|
-
let
|
|
925
|
+
let ot = 0;
|
|
915
926
|
function Re(a) {
|
|
916
927
|
if (!a || Pe.has(a))
|
|
917
928
|
return null;
|
|
918
|
-
Pe.add(a), console.debug("[gltf-progressive] found new model-viewer..." + ++
|
|
929
|
+
Pe.add(a), console.debug("[gltf-progressive] found new model-viewer..." + ++ot + `
|
|
919
930
|
`, a.getAttribute("src"));
|
|
920
931
|
let t = null, e = null, s = null;
|
|
921
932
|
for (let n = a; n != null; n = Object.getPrototypeOf(n)) {
|
|
@@ -936,7 +947,7 @@ function Re(a) {
|
|
|
936
947
|
};
|
|
937
948
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
938
949
|
const r = G.get(t, { engine: "model-viewer" });
|
|
939
|
-
return G.addPlugin(new
|
|
950
|
+
return G.addPlugin(new at()), r.enable(), r.addEventListener("changed", () => {
|
|
940
951
|
s == null || s.call(a);
|
|
941
952
|
}), a.addEventListener("model-visibility", (i) => {
|
|
942
953
|
i.detail.visible && (s == null || s.call(a));
|
|
@@ -948,7 +959,7 @@ function Re(a) {
|
|
|
948
959
|
}
|
|
949
960
|
return null;
|
|
950
961
|
}
|
|
951
|
-
class
|
|
962
|
+
class at {
|
|
952
963
|
constructor() {
|
|
953
964
|
d(this, "_didWarnAboutMissingUrl", !1);
|
|
954
965
|
}
|
|
@@ -968,16 +979,16 @@ class nt {
|
|
|
968
979
|
return t.element;
|
|
969
980
|
}
|
|
970
981
|
tryParseTextureLOD(t, e) {
|
|
971
|
-
if (e[
|
|
982
|
+
if (e[de] == !0)
|
|
972
983
|
return;
|
|
973
|
-
e[
|
|
984
|
+
e[de] = !0;
|
|
974
985
|
const s = this.tryGetCurrentGLTF(t), n = this.tryGetCurrentModelViewer(t), r = this.getUrl(n);
|
|
975
986
|
if (r && s && e.material) {
|
|
976
987
|
let i = function(l) {
|
|
977
988
|
var c, g, p;
|
|
978
|
-
if (l[
|
|
989
|
+
if (l[de] == !0)
|
|
979
990
|
return;
|
|
980
|
-
l[
|
|
991
|
+
l[de] = !0, l.userData && (l.userData.LOD = -1);
|
|
981
992
|
const u = Object.keys(l);
|
|
982
993
|
for (let M = 0; M < u.length; M++) {
|
|
983
994
|
const w = u[M], L = l[w];
|
|
@@ -1020,7 +1031,7 @@ class nt {
|
|
|
1020
1031
|
}
|
|
1021
1032
|
}
|
|
1022
1033
|
}
|
|
1023
|
-
function
|
|
1034
|
+
function mt(a, t, e, s) {
|
|
1024
1035
|
Be(t), Ie(e), e.register((r) => new _(r, a));
|
|
1025
1036
|
const n = G.get(t);
|
|
1026
1037
|
return (s == null ? void 0 : s.enableLODsManager) !== !1 && n.enable(), n;
|
|
@@ -1033,11 +1044,11 @@ export {
|
|
|
1033
1044
|
Ce as VERSION,
|
|
1034
1045
|
Ie as addDracoAndKTX2Loaders,
|
|
1035
1046
|
Be as createLoaders,
|
|
1036
|
-
|
|
1047
|
+
me as getRaycastMesh,
|
|
1037
1048
|
ke as patchModelViewer,
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1049
|
+
et as registerRaycastMesh,
|
|
1050
|
+
gt as setDracoDecoderLocation,
|
|
1051
|
+
pt as setKTX2TranscoderLocation,
|
|
1052
|
+
mt as useNeedleProgressive,
|
|
1053
|
+
yt as useRaycastMeshes
|
|
1043
1054
|
};
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var Re=Object.defineProperty,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ie,Mesh as q,Material as Ge,Texture as Q,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const ge="";globalThis.GLTF_PROGRESSIVE_VERSION=ge,console.debug(`[gltf-progressive] version ${ge}`);let le="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",me="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(le+"draco_decoder.js",{method:"head"}).catch(t=>{le="./include/draco/",me="./include/ktx2/"});function Xe(t){le=t}function Ke(t){me=t}let K,ae,H;function pe(t){return K||(K=new Ve,K.setDecoderPath(le),K.setDecoderConfig({type:"js"})),H||(H=new qe,H.setTranscoderPath(me)),ae||(ae=ze),t?H.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:H,meshoptDecoder:ae}}function ve(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(H),t.meshoptDecoder||t.setMeshoptDecoder(ae)}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 He(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function Ye(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const xe=Symbol("needle:raycast-mesh");function ee(t){return t?.[xe]instanceof ie?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=Qe(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Je(t=!0){if(t){if(te)return;const e=te=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=ee(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!te)return;q.prototype.raycast=te,te=null}}let te=null;function Qe(t){const e=new ie;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,R="NEEDLE_progressive",y=Z("debugprogressive"),ye=Symbol("needle-progressive-texture"),re=new Map,Le=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,re),re.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null){if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!y)return;re.has(t)||re.set(t,{keys:[],sourceId:r});const s=re.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[R];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;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[n]=e,e}if(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,y&&Ee(t,"geometry",s.url)):y&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),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 Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(y&&Le.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof Q||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(y&&n&&r){const o=this.getAssignedLODInformation(t);o&&Ee(r,n,o.url)}}return s}else y=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[R];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[R];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=y=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const f=t;f.source&&f.source[ye]&&(l=f.source[ye])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return y&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=He(a.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,O),null)),_=!1;if(d==null||(d instanceof
|
|
3
|
-
`,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let
|
|
1
|
+
var Re=Object.defineProperty,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ae,Mesh as q,Material as Ge,Texture as Z,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let K="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Xe=K,Ke=ee;fetch(K+"draco_decoder.js",{method:"head"}).catch(t=>{K===Xe&&(K="./include/draco/"),ee===Ke&&(ee="./include/ktx2/")});function He(t){K=t}function Ye(t){ee=t}let H,ue,Y;function pe(t){return H||(H=new Ve,H.setDecoderPath(K),H.setDecoderConfig({type:"js"})),Y||(Y=new qe,Y.setTranscoderPath(ee)),ue||(ue=ze),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:H,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(H),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}te("debugprogressive");function te(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 r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ce;function Qe(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const xe=Symbol("needle:raycast-mesh");function re(t){return t?.[xe]instanceof ae?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Ze(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=re(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function et(t){const e=new ae;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,R="NEEDLE_progressive",v=te("debugprogressive"),ve=Symbol("needle-progressive-texture"),oe=new Map,Le=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,oe),oe.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null){if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!v)return;oe.has(t)||oe.set(t,{keys:[],sourceId:r});const s=oe.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[R];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null}),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;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[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ee(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),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.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t instanceof Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&Le.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o&&Ee(r,n,o.url)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[R];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[R];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const f=t;f.source&&f.source[ve]&&(l=f.source[ve])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Je(a.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,O),null)),_=!1;if(d==null||(d instanceof Z&&t instanceof Z?(n=d.image)!=null&&n.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(_=!0,this.previouslyLoaded.delete(p)):d instanceof ae&&t instanceof ae&&((o=d.attributes.position)!=null&&o.array||(_=!0,this.previouslyLoaded.delete(p)))),!_)return d}const D=l,L=new Promise(async(d,_)=>{const O=new Ue;ye(O),v&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let I=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(I+="?v="+m.hash)}const T=await O.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let y=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){let h=await W.getDependency("texture",y);return h&&w.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,y,h,p),t instanceof Z&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else v&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(y=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){const h=await W.getDependency("mesh",y),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,y,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(a.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(a.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else v&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Z){i&&console.log("Load texture from uri: "+g);const p=await new Ne().loadAsync(g);return p?(p.guid=l.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(l,p)):v&&console.warn("failed loading",g),p}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new tt(t,r,n,s,o);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(),v&&console.warn(`Copying texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,n,s)=>{if(y&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(S,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){y&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!ee(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Ze{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=Z("debugprogressive"),et=Z("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),Y=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,J,se,ce,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,J,0),V(this,se,0),V(this,ce,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.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 B(t,{engine:"unknown",...e});return t[Me]=r,r}get plugins(){return F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(x(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,J,x(e,J)+1),G(e,se,x(e,we).getDelta()),G(e,ce,x(e,ce)+x(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,se)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,J)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(et||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,J)%x(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){P&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new tt,r[De]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,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);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[Y]===void 0||e<t[Y])&&(r=!0),r&&(t[Y]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[Y]!==e){t[Y]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[Y]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=ee(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=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 v=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(v)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const v=this._tempBox.min,m=this._tempBox.max;let h=v.x,M=v.y,b=m.x,C=m.y;const z=2,X=1.5,oe=(v.x+m.x)*.5,ne=(v.y+m.y)*.5;h=(h-oe)*z+oe,M=(M-ne)*z+ne,b=(b-oe)*z+oe,C=(C-ne)*z+ne;const ke=h<0&&b>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),fe=Math.max(ke,Ce);r.lastCentrality=(X-fe)*(X-fe)*(X-fe)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(v),h.applyMatrix4(v),M.applyMatrix4(v),b.applyMatrix4(v),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let v=0;v<l.length;v++)if(l[v].density/r.lastScreenCoverage<n){W=v;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Ye()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}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 S=w;c(S,"registerTexture",(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ve]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(S,"registerMesh",(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){v&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!re(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class tt{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=te("debugprogressive"),rt=te("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,Q,ne,de,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,Q,0),V(this,ne,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.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 B(t,{engine:"unknown",...e});return t[Me]=r,r}get plugins(){return F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(x(this,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,G(e,Q,x(e,Q)+1),G(e,ne,x(e,we).getDelta()),G(e,de,x(e,de)+x(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,ne)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,Q)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(rt||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,Q)%x(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){P&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new st,r[De]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,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);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=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 y=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const y=this._tempBox.min,m=this._tempBox.max;let h=y.x,M=y.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(y.x+m.x)*.5,le=(y.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-le)*z+le,b=(b-ie)*z+ie,C=(C-le)*z+le;const ke=h<0&&b>0?0:Math.min(Math.abs(y.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(m.y)),ge=Math.max(ke,Ce);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(y),h.applyMatrix4(y),M.applyMatrix4(y),b.applyMatrix4(y),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let y=0;y<l.length;y++)if(l[y].density/r.lastScreenCoverage<n){W=y;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Qe()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}px
|
|
6
6
|
Screensize: ${O.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${d.toFixed(1)}
|
|
7
|
-
${e.name}`)}break}}}}else s.texture_lod=0}};let j=B;E=new WeakMap,$=new WeakMap,we=new WeakMap,
|
|
8
|
-
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new
|
|
7
|
+
${e.name}`)}break}}}}else s.texture_lod=0}};let j=B;E=new WeakMap,$=new WeakMap,we=new WeakMap,Q=new WeakMap,ne=new WeakMap,de=new WeakMap,U=new WeakMap,c(j,"debugDrawLine"),c(j,"corner0",new N),c(j,"corner1",new N),c(j,"corner2",new N),c(j,"corner3",new N),c(j,"_tempPtInside",new N);class st{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new N),c(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let fe=null;function _e(){const t=ot();t&&(t.mapURLs(function(e){return Ie(),e}),Ie(),fe?.disconnect(),fe=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&Pe(n)})})}),fe.observe(document,{childList:!0,subtree:!0}))}function ot(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),_e()}),null)}function Ie(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Pe(t)})}const Be=new WeakSet;let nt=0;function Pe(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++nt+`
|
|
8
|
+
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new it),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class it{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[he]==!0)return;r[he]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var l,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(l=L.userData)==null?void 0:l.associations)==null?void 0:f.textures;if(d==null)continue;const _=n.parser.json.textures[d];if(!_){console.warn("Texture data not found for texture index "+d);continue}if((g=_?.extensions)!=null&&g[R]){const O=_.extensions[R];O&&o&&S.registerTexture(o,L,O.lods.length,d,O)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[Ae]==!0)return;r[Ae]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(a&&i){const u=r.uuid;S.registerMesh(i,u,r,0,a.lods.length,a)}}}function lt(t,e,r,n){pe(e),ye(r),r.register(o=>new S(o,t));const s=j.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}_e();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,me as VERSION,ye as addDracoAndKTX2Loaders,pe as createLoaders,re as getRaycastMesh,_e as patchModelViewer,Te 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 ke=(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)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(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)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),De="";globalThis.GLTF_PROGRESSIVE_VERSION=De;console.debug(`[gltf-progressive] version ${De}`);let fe="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",we="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(fe+"draco_decoder.js",{method:"head"}).catch(a=>{fe="./include/draco/",we="./include/ktx2/"});function Ne(a){fe=a}function Ue(a){we=a}let J,ue,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(fe),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(we)),ue||(ue=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:ue}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(ue)}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 ze(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 ee;function We(){return ee!==void 0||(ee=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ie("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ee)),ee}const xe=Symbol("needle:raycast-mesh");function oe(a){return(a==null?void 0:a[xe])instanceof p.BufferGeometry?a[xe]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!oe(a)){const r=Xe(t);r.userData={isRaycastMesh:!0},a[xe]=r}}function qe(a=!0){if(a){if(te)return;const t=te=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=oe(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!te)return;p.Mesh.prototype.raycast=te,te=null}}let te=null;function Xe(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ie("debugprogressive"),ye=Symbol("needle-progressive-texture"),se=new Map,Me=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,se),se.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",o=>{o.key==="p"&&a(),o.key==="w"&&(r=!r,Me&&Me.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)return;se.has(a)||se.set(a,{keys:[],sourceId:e});const r=se.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}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,o="LODS:minmax",s=t[o];if(s!=null)return s;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[o]=e,e}if(x==="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&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.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 g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&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 p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&Me.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.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)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[ye]&&(i=g.source[ye])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=ze(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
1
|
+
"use strict";var Re=Object.defineProperty;var ke=(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)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(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)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let Z="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ne=Z,Ue=oe;fetch(Z+"draco_decoder.js",{method:"head"}).catch(a=>{Z===Ne&&(Z="./include/draco/"),oe===Ue&&(oe="./include/ktx2/")});function ze(a){Z=a}function We(a){oe=a}let J,de,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(Z),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(oe)),de||(de=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:de}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(de)}ne("debugprogressive");function ne(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function qe(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 te;function Xe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ae(a){return(a==null?void 0:a[Me])instanceof p.BufferGeometry?a[Me]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ae(a)){const r=Ye(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(re)return;const t=re=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=ae(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!re)return;p.Mesh.prototype.raycast=re,re=null}}let re=null;function Ye(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),me=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",o=>{o.key==="p"&&a(),o.key==="w"&&(r=!r,De&&De.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)return;ie.has(a)||ie.set(a,{keys:[],sourceId:e});const r=ie.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}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,o="LODS:minmax",s=t[o];if(s!=null)return s;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[o]=e,e}if(x==="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&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.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 g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&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.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const i=this.assignTextureLOD(s,e);o.push(i)}return Promise.all(o).then(s=>{const i=new Array;for(const n of s)Array.isArray(n)&&i.push(...n);return i})}else return this.assignTextureLOD(r.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.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)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[me]&&(i=g.source[me])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=qe(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
2
|
`,$),null)),R=!1;if(h==null||(h instanceof p.Texture&&t instanceof p.Texture?(l=h.image)!=null&&l.data||(u=h.source)!=null&&u.data?h=this.copySettings(t,h):(R=!0,this.previouslyLoaded.delete(D)):h instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=h.attributes.position)!=null&&c.array||(R=!0,this.previouslyLoaded.delete(D)))),!R)return h}const M=i,F=new Promise(async(h,R)=>{const $=new Ge.GLTFLoader;_e($),x&&(await new Promise(E=>setTimeout(E,1e3)),r&&console.warn("Start loading (delayed) "+y,M.guid));let k=y;if(M&&Array.isArray(M.lods)){const E=M.lods[e];E.hash&&(k+="?v="+E.hash)}const b=await $.loadAsync(k).catch(E=>(console.error(`Error loading LOD ${e} from ${y}
|
|
3
|
-
`,E),null));if(!b)return null;const q=b.parser;r&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(r&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,s,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,s,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,F),await F}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,i){if(!e)return;e.userData||(e.userData={});const n=new
|
|
3
|
+
`,E),null));if(!b)return null;const q=b.parser;r&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(r&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,s,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,s,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,F),await F}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,i){if(!e)return;e.userData||(e.userData={});const n=new He(t,r,o,s,i);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(),x&&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 O=_;d(O,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=s);const i=s.guid;_.assignLODInformation(t,e,i,r,o,void 0),_.lodInfos.set(i,s),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,r,o,s,i)=>{var u;x&&console.log("> Progressive: register mesh",s,r.name,i,r.uuid,r);const n=r.geometry;if(!n){x&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),_.assignLODInformation(t,n,e,o,s,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],_.lowresCache.set(e,l),o>0&&!oe(r)&&Pe(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Ke{constructor(t,e,r,o,s){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const G=ie("debugprogressive"),Ye=ie("noprogressive"),me=Symbol("Needle:LODSManager"),Le=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),V={mesh_lod:-1,texture_lod:-1};var B,z,de,Z,j,he,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,de,new p.Clock);K(this,Z,0);K(this,j,0);K(this,he,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Le]}static addPlugin(t){Y.push(t)}static removePlugin(t){const e=Y.indexOf(t);e>=0&&Y.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 Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+1),N(e,j,L(e,de).getDelta()),N(e,he,L(e,he)+L(e,j)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,j)),N(e,W,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),G&&L(e,Z)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,z)&&(this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(s.length===1){const n=s[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Ye||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,Z)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const c of o){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")){G&&(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(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const i=r.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const n=r.transmissive;for(const c of n){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[Le];if(s||(s=new He,r[Le]=s),s.frames++<2)return;for(const u of Y)(n=u.onBeforeUpdateLOD)==null||n.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,o,V),V.mesh_lod=Math.round(V.mesh_lod),V.texture_lod=Math.round(V.texture_lod),V.mesh_lod>=0&&this.loadProgressiveMeshes(r,V.mesh_lod);let i=V.texture_lod;if(r.material&&i>=0){const u=r["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(r.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,V);s.lastLodLevel_Mesh=V.mesh_lod,s.lastLodLevel_Texture=V.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({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 O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,i=(r.y+o.y)*.5;return this._tempPtInside.set(s,i,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var F;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let n=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){s.mesh_lod=0,s.texture_lod=0;return}g||(l=!0,n=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(r.frames%30===0){const h=oe(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const ne=2,ge=1.5,ae=(f.x+m.x)*.5,le=(f.y+m.y)*.5;S=(S-ae)*ne+ae,T=(T-le)*ne+le,P=(P-ae)*ne+ae,X=(X-le)*ne+le;const Be=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ie=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),pe=Math.max(Be,Ie);r.lastCentrality=(ge-pe)*(ge-pe)*(ge-pe)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&r.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/r.lastScreenCoverage<o){A=f;break}}A<n&&(n=A,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const h=c==null?void 0:c[s.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let R=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(We()&&q.max_height>4096)&&q.max_height>k){if(s.texture_lod=b,s.texture_lod<r.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${A}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 O=_;d(O,"registerTexture",(t,e,r,o,s)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[me]=s);const i=s.guid;_.assignLODInformation(t,e,i,r,o,void 0),_.lodInfos.set(i,s),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,r,o,s,i)=>{var u;x&&console.log("> Progressive: register mesh",s,r.name,i,r.uuid,r);const n=r.geometry;if(!n){x&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),_.assignLODInformation(t,n,e,o,s,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],_.lowresCache.set(e,l),o>0&&!ae(r)&&Pe(r,n);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,r,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class He{constructor(t,e,r,o,s){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const G=ne("debugprogressive"),Je=ne("noprogressive"),Le=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),V={mesh_lod:-1,texture_lod:-1};var B,z,he,j,ee,ge,W;const C=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval","auto");K(this,B,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);K(this,z,void 0);K(this,he,new p.Clock);K(this,j,0);K(this,ee,0);K(this,ge,0);K(this,W,0);d(this,"_fpsBuffer",[60,60,60,60,60]);d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[xe]}static addPlugin(t){Y.push(t)}static removePlugin(t){const e=Y.indexOf(t);e>=0&&Y.splice(e,1)}static get(t,e){if(t[Le])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Le];const r=new C(t,{engine:"unknown",...e});return t[Le]=r,r}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(L(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,z,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,N(e,j,L(e,j)+1),N(e,ee,L(e,he).getDelta()),N(e,ge,L(e,ge)+L(e,ee)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,ee)),N(e,W,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),G&&L(e,j)%200===0&&console.log("FPS",Math.round(L(e,W)),"Interval:",L(e,B)));const i=t++;L(e,z).call(this,r,o),e.onAfterRender(r,o,i)}}disable(){L(this,z)&&(this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(s.length===1){const n=s[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Je||(this.updateInterval==="auto"?L(this,W)<40&&L(this,B)<10?(N(this,B,L(this,B)+1),G&&console.warn("↓ Reducing LOD updates",L(this,B),L(this,W).toFixed(0))):L(this,W)>=60&&L(this,B)>1&&(N(this,B,L(this,B)-1),G&&console.warn("↑ Increasing LOD updates",L(this,B),L(this,W).toFixed(0))):N(this,B,this.updateInterval),L(this,B)>0&&L(this,j)%L(this,B)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const c of o){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")){G&&(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(G==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const y=Math.random()*16777215,D=new p.MeshStandardMaterial({color:y});c.object.material=D}const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const i=r.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}const n=r.transmissive;for(const c of n){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,s)}}updateLODs(t,e,r,o){var n,l;r.userData||(r.userData={});let s=r[xe];if(s||(s=new Qe,r[xe]=s),s.frames++<2)return;for(const u of Y)(n=u.onBeforeUpdateLOD)==null||n.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,s,o,V),V.mesh_lod=Math.round(V.mesh_lod),V.texture_lod=Math.round(V.texture_lod),V.mesh_lod>=0&&this.loadProgressiveMeshes(r,V.mesh_lod);let i=V.texture_lod;if(r.material&&i>=0){const u=r["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(r.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,V);s.lastLodLevel_Mesh=V.mesh_lod,s.lastLodLevel_Texture=V.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[H]===void 0||e<t[H])&&(r=!0),r&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({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 O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,i=(r.y+o.y)*.5;return this._tempPtInside.set(s,i,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var F;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let n=10+1,l=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),c=u==null?void 0:u.lods,g=c&&c.length>0,y=O.getMaterialMinMaxLODsCount(e.material),D=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!g&&!D){s.mesh_lod=0,s.texture_lod=0;return}g||(l=!0,n=0);const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const w=e;if(!w.boundingBox)w.computeBoundingBox();else if(r.frames%30===0){const h=ae(w),R=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=R}M=w.boundingBox}if(M&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let S=f.x,T=f.y,P=m.x,X=m.y;const le=2,pe=1.5,ce=(f.x+m.x)*.5,ue=(f.y+m.y)*.5;S=(S-ce)*le+ce,T=(T-ue)*le+ue,P=(P-ce)*le+ce,X=(X-ue)*le+ue;const Be=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ie=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max(Be,Ie);r.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&v>0&&h.multiplyScalar(v/screen.availHeight),h.x*=w.aspect;const R=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(R);const k=$.getSize(this._tempBox2Size),b=Math.max(k.x,k.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=k.z/Math.max(k.x,k.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,G&&C.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=C.corner0,S=C.corner1,T=C.corner2,P=C.corner3;m.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=m.x,T.copy(this._tempBox.max),T.y=m.y,P.copy(this._tempBox.max);const X=(m.z+P.z)*.5;m.z=S.z=T.z=P.z=X,m.applyMatrix4(f),S.applyMatrix4(f),T.applyMatrix4(f),P.applyMatrix4(f),C.debugDrawLine(m,S,255),C.debugDrawLine(m,T,255),C.debugDrawLine(S,P,255),C.debugDrawLine(T,P,255)}let A=999;if(c&&r.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/r.lastScreenCoverage<o){A=f;break}}A<n&&(n=A,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const h=c==null?void 0:c[s.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let R=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(R*=2);const k=v/window.devicePixelRatio*R;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(Xe()&&q.max_height>4096)&&q.max_height>k){if(s.texture_lod=b,s.texture_lod<r.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${A}px
|
|
6
6
|
Screensize: ${k.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
|
|
7
|
-
${e.name}`)}break}}}}else s.texture_lod=0}};let I=C;B=new WeakMap,z=new WeakMap,
|
|
8
|
-
`,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),i=s.find(u=>u.toString()=="Symbol(renderer)"),n=s.find(u=>u.toString()=="Symbol(scene)"),l=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=a[i].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let o=function(){if(r){let i=0,n=setInterval(()=>{if(i++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=I.get(t,{engine:"model-viewer"});return I.addPlugin(new
|
|
7
|
+
${e.name}`)}break}}}}else s.texture_lod=0}};let I=C;B=new WeakMap,z=new WeakMap,he=new WeakMap,j=new WeakMap,ee=new WeakMap,ge=new WeakMap,W=new WeakMap,d(I,"debugDrawLine"),d(I,"corner0",new p.Vector3),d(I,"corner1",new p.Vector3),d(I,"corner2",new p.Vector3),d(I,"corner3",new p.Vector3),d(I,"_tempPtInside",new p.Vector3);class Qe{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const Te=Symbol("NEEDLE_mesh_lod"),fe=Symbol("NEEDLE_texture_lod");let se=null;function Oe(){const a=Ze();a&&(a.mapURLs(function(t){return Ae(),t}),Ae(),se==null||se.disconnect(),se=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ce(r)})})}),se.observe(document,{childList:!0,subtree:!0}))}function Ze(){if(typeof customElements>"u")return null;const a=customElements.get("model-viewer");return a||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Oe()}),null)}function Ae(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const Ee=new WeakSet;let je=0;function Ce(a){if(!a||Ee.has(a))return null;Ee.add(a),console.debug("[gltf-progressive] found new model-viewer..."+ ++je+`
|
|
8
|
+
`,a.getAttribute("src"));let t=null,e=null,r=null;for(let o=a;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),i=s.find(u=>u.toString()=="Symbol(renderer)"),n=s.find(u=>u.toString()=="Symbol(scene)"),l=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=a[i].threeRenderer),!e&&n!=null&&(e=a[n]),!r&&l!=null&&(r=a[l])}if(t&&e){let o=function(){if(r){let i=0,n=setInterval(()=>{if(i++>5){clearInterval(n);return}r==null||r.call(a)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=I.get(t,{engine:"model-viewer"});return I.addPlugin(new et),s.enable(),s.addEventListener("changed",()=>{r==null||r.call(a)}),a.addEventListener("model-visibility",i=>{i.detail.visible&&(r==null||r.call(a))}),a.addEventListener("load",()=>{o()}),()=>{s.disable()}}return null}class et{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,r,o){this.tryParseMeshLOD(e,o),this.tryParseTextureLOD(e,o)}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[fe]==!0)return;e[fe]=!0;const r=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),s=this.getUrl(o);if(s&&r&&e.material){let i=function(l){var c,g,y;if(l[fe]==!0)return;l[fe]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let D=0;D<u.length;D++){const v=u[D],M=l[v];if((M==null?void 0:M.isTexture)===!0){const F=(g=(c=M.userData)==null?void 0:c.associations)==null?void 0:g.textures;if(F==null)continue;const w=r.parser.json.textures[F];if(!w){console.warn("Texture data not found for texture index "+F);continue}if((y=w==null?void 0:w.extensions)!=null&&y[U]){const h=w.extensions[U];h&&s&&O.registerTexture(s,M,h.lods.length,F,h)}}}};const n=e.material;if(Array.isArray(n))for(const l of n)i(l);else i(n)}}tryParseMeshLOD(t,e){var i,n;if(e[Te]==!0)return;e[Te]=!0;const r=this.tryGetCurrentModelViewer(t),o=this.getUrl(r);if(!o)return;const s=(n=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:n[U];if(s&&o){const l=e.uuid;O.registerMesh(o,l,e,0,s.lods.length,s)}}}function tt(a,t,e,r){ve(t),_e(e),e.register(s=>new O(s,a));const o=I.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&o.enable(),o}Oe();exports.EXTENSION_NAME=U;exports.LODsManager=I;exports.NEEDLE_progressive=O;exports.VERSION=we;exports.addDracoAndKTX2Loaders=_e;exports.createLoaders=ve;exports.getRaycastMesh=ae;exports.patchModelViewer=Oe;exports.registerRaycastMesh=Pe;exports.setDracoDecoderLocation=ze;exports.setKTX2TranscoderLocation=We;exports.useNeedleProgressive=tt;exports.useRaycastMeshes=Ke;
|
package/lib/extension.d.ts
CHANGED
|
@@ -94,7 +94,9 @@ export declare class NEEDLE_progressive implements GLTFLoaderPlugin {
|
|
|
94
94
|
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
95
95
|
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
96
96
|
*/
|
|
97
|
-
static assignTextureLOD(materialOrTexture: Material
|
|
97
|
+
static assignTextureLOD(materialOrTexture: Material, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
|
|
98
|
+
static assignTextureLOD(materialOrTexture: Mesh, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
|
|
99
|
+
static assignTextureLOD(materialOrTexture: Texture, level: number): Promise<Texture | null>;
|
|
98
100
|
private static assignTextureLODForSlot;
|
|
99
101
|
private readonly parser;
|
|
100
102
|
private readonly url;
|
package/lib/extension.js
CHANGED
|
@@ -283,16 +283,31 @@ export class NEEDLE_progressive {
|
|
|
283
283
|
}
|
|
284
284
|
return Promise.resolve(null);
|
|
285
285
|
}
|
|
286
|
-
/** Load a different resolution of a texture (if available)
|
|
287
|
-
* @param context the context
|
|
288
|
-
* @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
|
|
289
|
-
* @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
|
|
290
|
-
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
291
|
-
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
292
|
-
*/
|
|
293
286
|
static assignTextureLOD(materialOrTexture, level = 0) {
|
|
294
287
|
if (!materialOrTexture)
|
|
295
288
|
return Promise.resolve(null);
|
|
289
|
+
if (materialOrTexture.isMesh === true) {
|
|
290
|
+
const mesh = materialOrTexture;
|
|
291
|
+
if (Array.isArray(mesh.material)) {
|
|
292
|
+
const arr = new Array();
|
|
293
|
+
for (const mat of mesh.material) {
|
|
294
|
+
const promise = this.assignTextureLOD(mat, level);
|
|
295
|
+
arr.push(promise);
|
|
296
|
+
}
|
|
297
|
+
return Promise.all(arr).then(res => {
|
|
298
|
+
const textures = new Array();
|
|
299
|
+
for (const tex of res) {
|
|
300
|
+
if (Array.isArray(tex)) {
|
|
301
|
+
textures.push(...tex);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return textures;
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
return this.assignTextureLOD(mesh.material, level);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
296
311
|
if (materialOrTexture instanceof Material || materialOrTexture.isMaterial === true) {
|
|
297
312
|
const material = materialOrTexture;
|
|
298
313
|
const promises = [];
|
package/lib/loaders.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
|
|
2
2
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
3
3
|
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
|
|
4
|
-
let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.
|
|
4
|
+
let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.5.7/';
|
|
5
5
|
let DEFAULT_KTX2_TRANSCODER_LOCATION = 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/';
|
|
6
|
+
const defaultDraco = DEFAULT_DRACO_DECODER_LOCATION;
|
|
7
|
+
const defaultKTX2 = DEFAULT_KTX2_TRANSCODER_LOCATION;
|
|
6
8
|
fetch(DEFAULT_DRACO_DECODER_LOCATION + "draco_decoder.js", { method: "head" })
|
|
7
9
|
.catch(_ => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
// check if the default values have been changed by the user.
|
|
11
|
+
// If they didnt change / the default paths are not reachable, fall back to local versions
|
|
12
|
+
if (DEFAULT_DRACO_DECODER_LOCATION === defaultDraco)
|
|
13
|
+
DEFAULT_DRACO_DECODER_LOCATION = "./include/draco/";
|
|
14
|
+
if (DEFAULT_KTX2_TRANSCODER_LOCATION === defaultKTX2)
|
|
15
|
+
DEFAULT_KTX2_TRANSCODER_LOCATION = "./include/ktx2/";
|
|
10
16
|
});
|
|
11
17
|
/**
|
|
12
18
|
* Set the location of the Draco decoder.
|
package/lib/version.js
CHANGED
package/package.json
CHANGED