@needle-tools/gltf-progressive 3.6.0-alpha.2 → 3.6.0-canary.027a4c9
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 +643 -539
- package/gltf-progressive.min.js +9 -9
- package/gltf-progressive.umd.cjs +9 -9
- package/lib/extension.d.ts +6 -0
- package/lib/extension.js +85 -16
- package/lib/loaders.d.ts +1 -8
- package/lib/loaders.js +15 -2
- package/lib/lods.manager.d.ts +1 -0
- package/lib/lods.manager.js +40 -5
- package/lib/utils.d.ts +1 -1
- package/lib/utils.internal.d.ts +27 -0
- package/lib/utils.internal.js +50 -19
- package/lib/version.js +1 -1
- package/lib/worker/loader.mainthread.js +6 -4
- package/package.json +9 -4
package/gltf-progressive.js
CHANGED
|
@@ -1,69 +1,98 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import * as Xe from "three";
|
|
2
|
+
import { RedFormat as je, RedIntegerFormat as Ke, RGFormat as Ye, RGIntegerFormat as He, RGBFormat as Qe, RGBAFormat as Je, RGBAIntegerFormat as Ze, BufferGeometry as j, Mesh as K, Box3 as ue, Vector3 as P, Sphere as Ae, CompressedTexture as et, Texture as q, Matrix3 as tt, InterleavedBuffer as st, InterleavedBufferAttribute as rt, BufferAttribute as nt, TextureLoader as it, Color as Ie, Matrix4 as $e } from "three";
|
|
3
|
+
import { GLTFLoader as De } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
|
+
import { MeshoptDecoder as ot } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
5
|
+
import { DRACOLoader as at } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
6
|
+
import { KTX2Loader as lt } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
7
|
+
const ut = "";
|
|
8
|
+
globalThis.GLTF_PROGRESSIVE_VERSION = ut;
|
|
8
9
|
console.debug("[gltf-progressive] version -");
|
|
9
|
-
let
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
fetch(
|
|
10
|
+
let $ = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", Y = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
|
|
11
|
+
const ct = $, ft = Y, Be = new URL($ + "draco_decoder.js");
|
|
12
|
+
Be.searchParams.append("range", "true");
|
|
13
|
+
fetch(Be, {
|
|
13
14
|
method: "GET",
|
|
14
15
|
headers: {
|
|
15
16
|
Range: "bytes=0-1"
|
|
16
17
|
}
|
|
17
18
|
}).catch((i) => {
|
|
18
|
-
console.debug(`Failed to fetch remote Draco decoder from ${
|
|
19
|
+
console.debug(`Failed to fetch remote Draco decoder from ${$} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), $ === ct && ht("./include/draco/"), Y === ft && gt("./include/ktx2/");
|
|
19
20
|
}).finally(() => {
|
|
20
|
-
|
|
21
|
+
qe();
|
|
21
22
|
});
|
|
22
|
-
const
|
|
23
|
-
dracoDecoderPath:
|
|
23
|
+
const dt = () => ({
|
|
24
|
+
dracoDecoderPath: $,
|
|
24
25
|
ktx2TranscoderPath: Y
|
|
25
26
|
});
|
|
26
|
-
function
|
|
27
|
-
|
|
27
|
+
function ht(i) {
|
|
28
|
+
$ = i, C && C[ye] != $ ? (console.debug("Updating Draco decoder path to " + i), C[ye] = $, C.setDecoderPath($), C.preload()) : console.debug("Setting Draco decoder path to " + i);
|
|
28
29
|
}
|
|
29
|
-
function
|
|
30
|
-
Y = i,
|
|
30
|
+
function gt(i) {
|
|
31
|
+
Y = i, B && B.transcoderPath != Y ? (console.debug("Updating KTX2 transcoder path to " + i), B.setTranscoderPath(Y), B.init()) : console.debug("Setting KTX2 transcoder path to " + i);
|
|
31
32
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
33
|
+
function _e(i) {
|
|
34
|
+
return qe(), i ? B.detectSupport(i) : i !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: B, meshoptDecoder: le };
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
-
i.dracoLoader || i.setDRACOLoader(
|
|
36
|
+
function Ge(i) {
|
|
37
|
+
i.dracoLoader || i.setDRACOLoader(C), i.ktx2Loader || i.setKTX2Loader(B), i.meshoptDecoder || i.setMeshoptDecoder(le);
|
|
37
38
|
}
|
|
38
|
-
const
|
|
39
|
-
let
|
|
40
|
-
function
|
|
41
|
-
|
|
39
|
+
const ye = /* @__PURE__ */ Symbol("dracoDecoderPath");
|
|
40
|
+
let C, le, B;
|
|
41
|
+
function qe() {
|
|
42
|
+
C || (C = new at(), C[ye] = $, C.setDecoderPath($), C.setDecoderConfig({ type: "js" }), C.preload()), B || (B = new lt(), B.setTranscoderPath(Y), B.init()), le || (le = ot);
|
|
42
43
|
}
|
|
43
|
-
const
|
|
44
|
-
function
|
|
45
|
-
let e =
|
|
46
|
-
e ? e = Object.assign(e, t) : e = t,
|
|
44
|
+
const xe = /* @__PURE__ */ new WeakMap();
|
|
45
|
+
function We(i, t) {
|
|
46
|
+
let e = xe.get(i);
|
|
47
|
+
e ? e = Object.assign(e, t) : e = t, xe.set(i, e);
|
|
47
48
|
}
|
|
48
|
-
const
|
|
49
|
-
function
|
|
50
|
-
const t =
|
|
49
|
+
const pt = De.prototype.load;
|
|
50
|
+
function mt(...i) {
|
|
51
|
+
const t = xe.get(this);
|
|
51
52
|
let e = i[0];
|
|
52
|
-
const s =
|
|
53
|
-
if (s
|
|
53
|
+
const s = yt(e);
|
|
54
|
+
if (s?.hostname.endsWith("needle.tools")) {
|
|
54
55
|
const n = t?.progressive !== void 0 ? t.progressive : !0, o = t?.usecase ? t.usecase : "default";
|
|
55
56
|
n ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${o}` : this.requestHeader.Accept = `*/*;usecase=${o}`, e = s.toString();
|
|
56
57
|
}
|
|
57
|
-
return i[0] = e,
|
|
58
|
+
return i[0] = e, pt?.call(this, ...i);
|
|
59
|
+
}
|
|
60
|
+
De.prototype.load = mt;
|
|
61
|
+
function yt(i) {
|
|
62
|
+
try {
|
|
63
|
+
if (i instanceof URL)
|
|
64
|
+
return i;
|
|
65
|
+
const t = globalThis.location?.href;
|
|
66
|
+
return t ? new URL(i, t) : new URL(i);
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function Oe(i) {
|
|
72
|
+
return i != null && i.data != null;
|
|
73
|
+
}
|
|
74
|
+
function we(i) {
|
|
75
|
+
const t = i.source?.data;
|
|
76
|
+
return t != null && typeof t == "object" ? t : null;
|
|
77
|
+
}
|
|
78
|
+
function xt(i) {
|
|
79
|
+
const t = i.image;
|
|
80
|
+
return t != null && typeof t == "object" ? t : null;
|
|
81
|
+
}
|
|
82
|
+
function Le(i) {
|
|
83
|
+
const t = xt(i), e = we(i);
|
|
84
|
+
return {
|
|
85
|
+
width: t?.width || e?.width || 0,
|
|
86
|
+
height: t?.height || e?.height || 0
|
|
87
|
+
};
|
|
58
88
|
}
|
|
59
|
-
we.prototype.load = ot;
|
|
60
89
|
N("debugprogressive");
|
|
61
90
|
function N(i) {
|
|
62
91
|
if (typeof window > "u") return !1;
|
|
63
92
|
const e = new URL(window.location.href).searchParams.get(i);
|
|
64
93
|
return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
|
|
65
94
|
}
|
|
66
|
-
function
|
|
95
|
+
function wt(i, t) {
|
|
67
96
|
if (t === void 0 || i === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
|
|
68
97
|
return t;
|
|
69
98
|
const e = i.lastIndexOf("/");
|
|
@@ -74,16 +103,18 @@ function it(i, t) {
|
|
|
74
103
|
}
|
|
75
104
|
return t;
|
|
76
105
|
}
|
|
77
|
-
function
|
|
78
|
-
|
|
106
|
+
function Me() {
|
|
107
|
+
if (Z !== void 0) return Z;
|
|
108
|
+
const i = globalThis.navigator?.userAgent || "";
|
|
109
|
+
return Z = /iPhone|iPad|iPod|Android|IEMobile/i.test(i), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", Z), Z;
|
|
79
110
|
}
|
|
80
111
|
let Z;
|
|
81
|
-
function
|
|
112
|
+
function Fe() {
|
|
82
113
|
if (typeof window > "u") return !1;
|
|
83
114
|
const i = new URL(window.location.href), t = i.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);
|
|
84
115
|
return i.hostname === "127.0.0.1" || t;
|
|
85
116
|
}
|
|
86
|
-
class
|
|
117
|
+
class Lt {
|
|
87
118
|
constructor(t, e = {}) {
|
|
88
119
|
this.maxConcurrent = t, this.debug = e.debug ?? !1, typeof window < "u" && window.requestAnimationFrame(this.tick);
|
|
89
120
|
}
|
|
@@ -117,29 +148,29 @@ class at {
|
|
|
117
148
|
}
|
|
118
149
|
}
|
|
119
150
|
}
|
|
120
|
-
function
|
|
121
|
-
const t = i.image?.width ?? 0,
|
|
122
|
-
return
|
|
151
|
+
function vt(i) {
|
|
152
|
+
const t = i.image, e = t?.width ?? 0, s = t?.height ?? 0, r = t?.depth ?? 1, n = Math.floor(Math.log2(Math.max(e, s, r))) + 1, o = Dt(i);
|
|
153
|
+
return e * s * r * o * (1 - Math.pow(0.25, n)) / (1 - 0.25);
|
|
123
154
|
}
|
|
124
|
-
function
|
|
155
|
+
function Dt(i) {
|
|
125
156
|
let t = 4;
|
|
126
157
|
const e = i.format;
|
|
127
|
-
e ===
|
|
158
|
+
e === je || e === Ke ? t = 1 : e === Ye || e === He ? t = 2 : e === Qe || e === 1029 ? t = 3 : (e === Je || e === Ze) && (t = 4);
|
|
128
159
|
let s = 1;
|
|
129
160
|
const r = i.type;
|
|
130
161
|
return r === 1009 || r === 1010 ? s = 1 : r === 1011 || r === 1012 ? s = 2 : r === 1013 || r === 1014 || r === 1015 ? s = 4 : r === 1016 && (s = 2), t * s;
|
|
131
162
|
}
|
|
132
|
-
const
|
|
163
|
+
const _t = typeof window > "u" && typeof document > "u", ve = /* @__PURE__ */ Symbol("needle:raycast-mesh");
|
|
133
164
|
function ne(i) {
|
|
134
|
-
return i?.[
|
|
165
|
+
return i?.[ve] instanceof j ? i[ve] : null;
|
|
135
166
|
}
|
|
136
|
-
function
|
|
167
|
+
function Mt(i, t) {
|
|
137
168
|
if ((i.type === "Mesh" || i.type === "SkinnedMesh") && !ne(i)) {
|
|
138
|
-
const s =
|
|
139
|
-
s.userData = { isRaycastMesh: !0 }, i[
|
|
169
|
+
const s = Ot(t);
|
|
170
|
+
s.userData = { isRaycastMesh: !0 }, i[ve] = s;
|
|
140
171
|
}
|
|
141
172
|
}
|
|
142
|
-
function
|
|
173
|
+
function bt(i = !0) {
|
|
143
174
|
if (i) {
|
|
144
175
|
if (ee) return;
|
|
145
176
|
const t = ee = K.prototype.raycast;
|
|
@@ -154,15 +185,15 @@ function ft(i = !0) {
|
|
|
154
185
|
}
|
|
155
186
|
}
|
|
156
187
|
let ee = null;
|
|
157
|
-
function
|
|
188
|
+
function Ot(i) {
|
|
158
189
|
const t = new j();
|
|
159
190
|
for (const e in i.attributes)
|
|
160
191
|
t.setAttribute(e, i.getAttribute(e));
|
|
161
192
|
return t.setIndex(i.getIndex()), t;
|
|
162
193
|
}
|
|
163
|
-
const E = new Array(),
|
|
194
|
+
const E = new Array(), h = N("debugprogressive");
|
|
164
195
|
let re, X = -1;
|
|
165
|
-
if (
|
|
196
|
+
if (h) {
|
|
166
197
|
let i = function() {
|
|
167
198
|
X += 1, X >= t && (X = -1), console.log(`Toggle LOD level [${X}]`);
|
|
168
199
|
};
|
|
@@ -173,27 +204,27 @@ if (f) {
|
|
|
173
204
|
!isNaN(s) && s >= 0 && (X = s, console.log(`Set LOD level to [${X}]`));
|
|
174
205
|
});
|
|
175
206
|
}
|
|
176
|
-
function
|
|
177
|
-
if (
|
|
207
|
+
function Ue(i) {
|
|
208
|
+
if (h && re !== void 0)
|
|
178
209
|
if (Array.isArray(i))
|
|
179
210
|
for (const t of i)
|
|
180
|
-
|
|
211
|
+
Ue(t);
|
|
181
212
|
else i && "wireframe" in i && (i.wireframe = re === !0);
|
|
182
213
|
}
|
|
183
214
|
const te = new Array();
|
|
184
|
-
let
|
|
185
|
-
const
|
|
186
|
-
function
|
|
187
|
-
if (te.length <
|
|
215
|
+
let Tt = 0;
|
|
216
|
+
const St = Me() ? 2 : 10;
|
|
217
|
+
function Rt(i) {
|
|
218
|
+
if (te.length < St) {
|
|
188
219
|
const s = te.length;
|
|
189
|
-
|
|
190
|
-
const r =
|
|
220
|
+
h && console.warn(`[Worker] Creating new worker #${s}`);
|
|
221
|
+
const r = be.createWorker(i || {});
|
|
191
222
|
return te.push(r), r;
|
|
192
223
|
}
|
|
193
|
-
const t =
|
|
224
|
+
const t = Tt++ % te.length;
|
|
194
225
|
return te[t];
|
|
195
226
|
}
|
|
196
|
-
class
|
|
227
|
+
class be {
|
|
197
228
|
constructor(t, e) {
|
|
198
229
|
this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
|
|
199
230
|
const r = s.data;
|
|
@@ -201,7 +232,7 @@ class _e {
|
|
|
201
232
|
case "loaded-gltf":
|
|
202
233
|
for (const n of this._running)
|
|
203
234
|
if (n.url === r.result.url) {
|
|
204
|
-
|
|
235
|
+
Ct(r.result), n.resolve(r.result);
|
|
205
236
|
const o = n.url;
|
|
206
237
|
o.startsWith("blob:") && URL.revokeObjectURL(o);
|
|
207
238
|
}
|
|
@@ -220,61 +251,68 @@ class _e {
|
|
|
220
251
|
), {
|
|
221
252
|
type: "module"
|
|
222
253
|
});
|
|
223
|
-
return new
|
|
254
|
+
return new be(e, t);
|
|
224
255
|
}
|
|
225
256
|
_running = [];
|
|
226
257
|
_webglRenderer = null;
|
|
227
258
|
async load(t, e) {
|
|
228
|
-
const s =
|
|
259
|
+
const s = dt();
|
|
229
260
|
let r = e?.renderer;
|
|
230
261
|
r || (this._webglRenderer ??= (async () => {
|
|
231
|
-
const { WebGLRenderer:
|
|
232
|
-
return new
|
|
262
|
+
const { WebGLRenderer: u } = await import("three");
|
|
263
|
+
return new u();
|
|
233
264
|
})(), r = await this._webglRenderer);
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
265
|
+
const a = _e(r).ktx2Loader.workerConfig;
|
|
266
|
+
if (t instanceof URL)
|
|
267
|
+
t = t.toString();
|
|
268
|
+
else if (t.startsWith("file:"))
|
|
269
|
+
t = URL.createObjectURL(new Blob([t]));
|
|
270
|
+
else if (!t.startsWith("blob:") && !t.startsWith("http:") && !t.startsWith("https:")) {
|
|
271
|
+
const u = globalThis.location?.href;
|
|
272
|
+
u && (t = new URL(t, u).toString());
|
|
273
|
+
}
|
|
274
|
+
const l = {
|
|
237
275
|
type: "load",
|
|
238
276
|
url: t,
|
|
239
277
|
dracoDecoderPath: s.dracoDecoderPath,
|
|
240
278
|
ktx2TranscoderPath: s.ktx2TranscoderPath,
|
|
241
|
-
ktx2LoaderConfig:
|
|
279
|
+
ktx2LoaderConfig: a
|
|
242
280
|
};
|
|
243
|
-
return this._debug && console.debug("[Worker] Sending load request",
|
|
281
|
+
return this._debug && console.debug("[Worker] Sending load request", l), this.worker.postMessage(l), new Promise((u) => {
|
|
244
282
|
this._running.push({
|
|
245
283
|
url: t.toString(),
|
|
246
|
-
resolve:
|
|
284
|
+
resolve: u
|
|
247
285
|
});
|
|
248
286
|
});
|
|
249
287
|
}
|
|
250
288
|
_debug = !1;
|
|
251
289
|
}
|
|
252
|
-
function
|
|
290
|
+
function Ct(i) {
|
|
253
291
|
for (const t of i.geometries) {
|
|
254
292
|
const e = t.geometry, s = new j();
|
|
255
293
|
if (s.name = e.name || "", e.index) {
|
|
256
294
|
const r = e.index;
|
|
257
|
-
s.setIndex(
|
|
295
|
+
s.setIndex(fe(r));
|
|
258
296
|
}
|
|
259
297
|
for (const r in e.attributes) {
|
|
260
|
-
const n = e.attributes[r], o =
|
|
298
|
+
const n = e.attributes[r], o = fe(n);
|
|
261
299
|
s.setAttribute(r, o);
|
|
262
300
|
}
|
|
263
301
|
if (e.morphAttributes)
|
|
264
302
|
for (const r in e.morphAttributes) {
|
|
265
|
-
const o = e.morphAttributes[r].map((
|
|
303
|
+
const o = e.morphAttributes[r].map((a) => fe(a));
|
|
266
304
|
s.morphAttributes[r] = o;
|
|
267
305
|
}
|
|
268
|
-
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new
|
|
306
|
+
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ue(), s.boundingBox.min = new P(
|
|
269
307
|
e.boundingBox?.min.x,
|
|
270
308
|
e.boundingBox?.min.y,
|
|
271
309
|
e.boundingBox?.min.z
|
|
272
|
-
), s.boundingBox.max = new
|
|
310
|
+
), s.boundingBox.max = new P(
|
|
273
311
|
e.boundingBox?.max.x,
|
|
274
312
|
e.boundingBox?.max.y,
|
|
275
313
|
e.boundingBox?.max.z
|
|
276
|
-
), s.boundingSphere = new
|
|
277
|
-
new
|
|
314
|
+
), s.boundingSphere = new Ae(
|
|
315
|
+
new P(
|
|
278
316
|
e.boundingSphere?.center.x,
|
|
279
317
|
e.boundingSphere?.center.y,
|
|
280
318
|
e.boundingSphere?.center.z
|
|
@@ -289,8 +327,8 @@ function yt(i) {
|
|
|
289
327
|
const e = t.texture;
|
|
290
328
|
let s = null;
|
|
291
329
|
if (e.isCompressedTexture) {
|
|
292
|
-
const r = e.mipmaps,
|
|
293
|
-
s = new
|
|
330
|
+
const r = e.mipmaps, { width: n, height: o } = Le(e);
|
|
331
|
+
s = new et(
|
|
294
332
|
r,
|
|
295
333
|
n,
|
|
296
334
|
o,
|
|
@@ -305,7 +343,7 @@ function yt(i) {
|
|
|
305
343
|
e.colorSpace
|
|
306
344
|
);
|
|
307
345
|
} else
|
|
308
|
-
s = new
|
|
346
|
+
s = new q(
|
|
309
347
|
e.image,
|
|
310
348
|
e.mapping,
|
|
311
349
|
e.wrapS,
|
|
@@ -316,7 +354,7 @@ function yt(i) {
|
|
|
316
354
|
e.type,
|
|
317
355
|
e.anisotropy,
|
|
318
356
|
e.colorSpace
|
|
319
|
-
), s.mipmaps = e.mipmaps, s.channel = e.channel, s.source.data = e.source.data, s.flipY = e.flipY, s.premultiplyAlpha = e.premultiplyAlpha, s.unpackAlignment = e.unpackAlignment, s.matrix = new
|
|
357
|
+
), s.mipmaps = e.mipmaps, s.channel = e.channel, s.source.data = e.source.data, s.flipY = e.flipY, s.premultiplyAlpha = e.premultiplyAlpha, s.unpackAlignment = e.unpackAlignment, s.matrix = new tt(...e.matrix.elements);
|
|
320
358
|
if (!s) {
|
|
321
359
|
console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");
|
|
322
360
|
continue;
|
|
@@ -325,18 +363,18 @@ function yt(i) {
|
|
|
325
363
|
}
|
|
326
364
|
return i;
|
|
327
365
|
}
|
|
328
|
-
function
|
|
366
|
+
function fe(i) {
|
|
329
367
|
let t = i;
|
|
330
368
|
if ("isInterleavedBufferAttribute" in i && i.isInterleavedBufferAttribute) {
|
|
331
|
-
const e = i.data, s = e.array, r = new
|
|
332
|
-
t = new
|
|
333
|
-
} else "isBufferAttribute" in i && i.isBufferAttribute && (t = new
|
|
369
|
+
const e = i.data, s = e.array, r = new st(s, e.stride);
|
|
370
|
+
t = new rt(r, i.itemSize, s.byteOffset, i.normalized), t.offset = i.offset;
|
|
371
|
+
} else "isBufferAttribute" in i && i.isBufferAttribute && (t = new nt(i.array, i.itemSize, i.normalized), t.usage = i.usage, t.gpuType = i.gpuType, t.updateRanges = i.updateRanges);
|
|
334
372
|
return t;
|
|
335
373
|
}
|
|
336
|
-
const
|
|
374
|
+
const Pt = N("gltf-progressive-worker");
|
|
337
375
|
N("gltf-progressive-reduce-mipmaps");
|
|
338
376
|
const se = N("gltf-progressive-gc"), de = /* @__PURE__ */ Symbol("needle-progressive-texture"), F = "NEEDLE_progressive";
|
|
339
|
-
class
|
|
377
|
+
class p {
|
|
340
378
|
/** The name of the extension */
|
|
341
379
|
get name() {
|
|
342
380
|
return F;
|
|
@@ -381,33 +419,33 @@ class h {
|
|
|
381
419
|
max_count: 0,
|
|
382
420
|
lods: []
|
|
383
421
|
}), Array.isArray(t)) {
|
|
384
|
-
for (const
|
|
385
|
-
this.getMaterialMinMaxLODsCount(
|
|
422
|
+
for (const a of t)
|
|
423
|
+
this.getMaterialMinMaxLODsCount(a, e);
|
|
386
424
|
return t[r] = e, e;
|
|
387
425
|
}
|
|
388
|
-
if (
|
|
389
|
-
const
|
|
390
|
-
for (const
|
|
391
|
-
const
|
|
392
|
-
|
|
426
|
+
if (h === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
|
|
427
|
+
const a = t;
|
|
428
|
+
for (const l of Object.keys(a.uniforms)) {
|
|
429
|
+
const u = a.uniforms[l].value;
|
|
430
|
+
u?.isTexture === !0 && o(u, e);
|
|
393
431
|
}
|
|
394
432
|
} else if (t.isMaterial)
|
|
395
|
-
for (const
|
|
396
|
-
const
|
|
397
|
-
|
|
433
|
+
for (const a of Object.keys(t)) {
|
|
434
|
+
const l = t[a];
|
|
435
|
+
l?.isTexture === !0 && o(l, e);
|
|
398
436
|
}
|
|
399
437
|
else
|
|
400
|
-
|
|
438
|
+
h && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
|
|
401
439
|
return t[r] = e, e;
|
|
402
|
-
function o(
|
|
403
|
-
const
|
|
404
|
-
if (
|
|
405
|
-
const
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
for (let
|
|
409
|
-
const
|
|
410
|
-
|
|
440
|
+
function o(a, l) {
|
|
441
|
+
const u = s.getAssignedLODInformation(a);
|
|
442
|
+
if (u) {
|
|
443
|
+
const f = s.lodInfos.get(u.key);
|
|
444
|
+
if (f && f.lods) {
|
|
445
|
+
l.min_count = Math.min(l.min_count, f.lods.length), l.max_count = Math.max(l.max_count, f.lods.length);
|
|
446
|
+
for (let c = 0; c < f.lods.length; c++) {
|
|
447
|
+
const d = f.lods[c];
|
|
448
|
+
d.width && (l.lods[c] = l.lods[c] || { min_height: 1 / 0, max_height: 0 }, l.lods[c].min_height = Math.min(l.lods[c].min_height, d.height), l.lods[c].max_height = Math.max(l.lods[c].max_height, d.height));
|
|
411
449
|
}
|
|
412
450
|
}
|
|
413
451
|
}
|
|
@@ -465,16 +503,21 @@ class h {
|
|
|
465
503
|
const r = t.geometry, n = this.getAssignedLODInformation(r);
|
|
466
504
|
if (!n)
|
|
467
505
|
return Promise.resolve(null);
|
|
468
|
-
for (const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
506
|
+
for (const a of E)
|
|
507
|
+
a.onBeforeGetLODMesh?.(t, e);
|
|
508
|
+
t["LOD:requested level"] = e;
|
|
509
|
+
const o = () => t["LOD:requested level"] === e || this.shouldApplyStaleMeshLOD(t, e);
|
|
510
|
+
return p.getOrLoadLOD(r, e, {
|
|
511
|
+
isCurrent: o
|
|
512
|
+
}).then((a) => {
|
|
513
|
+
if (Array.isArray(a)) {
|
|
472
514
|
const u = n.index || 0;
|
|
473
|
-
|
|
515
|
+
a = a[u];
|
|
474
516
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
517
|
+
const l = t["LOD:requested level"] === e;
|
|
518
|
+
return (l || this.shouldApplyStaleMeshLOD(t, e)) && (l && delete t["LOD:requested level"], a && r != a && (a?.isBufferGeometry ? typeof s?.apply == "function" ? s.apply(a, e, t) : s?.apply !== !1 && (t.geometry = a) : h && console.error("Invalid LOD geometry", a))), a;
|
|
519
|
+
}).catch((a) => (console.error("Error loading mesh LOD", t, a), null));
|
|
520
|
+
} else h && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
478
521
|
return Promise.resolve(null);
|
|
479
522
|
}
|
|
480
523
|
static assignTextureLOD(t, e = 0, s) {
|
|
@@ -484,48 +527,48 @@ class h {
|
|
|
484
527
|
const n = t;
|
|
485
528
|
if (Array.isArray(n.material)) {
|
|
486
529
|
const o = new Array();
|
|
487
|
-
for (const
|
|
488
|
-
const
|
|
489
|
-
o.push(
|
|
530
|
+
for (const a of n.material) {
|
|
531
|
+
const l = this.assignTextureLOD(a, e, s);
|
|
532
|
+
o.push(l);
|
|
490
533
|
}
|
|
491
|
-
return Promise.all(o).then((
|
|
492
|
-
const
|
|
493
|
-
for (const
|
|
494
|
-
Array.isArray(
|
|
495
|
-
return
|
|
534
|
+
return Promise.all(o).then((a) => {
|
|
535
|
+
const l = new Array();
|
|
536
|
+
for (const u of a)
|
|
537
|
+
Array.isArray(u) && l.push(...u);
|
|
538
|
+
return l;
|
|
496
539
|
});
|
|
497
540
|
} else
|
|
498
541
|
return this.assignTextureLOD(n.material, e, s);
|
|
499
542
|
}
|
|
500
543
|
if (t.isMaterial === !0) {
|
|
501
|
-
const n = t, o = [],
|
|
544
|
+
const n = t, o = [], a = new Array();
|
|
502
545
|
if (this.trackCurrentMaterialTextureSlots(n), n.uniforms && (n.isRawShaderMaterial || n.isShaderMaterial === !0)) {
|
|
503
|
-
const
|
|
504
|
-
for (const
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
507
|
-
const
|
|
508
|
-
o.push(
|
|
546
|
+
const l = n;
|
|
547
|
+
for (const u of Object.keys(l.uniforms)) {
|
|
548
|
+
const f = l.uniforms[u].value;
|
|
549
|
+
if (f?.isTexture === !0) {
|
|
550
|
+
const c = this.assignTextureLODForSlot(f, e, n, u, r).then((d) => (d && l.uniforms[u].value != d && (l.uniforms[u].value = d, l.uniformsNeedUpdate = !0), d));
|
|
551
|
+
o.push(c), a.push(u);
|
|
509
552
|
}
|
|
510
553
|
}
|
|
511
554
|
} else
|
|
512
|
-
for (const
|
|
513
|
-
const
|
|
514
|
-
if (
|
|
515
|
-
const
|
|
516
|
-
o.push(
|
|
555
|
+
for (const l of Object.keys(n)) {
|
|
556
|
+
const u = n[l];
|
|
557
|
+
if (u?.isTexture === !0) {
|
|
558
|
+
const f = this.assignTextureLODForSlot(u, e, n, l, r);
|
|
559
|
+
o.push(f), a.push(l);
|
|
517
560
|
}
|
|
518
561
|
}
|
|
519
|
-
return Promise.all(o).then((
|
|
520
|
-
const
|
|
521
|
-
for (let
|
|
522
|
-
const
|
|
523
|
-
|
|
562
|
+
return Promise.all(o).then((l) => {
|
|
563
|
+
const u = new Array();
|
|
564
|
+
for (let f = 0; f < l.length; f++) {
|
|
565
|
+
const c = l[f], d = a[f];
|
|
566
|
+
c && c.isTexture === !0 ? u.push({ material: n, slot: d, texture: c, level: e }) : u.push({ material: n, slot: d, texture: null, level: e });
|
|
524
567
|
}
|
|
525
|
-
return
|
|
568
|
+
return u;
|
|
526
569
|
});
|
|
527
570
|
}
|
|
528
|
-
if (t instanceof
|
|
571
|
+
if (t instanceof q || t.isTexture === !0) {
|
|
529
572
|
const n = t;
|
|
530
573
|
return this.assignTextureLODForSlot(n, e, null, null, r);
|
|
531
574
|
}
|
|
@@ -536,10 +579,10 @@ class h {
|
|
|
536
579
|
* @default 50 on desktop, 20 on mobile devices
|
|
537
580
|
*/
|
|
538
581
|
static set maxConcurrentLoadingTasks(t) {
|
|
539
|
-
|
|
582
|
+
p.queue.maxConcurrent = t;
|
|
540
583
|
}
|
|
541
584
|
static get maxConcurrentLoadingTasks() {
|
|
542
|
-
return
|
|
585
|
+
return p.queue.maxConcurrent;
|
|
543
586
|
}
|
|
544
587
|
// #region INTERNAL
|
|
545
588
|
static assignTextureLODForSlot(t, e, s, r, n) {
|
|
@@ -551,33 +594,38 @@ class h {
|
|
|
551
594
|
if (o && (o.level === e || !n && o.level < e))
|
|
552
595
|
return Promise.resolve(t);
|
|
553
596
|
if (s && r) {
|
|
554
|
-
const
|
|
555
|
-
if (
|
|
556
|
-
return
|
|
597
|
+
const c = this.getPendingTextureSlotRequest(s, r);
|
|
598
|
+
if (c && c.level === e && c.force === n)
|
|
599
|
+
return c.promise;
|
|
557
600
|
}
|
|
558
|
-
const
|
|
559
|
-
|
|
601
|
+
const a = s && r ? this.nextTextureSlotRequestId(s, r, e, n) : 0, l = () => !s || !r || this.getLatestTextureSlotRequest(s, r)?.id === a, u = () => l() || this.shouldApplyStaleTextureSlotLOD(s, r, e, n), f = p.getOrLoadLOD(t, e, {
|
|
602
|
+
isCurrent: u
|
|
603
|
+
}).then((c) => {
|
|
604
|
+
if (!l() && !this.shouldApplyStaleTextureSlotLOD(s, r, e, n)) return null;
|
|
605
|
+
if (Array.isArray(c))
|
|
560
606
|
return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), null;
|
|
561
|
-
if (
|
|
562
|
-
if (
|
|
563
|
-
const
|
|
564
|
-
if (
|
|
565
|
-
const
|
|
566
|
-
if (
|
|
567
|
-
return
|
|
607
|
+
if (c?.isTexture === !0) {
|
|
608
|
+
if (c != t && s && r) {
|
|
609
|
+
const d = this.getMaterialTextureSlot(s, r) ?? t;
|
|
610
|
+
if (d && !n) {
|
|
611
|
+
const g = this.getAssignedLODInformation(d);
|
|
612
|
+
if (g && g?.level < e)
|
|
613
|
+
return h === "verbose" && console.warn("Assigned texture level is already higher: ", g.level, e, s, d, c), null;
|
|
568
614
|
}
|
|
569
|
-
this.assignTrackedTextureSlot(s, r,
|
|
615
|
+
this.assignTrackedTextureSlot(s, r, c);
|
|
570
616
|
}
|
|
571
|
-
return
|
|
572
|
-
} else
|
|
617
|
+
return c;
|
|
618
|
+
} else h == "verbose" && console.warn("No LOD found for", t, e);
|
|
573
619
|
return null;
|
|
574
|
-
}).catch((
|
|
575
|
-
return s && r && this.setPendingTextureSlotRequest(s, r, e, n,
|
|
620
|
+
}).catch((c) => (console.error("Error loading LOD", t, c), null));
|
|
621
|
+
return s && r && this.setPendingTextureSlotRequest(s, r, e, n, a, f), f;
|
|
576
622
|
}
|
|
577
623
|
// Track material slots, not just texture objects. A shared fallback texture can be
|
|
578
624
|
// referenced by many slots and should only be disposed after every slot moved away.
|
|
579
625
|
static trackedTextureSlots = /* @__PURE__ */ new WeakMap();
|
|
580
626
|
static pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
|
|
627
|
+
static latestTextureSlotRequests = /* @__PURE__ */ new WeakMap();
|
|
628
|
+
static textureSlotRequestId = 0;
|
|
581
629
|
static trackCurrentMaterialTextureSlots(t) {
|
|
582
630
|
if (t.uniforms && (t.isRawShaderMaterial || t.isShaderMaterial === !0)) {
|
|
583
631
|
const e = t;
|
|
@@ -595,12 +643,32 @@ class h {
|
|
|
595
643
|
static getPendingTextureSlotRequest(t, e) {
|
|
596
644
|
return this.pendingTextureSlotRequests.get(t)?.get(e);
|
|
597
645
|
}
|
|
598
|
-
static
|
|
599
|
-
let
|
|
600
|
-
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
646
|
+
static nextTextureSlotRequestId(t, e, s, r) {
|
|
647
|
+
let n = this.latestTextureSlotRequests.get(t);
|
|
648
|
+
n || (n = /* @__PURE__ */ new Map(), this.latestTextureSlotRequests.set(t, n));
|
|
649
|
+
const o = ++this.textureSlotRequestId;
|
|
650
|
+
return n.set(e, { id: o, level: s, force: r }), o;
|
|
651
|
+
}
|
|
652
|
+
static getLatestTextureSlotRequest(t, e) {
|
|
653
|
+
return this.latestTextureSlotRequests.get(t)?.get(e);
|
|
654
|
+
}
|
|
655
|
+
static shouldApplyStaleTextureSlotLOD(t, e, s, r) {
|
|
656
|
+
if (!t || !e) return !1;
|
|
657
|
+
const n = this.getLatestTextureSlotRequest(t, e), o = this.getMaterialTextureSlot(t, e), a = this.getAssignedLODInformation(o)?.level ?? 1 / 0;
|
|
658
|
+
return s >= a ? !1 : r ? n ? s >= n.level : !1 : !0;
|
|
659
|
+
}
|
|
660
|
+
static shouldApplyStaleMeshLOD(t, e) {
|
|
661
|
+
const s = t["LOD:requested level"];
|
|
662
|
+
if (typeof s != "number") return !1;
|
|
663
|
+
const r = this.getAssignedLODInformation(t.geometry)?.level ?? 1 / 0;
|
|
664
|
+
return e < r && e >= s;
|
|
665
|
+
}
|
|
666
|
+
static setPendingTextureSlotRequest(t, e, s, r, n, o) {
|
|
667
|
+
let a = this.pendingTextureSlotRequests.get(t);
|
|
668
|
+
a || (a = /* @__PURE__ */ new Map(), this.pendingTextureSlotRequests.set(t, a));
|
|
669
|
+
const l = { level: s, force: r, id: n, promise: o };
|
|
670
|
+
a.set(e, l), o.finally(() => {
|
|
671
|
+
a.get(e)?.id === n && a.delete(e);
|
|
604
672
|
});
|
|
605
673
|
}
|
|
606
674
|
static getMaterialTextureSlot(t, e) {
|
|
@@ -633,7 +701,7 @@ class h {
|
|
|
633
701
|
}
|
|
634
702
|
static releaseTrackedTextureSlot(t, e, s) {
|
|
635
703
|
const r = this.trackedTextureSlots.get(t);
|
|
636
|
-
if (r?.get(e) === s && r.delete(e), this.untrackTextureUsage(s) && (
|
|
704
|
+
if (r?.get(e) === s && r.delete(e), this.untrackTextureUsage(s) && (h || se)) {
|
|
637
705
|
const o = this.getAssignedLODInformation(s);
|
|
638
706
|
console.log(`[gltf-progressive] Disposed old texture LOD ${o?.level ?? "?"} for ${t.name || t.type}.${e}`, s.uuid);
|
|
639
707
|
}
|
|
@@ -642,13 +710,13 @@ class h {
|
|
|
642
710
|
url;
|
|
643
711
|
constructor(t) {
|
|
644
712
|
const e = t.options.path;
|
|
645
|
-
|
|
713
|
+
h && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
|
|
646
714
|
}
|
|
647
715
|
_isLoadingMesh;
|
|
648
716
|
loadMesh = (t) => {
|
|
649
717
|
if (this._isLoadingMesh) return null;
|
|
650
718
|
const e = this.parser.json.meshes[t]?.extensions?.[F];
|
|
651
|
-
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s &&
|
|
719
|
+
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && p.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
|
|
652
720
|
};
|
|
653
721
|
// private _isLoadingTexture;
|
|
654
722
|
// loadTexture = (textureIndex: number) => {
|
|
@@ -665,19 +733,19 @@ class h {
|
|
|
665
733
|
// });
|
|
666
734
|
// }
|
|
667
735
|
afterRoot(t) {
|
|
668
|
-
return
|
|
736
|
+
return h && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
|
|
669
737
|
if (e?.extensions) {
|
|
670
738
|
const r = e?.extensions[F];
|
|
671
739
|
if (r) {
|
|
672
740
|
if (!r.lods) {
|
|
673
|
-
|
|
741
|
+
h && console.warn("Texture has no LODs", r);
|
|
674
742
|
return;
|
|
675
743
|
}
|
|
676
744
|
let n = !1;
|
|
677
745
|
for (const o of this.parser.associations.keys())
|
|
678
|
-
o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (n = !0,
|
|
746
|
+
o.isTexture === !0 && this.parser.associations.get(o)?.textures === s && (n = !0, p.registerTexture(this.url, o, r.lods?.length, s, r));
|
|
679
747
|
n || this.parser.getDependency("texture", s).then((o) => {
|
|
680
|
-
o &&
|
|
748
|
+
o && p.registerTexture(this.url, o, r.lods?.length, s, r);
|
|
681
749
|
});
|
|
682
750
|
}
|
|
683
751
|
}
|
|
@@ -688,7 +756,7 @@ class h {
|
|
|
688
756
|
for (const n of this.parser.associations.keys())
|
|
689
757
|
if (n.isMesh) {
|
|
690
758
|
const o = this.parser.associations.get(n);
|
|
691
|
-
o?.meshes === s &&
|
|
759
|
+
o?.meshes === s && p.registerMesh(this.url, r.guid, n, r.lods.length, o.primitives, r);
|
|
692
760
|
}
|
|
693
761
|
}
|
|
694
762
|
}
|
|
@@ -707,16 +775,16 @@ class h {
|
|
|
707
775
|
*/
|
|
708
776
|
static registerTexture = (t, e, s, r, n) => {
|
|
709
777
|
if (!e) {
|
|
710
|
-
|
|
778
|
+
h && console.error("!! gltf-progressive: Called register texture without texture");
|
|
711
779
|
return;
|
|
712
780
|
}
|
|
713
|
-
if (
|
|
714
|
-
const
|
|
715
|
-
console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${
|
|
781
|
+
if (h) {
|
|
782
|
+
const { width: a, height: l } = Le(e);
|
|
783
|
+
console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${a}x${l}, Max: ${n.lods[0]?.width}x${n.lods[0]?.height}, uuid: ${e.uuid}`, n, e);
|
|
716
784
|
}
|
|
717
785
|
e.source && (e.source[de] = n);
|
|
718
786
|
const o = n.guid;
|
|
719
|
-
|
|
787
|
+
p.assignLODInformation(t, e, o, s, r), p.lodInfos.set(o, n), p.lowresCache.set(o, new WeakRef(e));
|
|
720
788
|
};
|
|
721
789
|
/**
|
|
722
790
|
* Register a mesh with progressive LOD information. This associates the mesh geometry with its LOD extension data
|
|
@@ -732,16 +800,16 @@ class h {
|
|
|
732
800
|
* @param ext - The parsed progressive mesh extension data containing all available LOD levels with vertex/index counts and densities.
|
|
733
801
|
*/
|
|
734
802
|
static registerMesh = (t, e, s, r, n, o) => {
|
|
735
|
-
const
|
|
736
|
-
if (!
|
|
737
|
-
|
|
803
|
+
const a = s.geometry;
|
|
804
|
+
if (!a) {
|
|
805
|
+
h && console.warn("gltf-progressive: Register mesh without geometry");
|
|
738
806
|
return;
|
|
739
807
|
}
|
|
740
|
-
|
|
741
|
-
let
|
|
742
|
-
|
|
743
|
-
for (const
|
|
744
|
-
|
|
808
|
+
a.userData || (a.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: n, uuid: s.uuid }, o, s), p.assignLODInformation(t, a, e, r, n), p.lodInfos.set(e, o);
|
|
809
|
+
let u = p.lowresCache.get(e)?.deref();
|
|
810
|
+
u ? u.push(s.geometry) : u = [s.geometry], p.lowresCache.set(e, new WeakRef(u)), r > 0 && !ne(s) && Mt(s, a);
|
|
811
|
+
for (const f of E)
|
|
812
|
+
f.onRegisteredNewMesh?.(s, o);
|
|
745
813
|
};
|
|
746
814
|
/**
|
|
747
815
|
* Dispose cached resources to free memory.
|
|
@@ -782,7 +850,7 @@ class h {
|
|
|
782
850
|
this.lowresCache.clear();
|
|
783
851
|
for (const [, e] of this.cache)
|
|
784
852
|
this._disposeCacheEntry(e);
|
|
785
|
-
this.cache.clear(), this.textureRefCounts.clear(), this.trackedTextureSlots = /* @__PURE__ */ new WeakMap(), this.pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap();
|
|
853
|
+
this.cache.clear(), this.textureRefCounts.clear(), this.trackedTextureSlots = /* @__PURE__ */ new WeakMap(), this.pendingTextureSlotRequests = /* @__PURE__ */ new WeakMap(), this.latestTextureSlotRequests = /* @__PURE__ */ new WeakMap(), this.textureSlotRequestId = 0;
|
|
786
854
|
}
|
|
787
855
|
}
|
|
788
856
|
/** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
|
|
@@ -814,16 +882,16 @@ class h {
|
|
|
814
882
|
* The held value is the cache key string used in `previouslyLoaded`.
|
|
815
883
|
*/
|
|
816
884
|
static _resourceRegistry = new FinalizationRegistry((t) => {
|
|
817
|
-
const e =
|
|
818
|
-
(
|
|
819
|
-
${t}`), e instanceof WeakRef && (e.deref() || (
|
|
885
|
+
const e = p.cache.get(t);
|
|
886
|
+
(h || se) && console.debug(`[gltf-progressive] Memory: Resource GC'd
|
|
887
|
+
${t}`), e instanceof WeakRef && (e.deref() || (p.cache.delete(t), (h || se) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
|
|
820
888
|
});
|
|
821
889
|
/**
|
|
822
890
|
* Track texture usage by incrementing reference count
|
|
823
891
|
*/
|
|
824
892
|
static trackTextureUsage(t) {
|
|
825
893
|
const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
|
|
826
|
-
this.textureRefCounts.set(e, s + 1),
|
|
894
|
+
this.textureRefCounts.set(e, s + 1), h === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
|
|
827
895
|
}
|
|
828
896
|
/**
|
|
829
897
|
* Untrack texture usage by decrementing reference count.
|
|
@@ -833,147 +901,155 @@ ${t}`), e instanceof WeakRef && (e.deref() || (h.cache.delete(t), (f || se) && c
|
|
|
833
901
|
static untrackTextureUsage(t) {
|
|
834
902
|
const e = t.uuid, s = this.textureRefCounts.get(e);
|
|
835
903
|
if (!s)
|
|
836
|
-
return (
|
|
904
|
+
return (h === "verbose" || se) && n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
|
|
837
905
|
const r = s - 1;
|
|
838
906
|
if (r <= 0)
|
|
839
|
-
return this.textureRefCounts.delete(e), (
|
|
840
|
-
return this.textureRefCounts.set(e, r),
|
|
841
|
-
function n(o,
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
907
|
+
return this.textureRefCounts.delete(e), (h || se) && n("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
|
|
908
|
+
return this.textureRefCounts.set(e, r), h === "verbose" && n("[gltf-progressive] Memory: Untrack texture", r), !1;
|
|
909
|
+
function n(o, a) {
|
|
910
|
+
let { width: l, height: u } = Le(t);
|
|
911
|
+
const f = l && u ? `${l}x${u}` : "N/A";
|
|
912
|
+
let c = "N/A";
|
|
913
|
+
l && u && (c = `~${(vt(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${f} (${c}), refCount: ${s} → ${a}
|
|
845
914
|
${e}`);
|
|
846
915
|
}
|
|
847
916
|
}
|
|
848
917
|
static workers = [];
|
|
849
918
|
static _workersIndex = 0;
|
|
850
|
-
static async getOrLoadLOD(t, e) {
|
|
851
|
-
const
|
|
852
|
-
if (!
|
|
853
|
-
return
|
|
854
|
-
const
|
|
855
|
-
let
|
|
919
|
+
static async getOrLoadLOD(t, e, s) {
|
|
920
|
+
const r = h == "verbose", n = this.getAssignedLODInformation(t);
|
|
921
|
+
if (!n)
|
|
922
|
+
return h && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
|
|
923
|
+
const o = n?.key;
|
|
924
|
+
let a;
|
|
856
925
|
if (t.isTexture === !0) {
|
|
857
|
-
const
|
|
858
|
-
|
|
926
|
+
const u = t;
|
|
927
|
+
u.source && u.source[de] && (a = u.source[de]);
|
|
859
928
|
}
|
|
860
|
-
if (
|
|
861
|
-
|
|
929
|
+
if (a || (a = p.lodInfos.get(o)), !a)
|
|
930
|
+
h && console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`, t.type, p.lodInfos);
|
|
862
931
|
else {
|
|
863
932
|
if (e > 0) {
|
|
864
933
|
let c = !1;
|
|
865
|
-
const d = Array.isArray(
|
|
866
|
-
if (d && e >=
|
|
867
|
-
const g = this.lowresCache.get(
|
|
934
|
+
const d = Array.isArray(a.lods);
|
|
935
|
+
if (d && e >= a.lods.length ? c = !0 : d || (c = !0), c) {
|
|
936
|
+
const g = this.lowresCache.get(o);
|
|
868
937
|
if (g) {
|
|
869
|
-
const
|
|
870
|
-
if (
|
|
871
|
-
this.lowresCache.delete(
|
|
938
|
+
const b = g.deref();
|
|
939
|
+
if (b) return b;
|
|
940
|
+
this.lowresCache.delete(o), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${o}`);
|
|
872
941
|
}
|
|
873
942
|
return null;
|
|
874
943
|
}
|
|
875
944
|
}
|
|
876
|
-
const
|
|
877
|
-
if (!
|
|
878
|
-
return
|
|
879
|
-
const
|
|
880
|
-
if (
|
|
881
|
-
if (!
|
|
882
|
-
return console.warn("missing pointer for glb/gltf texture",
|
|
883
|
-
const c =
|
|
945
|
+
const u = Array.isArray(a.lods) ? a.lods[e]?.path : a.lods;
|
|
946
|
+
if (!u)
|
|
947
|
+
return h && !a["missing:uri"] && (a["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, a)), null;
|
|
948
|
+
const f = wt(n.url, u);
|
|
949
|
+
if (f.endsWith(".glb") || f.endsWith(".gltf")) {
|
|
950
|
+
if (!a.guid)
|
|
951
|
+
return console.warn("missing pointer for glb/gltf texture", a), null;
|
|
952
|
+
const c = f + "_" + a.guid, d = await this.tryResolveLODCacheEntry(this.cache.get(c), c, f, t, e, r);
|
|
884
953
|
if (d.found) return d.value;
|
|
885
|
-
|
|
886
|
-
|
|
954
|
+
if (s?.isCurrent?.() === !1)
|
|
955
|
+
return r && console.log(`Skipping stale LOD ${e} request before queue: ${f}`), null;
|
|
956
|
+
const g = await this.queue.slot(f);
|
|
957
|
+
if (s?.isCurrent?.() === !1)
|
|
958
|
+
return r && console.log(`Skipping stale LOD ${e} request after queue: ${f}`), null;
|
|
959
|
+
const b = await this.tryResolveLODCacheEntry(this.cache.get(c), c, f, t, e, r);
|
|
960
|
+
if (b.found) return b.value;
|
|
887
961
|
if (!g.use)
|
|
888
|
-
return
|
|
889
|
-
const
|
|
890
|
-
if (
|
|
891
|
-
const
|
|
892
|
-
if (
|
|
893
|
-
for (const
|
|
894
|
-
let
|
|
895
|
-
return
|
|
962
|
+
return h && console.log(`LOD ${e} was aborted: ${f}`), null;
|
|
963
|
+
const y = a, x = new Promise(async (L, V) => {
|
|
964
|
+
if (Pt) {
|
|
965
|
+
const m = await (await Rt({})).load(f);
|
|
966
|
+
if (m.textures.length > 0)
|
|
967
|
+
for (const _ of m.textures) {
|
|
968
|
+
let M = _.texture;
|
|
969
|
+
return p.assignLODInformation(n.url, M, o, e, void 0), t instanceof q && (M = this.copySettings(t, M)), M && (M.guid = y.guid), L(M);
|
|
896
970
|
}
|
|
897
|
-
if (
|
|
898
|
-
const
|
|
899
|
-
for (const
|
|
900
|
-
const
|
|
901
|
-
|
|
971
|
+
if (m.geometries.length > 0) {
|
|
972
|
+
const _ = new Array();
|
|
973
|
+
for (const M of m.geometries) {
|
|
974
|
+
const G = M.geometry;
|
|
975
|
+
p.assignLODInformation(n.url, G, o, e, M.primitiveIndex), _.push(G);
|
|
902
976
|
}
|
|
903
|
-
return _
|
|
977
|
+
return L(_);
|
|
904
978
|
}
|
|
905
|
-
return
|
|
979
|
+
return L(null);
|
|
906
980
|
}
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
let
|
|
910
|
-
if (
|
|
911
|
-
const
|
|
912
|
-
|
|
981
|
+
const w = new De();
|
|
982
|
+
Ge(w), h && (await new Promise((T) => setTimeout(T, 1e3)), r && console.warn("Start loading (delayed) " + f, y.guid));
|
|
983
|
+
let O = f;
|
|
984
|
+
if (y && Array.isArray(y.lods)) {
|
|
985
|
+
const T = y.lods[e];
|
|
986
|
+
T.hash && (O += "?v=" + T.hash);
|
|
913
987
|
}
|
|
914
|
-
const
|
|
915
|
-
`,
|
|
916
|
-
if (!
|
|
917
|
-
return
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
let
|
|
921
|
-
if (
|
|
922
|
-
let
|
|
923
|
-
for (const
|
|
924
|
-
if (
|
|
925
|
-
const
|
|
926
|
-
if (
|
|
927
|
-
|
|
988
|
+
const D = await w.loadAsync(O).catch((T) => (console.error(`Error loading LOD ${e} from ${f}
|
|
989
|
+
`, T), L(null)));
|
|
990
|
+
if (!D)
|
|
991
|
+
return L(null);
|
|
992
|
+
const k = D.parser;
|
|
993
|
+
r && console.log("Loading finished " + f, y.guid);
|
|
994
|
+
let R = 0;
|
|
995
|
+
if (D.parser.json.textures) {
|
|
996
|
+
let T = !1;
|
|
997
|
+
for (const m of D.parser.json.textures) {
|
|
998
|
+
if (m?.extensions) {
|
|
999
|
+
const _ = m?.extensions[F];
|
|
1000
|
+
if (_?.guid && _.guid === y.guid) {
|
|
1001
|
+
T = !0;
|
|
928
1002
|
break;
|
|
929
1003
|
}
|
|
930
1004
|
}
|
|
931
|
-
|
|
1005
|
+
R++;
|
|
932
1006
|
}
|
|
933
|
-
if (
|
|
934
|
-
let
|
|
935
|
-
return
|
|
936
|
-
} else
|
|
1007
|
+
if (T) {
|
|
1008
|
+
let m = await k.getDependency("texture", R);
|
|
1009
|
+
return m && p.assignLODInformation(n.url, m, o, e, void 0), r && console.log('change "' + t.name + '" → "' + m.name + '"', f, R, m, c), t instanceof q && (m = this.copySettings(t, m)), m && (m.guid = y.guid), L(m);
|
|
1010
|
+
} else h && console.warn("Could not find texture with guid", y.guid, D.parser.json);
|
|
937
1011
|
}
|
|
938
|
-
if (
|
|
939
|
-
let
|
|
940
|
-
for (const
|
|
941
|
-
if (
|
|
942
|
-
const
|
|
943
|
-
if (
|
|
944
|
-
|
|
1012
|
+
if (R = 0, D.parser.json.meshes) {
|
|
1013
|
+
let T = !1;
|
|
1014
|
+
for (const m of D.parser.json.meshes) {
|
|
1015
|
+
if (m?.extensions) {
|
|
1016
|
+
const _ = m?.extensions[F];
|
|
1017
|
+
if (_?.guid && _.guid === y.guid) {
|
|
1018
|
+
T = !0;
|
|
945
1019
|
break;
|
|
946
1020
|
}
|
|
947
1021
|
}
|
|
948
|
-
|
|
1022
|
+
R++;
|
|
949
1023
|
}
|
|
950
|
-
if (
|
|
951
|
-
const
|
|
952
|
-
if (
|
|
953
|
-
const
|
|
954
|
-
return
|
|
1024
|
+
if (T) {
|
|
1025
|
+
const m = await k.getDependency("mesh", R);
|
|
1026
|
+
if (r && console.log(`Loaded Mesh "${m.name}"`, f, R, m, c), m.isMesh === !0) {
|
|
1027
|
+
const _ = m.geometry;
|
|
1028
|
+
return p.assignLODInformation(n.url, _, o, e, 0), L(_);
|
|
955
1029
|
} else {
|
|
956
|
-
const
|
|
957
|
-
for (let
|
|
958
|
-
const
|
|
959
|
-
if (
|
|
960
|
-
const
|
|
961
|
-
|
|
1030
|
+
const _ = new Array();
|
|
1031
|
+
for (let M = 0; M < m.children.length; M++) {
|
|
1032
|
+
const G = m.children[M];
|
|
1033
|
+
if (G.isMesh === !0) {
|
|
1034
|
+
const ie = G.geometry;
|
|
1035
|
+
p.assignLODInformation(n.url, ie, o, e, M), _.push(ie);
|
|
962
1036
|
}
|
|
963
1037
|
}
|
|
964
|
-
return _
|
|
1038
|
+
return L(_);
|
|
965
1039
|
}
|
|
966
|
-
} else
|
|
1040
|
+
} else h && console.warn("Could not find mesh with guid", y.guid, D.parser.json);
|
|
967
1041
|
}
|
|
968
|
-
return
|
|
1042
|
+
return L(null);
|
|
969
1043
|
});
|
|
970
|
-
this.cache.set(c,
|
|
971
|
-
const
|
|
972
|
-
return
|
|
973
|
-
} else if (t instanceof
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1044
|
+
this.cache.set(c, x), g.use(x);
|
|
1045
|
+
const v = await x;
|
|
1046
|
+
return v != null ? v instanceof q ? (this.cache.set(c, new WeakRef(v)), p._resourceRegistry.register(v, c)) : Array.isArray(v) ? this.cache.set(c, Promise.resolve(v)) : this.cache.set(c, Promise.resolve(v)) : this.cache.set(c, Promise.resolve(null)), v;
|
|
1047
|
+
} else if (t instanceof q) {
|
|
1048
|
+
if (s?.isCurrent?.() === !1)
|
|
1049
|
+
return r && console.log(`Skipping stale texture LOD ${e} request: ${f}`), null;
|
|
1050
|
+
r && console.log("Load texture from uri: " + f);
|
|
1051
|
+
const d = await new it().loadAsync(f);
|
|
1052
|
+
return s?.isCurrent?.() === !1 ? (d?.dispose(), null) : (d ? (d.guid = a.guid, d.flipY = !1, d.needsUpdate = !0, d.colorSpace = t.colorSpace, r && console.log(a, d)) : h && console.warn("failed loading", f), d);
|
|
977
1053
|
}
|
|
978
1054
|
}
|
|
979
1055
|
return null;
|
|
@@ -982,26 +1058,26 @@ ${e}`);
|
|
|
982
1058
|
if (t === void 0)
|
|
983
1059
|
return { found: !1 };
|
|
984
1060
|
if (o && console.log(`LOD ${n} was already loading/loaded: ${e}`), t instanceof WeakRef) {
|
|
985
|
-
const
|
|
986
|
-
if (
|
|
987
|
-
let
|
|
988
|
-
if (
|
|
989
|
-
return { found: !0, value:
|
|
1061
|
+
const u = t.deref();
|
|
1062
|
+
if (u) {
|
|
1063
|
+
let f = u, c = !1;
|
|
1064
|
+
if (f instanceof q && r instanceof q ? Oe(f.image) || we(f) ? f = this.copySettings(r, f) : c = !0 : f instanceof j && r instanceof j && (f.attributes.position?.array || (c = !0)), !c)
|
|
1065
|
+
return { found: !0, value: f };
|
|
990
1066
|
}
|
|
991
|
-
return this.cache.delete(e),
|
|
1067
|
+
return this.cache.delete(e), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`), { found: !1 };
|
|
992
1068
|
}
|
|
993
|
-
let
|
|
994
|
-
`,
|
|
995
|
-
return
|
|
1069
|
+
let a = await t.catch((u) => (console.error(`Error loading LOD ${n} from ${s}
|
|
1070
|
+
`, u), null)), l = !1;
|
|
1071
|
+
return a == null || (a instanceof q && r instanceof q ? Oe(a.image) || we(a) ? a = this.copySettings(r, a) : (l = !0, this.cache.delete(e)) : a instanceof j && r instanceof j && (a.attributes.position?.array || (l = !0, this.cache.delete(e)))), l ? { found: !1 } : { found: !0, value: a };
|
|
996
1072
|
}
|
|
997
1073
|
static _queue;
|
|
998
1074
|
static get queue() {
|
|
999
|
-
return this._queue ??= new
|
|
1075
|
+
return this._queue ??= new Lt(Me() ? 20 : 50, { debug: h != !1 });
|
|
1000
1076
|
}
|
|
1001
1077
|
static assignLODInformation(t, e, s, r, n) {
|
|
1002
1078
|
if (!e) return;
|
|
1003
1079
|
e.userData || (e.userData = {});
|
|
1004
|
-
const o = new
|
|
1080
|
+
const o = new kt(t, s, r, n);
|
|
1005
1081
|
e.userData.LODS = o, "source" in e && typeof e.source == "object" && (e.source.LODS = o);
|
|
1006
1082
|
}
|
|
1007
1083
|
static getAssignedLODInformation(t) {
|
|
@@ -1009,12 +1085,12 @@ ${e}`);
|
|
|
1009
1085
|
}
|
|
1010
1086
|
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
1011
1087
|
static copySettings(t, e) {
|
|
1012
|
-
return e ? (
|
|
1088
|
+
return e ? (h === "verbose" && console.debug(`Copy texture settings
|
|
1013
1089
|
`, t.uuid, `
|
|
1014
1090
|
`, e.uuid), e = e.clone(), 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) : t;
|
|
1015
1091
|
}
|
|
1016
1092
|
}
|
|
1017
|
-
class
|
|
1093
|
+
class kt {
|
|
1018
1094
|
url;
|
|
1019
1095
|
/** the key to lookup the LOD information */
|
|
1020
1096
|
key;
|
|
@@ -1074,7 +1150,7 @@ class oe {
|
|
|
1074
1150
|
_seen = /* @__PURE__ */ new WeakMap();
|
|
1075
1151
|
add(t, e, s) {
|
|
1076
1152
|
if (this._resolved) {
|
|
1077
|
-
|
|
1153
|
+
h && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
|
|
1078
1154
|
return;
|
|
1079
1155
|
}
|
|
1080
1156
|
if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
|
|
@@ -1082,7 +1158,7 @@ class oe {
|
|
|
1082
1158
|
if (this._seen.has(e)) {
|
|
1083
1159
|
const r = this._seen.get(e);
|
|
1084
1160
|
if (r >= this._maxPromisesPerObject) {
|
|
1085
|
-
|
|
1161
|
+
h && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
|
|
1086
1162
|
return;
|
|
1087
1163
|
}
|
|
1088
1164
|
this._seen.set(e, r + 1);
|
|
@@ -1101,7 +1177,7 @@ class oe {
|
|
|
1101
1177
|
});
|
|
1102
1178
|
}
|
|
1103
1179
|
}
|
|
1104
|
-
const A = N("debugprogressive"),
|
|
1180
|
+
const A = N("debugprogressive"), At = A === "colors", It = N("noprogressive"), he = /* @__PURE__ */ Symbol("Needle:LODSManager"), ge = /* @__PURE__ */ Symbol("Needle:LODState"), U = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), Te = Xe, S = { mesh_lod: -1, texture_lod: -1 }, $t = new Ie(), Se = [
|
|
1105
1181
|
3526751,
|
|
1106
1182
|
11065402,
|
|
1107
1183
|
15978811,
|
|
@@ -1134,12 +1210,17 @@ const A = N("debugprogressive"), Lt = A === "colors", vt = N("noprogressive"), f
|
|
|
1134
1210
|
15817653,
|
|
1135
1211
|
5083278,
|
|
1136
1212
|
5592405
|
|
1137
|
-
]
|
|
1138
|
-
function
|
|
1213
|
+
];
|
|
1214
|
+
function Bt() {
|
|
1215
|
+
const i = Te.Timer || Te.Clock;
|
|
1216
|
+
return new i();
|
|
1217
|
+
}
|
|
1218
|
+
const pe = new ue(), z = new ue(), Re = new ue(), Gt = new P(), qt = new P(), Wt = new $e(), W = new P(), H = new P(), Q = new P(), J = new P();
|
|
1219
|
+
function Ft(i, t) {
|
|
1139
1220
|
const e = i.min, s = i.max, r = (e.x + s.x) * 0.5, n = (e.y + s.y) * 0.5;
|
|
1140
|
-
return
|
|
1221
|
+
return W.set(r, n, e.z).applyMatrix4(t).z < 0;
|
|
1141
1222
|
}
|
|
1142
|
-
function
|
|
1223
|
+
function Ut(i) {
|
|
1143
1224
|
const {
|
|
1144
1225
|
geometry: t,
|
|
1145
1226
|
matrixWorld: e,
|
|
@@ -1147,59 +1228,59 @@ function Tt(i) {
|
|
|
1147
1228
|
projectionScreenMatrix: r,
|
|
1148
1229
|
desiredDensity: n,
|
|
1149
1230
|
canvasHeight: o = 0,
|
|
1150
|
-
currentLevel:
|
|
1151
|
-
xrEnabled:
|
|
1152
|
-
debugDrawLine:
|
|
1153
|
-
warnMissingPrimitiveDensities:
|
|
1154
|
-
} = i,
|
|
1155
|
-
level:
|
|
1156
|
-
primitiveIndex:
|
|
1231
|
+
currentLevel: a = -1,
|
|
1232
|
+
xrEnabled: l = !1,
|
|
1233
|
+
debugDrawLine: u,
|
|
1234
|
+
warnMissingPrimitiveDensities: f = !1
|
|
1235
|
+
} = i, c = p.getMeshLODExtension(t)?.lods, d = p.getPrimitiveIndex(t), g = i.target ?? {
|
|
1236
|
+
level: a,
|
|
1237
|
+
primitiveIndex: d,
|
|
1157
1238
|
screenCoverage: 0,
|
|
1158
|
-
screenspaceVolume: new
|
|
1239
|
+
screenspaceVolume: new P(),
|
|
1159
1240
|
centrality: 1
|
|
1160
1241
|
};
|
|
1161
|
-
if (
|
|
1162
|
-
let
|
|
1163
|
-
if (
|
|
1164
|
-
if (
|
|
1165
|
-
return
|
|
1166
|
-
if (z.copy(
|
|
1167
|
-
const
|
|
1168
|
-
let
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
const
|
|
1172
|
-
|
|
1173
|
-
}
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1176
|
-
const
|
|
1177
|
-
|
|
1178
|
-
const
|
|
1179
|
-
if (
|
|
1180
|
-
if (
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
}
|
|
1186
|
-
for (let
|
|
1187
|
-
const
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1242
|
+
if (g.level = a, g.primitiveIndex = d, g.screenCoverage = 0, g.screenspaceVolume.set(0, 0, 0), g.centrality = 1, !c?.length) return g;
|
|
1243
|
+
let b = i.boundingBox ?? t.boundingBox;
|
|
1244
|
+
if (b || (t.computeBoundingBox(), b = t.boundingBox), !b) return g;
|
|
1245
|
+
if (pe.copy(b).applyMatrix4(e), s.isPerspectiveCamera && Ft(pe, r))
|
|
1246
|
+
return g.level = 0, g.screenCoverage = 1 / 0, g.screenspaceVolume.set(1 / 0, 1 / 0, 1 / 0), g;
|
|
1247
|
+
if (z.copy(pe).applyMatrix4(r), l && s.isPerspectiveCamera && s.fov > 70) {
|
|
1248
|
+
const w = z.min, O = z.max;
|
|
1249
|
+
let D = w.x, k = w.y, R = O.x, T = O.y;
|
|
1250
|
+
const m = 2, _ = 1.5, M = (w.x + O.x) * 0.5, G = (w.y + O.y) * 0.5;
|
|
1251
|
+
D = (D - M) * m + M, k = (k - G) * m + G, R = (R - M) * m + M, T = (T - G) * m + G;
|
|
1252
|
+
const ie = D < 0 && R > 0 ? 0 : Math.min(Math.abs(w.x), Math.abs(O.x)), Ve = k < 0 && T > 0 ? 0 : Math.min(Math.abs(w.y), Math.abs(O.y)), ce = Math.max(ie, Ve);
|
|
1253
|
+
g.centrality = (_ - ce) * (_ - ce) * (_ - ce);
|
|
1254
|
+
}
|
|
1255
|
+
const y = z.getSize(Gt);
|
|
1256
|
+
y.multiplyScalar(0.5), globalThis.screen?.availHeight > 0 && o > 0 && y.multiplyScalar(o / globalThis.screen.availHeight), s.isPerspectiveCamera && (y.x *= s.aspect), Re.copy(b).applyMatrix4(e).applyMatrix4(s.matrixWorldInverse);
|
|
1257
|
+
const x = Re.getSize(qt), v = Math.max(y.x, y.y), L = Math.max(x.x, x.y);
|
|
1258
|
+
v !== 0 && L !== 0 && (y.z = x.z / L * v);
|
|
1259
|
+
const V = Math.max(y.x, y.y, y.z) * g.centrality;
|
|
1260
|
+
if (g.screenCoverage = V, g.screenspaceVolume.copy(y), V <= 0) return g;
|
|
1261
|
+
if (u) {
|
|
1262
|
+
const w = Wt.copy(r);
|
|
1263
|
+
w.invert(), W.copy(z.min), H.copy(z.max), H.x = W.x, Q.copy(z.max), Q.y = W.y, J.copy(z.max);
|
|
1264
|
+
const O = (W.z + J.z) * 0.5;
|
|
1265
|
+
W.z = H.z = Q.z = J.z = O, W.applyMatrix4(w), H.applyMatrix4(w), Q.applyMatrix4(w), J.applyMatrix4(w), u(W, H, 255), u(W, Q, 255), u(H, J, 255), u(Q, J, 255);
|
|
1266
|
+
}
|
|
1267
|
+
for (let w = 0; w < c.length; w++) {
|
|
1268
|
+
const O = c[w], D = O.densities?.[d] || O.density || 1e-5;
|
|
1269
|
+
if (d > 0 && f && Fe() && !O.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), D / V < n) {
|
|
1270
|
+
g.level = w;
|
|
1190
1271
|
break;
|
|
1191
1272
|
}
|
|
1192
1273
|
}
|
|
1193
|
-
return
|
|
1274
|
+
return g;
|
|
1194
1275
|
}
|
|
1195
|
-
class
|
|
1276
|
+
class I {
|
|
1196
1277
|
/**
|
|
1197
1278
|
* 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.
|
|
1198
1279
|
*/
|
|
1199
1280
|
static debugDrawLine;
|
|
1200
1281
|
/** @internal */
|
|
1201
1282
|
static getObjectLODState(t) {
|
|
1202
|
-
return t[
|
|
1283
|
+
return t[ge];
|
|
1203
1284
|
}
|
|
1204
1285
|
static addPlugin(t) {
|
|
1205
1286
|
E.push(t);
|
|
@@ -1214,17 +1295,17 @@ class R {
|
|
|
1214
1295
|
* @returns The LODsManager instance.
|
|
1215
1296
|
*/
|
|
1216
1297
|
static get(t, e) {
|
|
1217
|
-
if (t[
|
|
1218
|
-
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[
|
|
1219
|
-
const s = new
|
|
1298
|
+
if (t[he])
|
|
1299
|
+
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[he];
|
|
1300
|
+
const s = new I(t, {
|
|
1220
1301
|
engine: "unknown",
|
|
1221
1302
|
...e
|
|
1222
1303
|
});
|
|
1223
|
-
return t[
|
|
1304
|
+
return t[he] = s, s;
|
|
1224
1305
|
}
|
|
1225
1306
|
renderer;
|
|
1226
1307
|
context;
|
|
1227
|
-
projectionScreenMatrix = new
|
|
1308
|
+
projectionScreenMatrix = new $e();
|
|
1228
1309
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
1229
1310
|
get plugins() {
|
|
1230
1311
|
return E;
|
|
@@ -1297,7 +1378,7 @@ class R {
|
|
|
1297
1378
|
const r = performance.now();
|
|
1298
1379
|
return s.ready.finally(() => {
|
|
1299
1380
|
const n = this._newPromiseGroups.indexOf(s);
|
|
1300
|
-
n >= 0 && (this._newPromiseGroups.splice(n, 1),
|
|
1381
|
+
n >= 0 && (this._newPromiseGroups.splice(n, 1), Fe() && performance.measure("LODsManager:awaitLoading", {
|
|
1301
1382
|
start: r,
|
|
1302
1383
|
detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
|
|
1303
1384
|
}));
|
|
@@ -1353,11 +1434,11 @@ class R {
|
|
|
1353
1434
|
this.renderer = t, this.context = { ...e };
|
|
1354
1435
|
}
|
|
1355
1436
|
#t;
|
|
1356
|
-
#o = new Ke();
|
|
1357
1437
|
#r = 0;
|
|
1358
1438
|
#n = 0;
|
|
1359
|
-
#
|
|
1439
|
+
#o = 0;
|
|
1360
1440
|
#s = 0;
|
|
1441
|
+
#i = Bt();
|
|
1361
1442
|
_fpsBuffer = [60, 60, 60, 60, 60];
|
|
1362
1443
|
/**
|
|
1363
1444
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
@@ -1368,9 +1449,9 @@ class R {
|
|
|
1368
1449
|
let t = 0;
|
|
1369
1450
|
this.#t = this.renderer.render;
|
|
1370
1451
|
const e = this;
|
|
1371
|
-
|
|
1452
|
+
_e(this.renderer), this.renderer.render = function(s, r) {
|
|
1372
1453
|
const n = e.renderer.getRenderTarget();
|
|
1373
|
-
(n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#r += 1, e.#n = e.#
|
|
1454
|
+
(n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i.update?.(), e.#n = Math.max(e.#i.getDelta(), 1 / 1e3), e.#o += e.#n, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#n), e.#s = e._fpsBuffer.reduce((a, l) => a + l) / e._fpsBuffer.length, A && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
|
|
1374
1455
|
const o = t++;
|
|
1375
1456
|
e.#t.call(this, s, r), e.onAfterRender(s, r, o);
|
|
1376
1457
|
};
|
|
@@ -1398,14 +1479,16 @@ class R {
|
|
|
1398
1479
|
}
|
|
1399
1480
|
onAfterRender(t, e, s) {
|
|
1400
1481
|
if (this.pause) return;
|
|
1401
|
-
const
|
|
1482
|
+
const r = this.getRenderList(t, e, s);
|
|
1483
|
+
if (!r) return;
|
|
1484
|
+
const n = r.opaque;
|
|
1402
1485
|
let o = !0;
|
|
1403
1486
|
if (n.length === 1) {
|
|
1404
|
-
const
|
|
1405
|
-
(
|
|
1487
|
+
const a = n[0].material;
|
|
1488
|
+
(a.name === "EffectMaterial" || a.name === "CopyShader") && (o = !1);
|
|
1406
1489
|
}
|
|
1407
1490
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
|
|
1408
|
-
if (
|
|
1491
|
+
if (It || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, A && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, A && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
|
|
1409
1492
|
return;
|
|
1410
1493
|
this.internalUpdate(t, e), this._postprocessPromiseGroups();
|
|
1411
1494
|
}
|
|
@@ -1414,15 +1497,17 @@ class R {
|
|
|
1414
1497
|
* Update LODs in a scene
|
|
1415
1498
|
*/
|
|
1416
1499
|
internalUpdate(t, e) {
|
|
1417
|
-
const s = this.
|
|
1500
|
+
const s = this.getRenderList(t, e, 0);
|
|
1501
|
+
if (!s) return;
|
|
1502
|
+
const r = s.opaque;
|
|
1418
1503
|
this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
|
|
1419
1504
|
const n = this.targetTriangleDensity;
|
|
1420
|
-
for (const
|
|
1421
|
-
if (
|
|
1422
|
-
A && (
|
|
1505
|
+
for (const l of r) {
|
|
1506
|
+
if (l.material && (l.geometry?.type === "BoxGeometry" || l.geometry?.type === "BufferGeometry") && (l.material.name === "SphericalGaussianBlur" || l.material.name == "BackgroundCubeMaterial" || l.material.name === "CubemapFromEquirect" || l.material.name === "EquirectangularToCubeUV")) {
|
|
1507
|
+
A && (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", l, l.material.name, l.material.type)));
|
|
1423
1508
|
continue;
|
|
1424
1509
|
}
|
|
1425
|
-
switch (
|
|
1510
|
+
switch (l.material.type) {
|
|
1426
1511
|
case "LineBasicMaterial":
|
|
1427
1512
|
case "LineDashedMaterial":
|
|
1428
1513
|
case "PointsMaterial":
|
|
@@ -1431,33 +1516,52 @@ class R {
|
|
|
1431
1516
|
case "MeshDepthMaterial":
|
|
1432
1517
|
continue;
|
|
1433
1518
|
}
|
|
1434
|
-
const
|
|
1435
|
-
(
|
|
1519
|
+
const u = l.object;
|
|
1520
|
+
(u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
|
|
1436
1521
|
}
|
|
1437
1522
|
const o = s.transparent;
|
|
1438
|
-
for (const
|
|
1439
|
-
const
|
|
1440
|
-
(
|
|
1523
|
+
for (const l of o) {
|
|
1524
|
+
const u = l.object;
|
|
1525
|
+
(u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
|
|
1441
1526
|
}
|
|
1442
|
-
const
|
|
1443
|
-
for (const
|
|
1444
|
-
const
|
|
1445
|
-
(
|
|
1527
|
+
const a = s.transmissive;
|
|
1528
|
+
for (const l of a) {
|
|
1529
|
+
const u = l.object;
|
|
1530
|
+
(u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
|
|
1446
1531
|
}
|
|
1447
1532
|
}
|
|
1533
|
+
getRenderList(t, e, s) {
|
|
1534
|
+
const r = this.renderer;
|
|
1535
|
+
let n = null;
|
|
1536
|
+
if (r.isWebGPURenderer === !0) {
|
|
1537
|
+
const o = r._renderLists;
|
|
1538
|
+
if (!o) return null;
|
|
1539
|
+
n = o.get(t, e);
|
|
1540
|
+
} else if (r.isWebGLRenderer === !0) {
|
|
1541
|
+
const o = r.renderLists;
|
|
1542
|
+
if (!o) return null;
|
|
1543
|
+
n = o.get(t, s);
|
|
1544
|
+
}
|
|
1545
|
+
return n ? {
|
|
1546
|
+
opaque: n.opaque || [],
|
|
1547
|
+
transparent: n.transparent || [],
|
|
1548
|
+
transmissive: n.transmissive || n.transparentDoublePass || [],
|
|
1549
|
+
transparentDoublePass: n.transparentDoublePass || []
|
|
1550
|
+
} : null;
|
|
1551
|
+
}
|
|
1448
1552
|
/** Update the LOD levels for the renderer. */
|
|
1449
1553
|
updateLODs(t, e, s, r) {
|
|
1450
1554
|
s.userData || (s.userData = {});
|
|
1451
|
-
let n = s[
|
|
1452
|
-
if (n || (n = new
|
|
1555
|
+
let n = s[ge];
|
|
1556
|
+
if (n || (n = new zt(), s[ge] = n), n.frames++ < 2)
|
|
1453
1557
|
return;
|
|
1454
|
-
for (const
|
|
1455
|
-
|
|
1558
|
+
for (const a of E)
|
|
1559
|
+
a.onBeforeUpdateLOD?.(this.renderer, t, e, s);
|
|
1456
1560
|
const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : X;
|
|
1457
|
-
o >= 0 ? (
|
|
1458
|
-
for (const
|
|
1459
|
-
|
|
1460
|
-
n.lastLodLevel_Mesh =
|
|
1561
|
+
o >= 0 ? (S.mesh_lod = o, S.texture_lod = o) : (this.calculateLodLevel(e, s, n, r, S), S.mesh_lod = Math.round(S.mesh_lod), S.texture_lod = Math.round(S.texture_lod)), S.mesh_lod >= 0 && this.loadProgressiveMeshes(s, S.mesh_lod), s.material && S.texture_lod >= 0 && this.loadProgressiveTextures(s.material, S.texture_lod, o), h && s.material && !s.isGizmo && Ue(s.material), At && s.material && !s.isGizmo && !s.isBatchedMesh && ze(s.material, S.mesh_lod);
|
|
1562
|
+
for (const a of E)
|
|
1563
|
+
a.onAfterUpdatedLOD?.(this.renderer, t, e, s, S);
|
|
1564
|
+
n.lastLodLevel_Mesh = S.mesh_lod, n.lastLodLevel_Texture = S.texture_lod;
|
|
1461
1565
|
}
|
|
1462
1566
|
/** Load progressive textures for the given material
|
|
1463
1567
|
* @param material the material to load the textures for
|
|
@@ -1472,14 +1576,14 @@ class R {
|
|
|
1472
1576
|
return;
|
|
1473
1577
|
}
|
|
1474
1578
|
let r = !1;
|
|
1475
|
-
(t[
|
|
1579
|
+
(t[U] === void 0 || e < t[U]) && (r = !0);
|
|
1476
1580
|
const n = s !== void 0 && s >= 0;
|
|
1477
|
-
if (n && (r = t[
|
|
1478
|
-
t[
|
|
1479
|
-
const o = n ? { force: !0 } : void 0,
|
|
1480
|
-
this._lodchangedlisteners.forEach((
|
|
1581
|
+
if (n && (r = t[U] != s, e = s), r) {
|
|
1582
|
+
t[U] = e;
|
|
1583
|
+
const o = n ? { force: !0 } : void 0, a = p.assignTextureLOD(t, e, o).then((l) => {
|
|
1584
|
+
this._lodchangedlisteners.forEach((u) => u({ type: "texture", level: e, object: t }));
|
|
1481
1585
|
});
|
|
1482
|
-
oe.addPromise("texture", t,
|
|
1586
|
+
oe.addPromise("texture", t, a, this._newPromiseGroups);
|
|
1483
1587
|
}
|
|
1484
1588
|
}
|
|
1485
1589
|
/** Load progressive meshes for the given mesh
|
|
@@ -1490,18 +1594,18 @@ class R {
|
|
|
1490
1594
|
*/
|
|
1491
1595
|
loadProgressiveMeshes(t, e) {
|
|
1492
1596
|
if (!t) return Promise.resolve(null);
|
|
1493
|
-
let s = t[
|
|
1597
|
+
let s = t[U] !== e;
|
|
1494
1598
|
const r = t["DEBUG:LOD"];
|
|
1495
|
-
if (r != null && (s = t[
|
|
1496
|
-
t[
|
|
1497
|
-
const n = t.geometry, o =
|
|
1599
|
+
if (r != null && (s = t[U] != r, e = r), s) {
|
|
1600
|
+
t[U] = e;
|
|
1601
|
+
const n = t.geometry, o = p.assignMeshLOD(t, e).then((a) => (a && t[U] == e && n != t.geometry && this._lodchangedlisteners.forEach((l) => l({ type: "mesh", level: e, object: t })), a));
|
|
1498
1602
|
return oe.addPromise("mesh", t, o, this._newPromiseGroups), o;
|
|
1499
1603
|
}
|
|
1500
1604
|
return Promise.resolve(null);
|
|
1501
1605
|
}
|
|
1502
1606
|
// private testIfLODLevelsAreAvailable() {
|
|
1503
|
-
_sphere = new
|
|
1504
|
-
_tempWorldPosition = new
|
|
1607
|
+
_sphere = new Ae();
|
|
1608
|
+
_tempWorldPosition = new P();
|
|
1505
1609
|
static skinnedMeshBoundsFrameOffsetCounter = 0;
|
|
1506
1610
|
static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
|
|
1507
1611
|
// #region calculateLodLevel
|
|
@@ -1514,86 +1618,86 @@ class R {
|
|
|
1514
1618
|
n.mesh_lod = -1, n.texture_lod = -1;
|
|
1515
1619
|
return;
|
|
1516
1620
|
}
|
|
1517
|
-
let
|
|
1621
|
+
let a = 10 + 1, l = !1;
|
|
1518
1622
|
if (A && e["DEBUG:LOD"] != null)
|
|
1519
1623
|
return e["DEBUG:LOD"];
|
|
1520
|
-
const
|
|
1521
|
-
if (!
|
|
1624
|
+
const u = p.getMeshLODExtension(e.geometry)?.lods, f = p.getPrimitiveIndex(e.geometry), c = u && u.length > 0, d = p.getMaterialMinMaxLODsCount(e.material), g = d.min_count !== 1 / 0 && d.min_count >= 0 && d.max_count >= 0;
|
|
1625
|
+
if (!c && !g) {
|
|
1522
1626
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
1523
1627
|
return;
|
|
1524
1628
|
}
|
|
1525
|
-
|
|
1526
|
-
const
|
|
1527
|
-
let
|
|
1629
|
+
c || (l = !0, a = 0);
|
|
1630
|
+
const b = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
|
|
1631
|
+
let y = e.geometry.boundingBox;
|
|
1528
1632
|
if (e.type === "SkinnedMesh") {
|
|
1529
|
-
const
|
|
1530
|
-
if (!
|
|
1531
|
-
|
|
1633
|
+
const x = e;
|
|
1634
|
+
if (!x.boundingBox)
|
|
1635
|
+
x.computeBoundingBox();
|
|
1532
1636
|
else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
|
|
1533
|
-
if (!
|
|
1534
|
-
const
|
|
1535
|
-
|
|
1637
|
+
if (!x[I.$skinnedMeshBoundsOffset]) {
|
|
1638
|
+
const L = I.skinnedMeshBoundsFrameOffsetCounter++;
|
|
1639
|
+
x[I.$skinnedMeshBoundsOffset] = L;
|
|
1536
1640
|
}
|
|
1537
|
-
const
|
|
1538
|
-
if ((s.frames +
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1641
|
+
const v = x[I.$skinnedMeshBoundsOffset];
|
|
1642
|
+
if ((s.frames + v) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
|
|
1643
|
+
const L = ne(x), V = x.geometry;
|
|
1644
|
+
L && (x.geometry = L), x.computeBoundingBox(), x.geometry = V;
|
|
1541
1645
|
}
|
|
1542
1646
|
}
|
|
1543
|
-
|
|
1647
|
+
y = x.boundingBox;
|
|
1544
1648
|
}
|
|
1545
|
-
if (
|
|
1649
|
+
if (y) {
|
|
1546
1650
|
if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
|
|
1547
1651
|
this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
|
|
1548
|
-
const
|
|
1549
|
-
if (this._sphere.containsPoint(
|
|
1652
|
+
const L = t.getWorldPosition(this._tempWorldPosition);
|
|
1653
|
+
if (this._sphere.containsPoint(L)) {
|
|
1550
1654
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
1551
1655
|
return;
|
|
1552
1656
|
}
|
|
1553
1657
|
}
|
|
1554
|
-
const
|
|
1658
|
+
const x = Ut({
|
|
1555
1659
|
geometry: e.geometry,
|
|
1556
1660
|
matrixWorld: e.matrixWorld,
|
|
1557
1661
|
camera: t,
|
|
1558
1662
|
projectionScreenMatrix: this.projectionScreenMatrix,
|
|
1559
1663
|
desiredDensity: r,
|
|
1560
|
-
canvasHeight:
|
|
1664
|
+
canvasHeight: b,
|
|
1561
1665
|
currentLevel: s.lastLodLevel_Mesh,
|
|
1562
|
-
boundingBox:
|
|
1666
|
+
boundingBox: y,
|
|
1563
1667
|
xrEnabled: this.renderer.xr.enabled,
|
|
1564
|
-
debugDrawLine: A ?
|
|
1668
|
+
debugDrawLine: A ? I.debugDrawLine : void 0,
|
|
1565
1669
|
warnMissingPrimitiveDensities: !0
|
|
1566
1670
|
});
|
|
1567
|
-
if (s.lastCentrality =
|
|
1671
|
+
if (s.lastCentrality = x.centrality, s.lastScreenCoverage = x.screenCoverage, s.lastScreenspaceVolume.copy(x.screenspaceVolume), x.screenCoverage === 1 / 0) {
|
|
1568
1672
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
1569
1673
|
return;
|
|
1570
1674
|
}
|
|
1571
|
-
|
|
1675
|
+
x.level >= 0 && x.level < a && (a = x.level, l = !0);
|
|
1572
1676
|
}
|
|
1573
|
-
if (
|
|
1574
|
-
const
|
|
1575
|
-
|
|
1677
|
+
if (l ? n.mesh_lod = a : n.mesh_lod = s.lastLodLevel_Mesh, A && n.mesh_lod != s.lastLodLevel_Mesh) {
|
|
1678
|
+
const v = u?.[n.mesh_lod];
|
|
1679
|
+
v && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${v.densities?.[f].toFixed(0)}) | ${e.name}`);
|
|
1576
1680
|
}
|
|
1577
|
-
if (
|
|
1578
|
-
const
|
|
1681
|
+
if (g) {
|
|
1682
|
+
const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
1579
1683
|
if (s.lastLodLevel_Texture < 0) {
|
|
1580
|
-
if (n.texture_lod =
|
|
1581
|
-
const
|
|
1582
|
-
A && console.log(`First Texture LOD ${n.texture_lod} (${
|
|
1684
|
+
if (n.texture_lod = d.max_count - 1, A) {
|
|
1685
|
+
const v = d.lods[d.max_count - 1];
|
|
1686
|
+
A && console.log(`First Texture LOD ${n.texture_lod} (${v.max_height}px) - ${e.name}`);
|
|
1583
1687
|
}
|
|
1584
1688
|
} else {
|
|
1585
|
-
const
|
|
1586
|
-
let
|
|
1587
|
-
this.context?.engine === "model-viewer" && (
|
|
1588
|
-
const
|
|
1589
|
-
let
|
|
1590
|
-
for (let
|
|
1591
|
-
const
|
|
1592
|
-
if (!(
|
|
1593
|
-
if (
|
|
1594
|
-
const
|
|
1595
|
-
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${
|
|
1596
|
-
Screensize: ${
|
|
1689
|
+
const v = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
1690
|
+
let L = s.lastScreenCoverage * 4;
|
|
1691
|
+
this.context?.engine === "model-viewer" && (L *= 1.5);
|
|
1692
|
+
const w = b / window.devicePixelRatio * L;
|
|
1693
|
+
let O = !1;
|
|
1694
|
+
for (let D = d.lods.length - 1; D >= 0; D--) {
|
|
1695
|
+
const k = d.lods[D];
|
|
1696
|
+
if (!(x && k.max_height >= 2048) && !(Me() && k.max_height > 4096) && (k.max_height > w || !O && D === 0)) {
|
|
1697
|
+
if (O = !0, n.texture_lod = D, A && n.texture_lod < s.lastLodLevel_Texture) {
|
|
1698
|
+
const R = k.max_height;
|
|
1699
|
+
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${R}px
|
|
1700
|
+
Screensize: ${w.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${v.toFixed(1)}
|
|
1597
1701
|
${e.name}`);
|
|
1598
1702
|
}
|
|
1599
1703
|
break;
|
|
@@ -1604,74 +1708,74 @@ ${e.name}`);
|
|
|
1604
1708
|
n.texture_lod = 0;
|
|
1605
1709
|
}
|
|
1606
1710
|
}
|
|
1607
|
-
class
|
|
1711
|
+
class zt {
|
|
1608
1712
|
frames = 0;
|
|
1609
1713
|
lastLodLevel_Mesh = -1;
|
|
1610
1714
|
lastLodLevel_Texture = -1;
|
|
1611
1715
|
lastScreenCoverage = 0;
|
|
1612
|
-
lastScreenspaceVolume = new
|
|
1716
|
+
lastScreenspaceVolume = new P();
|
|
1613
1717
|
lastCentrality = 0;
|
|
1614
1718
|
}
|
|
1615
|
-
function
|
|
1719
|
+
function ze(i, t) {
|
|
1616
1720
|
if (!(t < 0)) {
|
|
1617
1721
|
if (Array.isArray(i)) {
|
|
1618
1722
|
for (const e of i)
|
|
1619
|
-
|
|
1723
|
+
ze(e, t);
|
|
1620
1724
|
return;
|
|
1621
1725
|
}
|
|
1622
|
-
"color" in i && i.color instanceof
|
|
1726
|
+
"color" in i && i.color instanceof Ie && (i.color.copy(Et(t, $t)), i.needsUpdate = !0);
|
|
1623
1727
|
}
|
|
1624
1728
|
}
|
|
1625
|
-
function
|
|
1626
|
-
const e = Math.max(0, Math.min(
|
|
1627
|
-
return t.setHex(
|
|
1729
|
+
function Et(i, t) {
|
|
1730
|
+
const e = Math.max(0, Math.min(Se.length - 1, Math.floor(i)));
|
|
1731
|
+
return t.setHex(Se[e]);
|
|
1628
1732
|
}
|
|
1629
|
-
const
|
|
1630
|
-
let
|
|
1631
|
-
function
|
|
1632
|
-
const i =
|
|
1733
|
+
const Ce = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ae = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
|
|
1734
|
+
let me = null;
|
|
1735
|
+
function Ee() {
|
|
1736
|
+
const i = Nt();
|
|
1633
1737
|
i && (i.mapURLs(function(t) {
|
|
1634
|
-
return
|
|
1635
|
-
}),
|
|
1738
|
+
return Pe(), t;
|
|
1739
|
+
}), Pe(), me?.disconnect(), me = new MutationObserver((t) => {
|
|
1636
1740
|
t.forEach((e) => {
|
|
1637
1741
|
e.addedNodes.forEach((s) => {
|
|
1638
|
-
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" &&
|
|
1742
|
+
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ne(s);
|
|
1639
1743
|
});
|
|
1640
1744
|
});
|
|
1641
|
-
}),
|
|
1745
|
+
}), me.observe(document, { childList: !0, subtree: !0 }));
|
|
1642
1746
|
}
|
|
1643
|
-
function
|
|
1747
|
+
function Nt() {
|
|
1644
1748
|
if (typeof customElements > "u") return null;
|
|
1645
1749
|
const i = customElements.get("model-viewer");
|
|
1646
1750
|
return i || (customElements.whenDefined("model-viewer").then(() => {
|
|
1647
|
-
console.debug("[gltf-progressive] model-viewer defined"),
|
|
1751
|
+
console.debug("[gltf-progressive] model-viewer defined"), Ee();
|
|
1648
1752
|
}), null);
|
|
1649
1753
|
}
|
|
1650
|
-
function
|
|
1754
|
+
function Pe() {
|
|
1651
1755
|
if (typeof document > "u") return;
|
|
1652
1756
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
1653
|
-
|
|
1757
|
+
Ne(t);
|
|
1654
1758
|
});
|
|
1655
1759
|
}
|
|
1656
|
-
const
|
|
1657
|
-
let
|
|
1658
|
-
function
|
|
1659
|
-
if (!i ||
|
|
1760
|
+
const ke = /* @__PURE__ */ new WeakSet();
|
|
1761
|
+
let Vt = 0;
|
|
1762
|
+
function Ne(i) {
|
|
1763
|
+
if (!i || ke.has(i))
|
|
1660
1764
|
return null;
|
|
1661
|
-
|
|
1765
|
+
ke.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++Vt + `
|
|
1662
1766
|
`, i.getAttribute("src"));
|
|
1663
1767
|
let t = null, e = null, s = null;
|
|
1664
1768
|
for (let r = i; r != null; r = Object.getPrototypeOf(r)) {
|
|
1665
|
-
const n = Object.getOwnPropertySymbols(r), o = n.find((
|
|
1666
|
-
!t && o != null && (t = i[o].threeRenderer), !e &&
|
|
1769
|
+
const n = Object.getOwnPropertySymbols(r), o = n.find((u) => u.toString() == "Symbol(renderer)"), a = n.find((u) => u.toString() == "Symbol(scene)"), l = n.find((u) => u.toString() == "Symbol(needsRender)");
|
|
1770
|
+
!t && o != null && (t = i[o].threeRenderer), !e && a != null && (e = i[a]), !s && l != null && (s = i[l]);
|
|
1667
1771
|
}
|
|
1668
1772
|
if (t && e) {
|
|
1669
1773
|
let r = function() {
|
|
1670
1774
|
if (s) {
|
|
1671
1775
|
let o = 0;
|
|
1672
|
-
const
|
|
1776
|
+
const a = setInterval(() => {
|
|
1673
1777
|
if (o++ > 5) {
|
|
1674
|
-
clearInterval(
|
|
1778
|
+
clearInterval(a);
|
|
1675
1779
|
return;
|
|
1676
1780
|
}
|
|
1677
1781
|
s?.call(i);
|
|
@@ -1679,8 +1783,8 @@ function Ue(i) {
|
|
|
1679
1783
|
}
|
|
1680
1784
|
};
|
|
1681
1785
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
1682
|
-
const n =
|
|
1683
|
-
return
|
|
1786
|
+
const n = I.get(t, { engine: "model-viewer" });
|
|
1787
|
+
return I.addPlugin(new Xt()), n.enable(), n.addEventListener("changed", () => {
|
|
1684
1788
|
s?.call(i);
|
|
1685
1789
|
}), i.addEventListener("model-visibility", (o) => {
|
|
1686
1790
|
o.detail.visible && s?.call(i);
|
|
@@ -1692,7 +1796,7 @@ function Ue(i) {
|
|
|
1692
1796
|
}
|
|
1693
1797
|
return null;
|
|
1694
1798
|
}
|
|
1695
|
-
class
|
|
1799
|
+
class Xt {
|
|
1696
1800
|
_didWarnAboutMissingUrl = !1;
|
|
1697
1801
|
onBeforeUpdateLOD(t, e, s, r) {
|
|
1698
1802
|
this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
|
|
@@ -1710,50 +1814,50 @@ class At {
|
|
|
1710
1814
|
return t.element;
|
|
1711
1815
|
}
|
|
1712
1816
|
tryParseTextureLOD(t, e) {
|
|
1713
|
-
if (e[
|
|
1714
|
-
e[
|
|
1817
|
+
if (e[ae] == !0) return;
|
|
1818
|
+
e[ae] = !0;
|
|
1715
1819
|
const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), n = this.getUrl(r);
|
|
1716
1820
|
if (n && s && e.material) {
|
|
1717
|
-
let o = function(
|
|
1718
|
-
if (
|
|
1719
|
-
|
|
1720
|
-
const
|
|
1721
|
-
for (let
|
|
1722
|
-
const
|
|
1723
|
-
if (
|
|
1724
|
-
const
|
|
1725
|
-
if (
|
|
1726
|
-
const
|
|
1727
|
-
if (!
|
|
1728
|
-
console.warn("Texture data not found for texture index " +
|
|
1821
|
+
let o = function(l) {
|
|
1822
|
+
if (l[ae] == !0) return;
|
|
1823
|
+
l[ae] = !0, l.userData && (l.userData.LOD = -1);
|
|
1824
|
+
const u = Object.keys(l);
|
|
1825
|
+
for (let f = 0; f < u.length; f++) {
|
|
1826
|
+
const c = u[f], d = l[c];
|
|
1827
|
+
if (d?.isTexture === !0) {
|
|
1828
|
+
const g = d.userData?.associations?.textures;
|
|
1829
|
+
if (g == null) continue;
|
|
1830
|
+
const b = s.parser.json.textures[g];
|
|
1831
|
+
if (!b) {
|
|
1832
|
+
console.warn("Texture data not found for texture index " + g);
|
|
1729
1833
|
continue;
|
|
1730
1834
|
}
|
|
1731
|
-
if (
|
|
1732
|
-
const
|
|
1733
|
-
|
|
1835
|
+
if (b?.extensions?.[F]) {
|
|
1836
|
+
const y = b.extensions[F];
|
|
1837
|
+
y && n && p.registerTexture(n, d, y.lods.length, g, y);
|
|
1734
1838
|
}
|
|
1735
1839
|
}
|
|
1736
1840
|
}
|
|
1737
1841
|
};
|
|
1738
|
-
const
|
|
1739
|
-
if (Array.isArray(
|
|
1740
|
-
else o(
|
|
1842
|
+
const a = e.material;
|
|
1843
|
+
if (Array.isArray(a)) for (const l of a) o(l);
|
|
1844
|
+
else o(a);
|
|
1741
1845
|
}
|
|
1742
1846
|
}
|
|
1743
1847
|
tryParseMeshLOD(t, e) {
|
|
1744
|
-
if (e[
|
|
1745
|
-
e[
|
|
1848
|
+
if (e[Ce] == !0) return;
|
|
1849
|
+
e[Ce] = !0;
|
|
1746
1850
|
const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
|
|
1747
1851
|
if (!r)
|
|
1748
1852
|
return;
|
|
1749
1853
|
const n = e.userData?.gltfExtensions?.[F];
|
|
1750
1854
|
if (n && r) {
|
|
1751
1855
|
const o = e.uuid;
|
|
1752
|
-
|
|
1856
|
+
p.registerMesh(r, o, e, 0, n.lods.length, n);
|
|
1753
1857
|
}
|
|
1754
1858
|
}
|
|
1755
1859
|
}
|
|
1756
|
-
function
|
|
1860
|
+
function jt(...i) {
|
|
1757
1861
|
let t, e, s, r;
|
|
1758
1862
|
switch (i.length) {
|
|
1759
1863
|
case 2:
|
|
@@ -1768,22 +1872,22 @@ function Rt(...i) {
|
|
|
1768
1872
|
default:
|
|
1769
1873
|
throw new Error("Invalid arguments");
|
|
1770
1874
|
}
|
|
1771
|
-
|
|
1875
|
+
_e(e), Ge(s), We(s, {
|
|
1772
1876
|
progressive: !0,
|
|
1773
1877
|
...r?.hints
|
|
1774
|
-
}), s.register((o) => new
|
|
1775
|
-
const n =
|
|
1878
|
+
}), s.register((o) => new p(o));
|
|
1879
|
+
const n = I.get(e);
|
|
1776
1880
|
return r?.enableLODsManager !== !1 && n.enable(), n;
|
|
1777
1881
|
}
|
|
1778
|
-
|
|
1779
|
-
if (!
|
|
1882
|
+
Ee();
|
|
1883
|
+
if (!_t) {
|
|
1780
1884
|
const i = {
|
|
1781
1885
|
gltfProgressive: {
|
|
1782
|
-
useNeedleProgressive:
|
|
1783
|
-
LODsManager:
|
|
1784
|
-
configureLoader:
|
|
1886
|
+
useNeedleProgressive: jt,
|
|
1887
|
+
LODsManager: I,
|
|
1888
|
+
configureLoader: We,
|
|
1785
1889
|
getRaycastMesh: ne,
|
|
1786
|
-
useRaycastMeshes:
|
|
1890
|
+
useRaycastMeshes: bt
|
|
1787
1891
|
}
|
|
1788
1892
|
};
|
|
1789
1893
|
if (!globalThis.Needle)
|
|
@@ -1794,20 +1898,20 @@ if (!ct) {
|
|
|
1794
1898
|
}
|
|
1795
1899
|
export {
|
|
1796
1900
|
F as EXTENSION_NAME,
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1901
|
+
I as LODsManager,
|
|
1902
|
+
p as NEEDLE_progressive,
|
|
1903
|
+
ut as VERSION,
|
|
1904
|
+
Ge as addDracoAndKTX2Loaders,
|
|
1905
|
+
Ut as calculateMeshLODLevel,
|
|
1906
|
+
We as configureLoader,
|
|
1907
|
+
_e as createLoaders,
|
|
1908
|
+
Et as getLODColor,
|
|
1805
1909
|
ne as getRaycastMesh,
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1910
|
+
Se as lodDebugColors,
|
|
1911
|
+
Ee as patchModelViewer,
|
|
1912
|
+
Mt as registerRaycastMesh,
|
|
1913
|
+
ht as setDracoDecoderLocation,
|
|
1914
|
+
gt as setKTX2TranscoderLocation,
|
|
1915
|
+
jt as useNeedleProgressive,
|
|
1916
|
+
bt as useRaycastMeshes
|
|
1813
1917
|
};
|