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