@needle-tools/gltf-progressive 3.6.0-alpha.3 → 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 +4 -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 +429 -355
- package/gltf-progressive.min.js +9 -9
- package/gltf-progressive.umd.cjs +9 -9
- package/lib/extension.js +5 -7
- 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
10
|
let $ = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", Y = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
fetch(
|
|
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 ${$} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), $ ===
|
|
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
|
+
const dt = () => ({
|
|
23
24
|
dracoDecoderPath: $,
|
|
24
25
|
ktx2TranscoderPath: Y
|
|
25
26
|
});
|
|
26
|
-
function
|
|
27
|
-
$ = i,
|
|
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
|
+
function gt(i) {
|
|
30
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
39
|
const ye = /* @__PURE__ */ Symbol("dracoDecoderPath");
|
|
39
|
-
let
|
|
40
|
-
function
|
|
41
|
-
|
|
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
44
|
const xe = /* @__PURE__ */ new WeakMap();
|
|
44
|
-
function
|
|
45
|
+
function We(i, t) {
|
|
45
46
|
let e = xe.get(i);
|
|
46
47
|
e ? e = Object.assign(e, t) : e = t, xe.set(i, e);
|
|
47
48
|
}
|
|
48
|
-
const
|
|
49
|
-
function
|
|
49
|
+
const pt = De.prototype.load;
|
|
50
|
+
function mt(...i) {
|
|
50
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;
|
|
73
|
+
}
|
|
74
|
+
function Le(i) {
|
|
75
|
+
const t = i.source?.data;
|
|
76
|
+
return t != null && typeof t == "object" ? t : null;
|
|
58
77
|
}
|
|
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;
|
|
78
|
+
function xt(i) {
|
|
79
|
+
const t = i.image;
|
|
80
|
+
return t != null && typeof t == "object" ? t : null;
|
|
65
81
|
}
|
|
66
|
-
function
|
|
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 ot(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 (h) {
|
|
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 (h) {
|
|
|
173
206
|
!isNaN(s) && s >= 0 && (X = s, console.log(`Set LOD level to [${X}]`));
|
|
174
207
|
});
|
|
175
208
|
}
|
|
176
|
-
function
|
|
209
|
+
function Ue(i) {
|
|
177
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
222
|
h && console.warn(`[Worker] Creating new worker #${s}`);
|
|
190
|
-
const r =
|
|
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 De {
|
|
|
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,19 +253,26 @@ class De {
|
|
|
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
264
|
const { WebGLRenderer: u } = await import("three");
|
|
232
265
|
return new u();
|
|
233
266
|
})(), r = await this._webglRenderer);
|
|
234
|
-
const a =
|
|
235
|
-
|
|
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
|
+
}
|
|
236
276
|
const l = {
|
|
237
277
|
type: "load",
|
|
238
278
|
url: t,
|
|
@@ -249,32 +289,32 @@ class De {
|
|
|
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((a) =>
|
|
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 ue(), s.boundingBox.min = 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
|
|
272
|
-
), s.boundingBox.max = new
|
|
312
|
+
), s.boundingBox.max = new k(
|
|
273
313
|
e.boundingBox?.max.x,
|
|
274
314
|
e.boundingBox?.max.y,
|
|
275
315
|
e.boundingBox?.max.z
|
|
276
|
-
), s.boundingSphere = new
|
|
277
|
-
new
|
|
316
|
+
), s.boundingSphere = new Ae(
|
|
317
|
+
new k(
|
|
278
318
|
e.boundingSphere?.center.x,
|
|
279
319
|
e.boundingSphere?.center.y,
|
|
280
320
|
e.boundingSphere?.center.z
|
|
@@ -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,
|
|
@@ -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,18 +365,18 @@ 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
382
|
return U;
|
|
@@ -402,12 +442,12 @@ class p {
|
|
|
402
442
|
function o(a, l) {
|
|
403
443
|
const u = s.getAssignedLODInformation(a);
|
|
404
444
|
if (u) {
|
|
405
|
-
const
|
|
406
|
-
if (
|
|
407
|
-
l.min_count = Math.min(l.min_count,
|
|
408
|
-
for (let c = 0; c <
|
|
409
|
-
const
|
|
410
|
-
|
|
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,11 +505,11 @@ class p {
|
|
|
465
505
|
const r = t.geometry, n = this.getAssignedLODInformation(r);
|
|
466
506
|
if (!n)
|
|
467
507
|
return Promise.resolve(null);
|
|
468
|
-
for (const a of
|
|
508
|
+
for (const a of F)
|
|
469
509
|
a.onBeforeGetLODMesh?.(t, e);
|
|
470
510
|
t["LOD:requested level"] = e;
|
|
471
511
|
const o = () => t["LOD:requested level"] === e || this.shouldApplyStaleMeshLOD(t, e);
|
|
472
|
-
return
|
|
512
|
+
return g.getOrLoadLOD(r, e, {
|
|
473
513
|
isCurrent: o
|
|
474
514
|
}).then((a) => {
|
|
475
515
|
if (Array.isArray(a)) {
|
|
@@ -507,9 +547,9 @@ class p {
|
|
|
507
547
|
if (this.trackCurrentMaterialTextureSlots(n), n.uniforms && (n.isRawShaderMaterial || n.isShaderMaterial === !0)) {
|
|
508
548
|
const l = n;
|
|
509
549
|
for (const u of Object.keys(l.uniforms)) {
|
|
510
|
-
const
|
|
511
|
-
if (
|
|
512
|
-
const c = this.assignTextureLODForSlot(
|
|
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));
|
|
513
553
|
o.push(c), a.push(u);
|
|
514
554
|
}
|
|
515
555
|
}
|
|
@@ -517,15 +557,15 @@ class p {
|
|
|
517
557
|
for (const l of Object.keys(n)) {
|
|
518
558
|
const u = n[l];
|
|
519
559
|
if (u?.isTexture === !0) {
|
|
520
|
-
const
|
|
521
|
-
o.push(
|
|
560
|
+
const f = this.assignTextureLODForSlot(u, e, n, l, r);
|
|
561
|
+
o.push(f), a.push(l);
|
|
522
562
|
}
|
|
523
563
|
}
|
|
524
564
|
return Promise.all(o).then((l) => {
|
|
525
565
|
const u = new Array();
|
|
526
|
-
for (let
|
|
527
|
-
const c = l[
|
|
528
|
-
c && c.isTexture === !0 ? u.push({ material: n, slot:
|
|
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 });
|
|
529
569
|
}
|
|
530
570
|
return u;
|
|
531
571
|
});
|
|
@@ -541,10 +581,10 @@ class p {
|
|
|
541
581
|
* @default 50 on desktop, 20 on mobile devices
|
|
542
582
|
*/
|
|
543
583
|
static set maxConcurrentLoadingTasks(t) {
|
|
544
|
-
|
|
584
|
+
g.queue.maxConcurrent = t;
|
|
545
585
|
}
|
|
546
586
|
static get maxConcurrentLoadingTasks() {
|
|
547
|
-
return
|
|
587
|
+
return g.queue.maxConcurrent;
|
|
548
588
|
}
|
|
549
589
|
// #region INTERNAL
|
|
550
590
|
static assignTextureLODForSlot(t, e, s, r, n) {
|
|
@@ -560,7 +600,7 @@ class p {
|
|
|
560
600
|
if (c && c.level === e && c.force === n)
|
|
561
601
|
return c.promise;
|
|
562
602
|
}
|
|
563
|
-
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),
|
|
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, {
|
|
564
604
|
isCurrent: u
|
|
565
605
|
}).then((c) => {
|
|
566
606
|
if (!l() && !this.shouldApplyStaleTextureSlotLOD(s, r, e, n)) return null;
|
|
@@ -568,11 +608,11 @@ class p {
|
|
|
568
608
|
return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), null;
|
|
569
609
|
if (c?.isTexture === !0) {
|
|
570
610
|
if (c != t && s && r) {
|
|
571
|
-
const
|
|
572
|
-
if (
|
|
573
|
-
const
|
|
574
|
-
if (
|
|
575
|
-
return h === "verbose" && console.warn("Assigned texture level is already higher: ",
|
|
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;
|
|
576
616
|
}
|
|
577
617
|
this.assignTrackedTextureSlot(s, r, c);
|
|
578
618
|
}
|
|
@@ -580,7 +620,7 @@ class p {
|
|
|
580
620
|
} else h == "verbose" && console.warn("No LOD found for", t, e);
|
|
581
621
|
return null;
|
|
582
622
|
}).catch((c) => (console.error("Error loading LOD", t, c), null));
|
|
583
|
-
return s && r && this.setPendingTextureSlotRequest(s, r, e, n, a,
|
|
623
|
+
return s && r && this.setPendingTextureSlotRequest(s, r, e, n, a, f), f;
|
|
584
624
|
}
|
|
585
625
|
// Track material slots, not just texture objects. A shared fallback texture can be
|
|
586
626
|
// referenced by many slots and should only be disposed after every slot moved away.
|
|
@@ -678,7 +718,7 @@ class p {
|
|
|
678
718
|
loadMesh = (t) => {
|
|
679
719
|
if (this._isLoadingMesh) return null;
|
|
680
720
|
const e = this.parser.json.meshes[t]?.extensions?.[U];
|
|
681
|
-
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s &&
|
|
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;
|
|
682
722
|
};
|
|
683
723
|
// private _isLoadingTexture;
|
|
684
724
|
// loadTexture = (textureIndex: number) => {
|
|
@@ -705,9 +745,9 @@ class p {
|
|
|
705
745
|
}
|
|
706
746
|
let n = !1;
|
|
707
747
|
for (const o of this.parser.associations.keys())
|
|
708
|
-
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));
|
|
709
749
|
n || this.parser.getDependency("texture", s).then((o) => {
|
|
710
|
-
o &&
|
|
750
|
+
o && g.registerTexture(this.url, o, r.lods?.length, s, r);
|
|
711
751
|
});
|
|
712
752
|
}
|
|
713
753
|
}
|
|
@@ -718,7 +758,7 @@ class p {
|
|
|
718
758
|
for (const n of this.parser.associations.keys())
|
|
719
759
|
if (n.isMesh) {
|
|
720
760
|
const o = this.parser.associations.get(n);
|
|
721
|
-
o?.meshes === s &&
|
|
761
|
+
o?.meshes === s && g.registerMesh(this.url, r.guid, n, r.lods.length, o.primitives, r);
|
|
722
762
|
}
|
|
723
763
|
}
|
|
724
764
|
}
|
|
@@ -741,12 +781,12 @@ class p {
|
|
|
741
781
|
return;
|
|
742
782
|
}
|
|
743
783
|
if (h) {
|
|
744
|
-
const
|
|
784
|
+
const { width: a, height: l } = we(e);
|
|
745
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);
|
|
746
786
|
}
|
|
747
|
-
e.source && (e.source[
|
|
787
|
+
e.source && (e.source[de] = n);
|
|
748
788
|
const o = n.guid;
|
|
749
|
-
|
|
789
|
+
g.assignLODInformation(t, e, o, s, r), g.lodInfos.set(o, n), g.lowresCache.set(o, new WeakRef(e));
|
|
750
790
|
};
|
|
751
791
|
/**
|
|
752
792
|
* Register a mesh with progressive LOD information. This associates the mesh geometry with its LOD extension data
|
|
@@ -767,11 +807,11 @@ class p {
|
|
|
767
807
|
h && console.warn("gltf-progressive: Register mesh without geometry");
|
|
768
808
|
return;
|
|
769
809
|
}
|
|
770
|
-
a.userData || (a.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: n, uuid: s.uuid }, o, s),
|
|
771
|
-
let u =
|
|
772
|
-
u ? u.push(s.geometry) : u = [s.geometry],
|
|
773
|
-
for (const
|
|
774
|
-
|
|
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);
|
|
775
815
|
};
|
|
776
816
|
/**
|
|
777
817
|
* Dispose cached resources to free memory.
|
|
@@ -844,9 +884,9 @@ class p {
|
|
|
844
884
|
* The held value is the cache key string used in `previouslyLoaded`.
|
|
845
885
|
*/
|
|
846
886
|
static _resourceRegistry = new FinalizationRegistry((t) => {
|
|
847
|
-
const e =
|
|
887
|
+
const e = g.cache.get(t);
|
|
848
888
|
(h || se) && console.debug(`[gltf-progressive] Memory: Resource GC'd
|
|
849
|
-
${t}`), e instanceof WeakRef && (e.deref() || (
|
|
889
|
+
${t}`), e instanceof WeakRef && (e.deref() || (g.cache.delete(t), (h || se) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
|
|
850
890
|
});
|
|
851
891
|
/**
|
|
852
892
|
* Track texture usage by incrementing reference count
|
|
@@ -869,9 +909,10 @@ ${t}`), e instanceof WeakRef && (e.deref() || (p.cache.delete(t), (h || se) && c
|
|
|
869
909
|
return this.textureRefCounts.delete(e), (h || se) && n("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
|
|
870
910
|
return this.textureRefCounts.set(e, r), h === "verbose" && n("[gltf-progressive] Memory: Untrack texture", r), !1;
|
|
871
911
|
function n(o, a) {
|
|
872
|
-
|
|
912
|
+
let { width: l, height: u } = we(t);
|
|
913
|
+
const f = l && u ? `${l}x${u}` : "N/A";
|
|
873
914
|
let c = "N/A";
|
|
874
|
-
l && u && (c = `~${(
|
|
915
|
+
l && u && (c = `~${(vt(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${f} (${c}), refCount: ${s} → ${a}
|
|
875
916
|
${e}`);
|
|
876
917
|
}
|
|
877
918
|
}
|
|
@@ -885,19 +926,19 @@ ${e}`);
|
|
|
885
926
|
let a;
|
|
886
927
|
if (t.isTexture === !0) {
|
|
887
928
|
const u = t;
|
|
888
|
-
u.source && u.source[
|
|
929
|
+
u.source && u.source[de] && (a = u.source[de]);
|
|
889
930
|
}
|
|
890
|
-
if (a || (a =
|
|
891
|
-
h && console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`, t.type,
|
|
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);
|
|
892
933
|
else {
|
|
893
934
|
if (e > 0) {
|
|
894
935
|
let c = !1;
|
|
895
|
-
const
|
|
896
|
-
if (
|
|
897
|
-
const
|
|
898
|
-
if (
|
|
899
|
-
const
|
|
900
|
-
if (
|
|
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;
|
|
901
942
|
this.lowresCache.delete(o), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${o}`);
|
|
902
943
|
}
|
|
903
944
|
return null;
|
|
@@ -906,111 +947,111 @@ ${e}`);
|
|
|
906
947
|
const u = Array.isArray(a.lods) ? a.lods[e]?.path : a.lods;
|
|
907
948
|
if (!u)
|
|
908
949
|
return h && !a["missing:uri"] && (a["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, a)), null;
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
950
|
+
const f = Lt(n.url, u);
|
|
951
|
+
if (f.endsWith(".glb") || f.endsWith(".gltf")) {
|
|
911
952
|
if (!a.guid)
|
|
912
953
|
return console.warn("missing pointer for glb/gltf texture", a), null;
|
|
913
|
-
const c =
|
|
914
|
-
if (
|
|
954
|
+
const c = f + "_" + a.guid, d = await this.tryResolveLODCacheEntry(this.cache.get(c), c, f, t, e, r);
|
|
955
|
+
if (d.found) return d.value;
|
|
915
956
|
if (s?.isCurrent?.() === !1)
|
|
916
|
-
return r && console.log(`Skipping stale LOD ${e} request before queue: ${
|
|
917
|
-
const
|
|
957
|
+
return r && console.log(`Skipping stale LOD ${e} request before queue: ${f}`), null;
|
|
958
|
+
const p = await this.queue.slot(f);
|
|
918
959
|
if (s?.isCurrent?.() === !1)
|
|
919
|
-
return r && console.log(`Skipping stale LOD ${e} request after queue: ${
|
|
920
|
-
const
|
|
921
|
-
if (
|
|
922
|
-
if (!
|
|
923
|
-
return h && console.log(`LOD ${e} was aborted: ${
|
|
924
|
-
const y = a, x = new Promise(async (L,
|
|
925
|
-
if (
|
|
926
|
-
const m = await (await
|
|
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);
|
|
927
968
|
if (m.textures.length > 0)
|
|
928
969
|
for (const D of m.textures) {
|
|
929
970
|
let M = D.texture;
|
|
930
|
-
return
|
|
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);
|
|
931
972
|
}
|
|
932
973
|
if (m.geometries.length > 0) {
|
|
933
974
|
const D = new Array();
|
|
934
975
|
for (const M of m.geometries) {
|
|
935
976
|
const G = M.geometry;
|
|
936
|
-
|
|
977
|
+
g.assignLODInformation(n.url, G, o, e, M.primitiveIndex), D.push(G);
|
|
937
978
|
}
|
|
938
979
|
return L(D);
|
|
939
980
|
}
|
|
940
981
|
return L(null);
|
|
941
982
|
}
|
|
942
|
-
const
|
|
943
|
-
|
|
944
|
-
let
|
|
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;
|
|
945
986
|
if (y && Array.isArray(y.lods)) {
|
|
946
|
-
const
|
|
947
|
-
|
|
987
|
+
const _ = y.lods[e];
|
|
988
|
+
_.hash && (T += "?v=" + _.hash);
|
|
948
989
|
}
|
|
949
|
-
const
|
|
950
|
-
`,
|
|
951
|
-
if (!
|
|
990
|
+
const O = await v.loadAsync(T).catch((_) => (console.error(`Error loading LOD ${e} from ${f}
|
|
991
|
+
`, _), L(null)));
|
|
992
|
+
if (!O)
|
|
952
993
|
return L(null);
|
|
953
|
-
const
|
|
954
|
-
r && console.log("Loading finished " +
|
|
955
|
-
let
|
|
956
|
-
if (
|
|
957
|
-
let
|
|
958
|
-
for (const m of
|
|
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) {
|
|
959
1000
|
if (m?.extensions) {
|
|
960
1001
|
const D = m?.extensions[U];
|
|
961
1002
|
if (D?.guid && D.guid === y.guid) {
|
|
962
|
-
|
|
1003
|
+
_ = !0;
|
|
963
1004
|
break;
|
|
964
1005
|
}
|
|
965
1006
|
}
|
|
966
|
-
|
|
1007
|
+
S++;
|
|
967
1008
|
}
|
|
968
|
-
if (
|
|
969
|
-
let m = await
|
|
970
|
-
return m &&
|
|
971
|
-
} else h && console.warn("Could not find texture with guid", y.guid,
|
|
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);
|
|
972
1013
|
}
|
|
973
|
-
if (
|
|
974
|
-
let
|
|
975
|
-
for (const m of
|
|
1014
|
+
if (S = 0, O.parser.json.meshes) {
|
|
1015
|
+
let _ = !1;
|
|
1016
|
+
for (const m of O.parser.json.meshes) {
|
|
976
1017
|
if (m?.extensions) {
|
|
977
1018
|
const D = m?.extensions[U];
|
|
978
1019
|
if (D?.guid && D.guid === y.guid) {
|
|
979
|
-
|
|
1020
|
+
_ = !0;
|
|
980
1021
|
break;
|
|
981
1022
|
}
|
|
982
1023
|
}
|
|
983
|
-
|
|
1024
|
+
S++;
|
|
984
1025
|
}
|
|
985
|
-
if (
|
|
986
|
-
const m = await
|
|
987
|
-
if (r && console.log(`Loaded Mesh "${m.name}"`,
|
|
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) {
|
|
988
1029
|
const D = m.geometry;
|
|
989
|
-
return
|
|
1030
|
+
return g.assignLODInformation(n.url, D, o, e, 0), L(D);
|
|
990
1031
|
} else {
|
|
991
1032
|
const D = new Array();
|
|
992
1033
|
for (let M = 0; M < m.children.length; M++) {
|
|
993
1034
|
const G = m.children[M];
|
|
994
1035
|
if (G.isMesh === !0) {
|
|
995
1036
|
const ie = G.geometry;
|
|
996
|
-
|
|
1037
|
+
g.assignLODInformation(n.url, ie, o, e, M), D.push(ie);
|
|
997
1038
|
}
|
|
998
1039
|
}
|
|
999
1040
|
return L(D);
|
|
1000
1041
|
}
|
|
1001
|
-
} else h && console.warn("Could not find mesh with guid", y.guid,
|
|
1042
|
+
} else h && console.warn("Could not find mesh with guid", y.guid, O.parser.json);
|
|
1002
1043
|
}
|
|
1003
1044
|
return L(null);
|
|
1004
1045
|
});
|
|
1005
|
-
this.cache.set(c, x),
|
|
1006
|
-
const
|
|
1007
|
-
return
|
|
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;
|
|
1008
1049
|
} else if (t instanceof q) {
|
|
1009
1050
|
if (s?.isCurrent?.() === !1)
|
|
1010
|
-
return r && console.log(`Skipping stale texture LOD ${e} request: ${
|
|
1011
|
-
r && console.log("Load texture from uri: " +
|
|
1012
|
-
const
|
|
1013
|
-
return 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);
|
|
1014
1055
|
}
|
|
1015
1056
|
}
|
|
1016
1057
|
return null;
|
|
@@ -1021,24 +1062,24 @@ ${e}`);
|
|
|
1021
1062
|
if (o && console.log(`LOD ${n} was already loading/loaded: ${e}`), t instanceof WeakRef) {
|
|
1022
1063
|
const u = t.deref();
|
|
1023
1064
|
if (u) {
|
|
1024
|
-
let
|
|
1025
|
-
if (
|
|
1026
|
-
return { found: !0, value:
|
|
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 };
|
|
1027
1068
|
}
|
|
1028
1069
|
return this.cache.delete(e), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`), { found: !1 };
|
|
1029
1070
|
}
|
|
1030
1071
|
let a = await t.catch((u) => (console.error(`Error loading LOD ${n} from ${s}
|
|
1031
1072
|
`, u), null)), l = !1;
|
|
1032
|
-
return a == null || (a instanceof q && r instanceof q ? a.image
|
|
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 };
|
|
1033
1074
|
}
|
|
1034
1075
|
static _queue;
|
|
1035
1076
|
static get queue() {
|
|
1036
|
-
return this._queue ??= new
|
|
1077
|
+
return this._queue ??= new wt(Me() ? 20 : 50, { debug: h != !1 });
|
|
1037
1078
|
}
|
|
1038
1079
|
static assignLODInformation(t, e, s, r, n) {
|
|
1039
1080
|
if (!e) return;
|
|
1040
1081
|
e.userData || (e.userData = {});
|
|
1041
|
-
const o = new
|
|
1082
|
+
const o = new kt(t, s, r, n);
|
|
1042
1083
|
e.userData.LODS = o, "source" in e && typeof e.source == "object" && (e.source.LODS = o);
|
|
1043
1084
|
}
|
|
1044
1085
|
static getAssignedLODInformation(t) {
|
|
@@ -1051,7 +1092,7 @@ ${e}`);
|
|
|
1051
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;
|
|
1052
1093
|
}
|
|
1053
1094
|
}
|
|
1054
|
-
class
|
|
1095
|
+
class kt {
|
|
1055
1096
|
url;
|
|
1056
1097
|
/** the key to lookup the LOD information */
|
|
1057
1098
|
key;
|
|
@@ -1138,7 +1179,7 @@ class oe {
|
|
|
1138
1179
|
});
|
|
1139
1180
|
}
|
|
1140
1181
|
}
|
|
1141
|
-
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 = [
|
|
1142
1183
|
3526751,
|
|
1143
1184
|
11065402,
|
|
1144
1185
|
15978811,
|
|
@@ -1171,12 +1212,17 @@ const A = N("debugprogressive"), Lt = A === "colors", vt = N("noprogressive"), h
|
|
|
1171
1212
|
15817653,
|
|
1172
1213
|
5083278,
|
|
1173
1214
|
5592405
|
|
1174
|
-
]
|
|
1175
|
-
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) {
|
|
1176
1222
|
const e = i.min, s = i.max, r = (e.x + s.x) * 0.5, n = (e.y + s.y) * 0.5;
|
|
1177
1223
|
return W.set(r, n, e.z).applyMatrix4(t).z < 0;
|
|
1178
1224
|
}
|
|
1179
|
-
function
|
|
1225
|
+
function Ut(i) {
|
|
1180
1226
|
const {
|
|
1181
1227
|
geometry: t,
|
|
1182
1228
|
matrixWorld: e,
|
|
@@ -1187,47 +1233,48 @@ function bt(i) {
|
|
|
1187
1233
|
currentLevel: a = -1,
|
|
1188
1234
|
xrEnabled: l = !1,
|
|
1189
1235
|
debugDrawLine: u,
|
|
1190
|
-
warnMissingPrimitiveDensities:
|
|
1191
|
-
} = i, c =
|
|
1236
|
+
warnMissingPrimitiveDensities: f = !1
|
|
1237
|
+
} = i, c = g.getMeshLODExtension(t)?.lods, d = g.getPrimitiveIndex(t), p = i.target ?? {
|
|
1192
1238
|
level: a,
|
|
1193
|
-
primitiveIndex:
|
|
1239
|
+
primitiveIndex: d,
|
|
1194
1240
|
screenCoverage: 0,
|
|
1195
|
-
screenspaceVolume: new
|
|
1241
|
+
screenspaceVolume: new k(),
|
|
1196
1242
|
centrality: 1
|
|
1197
1243
|
};
|
|
1198
|
-
|
|
1199
|
-
let
|
|
1200
|
-
if (
|
|
1201
|
-
if (pe.copy(
|
|
1202
|
-
return
|
|
1203
|
-
if (
|
|
1204
|
-
const
|
|
1205
|
-
let
|
|
1206
|
-
const m = 2, D = 1.5, M = (
|
|
1207
|
-
|
|
1208
|
-
const ie =
|
|
1209
|
-
|
|
1210
|
-
}
|
|
1211
|
-
const y =
|
|
1212
|
-
y.multiplyScalar(0.5), globalThis.screen?.availHeight > 0 && o > 0 && y.multiplyScalar(o / globalThis.screen.availHeight), s.isPerspectiveCamera && (y.x *= s.aspect),
|
|
1213
|
-
const x =
|
|
1214
|
-
|
|
1215
|
-
const
|
|
1216
|
-
if (
|
|
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;
|
|
1217
1263
|
if (u) {
|
|
1218
|
-
const
|
|
1219
|
-
|
|
1220
|
-
const
|
|
1221
|
-
W.z = H.z = Q.z = J.z =
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
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
|
+
}
|
|
1228
1276
|
}
|
|
1229
|
-
|
|
1230
|
-
return g;
|
|
1277
|
+
return p;
|
|
1231
1278
|
}
|
|
1232
1279
|
class I {
|
|
1233
1280
|
/**
|
|
@@ -1239,11 +1286,15 @@ class I {
|
|
|
1239
1286
|
return t[ge];
|
|
1240
1287
|
}
|
|
1241
1288
|
static addPlugin(t) {
|
|
1242
|
-
|
|
1289
|
+
F.push(t);
|
|
1243
1290
|
}
|
|
1244
1291
|
static removePlugin(t) {
|
|
1245
|
-
const e =
|
|
1246
|
-
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;
|
|
1247
1298
|
}
|
|
1248
1299
|
/**
|
|
1249
1300
|
* Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
|
|
@@ -1261,10 +1312,10 @@ class I {
|
|
|
1261
1312
|
}
|
|
1262
1313
|
renderer;
|
|
1263
1314
|
context;
|
|
1264
|
-
projectionScreenMatrix = new
|
|
1315
|
+
projectionScreenMatrix = new $e();
|
|
1265
1316
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
1266
1317
|
get plugins() {
|
|
1267
|
-
return
|
|
1318
|
+
return F;
|
|
1268
1319
|
}
|
|
1269
1320
|
/**
|
|
1270
1321
|
* Force override the LOD level for all objects (meshes + textures) rendered in the scene
|
|
@@ -1334,7 +1385,7 @@ class I {
|
|
|
1334
1385
|
const r = performance.now();
|
|
1335
1386
|
return s.ready.finally(() => {
|
|
1336
1387
|
const n = this._newPromiseGroups.indexOf(s);
|
|
1337
|
-
n >= 0 && (this._newPromiseGroups.splice(n, 1),
|
|
1388
|
+
n >= 0 && (this._newPromiseGroups.splice(n, 1), Fe() && performance.measure("LODsManager:awaitLoading", {
|
|
1338
1389
|
start: r,
|
|
1339
1390
|
detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
|
|
1340
1391
|
}));
|
|
@@ -1390,11 +1441,11 @@ class I {
|
|
|
1390
1441
|
this.renderer = t, this.context = { ...e };
|
|
1391
1442
|
}
|
|
1392
1443
|
#t;
|
|
1393
|
-
#i = new Ke();
|
|
1394
1444
|
#r = 0;
|
|
1395
1445
|
#n = 0;
|
|
1396
1446
|
#o = 0;
|
|
1397
1447
|
#s = 0;
|
|
1448
|
+
#i = Bt();
|
|
1398
1449
|
_fpsBuffer = [60, 60, 60, 60, 60];
|
|
1399
1450
|
/**
|
|
1400
1451
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
@@ -1405,9 +1456,9 @@ class I {
|
|
|
1405
1456
|
let t = 0;
|
|
1406
1457
|
this.#t = this.renderer.render;
|
|
1407
1458
|
const e = this;
|
|
1408
|
-
|
|
1459
|
+
_e(this.renderer), this.renderer.render = function(s, r) {
|
|
1409
1460
|
const n = e.renderer.getRenderTarget();
|
|
1410
|
-
(n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#r += 1, e.#n = e.#i.getDelta(), 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));
|
|
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));
|
|
1411
1462
|
const o = t++;
|
|
1412
1463
|
e.#t.call(this, s, r), e.onAfterRender(s, r, o);
|
|
1413
1464
|
};
|
|
@@ -1435,14 +1486,16 @@ class I {
|
|
|
1435
1486
|
}
|
|
1436
1487
|
onAfterRender(t, e, s) {
|
|
1437
1488
|
if (this.pause) return;
|
|
1438
|
-
const
|
|
1489
|
+
const r = this.getRenderList(t, e, s);
|
|
1490
|
+
if (!r) return;
|
|
1491
|
+
const n = r.opaque;
|
|
1439
1492
|
let o = !0;
|
|
1440
1493
|
if (n.length === 1) {
|
|
1441
1494
|
const a = n[0].material;
|
|
1442
1495
|
(a.name === "EffectMaterial" || a.name === "CopyShader") && (o = !1);
|
|
1443
1496
|
}
|
|
1444
1497
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
|
|
1445
|
-
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))
|
|
1446
1499
|
return;
|
|
1447
1500
|
this.internalUpdate(t, e), this._postprocessPromiseGroups();
|
|
1448
1501
|
}
|
|
@@ -1451,7 +1504,9 @@ class I {
|
|
|
1451
1504
|
* Update LODs in a scene
|
|
1452
1505
|
*/
|
|
1453
1506
|
internalUpdate(t, e) {
|
|
1454
|
-
const s = this.
|
|
1507
|
+
const s = this.getRenderList(t, e, 0);
|
|
1508
|
+
if (!s) return;
|
|
1509
|
+
const r = s.opaque;
|
|
1455
1510
|
this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
|
|
1456
1511
|
const n = this.targetTriangleDensity;
|
|
1457
1512
|
for (const l of r) {
|
|
@@ -1482,19 +1537,38 @@ class I {
|
|
|
1482
1537
|
(u instanceof K || u.isMesh) && this.updateLODs(t, e, u, n);
|
|
1483
1538
|
}
|
|
1484
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);
|
|
1551
|
+
}
|
|
1552
|
+
return n ? {
|
|
1553
|
+
opaque: n.opaque || [],
|
|
1554
|
+
transparent: n.transparent || [],
|
|
1555
|
+
transmissive: n.transmissive || n.transparentDoublePass || [],
|
|
1556
|
+
transparentDoublePass: n.transparentDoublePass || []
|
|
1557
|
+
} : null;
|
|
1558
|
+
}
|
|
1485
1559
|
/** Update the LOD levels for the renderer. */
|
|
1486
1560
|
updateLODs(t, e, s, r) {
|
|
1487
1561
|
s.userData || (s.userData = {});
|
|
1488
1562
|
let n = s[ge];
|
|
1489
|
-
if (n || (n = new
|
|
1563
|
+
if (n || (n = new zt(), s[ge] = n), n.frames++ < 2)
|
|
1490
1564
|
return;
|
|
1491
|
-
for (const a of
|
|
1565
|
+
for (const a of F)
|
|
1492
1566
|
a.onBeforeUpdateLOD?.(this.renderer, t, e, s);
|
|
1493
1567
|
const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : X;
|
|
1494
|
-
o >= 0 ? (
|
|
1495
|
-
for (const a of
|
|
1496
|
-
a.onAfterUpdatedLOD?.(this.renderer, t, e, s,
|
|
1497
|
-
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;
|
|
1498
1572
|
}
|
|
1499
1573
|
/** Load progressive textures for the given material
|
|
1500
1574
|
* @param material the material to load the textures for
|
|
@@ -1509,11 +1583,11 @@ class I {
|
|
|
1509
1583
|
return;
|
|
1510
1584
|
}
|
|
1511
1585
|
let r = !1;
|
|
1512
|
-
(t[
|
|
1586
|
+
(t[E] === void 0 || e < t[E]) && (r = !0);
|
|
1513
1587
|
const n = s !== void 0 && s >= 0;
|
|
1514
|
-
if (n && (r = t[
|
|
1515
|
-
t[
|
|
1516
|
-
const o = n ? { force: !0 } : void 0, a =
|
|
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) => {
|
|
1517
1591
|
this._lodchangedlisteners.forEach((u) => u({ type: "texture", level: e, object: t }));
|
|
1518
1592
|
});
|
|
1519
1593
|
oe.addPromise("texture", t, a, this._newPromiseGroups);
|
|
@@ -1527,18 +1601,18 @@ class I {
|
|
|
1527
1601
|
*/
|
|
1528
1602
|
loadProgressiveMeshes(t, e) {
|
|
1529
1603
|
if (!t) return Promise.resolve(null);
|
|
1530
|
-
let s = t[
|
|
1604
|
+
let s = t[E] !== e;
|
|
1531
1605
|
const r = t["DEBUG:LOD"];
|
|
1532
|
-
if (r != null && (s = t[
|
|
1533
|
-
t[
|
|
1534
|
-
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));
|
|
1535
1609
|
return oe.addPromise("mesh", t, o, this._newPromiseGroups), o;
|
|
1536
1610
|
}
|
|
1537
1611
|
return Promise.resolve(null);
|
|
1538
1612
|
}
|
|
1539
1613
|
// private testIfLODLevelsAreAvailable() {
|
|
1540
|
-
_sphere = new
|
|
1541
|
-
_tempWorldPosition = new
|
|
1614
|
+
_sphere = new Ae();
|
|
1615
|
+
_tempWorldPosition = new k();
|
|
1542
1616
|
static skinnedMeshBoundsFrameOffsetCounter = 0;
|
|
1543
1617
|
static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
|
|
1544
1618
|
// #region calculateLodLevel
|
|
@@ -1554,13 +1628,13 @@ class I {
|
|
|
1554
1628
|
let a = 10 + 1, l = !1;
|
|
1555
1629
|
if (A && e["DEBUG:LOD"] != null)
|
|
1556
1630
|
return e["DEBUG:LOD"];
|
|
1557
|
-
const u =
|
|
1558
|
-
if (!c && !
|
|
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) {
|
|
1559
1633
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
1560
1634
|
return;
|
|
1561
1635
|
}
|
|
1562
1636
|
c || (l = !0, a = 0);
|
|
1563
|
-
const
|
|
1637
|
+
const b = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
|
|
1564
1638
|
let y = e.geometry.boundingBox;
|
|
1565
1639
|
if (e.type === "SkinnedMesh") {
|
|
1566
1640
|
const x = e;
|
|
@@ -1571,10 +1645,10 @@ class I {
|
|
|
1571
1645
|
const L = I.skinnedMeshBoundsFrameOffsetCounter++;
|
|
1572
1646
|
x[I.$skinnedMeshBoundsOffset] = L;
|
|
1573
1647
|
}
|
|
1574
|
-
const
|
|
1575
|
-
if ((s.frames +
|
|
1576
|
-
const L = ne(x),
|
|
1577
|
-
L && (x.geometry = L), x.computeBoundingBox(), x.geometry =
|
|
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;
|
|
1578
1652
|
}
|
|
1579
1653
|
}
|
|
1580
1654
|
y = x.boundingBox;
|
|
@@ -1588,13 +1662,13 @@ class I {
|
|
|
1588
1662
|
return;
|
|
1589
1663
|
}
|
|
1590
1664
|
}
|
|
1591
|
-
const x =
|
|
1665
|
+
const x = Ut({
|
|
1592
1666
|
geometry: e.geometry,
|
|
1593
1667
|
matrixWorld: e.matrixWorld,
|
|
1594
1668
|
camera: t,
|
|
1595
1669
|
projectionScreenMatrix: this.projectionScreenMatrix,
|
|
1596
1670
|
desiredDensity: r,
|
|
1597
|
-
canvasHeight:
|
|
1671
|
+
canvasHeight: b,
|
|
1598
1672
|
currentLevel: s.lastLodLevel_Mesh,
|
|
1599
1673
|
boundingBox: y,
|
|
1600
1674
|
xrEnabled: this.renderer.xr.enabled,
|
|
@@ -1608,29 +1682,29 @@ class I {
|
|
|
1608
1682
|
x.level >= 0 && x.level < a && (a = x.level, l = !0);
|
|
1609
1683
|
}
|
|
1610
1684
|
if (l ? n.mesh_lod = a : n.mesh_lod = s.lastLodLevel_Mesh, A && n.mesh_lod != s.lastLodLevel_Mesh) {
|
|
1611
|
-
const
|
|
1612
|
-
|
|
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}`);
|
|
1613
1687
|
}
|
|
1614
|
-
if (
|
|
1688
|
+
if (p) {
|
|
1615
1689
|
const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
1616
1690
|
if (s.lastLodLevel_Texture < 0) {
|
|
1617
|
-
if (n.texture_lod =
|
|
1618
|
-
const
|
|
1619
|
-
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}`);
|
|
1620
1694
|
}
|
|
1621
1695
|
} else {
|
|
1622
|
-
const
|
|
1696
|
+
const w = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
1623
1697
|
let L = s.lastScreenCoverage * 4;
|
|
1624
1698
|
this.context?.engine === "model-viewer" && (L *= 1.5);
|
|
1625
|
-
const
|
|
1626
|
-
let
|
|
1627
|
-
for (let
|
|
1628
|
-
const
|
|
1629
|
-
if (!(x &&
|
|
1630
|
-
if (
|
|
1631
|
-
const
|
|
1632
|
-
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${
|
|
1633
|
-
Screensize: ${
|
|
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)}
|
|
1634
1708
|
${e.name}`);
|
|
1635
1709
|
}
|
|
1636
1710
|
break;
|
|
@@ -1641,61 +1715,61 @@ ${e.name}`);
|
|
|
1641
1715
|
n.texture_lod = 0;
|
|
1642
1716
|
}
|
|
1643
1717
|
}
|
|
1644
|
-
class
|
|
1718
|
+
class zt {
|
|
1645
1719
|
frames = 0;
|
|
1646
1720
|
lastLodLevel_Mesh = -1;
|
|
1647
1721
|
lastLodLevel_Texture = -1;
|
|
1648
1722
|
lastScreenCoverage = 0;
|
|
1649
|
-
lastScreenspaceVolume = new
|
|
1723
|
+
lastScreenspaceVolume = new k();
|
|
1650
1724
|
lastCentrality = 0;
|
|
1651
1725
|
}
|
|
1652
|
-
function
|
|
1726
|
+
function ze(i, t) {
|
|
1653
1727
|
if (!(t < 0)) {
|
|
1654
1728
|
if (Array.isArray(i)) {
|
|
1655
1729
|
for (const e of i)
|
|
1656
|
-
|
|
1730
|
+
ze(e, t);
|
|
1657
1731
|
return;
|
|
1658
1732
|
}
|
|
1659
|
-
"color" in i && i.color instanceof
|
|
1733
|
+
"color" in i && i.color instanceof Ie && (i.color.copy(Et(t, $t)), i.needsUpdate = !0);
|
|
1660
1734
|
}
|
|
1661
1735
|
}
|
|
1662
|
-
function
|
|
1663
|
-
const e = Math.max(0, Math.min(
|
|
1664
|
-
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]);
|
|
1665
1739
|
}
|
|
1666
|
-
const
|
|
1740
|
+
const Ce = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ae = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
|
|
1667
1741
|
let me = null;
|
|
1668
|
-
function
|
|
1669
|
-
const i =
|
|
1742
|
+
function Ee() {
|
|
1743
|
+
const i = Nt();
|
|
1670
1744
|
i && (i.mapURLs(function(t) {
|
|
1671
|
-
return
|
|
1672
|
-
}),
|
|
1745
|
+
return Pe(), t;
|
|
1746
|
+
}), Pe(), me?.disconnect(), me = new MutationObserver((t) => {
|
|
1673
1747
|
t.forEach((e) => {
|
|
1674
1748
|
e.addedNodes.forEach((s) => {
|
|
1675
|
-
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" &&
|
|
1749
|
+
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ne(s);
|
|
1676
1750
|
});
|
|
1677
1751
|
});
|
|
1678
1752
|
}), me.observe(document, { childList: !0, subtree: !0 }));
|
|
1679
1753
|
}
|
|
1680
|
-
function
|
|
1754
|
+
function Nt() {
|
|
1681
1755
|
if (typeof customElements > "u") return null;
|
|
1682
1756
|
const i = customElements.get("model-viewer");
|
|
1683
1757
|
return i || (customElements.whenDefined("model-viewer").then(() => {
|
|
1684
|
-
console.debug("[gltf-progressive] model-viewer defined"),
|
|
1758
|
+
console.debug("[gltf-progressive] model-viewer defined"), Ee();
|
|
1685
1759
|
}), null);
|
|
1686
1760
|
}
|
|
1687
|
-
function
|
|
1761
|
+
function Pe() {
|
|
1688
1762
|
if (typeof document > "u") return;
|
|
1689
1763
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
1690
|
-
|
|
1764
|
+
Ne(t);
|
|
1691
1765
|
});
|
|
1692
1766
|
}
|
|
1693
|
-
const
|
|
1694
|
-
let
|
|
1695
|
-
function
|
|
1696
|
-
if (!i ||
|
|
1767
|
+
const ke = /* @__PURE__ */ new WeakSet();
|
|
1768
|
+
let Vt = 0;
|
|
1769
|
+
function Ne(i) {
|
|
1770
|
+
if (!i || ke.has(i))
|
|
1697
1771
|
return null;
|
|
1698
|
-
|
|
1772
|
+
ke.add(i), console.debug("[gltf-progressive] found new model-viewer..." + ++Vt + `
|
|
1699
1773
|
`, i.getAttribute("src"));
|
|
1700
1774
|
let t = null, e = null, s = null;
|
|
1701
1775
|
for (let r = i; r != null; r = Object.getPrototypeOf(r)) {
|
|
@@ -1717,7 +1791,7 @@ function Ue(i) {
|
|
|
1717
1791
|
};
|
|
1718
1792
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
1719
1793
|
const n = I.get(t, { engine: "model-viewer" });
|
|
1720
|
-
return I.addPlugin(new
|
|
1794
|
+
return I.addPlugin(new Xt()), n.enable(), n.addEventListener("changed", () => {
|
|
1721
1795
|
s?.call(i);
|
|
1722
1796
|
}), i.addEventListener("model-visibility", (o) => {
|
|
1723
1797
|
o.detail.visible && s?.call(i);
|
|
@@ -1729,7 +1803,7 @@ function Ue(i) {
|
|
|
1729
1803
|
}
|
|
1730
1804
|
return null;
|
|
1731
1805
|
}
|
|
1732
|
-
class
|
|
1806
|
+
class Xt {
|
|
1733
1807
|
_didWarnAboutMissingUrl = !1;
|
|
1734
1808
|
onBeforeUpdateLOD(t, e, s, r) {
|
|
1735
1809
|
this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
|
|
@@ -1755,19 +1829,19 @@ class Rt {
|
|
|
1755
1829
|
if (l[ae] == !0) return;
|
|
1756
1830
|
l[ae] = !0, l.userData && (l.userData.LOD = -1);
|
|
1757
1831
|
const u = Object.keys(l);
|
|
1758
|
-
for (let
|
|
1759
|
-
const c = u[
|
|
1760
|
-
if (
|
|
1761
|
-
const
|
|
1762
|
-
if (
|
|
1763
|
-
const
|
|
1764
|
-
if (!
|
|
1765
|
-
console.warn("Texture data not found for texture index " +
|
|
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);
|
|
1766
1840
|
continue;
|
|
1767
1841
|
}
|
|
1768
|
-
if (
|
|
1769
|
-
const y =
|
|
1770
|
-
y && n &&
|
|
1842
|
+
if (b?.extensions?.[U]) {
|
|
1843
|
+
const y = b.extensions[U];
|
|
1844
|
+
y && n && g.registerTexture(n, d, y.lods.length, p, y);
|
|
1771
1845
|
}
|
|
1772
1846
|
}
|
|
1773
1847
|
}
|
|
@@ -1778,19 +1852,19 @@ class Rt {
|
|
|
1778
1852
|
}
|
|
1779
1853
|
}
|
|
1780
1854
|
tryParseMeshLOD(t, e) {
|
|
1781
|
-
if (e[
|
|
1782
|
-
e[
|
|
1855
|
+
if (e[Ce] == !0) return;
|
|
1856
|
+
e[Ce] = !0;
|
|
1783
1857
|
const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
|
|
1784
1858
|
if (!r)
|
|
1785
1859
|
return;
|
|
1786
1860
|
const n = e.userData?.gltfExtensions?.[U];
|
|
1787
1861
|
if (n && r) {
|
|
1788
1862
|
const o = e.uuid;
|
|
1789
|
-
|
|
1863
|
+
g.registerMesh(r, o, e, 0, n.lods.length, n);
|
|
1790
1864
|
}
|
|
1791
1865
|
}
|
|
1792
1866
|
}
|
|
1793
|
-
function
|
|
1867
|
+
function jt(...i) {
|
|
1794
1868
|
let t, e, s, r;
|
|
1795
1869
|
switch (i.length) {
|
|
1796
1870
|
case 2:
|
|
@@ -1805,22 +1879,22 @@ function At(...i) {
|
|
|
1805
1879
|
default:
|
|
1806
1880
|
throw new Error("Invalid arguments");
|
|
1807
1881
|
}
|
|
1808
|
-
|
|
1882
|
+
_e(e), Ge(s), We(s, {
|
|
1809
1883
|
progressive: !0,
|
|
1810
1884
|
...r?.hints
|
|
1811
|
-
}), s.register((o) => new
|
|
1885
|
+
}), s.register((o) => new g(o));
|
|
1812
1886
|
const n = I.get(e);
|
|
1813
1887
|
return r?.enableLODsManager !== !1 && n.enable(), n;
|
|
1814
1888
|
}
|
|
1815
|
-
|
|
1816
|
-
if (!
|
|
1889
|
+
Ee();
|
|
1890
|
+
if (!_t) {
|
|
1817
1891
|
const i = {
|
|
1818
1892
|
gltfProgressive: {
|
|
1819
|
-
useNeedleProgressive:
|
|
1893
|
+
useNeedleProgressive: jt,
|
|
1820
1894
|
LODsManager: I,
|
|
1821
|
-
configureLoader:
|
|
1895
|
+
configureLoader: We,
|
|
1822
1896
|
getRaycastMesh: ne,
|
|
1823
|
-
useRaycastMeshes:
|
|
1897
|
+
useRaycastMeshes: bt
|
|
1824
1898
|
}
|
|
1825
1899
|
};
|
|
1826
1900
|
if (!globalThis.Needle)
|
|
@@ -1832,19 +1906,19 @@ if (!ct) {
|
|
|
1832
1906
|
export {
|
|
1833
1907
|
U as EXTENSION_NAME,
|
|
1834
1908
|
I as LODsManager,
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
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,
|
|
1842
1916
|
ne as getRaycastMesh,
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
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
|
|
1850
1924
|
};
|