@needle-tools/gltf-progressive 2.1.0-alpha → 2.1.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/gltf-progressive.js +182 -171
- package/gltf-progressive.min.js +7 -7
- package/gltf-progressive.umd.cjs +7 -7
- package/lib/extension.js +4 -4
- package/lib/index.js +18 -0
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.1.0-alpha.2] - 2025-01-17
|
|
8
|
+
- Add: expose methods in globalThis/window at `Needle.gltfProgressive`
|
|
9
|
+
|
|
10
|
+
## [2.1.0-alpha.1] - 2025-01-15
|
|
11
|
+
- Fix: issue where `getMeshLOD` for multi-material meshes would not return the correct index if called multiple times at the same time
|
|
12
|
+
|
|
7
13
|
## [2.1.0-alpha] - 2025-01-14
|
|
8
14
|
- Bump three types to r169
|
|
9
15
|
|
package/gltf-progressive.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var d = (o, t, e) => (
|
|
1
|
+
var We = Object.defineProperty;
|
|
2
|
+
var qe = (o, t, e) => t in o ? We(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
|
+
var d = (o, t, e) => (qe(o, typeof t != "symbol" ? t + "" : t, e), e), Ae = (o, t, e) => {
|
|
4
4
|
if (!t.has(o))
|
|
5
5
|
throw TypeError("Cannot " + e);
|
|
6
6
|
};
|
|
7
|
-
var m = (o, t, e) => (
|
|
7
|
+
var m = (o, t, e) => (Ae(o, t, "read from private field"), e ? e.call(o) : t.get(o)), K = (o, t, e) => {
|
|
8
8
|
if (t.has(o))
|
|
9
9
|
throw TypeError("Cannot add the same private member more than once");
|
|
10
10
|
t instanceof WeakSet ? t.add(o) : t.set(o, e);
|
|
11
|
-
}, U = (o, t, e, s) => (
|
|
12
|
-
import { BufferGeometry as
|
|
13
|
-
import { GLTFLoader as
|
|
14
|
-
import { MeshoptDecoder as
|
|
15
|
-
import { DRACOLoader as
|
|
16
|
-
import { KTX2Loader as
|
|
17
|
-
const
|
|
18
|
-
globalThis.GLTF_PROGRESSIVE_VERSION =
|
|
19
|
-
console.debug(`[gltf-progressive] version ${
|
|
11
|
+
}, U = (o, t, e, s) => (Ae(o, t, "write to private field"), s ? s.call(o, e) : t.set(o, e), e);
|
|
12
|
+
import { BufferGeometry as pe, Mesh as H, Material as Xe, Texture as se, TextureLoader as Ke, Matrix4 as Ee, Clock as Ye, MeshStandardMaterial as He, Sphere as Je, Box3 as Pe, Vector3 as N } from "three";
|
|
13
|
+
import { GLTFLoader as Te } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
14
|
+
import { MeshoptDecoder as Qe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
15
|
+
import { DRACOLoader as Ze } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
16
|
+
import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
17
|
+
const Re = "";
|
|
18
|
+
globalThis.GLTF_PROGRESSIVE_VERSION = Re;
|
|
19
|
+
console.debug(`[gltf-progressive] version ${Re}`);
|
|
20
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
|
|
21
|
+
const et = j, tt = ae;
|
|
22
22
|
fetch(j + "draco_decoder.js", { method: "head" }).catch((o) => {
|
|
23
|
-
j ===
|
|
23
|
+
j === et && (j = "./include/draco/"), ae === tt && (ae = "./include/ktx2/");
|
|
24
24
|
});
|
|
25
|
-
function
|
|
25
|
+
function Dt(o) {
|
|
26
26
|
j = o;
|
|
27
27
|
}
|
|
28
|
-
function
|
|
28
|
+
function wt(o) {
|
|
29
29
|
ae = o;
|
|
30
30
|
}
|
|
31
|
-
let Q,
|
|
32
|
-
function Re(o) {
|
|
33
|
-
return Q || (Q = new Je(), Q.setDecoderPath(j), Q.setDecoderConfig({ type: "js" })), Z || (Z = new Qe(), Z.setTranscoderPath(ae)), he || (he = He), o ? Z.detectSupport(o) : o !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: Q, ktx2Loader: Z, meshoptDecoder: he };
|
|
34
|
-
}
|
|
31
|
+
let Q, ge, Z;
|
|
35
32
|
function Ge(o) {
|
|
36
|
-
|
|
33
|
+
return Q || (Q = new Ze(), Q.setDecoderPath(j), Q.setDecoderConfig({ type: "js" })), Z || (Z = new je(), Z.setTranscoderPath(ae)), ge || (ge = Qe), o ? Z.detectSupport(o) : o !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: Q, ktx2Loader: Z, meshoptDecoder: ge };
|
|
34
|
+
}
|
|
35
|
+
function $e(o) {
|
|
36
|
+
o.dracoLoader || o.setDRACOLoader(Q), o.ktx2Loader || o.setKTX2Loader(Z), o.meshoptDecoder || o.setMeshoptDecoder(ge);
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
function
|
|
40
|
-
let e =
|
|
41
|
-
e ? e = Object.assign(e, t) : e = t,
|
|
38
|
+
const _e = /* @__PURE__ */ new WeakMap();
|
|
39
|
+
function Fe(o, t) {
|
|
40
|
+
let e = _e.get(o);
|
|
41
|
+
e ? e = Object.assign(e, t) : e = t, _e.set(o, e);
|
|
42
42
|
}
|
|
43
|
-
const Me =
|
|
44
|
-
function
|
|
45
|
-
const t =
|
|
43
|
+
const Me = Te.prototype.load;
|
|
44
|
+
function st(...o) {
|
|
45
|
+
const t = _e.get(this);
|
|
46
46
|
let e = o[0];
|
|
47
47
|
const s = new URL(e, window.location.href);
|
|
48
48
|
if (s.hostname.endsWith("needle.tools")) {
|
|
@@ -51,7 +51,7 @@ function tt(...o) {
|
|
|
51
51
|
}
|
|
52
52
|
return o[0] = e, Me == null ? void 0 : Me.call(this, ...o);
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
Te.prototype.load = st;
|
|
55
55
|
le("debugprogressive");
|
|
56
56
|
function le(o) {
|
|
57
57
|
if (typeof window > "u")
|
|
@@ -59,7 +59,7 @@ function le(o) {
|
|
|
59
59
|
const e = new URL(window.location.href).searchParams.get(o);
|
|
60
60
|
return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function rt(o, t) {
|
|
63
63
|
if (t === void 0 || t.startsWith("./") || t.startsWith("http") || o === void 0)
|
|
64
64
|
return t;
|
|
65
65
|
const e = o.lastIndexOf("/");
|
|
@@ -72,26 +72,26 @@ function st(o, t) {
|
|
|
72
72
|
return t;
|
|
73
73
|
}
|
|
74
74
|
let re;
|
|
75
|
-
function
|
|
75
|
+
function it() {
|
|
76
76
|
return re !== void 0 || (re = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), le("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", re)), re;
|
|
77
77
|
}
|
|
78
|
-
const
|
|
79
|
-
function
|
|
80
|
-
return (o == null ? void 0 : o[
|
|
78
|
+
const Se = Symbol("needle:raycast-mesh");
|
|
79
|
+
function ce(o) {
|
|
80
|
+
return (o == null ? void 0 : o[Se]) instanceof pe ? o[Se] : null;
|
|
81
81
|
}
|
|
82
|
-
function
|
|
83
|
-
if ((o.type === "Mesh" || o.type === "SkinnedMesh") && !
|
|
84
|
-
const s =
|
|
85
|
-
s.userData = { isRaycastMesh: !0 }, o[
|
|
82
|
+
function nt(o, t) {
|
|
83
|
+
if ((o.type === "Mesh" || o.type === "SkinnedMesh") && !ce(o)) {
|
|
84
|
+
const s = at(t);
|
|
85
|
+
s.userData = { isRaycastMesh: !0 }, o[Se] = s;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
function
|
|
88
|
+
function ot(o = !0) {
|
|
89
89
|
if (o) {
|
|
90
90
|
if (ie)
|
|
91
91
|
return;
|
|
92
92
|
const t = ie = H.prototype.raycast;
|
|
93
93
|
H.prototype.raycast = function(e, s) {
|
|
94
|
-
const n = this, r =
|
|
94
|
+
const n = this, r = ce(n);
|
|
95
95
|
let i;
|
|
96
96
|
r && n.isMesh && (i = n.geometry, n.geometry = r), t.call(this, e, s), i && (n.geometry = i);
|
|
97
97
|
};
|
|
@@ -102,13 +102,13 @@ function Mt(o = !0) {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
let ie = null;
|
|
105
|
-
function
|
|
106
|
-
const t = new
|
|
105
|
+
function at(o) {
|
|
106
|
+
const t = new pe();
|
|
107
107
|
for (const e in o.attributes)
|
|
108
108
|
t.setAttribute(e, o.getAttribute(e));
|
|
109
109
|
return t.setIndex(o.getIndex()), t;
|
|
110
110
|
}
|
|
111
|
-
const Y = new Array(),
|
|
111
|
+
const Y = new Array(), z = "NEEDLE_progressive", L = le("debugprogressive"), De = Symbol("needle-progressive-texture"), oe = /* @__PURE__ */ new Map(), be = /* @__PURE__ */ new Set();
|
|
112
112
|
if (L) {
|
|
113
113
|
let o = function() {
|
|
114
114
|
t += 1, console.log("Toggle LOD level", t, oe), oe.forEach((n, r) => {
|
|
@@ -127,12 +127,12 @@ if (L) {
|
|
|
127
127
|
}), t >= e && (t = -1);
|
|
128
128
|
}, t = -1, e = 2, s = !1;
|
|
129
129
|
window.addEventListener("keyup", (n) => {
|
|
130
|
-
n.key === "p" && o(), n.key === "w" && (s = !s,
|
|
130
|
+
n.key === "p" && o(), n.key === "w" && (s = !s, be && be.forEach((r) => {
|
|
131
131
|
r.name != "BackgroundCubeMaterial" && r.glyphMap == null && "wireframe" in r && (r.wireframe = s);
|
|
132
132
|
}));
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
function
|
|
135
|
+
function Ce(o, t, e) {
|
|
136
136
|
var n;
|
|
137
137
|
if (!L)
|
|
138
138
|
return;
|
|
@@ -149,7 +149,7 @@ const v = class {
|
|
|
149
149
|
var s, n;
|
|
150
150
|
if (this._isLoadingMesh)
|
|
151
151
|
return null;
|
|
152
|
-
const e = (n = (s = this.parser.json.meshes[t]) == null ? void 0 : s.extensions) == null ? void 0 : n[
|
|
152
|
+
const e = (n = (s = this.parser.json.meshes[t]) == null ? void 0 : s.extensions) == null ? void 0 : n[z];
|
|
153
153
|
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((r) => {
|
|
154
154
|
var i;
|
|
155
155
|
return this._isLoadingMesh = !1, r && v.registerMesh(this.url, e.guid, r, (i = e.lods) == null ? void 0 : i.length, void 0, e), r;
|
|
@@ -159,7 +159,7 @@ const v = class {
|
|
|
159
159
|
}
|
|
160
160
|
/** The name of the extension */
|
|
161
161
|
get name() {
|
|
162
|
-
return
|
|
162
|
+
return z;
|
|
163
163
|
}
|
|
164
164
|
static getMeshLODInformation(t) {
|
|
165
165
|
const e = this.getAssignedLODInformation(t);
|
|
@@ -264,14 +264,11 @@ const v = class {
|
|
|
264
264
|
for (const i of Y)
|
|
265
265
|
(s = i.onBeforeGetLODMesh) == null || s.call(i, t, e);
|
|
266
266
|
return t["LOD:requested level"] = e, v.getOrLoadLOD(n, e).then((i) => {
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
i = i[a];
|
|
271
|
-
}
|
|
272
|
-
i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, L && Pe(t, "geometry", r.url)) : L && console.error("Invalid LOD geometry", i));
|
|
267
|
+
if (Array.isArray(i)) {
|
|
268
|
+
const a = r.index || 0;
|
|
269
|
+
i = i[a];
|
|
273
270
|
}
|
|
274
|
-
return i;
|
|
271
|
+
return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? (t.geometry = i, L && Ce(t, "geometry", r.url)) : L && console.error("Invalid LOD geometry", i))), i;
|
|
275
272
|
}).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
|
|
276
273
|
} else
|
|
277
274
|
L && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
@@ -297,9 +294,9 @@ const v = class {
|
|
|
297
294
|
} else
|
|
298
295
|
return this.assignTextureLOD(s.material, e);
|
|
299
296
|
}
|
|
300
|
-
if (t instanceof
|
|
297
|
+
if (t instanceof Xe || t.isMaterial === !0) {
|
|
301
298
|
const s = t, n = [], r = new Array();
|
|
302
|
-
if (L &&
|
|
299
|
+
if (L && be.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
|
303
300
|
const i = s;
|
|
304
301
|
for (const a of Object.keys(i.uniforms)) {
|
|
305
302
|
const l = i.uniforms[a].value;
|
|
@@ -348,7 +345,7 @@ const v = class {
|
|
|
348
345
|
}
|
|
349
346
|
if (L && n && s) {
|
|
350
347
|
const i = this.getAssignedLODInformation(t);
|
|
351
|
-
i &&
|
|
348
|
+
i && Ce(s, n, i.url);
|
|
352
349
|
}
|
|
353
350
|
}
|
|
354
351
|
return r;
|
|
@@ -362,7 +359,7 @@ const v = class {
|
|
|
362
359
|
return L && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, r) => {
|
|
363
360
|
var i;
|
|
364
361
|
if (n != null && n.extensions) {
|
|
365
|
-
const a = n == null ? void 0 : n.extensions[
|
|
362
|
+
const a = n == null ? void 0 : n.extensions[z];
|
|
366
363
|
if (a) {
|
|
367
364
|
if (!a.lods) {
|
|
368
365
|
L && console.warn("Texture has no LODs", a);
|
|
@@ -382,7 +379,7 @@ const v = class {
|
|
|
382
379
|
}
|
|
383
380
|
}), (s = this.parser.json.meshes) == null || s.forEach((n, r) => {
|
|
384
381
|
if (n != null && n.extensions) {
|
|
385
|
-
const i = n == null ? void 0 : n.extensions[
|
|
382
|
+
const i = n == null ? void 0 : n.extensions[z];
|
|
386
383
|
if (i && i.lods) {
|
|
387
384
|
for (const a of this.parser.associations.keys())
|
|
388
385
|
if (a.isMesh) {
|
|
@@ -414,7 +411,7 @@ const v = class {
|
|
|
414
411
|
const g = Array.isArray(i.lods) ? (a = i.lods[e]) == null ? void 0 : a.path : i.lods;
|
|
415
412
|
if (!g)
|
|
416
413
|
return L && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
|
|
417
|
-
const p =
|
|
414
|
+
const p = rt(n.url, g);
|
|
418
415
|
if (p.endsWith(".glb") || p.endsWith(".gltf")) {
|
|
419
416
|
if (!i.guid)
|
|
420
417
|
return console.warn("missing pointer for glb/gltf texture", i), null;
|
|
@@ -422,19 +419,19 @@ const v = class {
|
|
|
422
419
|
if (w !== void 0) {
|
|
423
420
|
s && console.log(`LOD ${e} was already loading/loaded: ${M}`);
|
|
424
421
|
let h = await w.catch((F) => (console.error(`Error loading LOD ${e} from ${p}
|
|
425
|
-
`, F), null)),
|
|
426
|
-
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) : (
|
|
422
|
+
`, F), null)), k = !1;
|
|
423
|
+
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) : (k = !0, this.previouslyLoaded.delete(M)) : h instanceof pe && t instanceof pe && ((c = h.attributes.position) != null && c.array || (k = !0, this.previouslyLoaded.delete(M)))), !k)
|
|
427
424
|
return h;
|
|
428
425
|
}
|
|
429
|
-
const x = i, $ = new Promise(async (h,
|
|
430
|
-
const F = new
|
|
431
|
-
|
|
432
|
-
let
|
|
426
|
+
const x = i, $ = new Promise(async (h, k) => {
|
|
427
|
+
const F = new Te();
|
|
428
|
+
$e(F), L && (await new Promise((A) => setTimeout(A, 1e3)), s && console.warn("Start loading (delayed) " + p, x.guid));
|
|
429
|
+
let I = p;
|
|
433
430
|
if (x && Array.isArray(x.lods)) {
|
|
434
431
|
const A = x.lods[e];
|
|
435
|
-
A.hash && (
|
|
432
|
+
A.hash && (I += "?v=" + A.hash);
|
|
436
433
|
}
|
|
437
|
-
const S = await F.loadAsync(
|
|
434
|
+
const S = await F.loadAsync(I).catch((A) => (console.error(`Error loading LOD ${e} from ${p}
|
|
438
435
|
`, A), null));
|
|
439
436
|
if (!S)
|
|
440
437
|
return null;
|
|
@@ -445,7 +442,7 @@ const v = class {
|
|
|
445
442
|
let A = !1;
|
|
446
443
|
for (const f of S.parser.json.textures) {
|
|
447
444
|
if (f != null && f.extensions) {
|
|
448
|
-
const y = f == null ? void 0 : f.extensions[
|
|
445
|
+
const y = f == null ? void 0 : f.extensions[z];
|
|
449
446
|
if (y != null && y.guid && y.guid === x.guid) {
|
|
450
447
|
A = !0;
|
|
451
448
|
break;
|
|
@@ -463,7 +460,7 @@ const v = class {
|
|
|
463
460
|
let A = !1;
|
|
464
461
|
for (const f of S.parser.json.meshes) {
|
|
465
462
|
if (f != null && f.extensions) {
|
|
466
|
-
const y = f == null ? void 0 : f.extensions[
|
|
463
|
+
const y = f == null ? void 0 : f.extensions[z];
|
|
467
464
|
if (y != null && y.guid && y.guid === x.guid) {
|
|
468
465
|
A = !0;
|
|
469
466
|
break;
|
|
@@ -495,7 +492,7 @@ const v = class {
|
|
|
495
492
|
return this.previouslyLoaded.set(M, $), await $;
|
|
496
493
|
} else if (t instanceof se) {
|
|
497
494
|
s && console.log("Load texture from uri: " + p);
|
|
498
|
-
const w = await new
|
|
495
|
+
const w = await new Ke().loadAsync(p);
|
|
499
496
|
return w ? (w.guid = i.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = t.colorSpace, s && console.log(i, w)) : L && console.warn("failed loading", p), w;
|
|
500
497
|
}
|
|
501
498
|
} else
|
|
@@ -506,7 +503,7 @@ const v = class {
|
|
|
506
503
|
if (!e)
|
|
507
504
|
return;
|
|
508
505
|
e.userData || (e.userData = {});
|
|
509
|
-
const a = new
|
|
506
|
+
const a = new lt(t, s, n, r, i);
|
|
510
507
|
e.userData.LODS = a;
|
|
511
508
|
}
|
|
512
509
|
static getAssignedLODInformation(t) {
|
|
@@ -545,14 +542,14 @@ d(_, "registerMesh", (t, e, s, n, r, i) => {
|
|
|
545
542
|
}
|
|
546
543
|
a.userData || (a.userData = {}), v.assignLODInformation(t, a, e, n, r, i.density), v.lodInfos.set(e, i);
|
|
547
544
|
let l = v.lowresCache.get(e);
|
|
548
|
-
l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !
|
|
545
|
+
l ? l.push(s.geometry) : l = [s.geometry], v.lowresCache.set(e, l), n > 0 && !ce(s) && nt(s, a);
|
|
549
546
|
for (const c of Y)
|
|
550
547
|
(u = c.onRegisteredNewMesh) == null || u.call(c, s, i);
|
|
551
548
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
552
549
|
d(_, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
553
550
|
d(_, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
554
551
|
d(_, "lowresCache", /* @__PURE__ */ new Map());
|
|
555
|
-
class
|
|
552
|
+
class lt {
|
|
556
553
|
constructor(t, e, s, n, r) {
|
|
557
554
|
d(this, "url");
|
|
558
555
|
/** the key to lookup the LOD information */
|
|
@@ -565,14 +562,14 @@ class ot {
|
|
|
565
562
|
this.url = t, this.key = e, this.level = s, n != null && (this.index = n), r != null && (this.density = r);
|
|
566
563
|
}
|
|
567
564
|
}
|
|
568
|
-
const
|
|
569
|
-
var C,
|
|
565
|
+
const R = le("debugprogressive"), ct = le("noprogressive"), we = Symbol("Needle:LODSManager"), ve = Symbol("Needle:LODState"), J = Symbol("Needle:CurrentLOD"), G = { mesh_lod: -1, texture_lod: -1 };
|
|
566
|
+
var C, V, ye, ee, te, me, W;
|
|
570
567
|
const P = class {
|
|
571
568
|
// readonly plugins: NEEDLE_progressive_plugin[] = [];
|
|
572
569
|
constructor(t, e) {
|
|
573
570
|
d(this, "context");
|
|
574
571
|
d(this, "renderer");
|
|
575
|
-
d(this, "projectionScreenMatrix", new
|
|
572
|
+
d(this, "projectionScreenMatrix", new Ee());
|
|
576
573
|
/**
|
|
577
574
|
* The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
|
|
578
575
|
* @default 200_000
|
|
@@ -596,21 +593,21 @@ const P = class {
|
|
|
596
593
|
*/
|
|
597
594
|
d(this, "manual", !1);
|
|
598
595
|
d(this, "_lodchangedlisteners", []);
|
|
599
|
-
K(this,
|
|
600
|
-
K(this,
|
|
596
|
+
K(this, V, void 0);
|
|
597
|
+
K(this, ye, new Ye());
|
|
601
598
|
K(this, ee, 0);
|
|
602
599
|
K(this, te, 0);
|
|
603
|
-
K(this,
|
|
600
|
+
K(this, me, 0);
|
|
604
601
|
K(this, W, 0);
|
|
605
602
|
d(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
|
|
606
603
|
// private testIfLODLevelsAreAvailable() {
|
|
607
|
-
d(this, "_sphere", new
|
|
608
|
-
d(this, "_tempBox", new
|
|
609
|
-
d(this, "_tempBox2", new
|
|
610
|
-
d(this, "tempMatrix", new
|
|
611
|
-
d(this, "_tempWorldPosition", new
|
|
612
|
-
d(this, "_tempBoxSize", new
|
|
613
|
-
d(this, "_tempBox2Size", new
|
|
604
|
+
d(this, "_sphere", new Je());
|
|
605
|
+
d(this, "_tempBox", new Pe());
|
|
606
|
+
d(this, "_tempBox2", new Pe());
|
|
607
|
+
d(this, "tempMatrix", new Ee());
|
|
608
|
+
d(this, "_tempWorldPosition", new N());
|
|
609
|
+
d(this, "_tempBoxSize", new N());
|
|
610
|
+
d(this, "_tempBox2Size", new N());
|
|
614
611
|
this.renderer = t, this.context = { ...e };
|
|
615
612
|
}
|
|
616
613
|
/** @internal */
|
|
@@ -655,21 +652,21 @@ const P = class {
|
|
|
655
652
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
656
653
|
*/
|
|
657
654
|
enable() {
|
|
658
|
-
if (m(this,
|
|
655
|
+
if (m(this, V))
|
|
659
656
|
return;
|
|
660
657
|
console.debug("[gltf-progressive] Enabling LODsManager for renderer");
|
|
661
658
|
let t = 0;
|
|
662
|
-
U(this,
|
|
659
|
+
U(this, V, this.renderer.render);
|
|
663
660
|
const e = this;
|
|
664
|
-
|
|
661
|
+
Ge(this.renderer), this.renderer.render = function(s, n) {
|
|
665
662
|
const r = e.renderer.getRenderTarget();
|
|
666
|
-
(r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e, ee, m(e, ee) + 1), U(e, te, m(e,
|
|
663
|
+
(r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (t = 0, U(e, ee, m(e, ee) + 1), U(e, te, m(e, ye).getDelta()), U(e, me, m(e, me) + m(e, te)), e._fpsBuffer.shift(), e._fpsBuffer.push(1 / m(e, te)), U(e, W, e._fpsBuffer.reduce((a, l) => a + l) / e._fpsBuffer.length), R && m(e, ee) % 200 === 0 && console.log("FPS", Math.round(m(e, W)), "Interval:", m(e, C)));
|
|
667
664
|
const i = t++;
|
|
668
|
-
m(e,
|
|
665
|
+
m(e, V).call(this, s, n), e.onAfterRender(s, n, i);
|
|
669
666
|
};
|
|
670
667
|
}
|
|
671
668
|
disable() {
|
|
672
|
-
m(this,
|
|
669
|
+
m(this, V) && (console.debug("[gltf-progressive] Disabling LODsManager for renderer"), this.renderer.render = m(this, V), U(this, V, void 0));
|
|
673
670
|
}
|
|
674
671
|
update(t, e) {
|
|
675
672
|
this.internalUpdate(t, e);
|
|
@@ -684,7 +681,7 @@ const P = class {
|
|
|
684
681
|
(a.name === "EffectMaterial" || a.name === "CopyShader") && (i = !1);
|
|
685
682
|
}
|
|
686
683
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
|
|
687
|
-
if (
|
|
684
|
+
if (ct || (this.updateInterval === "auto" ? m(this, W) < 40 && m(this, C) < 10 ? (U(this, C, m(this, C) + 1), R && 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), R && 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))
|
|
688
685
|
return;
|
|
689
686
|
this.internalUpdate(t, e);
|
|
690
687
|
}
|
|
@@ -699,7 +696,7 @@ const P = class {
|
|
|
699
696
|
const r = this.targetTriangleDensity;
|
|
700
697
|
for (const c of n) {
|
|
701
698
|
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")) {
|
|
702
|
-
|
|
699
|
+
R && (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)));
|
|
703
700
|
continue;
|
|
704
701
|
}
|
|
705
702
|
switch (c.material.type) {
|
|
@@ -711,9 +708,9 @@ const P = class {
|
|
|
711
708
|
case "MeshDepthMaterial":
|
|
712
709
|
continue;
|
|
713
710
|
}
|
|
714
|
-
if (
|
|
711
|
+
if (R === "color" && c.material && !c.object.progressive_debug_color) {
|
|
715
712
|
c.object.progressive_debug_color = !0;
|
|
716
|
-
const p = Math.random() * 16777215, M = new
|
|
713
|
+
const p = Math.random() * 16777215, M = new He({ color: p });
|
|
717
714
|
c.object.material = M;
|
|
718
715
|
}
|
|
719
716
|
const g = c.object;
|
|
@@ -735,19 +732,19 @@ const P = class {
|
|
|
735
732
|
var a, l;
|
|
736
733
|
s.userData || (s.userData = {});
|
|
737
734
|
let r = s[ve];
|
|
738
|
-
if (r || (r = new
|
|
735
|
+
if (r || (r = new ut(), s[ve] = r), r.frames++ < 2)
|
|
739
736
|
return;
|
|
740
737
|
for (const u of Y)
|
|
741
738
|
(a = u.onBeforeUpdateLOD) == null || a.call(u, this.renderer, t, e, s);
|
|
742
|
-
this.calculateLodLevel(e, s, r, n,
|
|
743
|
-
let i =
|
|
739
|
+
this.calculateLodLevel(e, s, r, n, G), G.mesh_lod = Math.round(G.mesh_lod), G.texture_lod = Math.round(G.texture_lod), G.mesh_lod >= 0 && this.loadProgressiveMeshes(s, G.mesh_lod);
|
|
740
|
+
let i = G.texture_lod;
|
|
744
741
|
if (s.material && i >= 0) {
|
|
745
742
|
const u = s["DEBUG:LOD"];
|
|
746
743
|
u != null && (i = u), this.loadProgressiveTextures(s.material, i);
|
|
747
744
|
}
|
|
748
745
|
for (const u of Y)
|
|
749
|
-
(l = u.onAfterUpdatedLOD) == null || l.call(u, this.renderer, t, e, s,
|
|
750
|
-
r.lastLodLevel_Mesh =
|
|
746
|
+
(l = u.onAfterUpdatedLOD) == null || l.call(u, this.renderer, t, e, s, G);
|
|
747
|
+
r.lastLodLevel_Mesh = G.mesh_lod, r.lastLodLevel_Texture = G.texture_lod;
|
|
751
748
|
}
|
|
752
749
|
/** Load progressive textures for the given material
|
|
753
750
|
* @param material the material to load the textures for
|
|
@@ -798,7 +795,7 @@ const P = class {
|
|
|
798
795
|
return;
|
|
799
796
|
}
|
|
800
797
|
let a = 10 + 1, l = !1;
|
|
801
|
-
if (
|
|
798
|
+
if (R && e["DEBUG:LOD"] != null)
|
|
802
799
|
return e["DEBUG:LOD"];
|
|
803
800
|
const u = _.getMeshLODInformation(e.geometry), c = u == null ? void 0 : u.lods, g = c && c.length > 0, p = _.getMaterialMinMaxLODsCount(e.material), M = (p == null ? void 0 : p.min_count) != 1 / 0 && p.min_count > 0 && p.max_count > 0;
|
|
804
801
|
if (!g && !M) {
|
|
@@ -813,8 +810,8 @@ const P = class {
|
|
|
813
810
|
if (!D.boundingBox)
|
|
814
811
|
D.computeBoundingBox();
|
|
815
812
|
else if (s.frames % 30 === 0) {
|
|
816
|
-
const h =
|
|
817
|
-
h && (D.geometry = h), D.computeBoundingBox(), D.geometry =
|
|
813
|
+
const h = ce(D), k = D.geometry;
|
|
814
|
+
h && (D.geometry = h), D.computeBoundingBox(), D.geometry = k;
|
|
818
815
|
}
|
|
819
816
|
x = D.boundingBox;
|
|
820
817
|
}
|
|
@@ -835,18 +832,18 @@ const P = class {
|
|
|
835
832
|
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && D.fov > 70) {
|
|
836
833
|
const f = this._tempBox.min, y = this._tempBox.max;
|
|
837
834
|
let O = f.x, b = f.y, E = y.x, X = y.y;
|
|
838
|
-
const
|
|
839
|
-
O = (O -
|
|
840
|
-
const
|
|
835
|
+
const ue = 2, Le = 1.5, fe = (f.x + y.x) * 0.5, de = (f.y + y.y) * 0.5;
|
|
836
|
+
O = (O - fe) * ue + fe, b = (b - de) * ue + de, E = (E - fe) * ue + fe, X = (X - de) * ue + de;
|
|
837
|
+
const ze = O < 0 && E > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(y.x)), Ve = b < 0 && X > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(y.y)), xe = Math.max(ze, Ve);
|
|
841
838
|
s.lastCentrality = (Le - xe) * (Le - xe) * (Le - xe);
|
|
842
839
|
} else
|
|
843
840
|
s.lastCentrality = 1;
|
|
844
841
|
const h = this._tempBox.getSize(this._tempBoxSize);
|
|
845
842
|
h.multiplyScalar(0.5), screen.availHeight > 0 && w > 0 && h.multiplyScalar(w / screen.availHeight), h.x *= D.aspect;
|
|
846
|
-
const
|
|
847
|
-
F.copy(x), F.applyMatrix4(e.matrixWorld), F.applyMatrix4(
|
|
848
|
-
const
|
|
849
|
-
if (Math.max(h.x, h.y) != 0 && S != 0 && (h.z =
|
|
843
|
+
const k = t.matrixWorldInverse, F = this._tempBox2;
|
|
844
|
+
F.copy(x), F.applyMatrix4(e.matrixWorld), F.applyMatrix4(k);
|
|
845
|
+
const I = F.getSize(this._tempBox2Size), S = Math.max(I.x, I.y);
|
|
846
|
+
if (Math.max(h.x, h.y) != 0 && S != 0 && (h.z = I.z / Math.max(I.x, I.y) * Math.max(h.x, h.y)), s.lastScreenCoverage = Math.max(h.x, h.y, h.z), s.lastScreenspaceVolume.copy(h), s.lastScreenCoverage *= s.lastCentrality, R && P.debugDrawLine) {
|
|
850
847
|
const f = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
851
848
|
f.invert();
|
|
852
849
|
const y = P.corner0, O = P.corner1, b = P.corner2, E = P.corner3;
|
|
@@ -864,29 +861,29 @@ const P = class {
|
|
|
864
861
|
}
|
|
865
862
|
T < a && (a = T, l = !0);
|
|
866
863
|
}
|
|
867
|
-
if (l ? r.mesh_lod = a : r.mesh_lod = s.lastLodLevel_Mesh,
|
|
864
|
+
if (l ? r.mesh_lod = a : r.mesh_lod = s.lastLodLevel_Mesh, R && r.mesh_lod != s.lastLodLevel_Mesh) {
|
|
868
865
|
const h = c == null ? void 0 : c[r.mesh_lod];
|
|
869
866
|
h && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`);
|
|
870
867
|
}
|
|
871
868
|
if (M) {
|
|
872
869
|
const D = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
873
870
|
if (s.lastLodLevel_Texture < 0) {
|
|
874
|
-
if (r.texture_lod = p.max_count - 1,
|
|
871
|
+
if (r.texture_lod = p.max_count - 1, R) {
|
|
875
872
|
const h = p.lods[p.max_count - 1];
|
|
876
|
-
|
|
873
|
+
R && console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`);
|
|
877
874
|
}
|
|
878
875
|
} else {
|
|
879
876
|
const h = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
880
|
-
let
|
|
881
|
-
(($ = this.context) == null ? void 0 : $.engine) === "model-viewer" && (
|
|
882
|
-
const
|
|
877
|
+
let k = s.lastScreenCoverage * 4;
|
|
878
|
+
(($ = this.context) == null ? void 0 : $.engine) === "model-viewer" && (k *= 1.5);
|
|
879
|
+
const I = w / window.devicePixelRatio * k;
|
|
883
880
|
for (let S = p.lods.length - 1; S >= 0; S--) {
|
|
884
881
|
let q = p.lods[S];
|
|
885
|
-
if (!(D && q.max_height >= 2048) && !(
|
|
882
|
+
if (!(D && q.max_height >= 2048) && !(it() && q.max_height > 4096) && q.max_height > I) {
|
|
886
883
|
if (r.texture_lod = S, r.texture_lod < s.lastLodLevel_Texture) {
|
|
887
884
|
const T = q.max_height;
|
|
888
|
-
|
|
889
|
-
Screensize: ${
|
|
885
|
+
R && console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${T}px
|
|
886
|
+
Screensize: ${I.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
|
|
890
887
|
${e.name}`);
|
|
891
888
|
}
|
|
892
889
|
break;
|
|
@@ -897,55 +894,55 @@ ${e.name}`);
|
|
|
897
894
|
r.texture_lod = 0;
|
|
898
895
|
}
|
|
899
896
|
};
|
|
900
|
-
let
|
|
901
|
-
C = new WeakMap(),
|
|
897
|
+
let B = P;
|
|
898
|
+
C = new WeakMap(), V = new WeakMap(), ye = new WeakMap(), ee = new WeakMap(), te = new WeakMap(), me = 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.
|
|
902
899
|
*/
|
|
903
|
-
d(
|
|
904
|
-
class
|
|
900
|
+
d(B, "debugDrawLine"), d(B, "corner0", new N()), d(B, "corner1", new N()), d(B, "corner2", new N()), d(B, "corner3", new N()), d(B, "_tempPtInside", new N());
|
|
901
|
+
class ut {
|
|
905
902
|
constructor() {
|
|
906
903
|
d(this, "frames", 0);
|
|
907
904
|
d(this, "lastLodLevel_Mesh", -1);
|
|
908
905
|
d(this, "lastLodLevel_Texture", -1);
|
|
909
906
|
d(this, "lastScreenCoverage", 0);
|
|
910
|
-
d(this, "lastScreenspaceVolume", new
|
|
907
|
+
d(this, "lastScreenspaceVolume", new N());
|
|
911
908
|
d(this, "lastCentrality", 0);
|
|
912
909
|
}
|
|
913
910
|
}
|
|
914
|
-
const
|
|
911
|
+
const Be = Symbol("NEEDLE_mesh_lod"), he = Symbol("NEEDLE_texture_lod");
|
|
915
912
|
let ne = null;
|
|
916
|
-
function
|
|
917
|
-
const o =
|
|
913
|
+
function Ue() {
|
|
914
|
+
const o = ft();
|
|
918
915
|
o && (o.mapURLs(function(t) {
|
|
919
|
-
return
|
|
920
|
-
}),
|
|
916
|
+
return ke(), t;
|
|
917
|
+
}), ke(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
|
|
921
918
|
t.forEach((e) => {
|
|
922
919
|
e.addedNodes.forEach((s) => {
|
|
923
|
-
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" &&
|
|
920
|
+
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ne(s);
|
|
924
921
|
});
|
|
925
922
|
});
|
|
926
923
|
}), ne.observe(document, { childList: !0, subtree: !0 }));
|
|
927
924
|
}
|
|
928
|
-
function
|
|
925
|
+
function ft() {
|
|
929
926
|
if (typeof customElements > "u")
|
|
930
927
|
return null;
|
|
931
928
|
const o = customElements.get("model-viewer");
|
|
932
929
|
return o || (customElements.whenDefined("model-viewer").then(() => {
|
|
933
|
-
console.debug("[gltf-progressive] model-viewer defined"),
|
|
930
|
+
console.debug("[gltf-progressive] model-viewer defined"), Ue();
|
|
934
931
|
}), null);
|
|
935
932
|
}
|
|
936
|
-
function
|
|
933
|
+
function ke() {
|
|
937
934
|
if (typeof document > "u")
|
|
938
935
|
return;
|
|
939
936
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
940
|
-
|
|
937
|
+
Ne(t);
|
|
941
938
|
});
|
|
942
939
|
}
|
|
943
|
-
const
|
|
944
|
-
let
|
|
945
|
-
function
|
|
946
|
-
if (!o ||
|
|
940
|
+
const Ie = /* @__PURE__ */ new WeakSet();
|
|
941
|
+
let dt = 0;
|
|
942
|
+
function Ne(o) {
|
|
943
|
+
if (!o || Ie.has(o))
|
|
947
944
|
return null;
|
|
948
|
-
|
|
945
|
+
Ie.add(o), console.debug("[gltf-progressive] found new model-viewer..." + ++dt + `
|
|
949
946
|
`, o.getAttribute("src"));
|
|
950
947
|
let t = null, e = null, s = null;
|
|
951
948
|
for (let n = o; n != null; n = Object.getPrototypeOf(n)) {
|
|
@@ -965,8 +962,8 @@ function Fe(o) {
|
|
|
965
962
|
}
|
|
966
963
|
};
|
|
967
964
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
968
|
-
const r =
|
|
969
|
-
return
|
|
965
|
+
const r = B.get(t, { engine: "model-viewer" });
|
|
966
|
+
return B.addPlugin(new ht()), r.enable(), r.addEventListener("changed", () => {
|
|
970
967
|
s == null || s.call(o);
|
|
971
968
|
}), o.addEventListener("model-visibility", (i) => {
|
|
972
969
|
i.detail.visible && (s == null || s.call(o));
|
|
@@ -978,7 +975,7 @@ function Fe(o) {
|
|
|
978
975
|
}
|
|
979
976
|
return null;
|
|
980
977
|
}
|
|
981
|
-
class
|
|
978
|
+
class ht {
|
|
982
979
|
constructor() {
|
|
983
980
|
d(this, "_didWarnAboutMissingUrl", !1);
|
|
984
981
|
}
|
|
@@ -998,16 +995,16 @@ class ft {
|
|
|
998
995
|
return t.element;
|
|
999
996
|
}
|
|
1000
997
|
tryParseTextureLOD(t, e) {
|
|
1001
|
-
if (e[
|
|
998
|
+
if (e[he] == !0)
|
|
1002
999
|
return;
|
|
1003
|
-
e[
|
|
1000
|
+
e[he] = !0;
|
|
1004
1001
|
const s = this.tryGetCurrentGLTF(t), n = this.tryGetCurrentModelViewer(t), r = this.getUrl(n);
|
|
1005
1002
|
if (r && s && e.material) {
|
|
1006
1003
|
let i = function(l) {
|
|
1007
1004
|
var c, g, p;
|
|
1008
|
-
if (l[
|
|
1005
|
+
if (l[he] == !0)
|
|
1009
1006
|
return;
|
|
1010
|
-
l[
|
|
1007
|
+
l[he] = !0, l.userData && (l.userData.LOD = -1);
|
|
1011
1008
|
const u = Object.keys(l);
|
|
1012
1009
|
for (let M = 0; M < u.length; M++) {
|
|
1013
1010
|
const w = u[M], x = l[w];
|
|
@@ -1020,8 +1017,8 @@ class ft {
|
|
|
1020
1017
|
console.warn("Texture data not found for texture index " + $);
|
|
1021
1018
|
continue;
|
|
1022
1019
|
}
|
|
1023
|
-
if ((p = D == null ? void 0 : D.extensions) != null && p[
|
|
1024
|
-
const h = D.extensions[
|
|
1020
|
+
if ((p = D == null ? void 0 : D.extensions) != null && p[z]) {
|
|
1021
|
+
const h = D.extensions[z];
|
|
1025
1022
|
h && r && _.registerTexture(r, x, h.lods.length, $, h);
|
|
1026
1023
|
}
|
|
1027
1024
|
}
|
|
@@ -1037,41 +1034,55 @@ class ft {
|
|
|
1037
1034
|
}
|
|
1038
1035
|
tryParseMeshLOD(t, e) {
|
|
1039
1036
|
var i, a;
|
|
1040
|
-
if (e[
|
|
1037
|
+
if (e[Be] == !0)
|
|
1041
1038
|
return;
|
|
1042
|
-
e[
|
|
1039
|
+
e[Be] = !0;
|
|
1043
1040
|
const s = this.tryGetCurrentModelViewer(t), n = this.getUrl(s);
|
|
1044
1041
|
if (!n)
|
|
1045
1042
|
return;
|
|
1046
|
-
const r = (a = (i = e.userData) == null ? void 0 : i.gltfExtensions) == null ? void 0 : a[
|
|
1043
|
+
const r = (a = (i = e.userData) == null ? void 0 : i.gltfExtensions) == null ? void 0 : a[z];
|
|
1047
1044
|
if (r && n) {
|
|
1048
1045
|
const l = e.uuid;
|
|
1049
1046
|
_.registerMesh(n, l, e, 0, r.lods.length, r);
|
|
1050
1047
|
}
|
|
1051
1048
|
}
|
|
1052
1049
|
}
|
|
1053
|
-
function
|
|
1054
|
-
|
|
1050
|
+
function gt(o, t, e, s) {
|
|
1051
|
+
Ge(t), $e(e), Fe(e, {
|
|
1055
1052
|
progressive: !0,
|
|
1056
1053
|
...s == null ? void 0 : s.hints
|
|
1057
1054
|
}), e.register((r) => new _(r, o));
|
|
1058
|
-
const n =
|
|
1055
|
+
const n = B.get(t);
|
|
1059
1056
|
return (s == null ? void 0 : s.enableLODsManager) !== !1 && n.enable(), n;
|
|
1060
1057
|
}
|
|
1061
|
-
|
|
1058
|
+
Ue();
|
|
1059
|
+
const Oe = {
|
|
1060
|
+
gltfProgressive: {
|
|
1061
|
+
useNeedleProgressive: gt,
|
|
1062
|
+
LODsManager: B,
|
|
1063
|
+
configureLoader: Fe,
|
|
1064
|
+
getRaycastMesh: ce,
|
|
1065
|
+
useRaycastMeshes: ot
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
if (!globalThis.Needle)
|
|
1069
|
+
globalThis.Needle = Oe;
|
|
1070
|
+
else
|
|
1071
|
+
for (const o in Oe)
|
|
1072
|
+
globalThis.Needle[o] = Oe[o];
|
|
1062
1073
|
export {
|
|
1063
|
-
|
|
1064
|
-
|
|
1074
|
+
z as EXTENSION_NAME,
|
|
1075
|
+
B as LODsManager,
|
|
1065
1076
|
_ as NEEDLE_progressive,
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
+
Re as VERSION,
|
|
1078
|
+
$e as addDracoAndKTX2Loaders,
|
|
1079
|
+
Fe as configureLoader,
|
|
1080
|
+
Ge as createLoaders,
|
|
1081
|
+
ce as getRaycastMesh,
|
|
1082
|
+
Ue as patchModelViewer,
|
|
1083
|
+
nt as registerRaycastMesh,
|
|
1084
|
+
Dt as setDracoDecoderLocation,
|
|
1085
|
+
wt as setKTX2TranscoderLocation,
|
|
1086
|
+
gt as useNeedleProgressive,
|
|
1087
|
+
ot as useRaycastMeshes
|
|
1077
1088
|
};
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var $e=Object.defineProperty,Ne=(t,e,r)=>e in t?$e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Ne(t,typeof e!="symbol"?e+"":e,r),r),Se=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},y=(t,e,r)=>(Se(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,o)=>(Se(t,e,"write to private field"),o?o.call(t,r):e.set(t,r),r);import{BufferGeometry as le,Mesh as q,Material as Fe,Texture as Z,TextureLoader as Ue,Matrix4 as Te,Clock as ze,MeshStandardMaterial as Ve,Sphere as qe,Box3 as Ee,Vector3 as W}from"three";import{GLTFLoader as me}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as He}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Ke}from"three/examples/jsm/loaders/KTX2Loader.js";const pe="";globalThis.GLTF_PROGRESSIVE_VERSION=pe,console.debug(`[gltf-progressive] version ${pe}`);let H="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=H,Je=ee;fetch(H+"draco_decoder.js",{method:"head"}).catch(t=>{H===Ye&&(H="./include/draco/"),ee===Je&&(ee="./include/ktx2/")});function Qe(t){H=t}function Ze(t){ee=t}let K,ue,Y;function ve(t){return K||(K=new He,K.setDecoderPath(H),K.setDecoderConfig({type:"js"})),Y||(Y=new Ke,Y.setTranscoderPath(ee)),ue||(ue=Xe),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}const xe=new WeakMap;function Ae(t,e){let r=xe.get(t);r?r=Object.assign(r,e):r=e,xe.set(t,r)}const Be=me.prototype.load;function et(...t){const e=xe.get(this);let r=t[0];const o=new URL(r,window.location.href);if(o.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,n=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${n}`:this.requestHeader.Accept=`*/*;usecase=${n}`,r=o.toString()}return t[0]=r,Be?.call(this,...t)}me.prototype.load=et,te("debugprogressive");function te(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function tt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const o=t.substring(0,r+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let ce;function rt(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const Le=Symbol("needle:raycast-mesh");function re(t){return t?.[Le]instanceof le?t[Le]:null}function Ie(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=nt(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,o){const s=this,n=re(s);let i;n&&s.isMesh&&(i=s.geometry,s.geometry=n),e.call(this,r,o),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function nt(t){const e=new le;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const N=new Array,R="NEEDLE_progressive",x=te("debugprogressive"),Me=Symbol("needle-progressive-texture"),ne=new Map,De=new Set;if(x){let t=function(){e+=1,console.log("Toggle LOD level",e,ne),ne.forEach((s,n)=>{for(const i of s.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,S.assignMeshLOD(n,a),u&&(r=Math.max(r,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,S.assignTextureLOD(n,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,o=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(o=!o,De&&De.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Pe(t,e,r){var o;if(!x)return;ne.has(t)||ne.set(t,{keys:[],sourceId:r});const s=ne.get(t);((o=s?.keys)==null?void 0:o.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 o,s;if(this._isLoadingMesh)return null;const n=(s=(o=this.parser.json.meshes[r])==null?void 0:o.extensions)==null?void 0:s[R];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),x&&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,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 i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let f=0;f<a.lods.length;f++){const g=a.lods[f];g.width&&(l.lods[f]=l.lods[f]||{min_height:1/0,max_height:0},l.lods[f].min_height=Math.min(l.lods[f].min_height,g.height),l.lods[f].max_height=Math.max(l.lods[f].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,s;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(r=o?.userData)!=null&&r.LODS){const n=o.userData.LODS;if(s=this.lodInfos.get(n.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 o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const n of N)(r=n.onBeforeGetLODMesh)==null||r.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=s.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,x&&Pe(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),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 n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const i of s)Array.isArray(i)&&n.push(...i);return n})}else return this.assignTextureLOD(r.material,e)}if(t instanceof Fe||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&n.uniforms[i].value!=a&&(n.uniforms[i].value=a,n.uniformsNeedUpdate=!0),a));o.push(u),s.push(i)}}}else for(const n of Object.keys(r)){const i=r[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,n);o.push(l),s.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,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,o){return t?.isTexture!==!0?Promise.resolve(null):o==="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&&o){const n=r[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,n,s),null}r[o]=s}if(x&&o&&r){const n=this.getAssignedLODInformation(t);n&&Pe(r,o,n.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 n;if(o!=null&&o.extensions){const i=o?.extensions[R];if(i){if(!i.lods){x&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const n=o?.extensions[R];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var r,o,s,n;const i=x=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const f=t;f.source&&f.source[Me]&&(a=f.source[Me])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let p=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!f)return x&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const g=tt(l.url,f);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=g+"_"+a.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(_=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,
|
|
3
|
-
`,m),null));if(!T)return null;const
|
|
1
|
+
var Ue=Object.defineProperty,ze=(t,e,s)=>e in t?Ue(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,c=(t,e,s)=>(ze(t,typeof e!="symbol"?e+"":e,s),s),Ee=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},y=(t,e,s)=>(Ee(t,e,"read from private field"),s?s.call(t):e.get(t)),V=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},N=(t,e,s,o)=>(Ee(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as le,Mesh as q,Material as Ve,Texture as ee,TextureLoader as qe,Matrix4 as Ae,Clock as Xe,MeshStandardMaterial as He,Sphere as Ke,Box3 as Ie,Vector3 as G}from"three";import{GLTFLoader as me}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Ye}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Je}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Qe}from"three/examples/jsm/loaders/KTX2Loader.js";const pe="";globalThis.GLTF_PROGRESSIVE_VERSION=pe,console.debug(`[gltf-progressive] version ${pe}`);let H="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",te="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ze=H,et=te;fetch(H+"draco_decoder.js",{method:"head"}).catch(t=>{H===Ze&&(H="./include/draco/"),te===et&&(te="./include/ktx2/")});function tt(t){H=t}function st(t){te=t}let K,ue,Y;function ve(t){return K||(K=new Je,K.setDecoderPath(H),K.setDecoderConfig({type:"js"})),Y||(Y=new Qe,Y.setTranscoderPath(te)),ue||(ue=Ye),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:K,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(K),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}const xe=new WeakMap;function Le(t,e){let s=xe.get(t);s?s=Object.assign(s,e):s=e,xe.set(t,s)}const Pe=me.prototype.load;function rt(...t){const e=xe.get(this);let s=t[0];const o=new URL(s,window.location.href);if(o.hostname.endsWith("needle.tools")){const r=e?.progressive!==void 0?e.progressive:!0,n=e!=null&&e.usecase?e.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${n}`:this.requestHeader.Accept=`*/*;usecase=${n}`,s=o.toString()}return t[0]=s,Pe?.call(this,...t)}me.prototype.load=rt,se("debugprogressive");function se(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function nt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let ce;function ot(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),se("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const Me=Symbol("needle:raycast-mesh");function J(t){return t?.[Me]instanceof le?t[Me]:null}function ke(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!J(t)){const s=it(e);s.userData={isRaycastMesh:!0},t[Me]=s}}function Be(t=!0){if(t){if(re)return;const e=re=q.prototype.raycast;q.prototype.raycast=function(s,o){const r=this,n=J(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),e.call(this,s,o),i&&(r.geometry=i)}}else{if(!re)return;q.prototype.raycast=re,re=null}}let re=null;function it(t){const e=new le;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const $=new Array,j="NEEDLE_progressive",x=se("debugprogressive"),De=Symbol("needle-progressive-texture"),ne=new Map,we=new Set;if(x){let t=function(){e+=1,console.log("Toggle LOD level",e,ne),ne.forEach((r,n)=>{for(const i of r.keys){const l=n[i];if(l!=null){if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,S.assignMeshLOD(n,a),u&&(s=Math.max(s,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,S.assignTextureLOD(n,e);break}}}}),e>=s&&(e=-1)},e=-1,s=2,o=!1;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(o=!o,we&&we.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function Ce(t,e,s){var o;if(!x)return;ne.has(t)||ne.set(t,{keys:[],sourceId:s});const r=ne.get(t);((o=r?.keys)==null?void 0:o.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const n=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[j];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,void 0,n),i})):null}),x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return j}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=s.getAssignedLODInformation(i);if(u){const a=s.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let g=0;g<a.lods.length;g++){const f=a.lods[g];f.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,f.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,f.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const n=o.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof q||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const n of $)(s=n.onBeforeGetLODMesh)==null||s.call(n,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(o,e).then(n=>{if(Array.isArray(n)){const i=r.index||0;n=n[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,x&&Ce(t,"geometry",r.url)):x&&console.error("Invalid LOD geometry",n))),n}).catch(n=>(console.error("Error loading mesh LOD",t,n),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 s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const n=this.assignTextureLOD(r,e);o.push(n)}return Promise.all(o).then(r=>{const n=new Array;for(const i of r)Array.isArray(i)&&n.push(...i);return n})}else return this.assignTextureLOD(s.material,e)}if(t instanceof Ve||t.isMaterial===!0){const s=t,o=[],r=new Array;if(x&&we.add(s),s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const n=s;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i).then(a=>(a&&n.uniforms[i].value!=a&&(n.uniforms[i].value=a,n.uniformsNeedUpdate=!0),a));o.push(u),r.push(i)}}}else for(const n of Object.keys(s)){const i=s[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,n);o.push(l),r.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof ee||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t){if(s&&o){const n=s[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,n,r),null}s[o]=r}if(x&&o&&s){const n=this.getAssignedLODInformation(t);n&&Ce(s,o,n.url)}}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[j];if(i){if(!i.lods){x&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===r&&(l=!0,w.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,r,i))}l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const n=o?.extensions[j];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&w.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,n;const i=x=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const g=t;g.source&&g.source[De]&&(a=g.source[De])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let p=!1;const A=Array.isArray(a.lods);if(A&&e>=a.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const g=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!g)return x&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const f=nt(l.url,g);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=f+"_"+a.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(b=>(console.error(`Error loading LOD ${e} from ${f}
|
|
2
|
+
`,b),null)),O=!1;if(d==null||(d instanceof ee&&t instanceof ee?(o=d.image)!=null&&o.data||(r=d.source)!=null&&r.data?d=this.copySettings(t,d):(O=!0,this.previouslyLoaded.delete(p)):d instanceof le&&t instanceof le&&((n=d.attributes.position)!=null&&n.array||(O=!0,this.previouslyLoaded.delete(p)))),!O)return d}const D=a,L=new Promise(async(d,O)=>{const b=new me;ye(b),x&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+f,D.guid));let I=f;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(I+="?v="+m.hash)}const T=await b.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${f}
|
|
3
|
+
`,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+f,D.guid);let v=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[j];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){let h=await W.getDependency("texture",v);return h&&w.assignLODInformation(l.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',f,v,h,p),t instanceof ee&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else x&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(v=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[j];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}v++}if(m){const h=await W.getDependency("mesh",v),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,f,v,h,p),h.isMesh===!0){const _=h.geometry;return w.assignLODInformation(l.url,_,u,e,void 0,M.density),d(_)}else{const _=new Array;for(let R=0;R<h.children.length;R++){const z=h.children[R];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(l.url,X,u,e,R,M.density),_.push(X)}}return d(_)}}else x&&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 ee){i&&console.log("Load texture from uri: "+f);const p=await new qe().loadAsync(f);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):x&&console.warn("failed loading",f),p}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,n){if(!e)return;e.userData||(e.userData={});const i=new at(t,s,o,r,n);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),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 S=w;c(S,"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 n=s.guid;w.assignLODInformation(t,e,n,r,o,void 0),w.lodInfos.set(n,s),w.lowresCache.set(n,e)}),c(S,"registerMesh",(t,e,r,o,s,n)=>{var i;x&&console.log("> Progressive: register mesh",s,r.name,n,r.uuid,r);const l=r.geometry;if(!l){x&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,s,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),o>0&&!re(r)&&Ie(r,l);for(const a of N)(i=a.onRegisteredNewMesh)==null||i.call(a,r,n)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class ot{constructor(e,r,o,s,n){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=o,s!=null&&(this.index=s),n!=null&&(this.density=n)}}const P=te("debugprogressive"),it=te("noprogressive"),we=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,F,_e,Q,oe,de,U;const I=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Te),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,F,void 0),V(this,_e,new ze),V(this,Q,0),V(this,oe,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new qe),c(this,"_tempBox",new Ee),c(this,"_tempBox2",new Ee),c(this,"tempMatrix",new Te),c(this,"_tempWorldPosition",new W),c(this,"_tempBoxSize",new W),c(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Oe]}static addPlugin(t){N.push(t)}static removePlugin(t){const e=N.indexOf(t);e>=0&&N.splice(e,1)}static get(t,e){if(t[we])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[we];const r=new I(t,{engine:"unknown",...e});return t[we]=r,r}get plugins(){return N}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(y(this,F))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,F,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,G(e,Q,y(e,Q)+1),G(e,oe,y(e,_e).getDelta()),G(e,de,y(e,de)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),G(e,U,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),P&&y(e,Q)%200===0&&console.log("FPS",Math.round(y(e,U)),"Interval:",y(e,E)));const n=t++;y(e,F).call(this,r,o),e.onAfterRender(r,o,n)}}disable(){y(this,F)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,F),G(this,F,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?y(this,U)<40&&y(this,E)<10?(G(this,E,y(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",y(this,E),y(this,U).toFixed(0))):y(this,U)>=60&&y(this,E)>1&&(G(this,E,y(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",y(this,E),y(this,U).toFixed(0))):G(this,E,this.updateInterval),y(this,E)>0&&y(this,Q)%y(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,o;const s=this.renderer.renderLists.get(t,0),n=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of n){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((o=a.geometry)==null?void 0:o.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){P&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(P==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Ve({color:g});a.object.material=p}const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const l=s.transparent;for(const a of l){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const a of u){const f=a.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,o){var s,n;r.userData||(r.userData={});let i=r[Oe];if(i||(i=new at,r[Oe]=i),i.frames++<2)return;for(const u of N)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,o,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let l=k.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of N)(n=u.onAfterUpdatedLOD)==null||n.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 o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.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[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[J]==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,n=(r.y+o.y)*.5;return this._tempPtInside.set(s,n,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var n;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,l=!1;if(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,f=a&&a.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||(l=!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),O=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=O}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),I.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,ie=(v.x+m.x)*.5,ae=(v.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-ae)*z+ae,b=(b-ie)*z+ie,C=(C-ae)*z+ae;const Ge=h<0&&b>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),We=M<0&&C>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),ge=Math.max(Ge,We);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 O=t.matrixWorldInverse,_=this._tempBox2;_.copy(D),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(O);const B=_.getSize(this._tempBox2Size),T=Math.max(B.x,B.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=B.z/Math.max(B.x,B.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&&I.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=I.corner0,h=I.corner1,M=I.corner2,b=I.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),I.debugDrawLine(m,h,255),I.debugDrawLine(m,M,255),I.debugDrawLine(h,b,255),I.debugDrawLine(M,b,255)}let $=999;if(a&&r.lastScreenCoverage>0){for(let v=0;v<a.length;v++)if(a[v].density/r.lastScreenCoverage<o){$=v;break}}$<i&&(i=$,l=!0)}if(l?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=a?.[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 O=r.lastScreenCoverage*4;((n=this.context)==null?void 0:n.engine)==="model-viewer"&&(O*=1.5);const _=A/window.devicePixelRatio*O;for(let B=g.lods.length-1;B>=0;B--){let T=g.lods[B];if(!(L&&T.max_height>=2048)&&!(rt()&&T.max_height>4096)&&T.max_height>_){if(s.texture_lod=B,s.texture_lod<r.lastLodLevel_Texture){const $=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${$}px
|
|
6
|
-
Screensize: ${
|
|
7
|
-
${e.name}`)}break}}}}else
|
|
8
|
-
`,t.getAttribute("src"));let e=null,
|
|
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,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=r);const n=r.guid;w.assignLODInformation(t,e,n,s,o,void 0),w.lodInfos.set(n,r),w.lowresCache.set(n,e)}),c(S,"registerMesh",(t,e,s,o,r,n)=>{var i;x&&console.log("> Progressive: register mesh",r,s.name,n,s.uuid,s);const l=s.geometry;if(!l){x&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),w.assignLODInformation(t,l,e,o,r,n.density),w.lodInfos.set(e,n);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),o>0&&!J(s)&&ke(s,l);for(const a of $)(i=a.onRegisteredNewMesh)==null||i.call(a,s,n)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class at{constructor(e,s,o,r,n){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r),n!=null&&(this.density=n)}}const k=se("debugprogressive"),lt=se("noprogressive"),Oe=Symbol("Needle:LODSManager"),be=Symbol("Needle:LODState"),Q=Symbol("Needle:CurrentLOD"),B={mesh_lod:-1,texture_lod:-1};var E,F,_e,Z,oe,de,U;const P=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new Ae),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,F,void 0),V(this,_e,new Xe),V(this,Z,0),V(this,oe,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new Ke),c(this,"_tempBox",new Ie),c(this,"_tempBox2",new Ie),c(this,"tempMatrix",new Ae),c(this,"_tempWorldPosition",new G),c(this,"_tempBoxSize",new G),c(this,"_tempBox2Size",new G),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[be]}static addPlugin(t){$.push(t)}static removePlugin(t){const e=$.indexOf(t);e>=0&&$.splice(e,1)}static get(t,e){if(t[Oe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Oe];const s=new P(t,{engine:"unknown",...e});return t[Oe]=s,s}get plugins(){return $}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(y(this,F))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;N(this,F,this.renderer.render);const e=this;ve(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,N(e,Z,y(e,Z)+1),N(e,oe,y(e,_e).getDelta()),N(e,de,y(e,de)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),N(e,U,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),k&&y(e,Z)%200===0&&console.log("FPS",Math.round(y(e,U)),"Interval:",y(e,E)));const n=t++;y(e,F).call(this,s,o),e.onAfterRender(s,o,n)}}disable(){y(this,F)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,F),N(this,F,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let r=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(r=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(r=!1),r){if(lt||(this.updateInterval==="auto"?y(this,U)<40&&y(this,E)<10?(N(this,E,y(this,E)+1),k&&console.warn("\u2193 Reducing LOD updates",y(this,E),y(this,U).toFixed(0))):y(this,U)>=60&&y(this,E)>1&&(N(this,E,y(this,E)-1),k&&console.warn("\u2191 Increasing LOD updates",y(this,E),y(this,U).toFixed(0))):N(this,E,this.updateInterval),y(this,E)>0&&y(this,Z)%y(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var s,o;const r=this.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of n){if(a.material&&(((s=a.geometry)==null?void 0:s.type)==="BoxGeometry"||((o=a.geometry)==null?void 0:o.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){k&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const f=Math.random()*16777215,p=new He({color:f});a.object.material=p}const g=a.object;(g instanceof q||g.isMesh)&&this.updateLODs(t,e,g,i)}const l=r.transparent;for(const a of l){const g=a.object;(g instanceof q||g.isMesh)&&this.updateLODs(t,e,g,i)}const u=r.transmissive;for(const a of u){const g=a.object;(g instanceof q||g.isMesh)&&this.updateLODs(t,e,g,i)}}updateLODs(t,e,s,o){var r,n;s.userData||(s.userData={});let i=s[be];if(i||(i=new ut,s[be]=i),i.frames++<2)return;for(const u of $)(r=u.onBeforeUpdateLOD)==null||r.call(u,this.renderer,t,e,s);this.calculateLodLevel(e,s,i,o,B),B.mesh_lod=Math.round(B.mesh_lod),B.texture_lod=Math.round(B.texture_lod),B.mesh_lod>=0&&this.loadProgressiveMeshes(s,B.mesh_lod);let l=B.texture_lod;if(s.material&&l>=0){const u=s["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(s.material,l)}for(const u of $)(n=u.onAfterUpdatedLOD)==null||n.call(u,this.renderer,t,e,s,B);i.lastLodLevel_Mesh=B.mesh_lod,i.lastLodLevel_Texture=B.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[Q]===void 0||e<t[Q])&&(s=!0),s&&(t[Q]=e,S.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[Q]!==e){t[Q]=e;const s=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[Q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,n=(s.y+o.y)*.5;return this._tempPtInside.set(r,n,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var n;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let i=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,g=a&&a.length>0,f=S.getMaterialMinMaxLODsCount(e.material),p=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!g&&!p){r.mesh_lod=0,r.texture_lod=0;return}g||(l=!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(s.frames%30===0){const d=J(L),O=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=O}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)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const v=this._tempBox.min,m=this._tempBox.max;let h=v.x,M=v.y,_=m.x,R=m.y;const z=2,X=1.5,ie=(v.x+m.x)*.5,ae=(v.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-ae)*z+ae,_=(_-ie)*z+ie,R=(R-ae)*z+ae;const $e=h<0&&_>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),Fe=M<0&&R>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),fe=Math.max($e,Fe);s.lastCentrality=(X-fe)*(X-fe)*(X-fe)}else s.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 O=t.matrixWorldInverse,b=this._tempBox2;b.copy(D),b.applyMatrix4(e.matrixWorld),b.applyMatrix4(O);const I=b.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)),s.lastScreenCoverage=Math.max(d.x,d.y,d.z),s.lastScreenspaceVolume.copy(d),s.lastScreenCoverage*=s.lastCentrality,k&&P.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=P.corner0,h=P.corner1,M=P.corner2,_=P.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,_.copy(this._tempBox.max);const R=(m.z+_.z)*.5;m.z=h.z=M.z=_.z=R,m.applyMatrix4(v),h.applyMatrix4(v),M.applyMatrix4(v),_.applyMatrix4(v),P.debugDrawLine(m,h,255),P.debugDrawLine(m,M,255),P.debugDrawLine(h,_,255),P.debugDrawLine(M,_,255)}let W=999;if(a&&s.lastScreenCoverage>0){for(let v=0;v<a.length;v++)if(a[v].density/s.lastScreenCoverage<o){W=v;break}}W<i&&(i=W,l=!0)}if(l?r.mesh_lod=i:r.mesh_lod=s.lastLodLevel_Mesh,k&&r.mesh_lod!=s.lastLodLevel_Mesh){const L=a?.[r.mesh_lod];L&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,k){const d=f.lods[f.max_count-1];k&&console.log(`First Texture LOD ${r.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let O=s.lastScreenCoverage*4;((n=this.context)==null?void 0:n.engine)==="model-viewer"&&(O*=1.5);const b=A/window.devicePixelRatio*O;for(let I=f.lods.length-1;I>=0;I--){let T=f.lods[I];if(!(L&&T.max_height>=2048)&&!(ot()&&T.max_height>4096)&&T.max_height>b){if(r.texture_lod=I,r.texture_lod<s.lastLodLevel_Texture){const W=T.max_height;k&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${W}px
|
|
6
|
+
Screensize: ${b.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${d.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else r.texture_lod=0}};let C=P;E=new WeakMap,F=new WeakMap,_e=new WeakMap,Z=new WeakMap,oe=new WeakMap,de=new WeakMap,U=new WeakMap,c(C,"debugDrawLine"),c(C,"corner0",new G),c(C,"corner1",new G),c(C,"corner2",new G),c(C,"corner3",new G),c(C,"_tempPtInside",new G);class ut{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new G),c(this,"lastCentrality",0)}}const Re=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let ge=null;function Se(){const t=ct();t&&(t.mapURLs(function(e){return je(),e}),je(),ge?.disconnect(),ge=new MutationObserver(e=>{e.forEach(s=>{s.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&Ge(o)})})}),ge.observe(document,{childList:!0,subtree:!0}))}function ct(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Se()}),null)}function je(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Ge(t)})}const Ne=new WeakSet;let dt=0;function Ge(t){if(!t||Ne.has(t))return null;Ne.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++dt+`
|
|
8
|
+
`,t.getAttribute("src"));let e=null,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!s&&l!=null&&(s=t[l]),!o&&u!=null&&(o=t[u])}if(e&&s){let r=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=C.get(e,{engine:"model-viewer"});return C.addPlugin(new ht),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class ht{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[he]==!0)return;s[he]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),n=this.getUrl(r);if(n&&o&&s.material){let i=function(u){var a,g,f;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=(g=(a=L.userData)==null?void 0:a.associations)==null?void 0:g.textures;if(d==null)continue;const O=o.parser.json.textures[d];if(!O){console.warn("Texture data not found for texture index "+d);continue}if((f=O?.extensions)!=null&&f[j]){const b=O.extensions[j];b&&n&&S.registerTexture(n,L,b.lods.length,d,b)}}}};const l=s.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Re]==!0)return;s[Re]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[j];if(l&&i){const u=s.uuid;S.registerMesh(i,u,s,0,l.lods.length,l)}}}function We(t,e,s,o){ve(e),ye(s),Le(s,{progressive:!0,...o?.hints}),s.register(n=>new S(n,t));const r=C.get(e);return o?.enableLODsManager!==!1&&r.enable(),r}Se();const Te={gltfProgressive:{useNeedleProgressive:We,LODsManager:C,configureLoader:Le,getRaycastMesh:J,useRaycastMeshes:Be}};if(!globalThis.Needle)globalThis.Needle=Te;else for(const t in Te)globalThis.Needle[t]=Te[t];export{j as EXTENSION_NAME,C as LODsManager,S as NEEDLE_progressive,pe as VERSION,ye as addDracoAndKTX2Loaders,Le as configureLoader,ve as createLoaders,J as getRaycastMesh,Se as patchModelViewer,ke as registerRaycastMesh,tt as setDracoDecoderLocation,st as setKTX2TranscoderLocation,We as useNeedleProgressive,Be as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";var Ve=Object.defineProperty;var $e=(n,t,e)=>t in n?Ve(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>($e(n,typeof t!="symbol"?t+"":t,e),e),Ae=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var L=(n,t,e)=>(Ae(n,t,"read from private field"),e?e.call(n):t.get(n)),K=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},N=(n,t,e,s)=>(Ae(n,t,"write to private field"),s?s.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),_e=require("three/examples/jsm/loaders/GLTFLoader.js"),Ne=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Ue=require("three/examples/jsm/loaders/DRACOLoader.js"),ze=require("three/examples/jsm/loaders/KTX2Loader.js"),Oe="";globalThis.GLTF_PROGRESSIVE_VERSION=Oe;console.debug(`[gltf-progressive] version ${Oe}`);let Q="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const We=Q,qe=oe;fetch(Q+"draco_decoder.js",{method:"head"}).catch(n=>{Q===We&&(Q="./include/draco/"),oe===qe&&(oe="./include/ktx2/")});function Xe(n){Q=n}function Ke(n){oe=n}let j,de,J;function Se(n){return j||(j=new Ue.DRACOLoader,j.setDecoderPath(Q),j.setDecoderConfig({type:"js"})),J||(J=new ze.KTX2Loader,J.setTranscoderPath(oe)),de||(de=Ne.MeshoptDecoder),n?J.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:de}}function be(n){n.dracoLoader||n.setDRACOLoader(j),n.ktx2Loader||n.setKTX2Loader(J),n.meshoptDecoder||n.setMeshoptDecoder(de)}const De=new WeakMap;function Ie(n,t){let e=De.get(n);e?e=Object.assign(e,t):e=t,De.set(n,e)}const me=_e.GLTFLoader.prototype.load;function Ye(...n){const t=De.get(this);let e=n[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,i=t!=null&&t.usecase?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return n[0]=e,me==null?void 0:me.call(this,...n)}_e.GLTFLoader.prototype.load=Ye;ne("debugprogressive");function ne(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function He(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const s=n.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}let te;function je(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const we=Symbol("needle:raycast-mesh");function ae(n){return(n==null?void 0:n[we])instanceof p.BufferGeometry?n[we]:null}function Re(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!ae(n)){const s=Qe(t);s.userData={isRaycastMesh:!0},n[we]=s}}function Je(n=!0){if(n){if(se)return;const t=se=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,s){const o=this,r=ae(o);let i;r&&o.isMesh&&(i=o.geometry,o.geometry=r),t.call(this,e,s),i&&(o.geometry=i)}}else{if(!se)return;p.Mesh.prototype.raycast=se,se=null}}let se=null;function Qe(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),Le=Symbol("needle-progressive-texture"),ie=new Map,ve=new Set;if(x){let n=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,r)=>{for(const i of o.keys){const a=r[i];if(a!=null){if(a.isBufferGeometry===!0){const l=O.getMeshLODInformation(a),u=l?Math.min(t,l.lods.length):0;r["DEBUG:LOD"]=t,O.assignMeshLOD(r,u),l&&(e=Math.max(e,l.lods.length-1))}else if(r.isMaterial===!0){r["DEBUG:LOD"]=t,O.assignTextureLOD(r,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,s=!1;window.addEventListener("keyup",o=>{o.key==="p"&&n(),o.key==="w"&&(s=!s,ve&&ve.forEach(r=>{r.name!="BackgroundCubeMaterial"&&r.glyphMap==null&&"wireframe"in r&&(r.wireframe=s)}))})}function Ee(n,t,e){var o;if(!x)return;ie.has(n)||ie.set(n,{keys:[],sourceId:e});const s=ie.get(n);((o=s==null?void 0:s.keys)==null?void 0:o.includes(t))==!1&&s.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var s,o;if(this._isLoadingMesh)return null;const e=(o=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var i;return this._isLoadingMesh=!1,r&&_.registerMesh(this.url,e.guid,r,(i=e.lods)==null?void 0:i.length,void 0,e),r})):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 s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(a,l){const u=s.getAssignedLODInformation(a);if(u){const c=s.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 r;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 a=t[i];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,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 s,o;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const i=s.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 s;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const i of Y)(s=i.onBeforeGetLODMesh)==null||s.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 a=r.index||0;i=i[a]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&Ee(t,"geometry",r.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 s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);o.push(i)}return Promise.all(o).then(r=>{const i=new Array;for(const a of r)Array.isArray(a)&&i.push(...a);return i})}else return this.assignTextureLOD(s.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const s=t,o=[],r=new Array;if(x&&ve.add(s),s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,s,a).then(c=>(c&&i.uniforms[a].value!=c&&(i.uniforms[a].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),r.push(a)}}}else for(const i of Object.keys(s)){const a=s[i];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,i);o.push(l),r.push(i)}}return Promise.all(o).then(i=>{const a=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=r[l];u&&u.isTexture===!0?a.push({material:s,slot:c,texture:u,level:e}):a.push({material:s,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t){if(s&&o){const i=s[o];if(i){const a=this.getAssignedLODInformation(i);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,i,r),null}s[o]=r}if(x&&o&&s){const i=this.getAssignedLODInformation(t);i&&Ee(s,o,i.url)}}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var i;if(o!=null&&o.extensions){const a=o==null?void 0:o.extensions[U];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);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)===r&&(l=!0,_.registerTexture(this.url,u,(i=a.lods)==null?void 0:i.length,r,a))}l||this.parser.getDependency("texture",r).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&_.registerMesh(this.url,i.guid,a,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const s=x=="verbose",o=t.userData.LODS;if(!o)return null;const r=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[Le]&&(i=g.source[Le])}if(i||(i=_.lodInfos.get(r)),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(r)}const g=Array.isArray(i.lods)?(a=i.lods[e])==null?void 0:a.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=He(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){s&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
|
-
`,$),null)),
|
|
3
|
-
`,E),null));if(!b)return null;const q=b.parser;s&&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,r,e,void 0,void 0),s&&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(s&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,r,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,r,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,V),await V}else if(t instanceof p.Texture){s&&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,s&&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 "${r}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,i){if(!e)return;e.userData||(e.userData={});const a=new
|
|
1
|
+
"use strict";var Ue=Object.defineProperty;var ze=(n,t,e)=>t in n?Ue(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>(ze(n,typeof t!="symbol"?t+"":t,e),e),Pe=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var L=(n,t,e)=>(Pe(n,t,"read from private field"),e?e.call(n):t.get(n)),K=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},N=(n,t,e,s)=>(Pe(n,t,"write to private field"),s?s.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Oe=require("three/examples/jsm/loaders/GLTFLoader.js"),We=require("three/examples/jsm/libs/meshopt_decoder.module.js"),qe=require("three/examples/jsm/loaders/DRACOLoader.js"),Xe=require("three/examples/jsm/loaders/KTX2Loader.js"),Se="";globalThis.GLTF_PROGRESSIVE_VERSION=Se;console.debug(`[gltf-progressive] version ${Se}`);let Q="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ne="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ke=Q,Ye=ne;fetch(Q+"draco_decoder.js",{method:"head"}).catch(n=>{Q===Ke&&(Q="./include/draco/"),ne===Ye&&(ne="./include/ktx2/")});function He(n){Q=n}function je(n){ne=n}let j,de,J;function be(n){return j||(j=new qe.DRACOLoader,j.setDecoderPath(Q),j.setDecoderConfig({type:"js"})),J||(J=new Xe.KTX2Loader,J.setTranscoderPath(ne)),de||(de=We.MeshoptDecoder),n?J.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:j,ktx2Loader:J,meshoptDecoder:de}}function Te(n){n.dracoLoader||n.setDRACOLoader(j),n.ktx2Loader||n.setKTX2Loader(J),n.meshoptDecoder||n.setMeshoptDecoder(de)}const we=new WeakMap;function Ae(n,t){let e=we.get(n);e?e=Object.assign(e,t):e=t,we.set(n,e)}const me=Oe.GLTFLoader.prototype.load;function Je(...n){const t=we.get(this);let e=n[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,i=t!=null&&t.usecase?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return n[0]=e,me==null?void 0:me.call(this,...n)}Oe.GLTFLoader.prototype.load=Je;ae("debugprogressive");function ae(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Qe(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const s=n.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}let se;function Ze(){return se!==void 0||(se=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ae("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",se)),se}const ve=Symbol("needle:raycast-mesh");function te(n){return(n==null?void 0:n[ve])instanceof p.BufferGeometry?n[ve]:null}function Re(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!te(n)){const s=et(t);s.userData={isRaycastMesh:!0},n[ve]=s}}function Ge(n=!0){if(n){if(re)return;const t=re=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,s){const o=this,r=te(o);let i;r&&o.isMesh&&(i=o.geometry,o.geometry=r),t.call(this,e,s),i&&(o.geometry=i)}}else{if(!re)return;p.Mesh.prototype.raycast=re,re=null}}let re=null;function et(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ae("debugprogressive"),Le=Symbol("needle-progressive-texture"),oe=new Map,_e=new Set;if(x){let n=function(){t+=1,console.log("Toggle LOD level",t,oe),oe.forEach((o,r)=>{for(const i of o.keys){const a=r[i];if(a!=null){if(a.isBufferGeometry===!0){const l=O.getMeshLODInformation(a),u=l?Math.min(t,l.lods.length):0;r["DEBUG:LOD"]=t,O.assignMeshLOD(r,u),l&&(e=Math.max(e,l.lods.length-1))}else if(r.isMaterial===!0){r["DEBUG:LOD"]=t,O.assignTextureLOD(r,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,s=!1;window.addEventListener("keyup",o=>{o.key==="p"&&n(),o.key==="w"&&(s=!s,_e&&_e.forEach(r=>{r.name!="BackgroundCubeMaterial"&&r.glyphMap==null&&"wireframe"in r&&(r.wireframe=s)}))})}function Ce(n,t,e){var o;if(!x)return;oe.has(n)||oe.set(n,{keys:[],sourceId:e});const s=oe.get(n);((o=s==null?void 0:s.keys)==null?void 0:o.includes(t))==!1&&s.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var s,o;if(this._isLoadingMesh)return null;const e=(o=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var i;return this._isLoadingMesh=!1,r&&_.registerMesh(this.url,e.guid,r,(i=e.lods)==null?void 0:i.length,void 0,e),r})):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 s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(a,l){const u=s.getAssignedLODInformation(a);if(u){const c=s.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 r;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 a=t[i];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,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 s,o;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const i=s.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 s;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const i of Y)(s=i.onBeforeGetLODMesh)==null||s.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(Array.isArray(i)){const a=r.index||0;i=i[a]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&Ce(t,"geometry",r.url)):x&&console.error("Invalid LOD geometry",i))),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 s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);o.push(i)}return Promise.all(o).then(r=>{const i=new Array;for(const a of r)Array.isArray(a)&&i.push(...a);return i})}else return this.assignTextureLOD(s.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const s=t,o=[],r=new Array;if(x&&_e.add(s),s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,s,a).then(c=>(c&&i.uniforms[a].value!=c&&(i.uniforms[a].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),r.push(a)}}}else for(const i of Object.keys(s)){const a=s[i];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,i);o.push(l),r.push(i)}}return Promise.all(o).then(i=>{const a=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=r[l];u&&u.isTexture===!0?a.push({material:s,slot:c,texture:u,level:e}):a.push({material:s,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t){if(s&&o){const i=s[o];if(i){const a=this.getAssignedLODInformation(i);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,i,r),null}s[o]=r}if(x&&o&&s){const i=this.getAssignedLODInformation(t);i&&Ce(s,o,i.url)}}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var i;if(o!=null&&o.extensions){const a=o==null?void 0:o.extensions[U];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);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)===r&&(l=!0,_.registerTexture(this.url,u,(i=a.lods)==null?void 0:i.length,r,a))}l||this.parser.getDependency("texture",r).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&_.registerMesh(this.url,i.guid,a,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const s=x=="verbose",o=t.userData.LODS;if(!o)return null;const r=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[Le]&&(i=g.source[Le])}if(i||(i=_.lodInfos.get(r)),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(r)}const g=Array.isArray(i.lods)?(a=i.lods[e])==null?void 0:a.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){s&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
|
+
`,$),null)),I=!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):(I=!0,this.previouslyLoaded.delete(D)):h instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=h.attributes.position)!=null&&c.array||(I=!0,this.previouslyLoaded.delete(D)))),!I)return h}const M=i,V=new Promise(async(h,I)=>{const $=new Oe.GLTFLoader;Te($),x&&(await new Promise(E=>setTimeout(E,1e3)),s&&console.warn("Start loading (delayed) "+y,M.guid));let R=y;if(M&&Array.isArray(M.lods)){const E=M.lods[e];E.hash&&(R+="?v="+E.hash)}const b=await $.loadAsync(R).catch(E=>(console.error(`Error loading LOD ${e} from ${y}
|
|
3
|
+
`,E),null));if(!b)return null;const q=b.parser;s&&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,r,e,void 0,void 0),s&&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(s&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,r,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,r,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,V),await V}else if(t instanceof p.Texture){s&&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,s&&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 "${r}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r,i){if(!e)return;e.userData||(e.userData={});const a=new tt(t,s,o,r,i);e.userData.LODS=a}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,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const i=r.guid;_.assignLODInformation(t,e,i,s,o,void 0),_.lodInfos.set(i,r),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,s,o,r,i)=>{var u;x&&console.log("> Progressive: register mesh",r,s.name,i,s.uuid,s);const a=s.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),_.assignLODInformation(t,a,e,o,r,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],_.lowresCache.set(e,l),o>0&&!ae(s)&&Re(s,a);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,s,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Ze{constructor(t,e,s,o,r){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=s,o!=null&&(this.index=o),r!=null&&(this.density=r)}}const G=ne("debugprogressive"),et=ne("noprogressive"),xe=Symbol("Needle:LODSManager"),Me=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),F={mesh_lod:-1,texture_lod:-1};var B,z,he,Z,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,Z,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[Me]}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[xe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[xe];const s=new C(t,{engine:"unknown",...e});return t[xe]=s,s}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,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;Se(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+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((a,l)=>a+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,s,o),e.onAfterRender(s,o,i)}}disable(){L(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(et||(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 s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=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,r)}const i=s.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const a=s.transmissive;for(const c of a){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}}updateLODs(t,e,s,o){var a,l;s.userData||(s.userData={});let r=s[Me];if(r||(r=new tt,s[Me]=r),r.frames++<2)return;for(const u of Y)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,s);this.calculateLodLevel(e,s,r,o,F),F.mesh_lod=Math.round(F.mesh_lod),F.texture_lod=Math.round(F.texture_lod),F.mesh_lod>=0&&this.loadProgressiveMeshes(s,F.mesh_lod);let i=F.texture_lod;if(s.material&&i>=0){const u=s["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(s.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,s,F);r.lastLodLevel_Mesh=F.mesh_lod,r.lastLodLevel_Texture=F.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[H]===void 0||e<t[H])&&(s=!0),s&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const s=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,i=(s.y+o.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var V;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=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){r.mesh_lod=0,r.texture_lod=0;return}g||(l=!0,a=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(s.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)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.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 Ge=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Fe=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max(Ge,Fe);s.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else s.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)),s.lastScreenCoverage=Math.max(h.x,h.y,h.z),s.lastScreenspaceVolume.copy(h),s.lastScreenCoverage*=s.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&&s.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/s.lastScreenCoverage<o){A=f;break}}A<a&&(a=A,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,G&&r.mesh_lod!=s.lastLodLevel_Mesh){const h=c==null?void 0:c[r.mesh_lod];h&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let R=s.lastScreenCoverage*4;((V=this.context)==null?void 0:V.engine)==="model-viewer"&&(R*=1.5);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)&&!(je()&&q.max_height>4096)&&q.max_height>k){if(r.texture_lod=b,r.texture_lod<s.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${A}px
|
|
6
|
-
Screensize: ${
|
|
7
|
-
${e.name}`)}break}}}}else r.texture_lod=0}};let
|
|
8
|
-
`,n.getAttribute("src"));let t=null,e=null,s=null;for(let o=n;o!=null;o=Object.getPrototypeOf(o)){const r=Object.getOwnPropertySymbols(o),i=r.find(u=>u.toString()=="Symbol(renderer)"),a=r.find(u=>u.toString()=="Symbol(scene)"),l=r.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=n[i].threeRenderer),!e&&a!=null&&(e=n[a]),!s&&l!=null&&(s=n[l])}if(t&&e){let o=function(){if(s){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}s==null||s.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const r=
|
|
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,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Le]=r);const i=r.guid;_.assignLODInformation(t,e,i,s,o,void 0),_.lodInfos.set(i,r),_.lowresCache.set(i,e)}),d(O,"registerMesh",(t,e,s,o,r,i)=>{var u;x&&console.log("> Progressive: register mesh",r,s.name,i,s.uuid,s);const a=s.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),_.assignLODInformation(t,a,e,o,r,i.density),_.lodInfos.set(e,i);let l=_.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],_.lowresCache.set(e,l),o>0&&!te(s)&&Re(s,a);for(const c of Y)(u=c.onRegisteredNewMesh)==null||u.call(c,s,i)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class tt{constructor(t,e,s,o,r){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=t,this.key=e,this.level=s,o!=null&&(this.index=o),r!=null&&(this.density=r)}}const G=ae("debugprogressive"),st=ae("noprogressive"),xe=Symbol("Needle:LODSManager"),Me=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),F={mesh_lod:-1,texture_lod:-1};var B,z,he,Z,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,Z,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[Me]}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[xe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[xe];const s=new C(t,{engine:"unknown",...e});return t[xe]=s,s}get plugins(){return Y}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,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;be(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,N(e,Z,L(e,Z)+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((a,l)=>a+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,s,o),e.onAfterRender(s,o,i)}}disable(){L(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=L(this,z),N(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(st||(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 s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=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,r)}const i=s.transparent;for(const c of i){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}const a=s.transmissive;for(const c of a){const g=c.object;(g instanceof p.Mesh||g.isMesh)&&this.updateLODs(t,e,g,r)}}updateLODs(t,e,s,o){var a,l;s.userData||(s.userData={});let r=s[Me];if(r||(r=new rt,s[Me]=r),r.frames++<2)return;for(const u of Y)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,s);this.calculateLodLevel(e,s,r,o,F),F.mesh_lod=Math.round(F.mesh_lod),F.texture_lod=Math.round(F.texture_lod),F.mesh_lod>=0&&this.loadProgressiveMeshes(s,F.mesh_lod);let i=F.texture_lod;if(s.material&&i>=0){const u=s["DEBUG:LOD"];u!=null&&(i=u),this.loadProgressiveTextures(s.material,i)}for(const u of Y)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,s,F);r.lastLodLevel_Mesh=F.mesh_lod,r.lastLodLevel_Texture=F.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let s=!1;(t[H]===void 0||e<t[H])&&(s=!0),s&&(t[H]=e,O.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(r=>r({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[H]!==e){t[H]=e;const s=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[H]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(r=>r({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,i=(s.y+o.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var V;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=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){r.mesh_lod=0,r.texture_lod=0;return}g||(l=!0,a=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(s.frames%30===0){const h=te(w),I=w.geometry;h&&(w.geometry=h),w.computeBoundingBox(),w.geometry=I}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)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.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 $e=S<0&&P>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ne=T<0&&X>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ye=Math.max($e,Ne);s.lastCentrality=(pe-ye)*(pe-ye)*(pe-ye)}else s.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 I=t.matrixWorldInverse,$=this._tempBox2;$.copy(M),$.applyMatrix4(e.matrixWorld),$.applyMatrix4(I);const R=$.getSize(this._tempBox2Size),b=Math.max(R.x,R.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=R.z/Math.max(R.x,R.y)*Math.max(h.x,h.y)),s.lastScreenCoverage=Math.max(h.x,h.y,h.z),s.lastScreenspaceVolume.copy(h),s.lastScreenCoverage*=s.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&&s.lastScreenCoverage>0){for(let f=0;f<c.length;f++)if(c[f].density/s.lastScreenCoverage<o){A=f;break}}A<a&&(a=A,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,G&&r.mesh_lod!=s.lastLodLevel_Mesh){const h=c==null?void 0:c[r.mesh_lod];h&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(D){const w="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=y.max_count-1,G){const h=y.lods[y.max_count-1];G&&console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`)}}else{const h=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let I=s.lastScreenCoverage*4;((V=this.context)==null?void 0:V.engine)==="model-viewer"&&(I*=1.5);const R=v/window.devicePixelRatio*I;for(let b=y.lods.length-1;b>=0;b--){let q=y.lods[b];if(!(w&&q.max_height>=2048)&&!(Ze()&&q.max_height>4096)&&q.max_height>R){if(r.texture_lod=b,r.texture_lod<s.lastLodLevel_Texture){const A=q.max_height;G&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${A}px
|
|
6
|
+
Screensize: ${R.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${h.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else r.texture_lod=0}};let k=C;B=new WeakMap,z=new WeakMap,he=new WeakMap,Z=new WeakMap,ee=new WeakMap,ge=new WeakMap,W=new WeakMap,d(k,"debugDrawLine"),d(k,"corner0",new p.Vector3),d(k,"corner1",new p.Vector3),d(k,"corner2",new p.Vector3),d(k,"corner3",new p.Vector3),d(k,"_tempPtInside",new p.Vector3);class rt{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const Be=Symbol("NEEDLE_mesh_lod"),fe=Symbol("NEEDLE_texture_lod");let ie=null;function Ee(){const n=it();n&&(n.mapURLs(function(t){return ke(),t}),ke(),ie==null||ie.disconnect(),ie=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&Fe(s)})})}),ie.observe(document,{childList:!0,subtree:!0}))}function it(){if(typeof customElements>"u")return null;const n=customElements.get("model-viewer");return n||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ee()}),null)}function ke(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Fe(t)})}const Ie=new WeakSet;let ot=0;function Fe(n){if(!n||Ie.has(n))return null;Ie.add(n),console.debug("[gltf-progressive] found new model-viewer..."+ ++ot+`
|
|
8
|
+
`,n.getAttribute("src"));let t=null,e=null,s=null;for(let o=n;o!=null;o=Object.getPrototypeOf(o)){const r=Object.getOwnPropertySymbols(o),i=r.find(u=>u.toString()=="Symbol(renderer)"),a=r.find(u=>u.toString()=="Symbol(scene)"),l=r.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=n[i].threeRenderer),!e&&a!=null&&(e=n[a]),!s&&l!=null&&(s=n[l])}if(t&&e){let o=function(){if(s){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}s==null||s.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const r=k.get(t,{engine:"model-viewer"});return k.addPlugin(new nt),r.enable(),r.addEventListener("changed",()=>{s==null||s.call(n)}),n.addEventListener("model-visibility",i=>{i.detail.visible&&(s==null||s.call(n))}),n.addEventListener("load",()=>{o()}),()=>{r.disable()}}return null}class nt{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,s,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 s=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),r=this.getUrl(o);if(r&&s&&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 V=(g=(c=M.userData)==null?void 0:c.associations)==null?void 0:g.textures;if(V==null)continue;const w=s.parser.json.textures[V];if(!w){console.warn("Texture data not found for texture index "+V);continue}if((y=w==null?void 0:w.extensions)!=null&&y[U]){const h=w.extensions[U];h&&r&&O.registerTexture(r,M,h.lods.length,V,h)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(t,e){var i,a;if(e[Be]==!0)return;e[Be]=!0;const s=this.tryGetCurrentModelViewer(t),o=this.getUrl(s);if(!o)return;const r=(a=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:a[U];if(r&&o){const l=e.uuid;O.registerMesh(o,l,e,0,r.lods.length,r)}}}function Ve(n,t,e,s){be(t),Te(e),Ae(e,{progressive:!0,...s==null?void 0:s.hints}),e.register(r=>new O(r,n));const o=k.get(t);return(s==null?void 0:s.enableLODsManager)!==!1&&o.enable(),o}Ee();const De={gltfProgressive:{useNeedleProgressive:Ve,LODsManager:k,configureLoader:Ae,getRaycastMesh:te,useRaycastMeshes:Ge}};if(!globalThis.Needle)globalThis.Needle=De;else for(const n in De)globalThis.Needle[n]=De[n];exports.EXTENSION_NAME=U;exports.LODsManager=k;exports.NEEDLE_progressive=O;exports.VERSION=Se;exports.addDracoAndKTX2Loaders=Te;exports.configureLoader=Ae;exports.createLoaders=be;exports.getRaycastMesh=te;exports.patchModelViewer=Ee;exports.registerRaycastMesh=Re;exports.setDracoDecoderLocation=He;exports.setKTX2TranscoderLocation=je;exports.useNeedleProgressive=Ve;exports.useRaycastMeshes=Ge;
|
package/lib/extension.js
CHANGED
|
@@ -251,12 +251,12 @@ export class NEEDLE_progressive {
|
|
|
251
251
|
// const info = this.onProgressiveLoadStart(context, source, mesh, null);
|
|
252
252
|
mesh["LOD:requested level"] = level;
|
|
253
253
|
return NEEDLE_progressive.getOrLoadLOD(currentGeometry, level).then(geo => {
|
|
254
|
+
if (Array.isArray(geo)) {
|
|
255
|
+
const index = lodinfo.index || 0;
|
|
256
|
+
geo = geo[index];
|
|
257
|
+
}
|
|
254
258
|
if (mesh["LOD:requested level"] === level) {
|
|
255
259
|
delete mesh["LOD:requested level"];
|
|
256
|
-
if (Array.isArray(geo)) {
|
|
257
|
-
const index = lodinfo.index || 0;
|
|
258
|
-
geo = geo[index];
|
|
259
|
-
}
|
|
260
260
|
if (geo && currentGeometry != geo) {
|
|
261
261
|
const isGeometry = geo?.isBufferGeometry;
|
|
262
262
|
// if (debug == "verbose") console.log("Progressive Mesh " + mesh.name + " loaded", currentGeometry, "→", geo, "\n", mesh)
|
package/lib/index.js
CHANGED
|
@@ -39,3 +39,21 @@ export function useNeedleProgressive(url, renderer, loader, opts) {
|
|
|
39
39
|
/** Modelviewer */
|
|
40
40
|
import { patchModelViewer } from "./plugins/modelviewer.js";
|
|
41
41
|
patchModelViewer();
|
|
42
|
+
import { getRaycastMesh, useRaycastMeshes } from "./utils.js";
|
|
43
|
+
const global = {
|
|
44
|
+
gltfProgressive: {
|
|
45
|
+
useNeedleProgressive,
|
|
46
|
+
LODsManager,
|
|
47
|
+
configureLoader,
|
|
48
|
+
getRaycastMesh,
|
|
49
|
+
useRaycastMeshes,
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
if (!globalThis["Needle"]) {
|
|
53
|
+
globalThis["Needle"] = global;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
for (const key in global) {
|
|
57
|
+
globalThis["Needle"][key] = global[key];
|
|
58
|
+
}
|
|
59
|
+
}
|
package/lib/version.js
CHANGED
package/package.json
CHANGED