@needle-tools/gltf-progressive 2.1.0-alpha.1 → 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 +3 -0
- package/gltf-progressive.js +179 -165
- package/gltf-progressive.min.js +7 -7
- package/gltf-progressive.umd.cjs +7 -7
- package/lib/index.js +18 -0
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,9 @@ 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
|
+
|
|
7
10
|
## [2.1.0-alpha.1] - 2025-01-15
|
|
8
11
|
- Fix: issue where `getMeshLOD` for multi-material meshes would not return the correct index if called multiple times at the same time
|
|
9
12
|
|
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);
|
|
@@ -268,7 +268,7 @@ const v = class {
|
|
|
268
268
|
const a = r.index || 0;
|
|
269
269
|
i = i[a];
|
|
270
270
|
}
|
|
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 &&
|
|
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;
|
|
272
272
|
}).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
|
|
273
273
|
} else
|
|
274
274
|
L && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
@@ -294,9 +294,9 @@ const v = class {
|
|
|
294
294
|
} else
|
|
295
295
|
return this.assignTextureLOD(s.material, e);
|
|
296
296
|
}
|
|
297
|
-
if (t instanceof
|
|
297
|
+
if (t instanceof Xe || t.isMaterial === !0) {
|
|
298
298
|
const s = t, n = [], r = new Array();
|
|
299
|
-
if (L &&
|
|
299
|
+
if (L && be.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
|
300
300
|
const i = s;
|
|
301
301
|
for (const a of Object.keys(i.uniforms)) {
|
|
302
302
|
const l = i.uniforms[a].value;
|
|
@@ -345,7 +345,7 @@ const v = class {
|
|
|
345
345
|
}
|
|
346
346
|
if (L && n && s) {
|
|
347
347
|
const i = this.getAssignedLODInformation(t);
|
|
348
|
-
i &&
|
|
348
|
+
i && Ce(s, n, i.url);
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
351
|
return r;
|
|
@@ -359,7 +359,7 @@ const v = class {
|
|
|
359
359
|
return L && console.log("AFTER", this.url, t), (e = this.parser.json.textures) == null || e.forEach((n, r) => {
|
|
360
360
|
var i;
|
|
361
361
|
if (n != null && n.extensions) {
|
|
362
|
-
const a = n == null ? void 0 : n.extensions[
|
|
362
|
+
const a = n == null ? void 0 : n.extensions[z];
|
|
363
363
|
if (a) {
|
|
364
364
|
if (!a.lods) {
|
|
365
365
|
L && console.warn("Texture has no LODs", a);
|
|
@@ -379,7 +379,7 @@ const v = class {
|
|
|
379
379
|
}
|
|
380
380
|
}), (s = this.parser.json.meshes) == null || s.forEach((n, r) => {
|
|
381
381
|
if (n != null && n.extensions) {
|
|
382
|
-
const i = n == null ? void 0 : n.extensions[
|
|
382
|
+
const i = n == null ? void 0 : n.extensions[z];
|
|
383
383
|
if (i && i.lods) {
|
|
384
384
|
for (const a of this.parser.associations.keys())
|
|
385
385
|
if (a.isMesh) {
|
|
@@ -411,7 +411,7 @@ const v = class {
|
|
|
411
411
|
const g = Array.isArray(i.lods) ? (a = i.lods[e]) == null ? void 0 : a.path : i.lods;
|
|
412
412
|
if (!g)
|
|
413
413
|
return L && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, i)), null;
|
|
414
|
-
const p =
|
|
414
|
+
const p = rt(n.url, g);
|
|
415
415
|
if (p.endsWith(".glb") || p.endsWith(".gltf")) {
|
|
416
416
|
if (!i.guid)
|
|
417
417
|
return console.warn("missing pointer for glb/gltf texture", i), null;
|
|
@@ -419,19 +419,19 @@ const v = class {
|
|
|
419
419
|
if (w !== void 0) {
|
|
420
420
|
s && console.log(`LOD ${e} was already loading/loaded: ${M}`);
|
|
421
421
|
let h = await w.catch((F) => (console.error(`Error loading LOD ${e} from ${p}
|
|
422
|
-
`, F), null)),
|
|
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) : (
|
|
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)
|
|
424
424
|
return h;
|
|
425
425
|
}
|
|
426
|
-
const x = i, $ = new Promise(async (h,
|
|
427
|
-
const F = new
|
|
428
|
-
|
|
429
|
-
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;
|
|
430
430
|
if (x && Array.isArray(x.lods)) {
|
|
431
431
|
const A = x.lods[e];
|
|
432
|
-
A.hash && (
|
|
432
|
+
A.hash && (I += "?v=" + A.hash);
|
|
433
433
|
}
|
|
434
|
-
const S = await F.loadAsync(
|
|
434
|
+
const S = await F.loadAsync(I).catch((A) => (console.error(`Error loading LOD ${e} from ${p}
|
|
435
435
|
`, A), null));
|
|
436
436
|
if (!S)
|
|
437
437
|
return null;
|
|
@@ -442,7 +442,7 @@ const v = class {
|
|
|
442
442
|
let A = !1;
|
|
443
443
|
for (const f of S.parser.json.textures) {
|
|
444
444
|
if (f != null && f.extensions) {
|
|
445
|
-
const y = f == null ? void 0 : f.extensions[
|
|
445
|
+
const y = f == null ? void 0 : f.extensions[z];
|
|
446
446
|
if (y != null && y.guid && y.guid === x.guid) {
|
|
447
447
|
A = !0;
|
|
448
448
|
break;
|
|
@@ -460,7 +460,7 @@ const v = class {
|
|
|
460
460
|
let A = !1;
|
|
461
461
|
for (const f of S.parser.json.meshes) {
|
|
462
462
|
if (f != null && f.extensions) {
|
|
463
|
-
const y = f == null ? void 0 : f.extensions[
|
|
463
|
+
const y = f == null ? void 0 : f.extensions[z];
|
|
464
464
|
if (y != null && y.guid && y.guid === x.guid) {
|
|
465
465
|
A = !0;
|
|
466
466
|
break;
|
|
@@ -492,7 +492,7 @@ const v = class {
|
|
|
492
492
|
return this.previouslyLoaded.set(M, $), await $;
|
|
493
493
|
} else if (t instanceof se) {
|
|
494
494
|
s && console.log("Load texture from uri: " + p);
|
|
495
|
-
const w = await new
|
|
495
|
+
const w = await new Ke().loadAsync(p);
|
|
496
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;
|
|
497
497
|
}
|
|
498
498
|
} else
|
|
@@ -503,7 +503,7 @@ const v = class {
|
|
|
503
503
|
if (!e)
|
|
504
504
|
return;
|
|
505
505
|
e.userData || (e.userData = {});
|
|
506
|
-
const a = new
|
|
506
|
+
const a = new lt(t, s, n, r, i);
|
|
507
507
|
e.userData.LODS = a;
|
|
508
508
|
}
|
|
509
509
|
static getAssignedLODInformation(t) {
|
|
@@ -542,14 +542,14 @@ d(_, "registerMesh", (t, e, s, n, r, i) => {
|
|
|
542
542
|
}
|
|
543
543
|
a.userData || (a.userData = {}), v.assignLODInformation(t, a, e, n, r, i.density), v.lodInfos.set(e, i);
|
|
544
544
|
let l = v.lowresCache.get(e);
|
|
545
|
-
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);
|
|
546
546
|
for (const c of Y)
|
|
547
547
|
(u = c.onRegisteredNewMesh) == null || u.call(c, s, i);
|
|
548
548
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
549
549
|
d(_, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
550
550
|
d(_, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
551
551
|
d(_, "lowresCache", /* @__PURE__ */ new Map());
|
|
552
|
-
class
|
|
552
|
+
class lt {
|
|
553
553
|
constructor(t, e, s, n, r) {
|
|
554
554
|
d(this, "url");
|
|
555
555
|
/** the key to lookup the LOD information */
|
|
@@ -562,14 +562,14 @@ class ot {
|
|
|
562
562
|
this.url = t, this.key = e, this.level = s, n != null && (this.index = n), r != null && (this.density = r);
|
|
563
563
|
}
|
|
564
564
|
}
|
|
565
|
-
const
|
|
566
|
-
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;
|
|
567
567
|
const P = class {
|
|
568
568
|
// readonly plugins: NEEDLE_progressive_plugin[] = [];
|
|
569
569
|
constructor(t, e) {
|
|
570
570
|
d(this, "context");
|
|
571
571
|
d(this, "renderer");
|
|
572
|
-
d(this, "projectionScreenMatrix", new
|
|
572
|
+
d(this, "projectionScreenMatrix", new Ee());
|
|
573
573
|
/**
|
|
574
574
|
* The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
|
|
575
575
|
* @default 200_000
|
|
@@ -593,21 +593,21 @@ const P = class {
|
|
|
593
593
|
*/
|
|
594
594
|
d(this, "manual", !1);
|
|
595
595
|
d(this, "_lodchangedlisteners", []);
|
|
596
|
-
K(this,
|
|
597
|
-
K(this,
|
|
596
|
+
K(this, V, void 0);
|
|
597
|
+
K(this, ye, new Ye());
|
|
598
598
|
K(this, ee, 0);
|
|
599
599
|
K(this, te, 0);
|
|
600
|
-
K(this,
|
|
600
|
+
K(this, me, 0);
|
|
601
601
|
K(this, W, 0);
|
|
602
602
|
d(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
|
|
603
603
|
// private testIfLODLevelsAreAvailable() {
|
|
604
|
-
d(this, "_sphere", new
|
|
605
|
-
d(this, "_tempBox", new
|
|
606
|
-
d(this, "_tempBox2", new
|
|
607
|
-
d(this, "tempMatrix", new
|
|
608
|
-
d(this, "_tempWorldPosition", new
|
|
609
|
-
d(this, "_tempBoxSize", new
|
|
610
|
-
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());
|
|
611
611
|
this.renderer = t, this.context = { ...e };
|
|
612
612
|
}
|
|
613
613
|
/** @internal */
|
|
@@ -652,21 +652,21 @@ const P = class {
|
|
|
652
652
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
653
653
|
*/
|
|
654
654
|
enable() {
|
|
655
|
-
if (m(this,
|
|
655
|
+
if (m(this, V))
|
|
656
656
|
return;
|
|
657
657
|
console.debug("[gltf-progressive] Enabling LODsManager for renderer");
|
|
658
658
|
let t = 0;
|
|
659
|
-
U(this,
|
|
659
|
+
U(this, V, this.renderer.render);
|
|
660
660
|
const e = this;
|
|
661
|
-
|
|
661
|
+
Ge(this.renderer), this.renderer.render = function(s, n) {
|
|
662
662
|
const r = e.renderer.getRenderTarget();
|
|
663
|
-
(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)));
|
|
664
664
|
const i = t++;
|
|
665
|
-
m(e,
|
|
665
|
+
m(e, V).call(this, s, n), e.onAfterRender(s, n, i);
|
|
666
666
|
};
|
|
667
667
|
}
|
|
668
668
|
disable() {
|
|
669
|
-
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));
|
|
670
670
|
}
|
|
671
671
|
update(t, e) {
|
|
672
672
|
this.internalUpdate(t, e);
|
|
@@ -681,7 +681,7 @@ const P = class {
|
|
|
681
681
|
(a.name === "EffectMaterial" || a.name === "CopyShader") && (i = !1);
|
|
682
682
|
}
|
|
683
683
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
|
|
684
|
-
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))
|
|
685
685
|
return;
|
|
686
686
|
this.internalUpdate(t, e);
|
|
687
687
|
}
|
|
@@ -696,7 +696,7 @@ const P = class {
|
|
|
696
696
|
const r = this.targetTriangleDensity;
|
|
697
697
|
for (const c of n) {
|
|
698
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")) {
|
|
699
|
-
|
|
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)));
|
|
700
700
|
continue;
|
|
701
701
|
}
|
|
702
702
|
switch (c.material.type) {
|
|
@@ -708,9 +708,9 @@ const P = class {
|
|
|
708
708
|
case "MeshDepthMaterial":
|
|
709
709
|
continue;
|
|
710
710
|
}
|
|
711
|
-
if (
|
|
711
|
+
if (R === "color" && c.material && !c.object.progressive_debug_color) {
|
|
712
712
|
c.object.progressive_debug_color = !0;
|
|
713
|
-
const p = Math.random() * 16777215, M = new
|
|
713
|
+
const p = Math.random() * 16777215, M = new He({ color: p });
|
|
714
714
|
c.object.material = M;
|
|
715
715
|
}
|
|
716
716
|
const g = c.object;
|
|
@@ -732,19 +732,19 @@ const P = class {
|
|
|
732
732
|
var a, l;
|
|
733
733
|
s.userData || (s.userData = {});
|
|
734
734
|
let r = s[ve];
|
|
735
|
-
if (r || (r = new
|
|
735
|
+
if (r || (r = new ut(), s[ve] = r), r.frames++ < 2)
|
|
736
736
|
return;
|
|
737
737
|
for (const u of Y)
|
|
738
738
|
(a = u.onBeforeUpdateLOD) == null || a.call(u, this.renderer, t, e, s);
|
|
739
|
-
this.calculateLodLevel(e, s, r, n,
|
|
740
|
-
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;
|
|
741
741
|
if (s.material && i >= 0) {
|
|
742
742
|
const u = s["DEBUG:LOD"];
|
|
743
743
|
u != null && (i = u), this.loadProgressiveTextures(s.material, i);
|
|
744
744
|
}
|
|
745
745
|
for (const u of Y)
|
|
746
|
-
(l = u.onAfterUpdatedLOD) == null || l.call(u, this.renderer, t, e, s,
|
|
747
|
-
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;
|
|
748
748
|
}
|
|
749
749
|
/** Load progressive textures for the given material
|
|
750
750
|
* @param material the material to load the textures for
|
|
@@ -795,7 +795,7 @@ const P = class {
|
|
|
795
795
|
return;
|
|
796
796
|
}
|
|
797
797
|
let a = 10 + 1, l = !1;
|
|
798
|
-
if (
|
|
798
|
+
if (R && e["DEBUG:LOD"] != null)
|
|
799
799
|
return e["DEBUG:LOD"];
|
|
800
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;
|
|
801
801
|
if (!g && !M) {
|
|
@@ -810,8 +810,8 @@ const P = class {
|
|
|
810
810
|
if (!D.boundingBox)
|
|
811
811
|
D.computeBoundingBox();
|
|
812
812
|
else if (s.frames % 30 === 0) {
|
|
813
|
-
const h =
|
|
814
|
-
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;
|
|
815
815
|
}
|
|
816
816
|
x = D.boundingBox;
|
|
817
817
|
}
|
|
@@ -832,18 +832,18 @@ const P = class {
|
|
|
832
832
|
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && D.fov > 70) {
|
|
833
833
|
const f = this._tempBox.min, y = this._tempBox.max;
|
|
834
834
|
let O = f.x, b = f.y, E = y.x, X = y.y;
|
|
835
|
-
const
|
|
836
|
-
O = (O -
|
|
837
|
-
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);
|
|
838
838
|
s.lastCentrality = (Le - xe) * (Le - xe) * (Le - xe);
|
|
839
839
|
} else
|
|
840
840
|
s.lastCentrality = 1;
|
|
841
841
|
const h = this._tempBox.getSize(this._tempBoxSize);
|
|
842
842
|
h.multiplyScalar(0.5), screen.availHeight > 0 && w > 0 && h.multiplyScalar(w / screen.availHeight), h.x *= D.aspect;
|
|
843
|
-
const
|
|
844
|
-
F.copy(x), F.applyMatrix4(e.matrixWorld), F.applyMatrix4(
|
|
845
|
-
const
|
|
846
|
-
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) {
|
|
847
847
|
const f = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
848
848
|
f.invert();
|
|
849
849
|
const y = P.corner0, O = P.corner1, b = P.corner2, E = P.corner3;
|
|
@@ -861,29 +861,29 @@ const P = class {
|
|
|
861
861
|
}
|
|
862
862
|
T < a && (a = T, l = !0);
|
|
863
863
|
}
|
|
864
|
-
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) {
|
|
865
865
|
const h = c == null ? void 0 : c[r.mesh_lod];
|
|
866
866
|
h && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`);
|
|
867
867
|
}
|
|
868
868
|
if (M) {
|
|
869
869
|
const D = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
870
870
|
if (s.lastLodLevel_Texture < 0) {
|
|
871
|
-
if (r.texture_lod = p.max_count - 1,
|
|
871
|
+
if (r.texture_lod = p.max_count - 1, R) {
|
|
872
872
|
const h = p.lods[p.max_count - 1];
|
|
873
|
-
|
|
873
|
+
R && console.log(`First Texture LOD ${r.texture_lod} (${h.max_height}px) - ${e.name}`);
|
|
874
874
|
}
|
|
875
875
|
} else {
|
|
876
876
|
const h = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
877
|
-
let
|
|
878
|
-
(($ = this.context) == null ? void 0 : $.engine) === "model-viewer" && (
|
|
879
|
-
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;
|
|
880
880
|
for (let S = p.lods.length - 1; S >= 0; S--) {
|
|
881
881
|
let q = p.lods[S];
|
|
882
|
-
if (!(D && q.max_height >= 2048) && !(
|
|
882
|
+
if (!(D && q.max_height >= 2048) && !(it() && q.max_height > 4096) && q.max_height > I) {
|
|
883
883
|
if (r.texture_lod = S, r.texture_lod < s.lastLodLevel_Texture) {
|
|
884
884
|
const T = q.max_height;
|
|
885
|
-
|
|
886
|
-
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)}
|
|
887
887
|
${e.name}`);
|
|
888
888
|
}
|
|
889
889
|
break;
|
|
@@ -894,55 +894,55 @@ ${e.name}`);
|
|
|
894
894
|
r.texture_lod = 0;
|
|
895
895
|
}
|
|
896
896
|
};
|
|
897
|
-
let
|
|
898
|
-
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.
|
|
899
899
|
*/
|
|
900
|
-
d(
|
|
901
|
-
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 {
|
|
902
902
|
constructor() {
|
|
903
903
|
d(this, "frames", 0);
|
|
904
904
|
d(this, "lastLodLevel_Mesh", -1);
|
|
905
905
|
d(this, "lastLodLevel_Texture", -1);
|
|
906
906
|
d(this, "lastScreenCoverage", 0);
|
|
907
|
-
d(this, "lastScreenspaceVolume", new
|
|
907
|
+
d(this, "lastScreenspaceVolume", new N());
|
|
908
908
|
d(this, "lastCentrality", 0);
|
|
909
909
|
}
|
|
910
910
|
}
|
|
911
|
-
const
|
|
911
|
+
const Be = Symbol("NEEDLE_mesh_lod"), he = Symbol("NEEDLE_texture_lod");
|
|
912
912
|
let ne = null;
|
|
913
|
-
function
|
|
914
|
-
const o =
|
|
913
|
+
function Ue() {
|
|
914
|
+
const o = ft();
|
|
915
915
|
o && (o.mapURLs(function(t) {
|
|
916
|
-
return
|
|
917
|
-
}),
|
|
916
|
+
return ke(), t;
|
|
917
|
+
}), ke(), ne == null || ne.disconnect(), ne = new MutationObserver((t) => {
|
|
918
918
|
t.forEach((e) => {
|
|
919
919
|
e.addedNodes.forEach((s) => {
|
|
920
|
-
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" &&
|
|
920
|
+
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ne(s);
|
|
921
921
|
});
|
|
922
922
|
});
|
|
923
923
|
}), ne.observe(document, { childList: !0, subtree: !0 }));
|
|
924
924
|
}
|
|
925
|
-
function
|
|
925
|
+
function ft() {
|
|
926
926
|
if (typeof customElements > "u")
|
|
927
927
|
return null;
|
|
928
928
|
const o = customElements.get("model-viewer");
|
|
929
929
|
return o || (customElements.whenDefined("model-viewer").then(() => {
|
|
930
|
-
console.debug("[gltf-progressive] model-viewer defined"),
|
|
930
|
+
console.debug("[gltf-progressive] model-viewer defined"), Ue();
|
|
931
931
|
}), null);
|
|
932
932
|
}
|
|
933
|
-
function
|
|
933
|
+
function ke() {
|
|
934
934
|
if (typeof document > "u")
|
|
935
935
|
return;
|
|
936
936
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
937
|
-
|
|
937
|
+
Ne(t);
|
|
938
938
|
});
|
|
939
939
|
}
|
|
940
|
-
const
|
|
941
|
-
let
|
|
942
|
-
function
|
|
943
|
-
if (!o ||
|
|
940
|
+
const Ie = /* @__PURE__ */ new WeakSet();
|
|
941
|
+
let dt = 0;
|
|
942
|
+
function Ne(o) {
|
|
943
|
+
if (!o || Ie.has(o))
|
|
944
944
|
return null;
|
|
945
|
-
|
|
945
|
+
Ie.add(o), console.debug("[gltf-progressive] found new model-viewer..." + ++dt + `
|
|
946
946
|
`, o.getAttribute("src"));
|
|
947
947
|
let t = null, e = null, s = null;
|
|
948
948
|
for (let n = o; n != null; n = Object.getPrototypeOf(n)) {
|
|
@@ -962,8 +962,8 @@ function Fe(o) {
|
|
|
962
962
|
}
|
|
963
963
|
};
|
|
964
964
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
965
|
-
const r =
|
|
966
|
-
return
|
|
965
|
+
const r = B.get(t, { engine: "model-viewer" });
|
|
966
|
+
return B.addPlugin(new ht()), r.enable(), r.addEventListener("changed", () => {
|
|
967
967
|
s == null || s.call(o);
|
|
968
968
|
}), o.addEventListener("model-visibility", (i) => {
|
|
969
969
|
i.detail.visible && (s == null || s.call(o));
|
|
@@ -975,7 +975,7 @@ function Fe(o) {
|
|
|
975
975
|
}
|
|
976
976
|
return null;
|
|
977
977
|
}
|
|
978
|
-
class
|
|
978
|
+
class ht {
|
|
979
979
|
constructor() {
|
|
980
980
|
d(this, "_didWarnAboutMissingUrl", !1);
|
|
981
981
|
}
|
|
@@ -995,16 +995,16 @@ class ft {
|
|
|
995
995
|
return t.element;
|
|
996
996
|
}
|
|
997
997
|
tryParseTextureLOD(t, e) {
|
|
998
|
-
if (e[
|
|
998
|
+
if (e[he] == !0)
|
|
999
999
|
return;
|
|
1000
|
-
e[
|
|
1000
|
+
e[he] = !0;
|
|
1001
1001
|
const s = this.tryGetCurrentGLTF(t), n = this.tryGetCurrentModelViewer(t), r = this.getUrl(n);
|
|
1002
1002
|
if (r && s && e.material) {
|
|
1003
1003
|
let i = function(l) {
|
|
1004
1004
|
var c, g, p;
|
|
1005
|
-
if (l[
|
|
1005
|
+
if (l[he] == !0)
|
|
1006
1006
|
return;
|
|
1007
|
-
l[
|
|
1007
|
+
l[he] = !0, l.userData && (l.userData.LOD = -1);
|
|
1008
1008
|
const u = Object.keys(l);
|
|
1009
1009
|
for (let M = 0; M < u.length; M++) {
|
|
1010
1010
|
const w = u[M], x = l[w];
|
|
@@ -1017,8 +1017,8 @@ class ft {
|
|
|
1017
1017
|
console.warn("Texture data not found for texture index " + $);
|
|
1018
1018
|
continue;
|
|
1019
1019
|
}
|
|
1020
|
-
if ((p = D == null ? void 0 : D.extensions) != null && p[
|
|
1021
|
-
const h = D.extensions[
|
|
1020
|
+
if ((p = D == null ? void 0 : D.extensions) != null && p[z]) {
|
|
1021
|
+
const h = D.extensions[z];
|
|
1022
1022
|
h && r && _.registerTexture(r, x, h.lods.length, $, h);
|
|
1023
1023
|
}
|
|
1024
1024
|
}
|
|
@@ -1034,41 +1034,55 @@ class ft {
|
|
|
1034
1034
|
}
|
|
1035
1035
|
tryParseMeshLOD(t, e) {
|
|
1036
1036
|
var i, a;
|
|
1037
|
-
if (e[
|
|
1037
|
+
if (e[Be] == !0)
|
|
1038
1038
|
return;
|
|
1039
|
-
e[
|
|
1039
|
+
e[Be] = !0;
|
|
1040
1040
|
const s = this.tryGetCurrentModelViewer(t), n = this.getUrl(s);
|
|
1041
1041
|
if (!n)
|
|
1042
1042
|
return;
|
|
1043
|
-
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];
|
|
1044
1044
|
if (r && n) {
|
|
1045
1045
|
const l = e.uuid;
|
|
1046
1046
|
_.registerMesh(n, l, e, 0, r.lods.length, r);
|
|
1047
1047
|
}
|
|
1048
1048
|
}
|
|
1049
1049
|
}
|
|
1050
|
-
function
|
|
1051
|
-
|
|
1050
|
+
function gt(o, t, e, s) {
|
|
1051
|
+
Ge(t), $e(e), Fe(e, {
|
|
1052
1052
|
progressive: !0,
|
|
1053
1053
|
...s == null ? void 0 : s.hints
|
|
1054
1054
|
}), e.register((r) => new _(r, o));
|
|
1055
|
-
const n =
|
|
1055
|
+
const n = B.get(t);
|
|
1056
1056
|
return (s == null ? void 0 : s.enableLODsManager) !== !1 && n.enable(), n;
|
|
1057
1057
|
}
|
|
1058
|
-
|
|
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];
|
|
1059
1073
|
export {
|
|
1060
|
-
|
|
1061
|
-
|
|
1074
|
+
z as EXTENSION_NAME,
|
|
1075
|
+
B as LODsManager,
|
|
1062
1076
|
_ as NEEDLE_progressive,
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
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
|
|
1074
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(Array.isArray(n)){const i=s.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&&Pe(t,"geometry",s.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 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(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&&Ee(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&&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/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