@needle-tools/engine 4.13.1-next.6cb1b73 → 4.13.1-next.9fc3e64
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/dist/gltf-progressive-CaUGGjVL.umd.cjs +10 -0
- package/dist/{gltf-progressive-CsyU_5lc.js → gltf-progressive-Dbi_Tfhb.js} +628 -577
- package/dist/gltf-progressive-DuAR0MQR.min.js +10 -0
- package/dist/{needle-engine.bundle-wB3o8RB6.js → needle-engine.bundle-BZRE5G6O.js} +3 -3
- package/dist/{needle-engine.bundle-qTjHpin6.umd.cjs → needle-engine.bundle-Dqrh7aWw.umd.cjs} +4 -4
- package/dist/{needle-engine.bundle-DRSn34Va.min.js → needle-engine.bundle-DwybonUg.min.js} +2 -2
- package/dist/needle-engine.js +3 -3
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/package.json +2 -2
- package/plugins/vite/build-pipeline.js +16 -2
- package/dist/gltf-progressive-BTd714P0.min.js +0 -9
- package/dist/gltf-progressive-CrHduHPm.umd.cjs +0 -9
- package/src/include/three/DragControls.js +0 -232
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
import { BufferGeometry as
|
|
2
|
-
import { DRACOLoader as
|
|
3
|
-
const
|
|
4
|
-
globalThis.GLTF_PROGRESSIVE_VERSION =
|
|
1
|
+
import { BufferGeometry as V, Mesh as X, Box3 as pe, Vector3 as A, Sphere as Se, CompressedTexture as Fe, Texture as F, Matrix3 as We, InterleavedBuffer as Ue, InterleavedBufferAttribute as ze, BufferAttribute as Ne, TextureLoader as qe, Matrix4 as Me, Clock as Ee, MeshStandardMaterial as Ve } from "./three-VvRoMeIN.js";
|
|
2
|
+
import { DRACOLoader as Xe, KTX2Loader as je, MeshoptDecoder as Ke, GLTFLoader as we } from "./three-examples-BhfOE7NG.js";
|
|
3
|
+
const Ye = "";
|
|
4
|
+
globalThis.GLTF_PROGRESSIVE_VERSION = Ye;
|
|
5
5
|
console.debug("[gltf-progressive] version -");
|
|
6
|
-
let
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
fetch(
|
|
6
|
+
let I = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", j = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
|
|
7
|
+
const He = I, Qe = j, Pe = new URL(I + "draco_decoder.js");
|
|
8
|
+
Pe.searchParams.append("range", "true");
|
|
9
|
+
fetch(Pe, {
|
|
10
10
|
method: "GET",
|
|
11
11
|
headers: {
|
|
12
12
|
Range: "bytes=0-1"
|
|
13
13
|
}
|
|
14
|
-
}).catch((
|
|
15
|
-
console.debug(`Failed to fetch remote Draco decoder from ${
|
|
14
|
+
}).catch((o) => {
|
|
15
|
+
console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), I === He && Ze("./include/draco/"), j === Qe && et("./include/ktx2/");
|
|
16
16
|
}).finally(() => {
|
|
17
|
-
|
|
17
|
+
Ce();
|
|
18
18
|
});
|
|
19
|
-
const
|
|
20
|
-
dracoDecoderPath:
|
|
21
|
-
ktx2TranscoderPath:
|
|
19
|
+
const Je = () => ({
|
|
20
|
+
dracoDecoderPath: I,
|
|
21
|
+
ktx2TranscoderPath: j
|
|
22
22
|
});
|
|
23
|
-
function
|
|
24
|
-
|
|
23
|
+
function Ze(o) {
|
|
24
|
+
I = o, C && C[me] != I ? (console.debug("Updating Draco decoder path to " + o), C[me] = I, C.setDecoderPath(I), C.preload()) : console.debug("Setting Draco decoder path to " + o);
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
26
|
+
function et(o) {
|
|
27
|
+
j = o, $ && $.transcoderPath != j ? (console.debug("Updating KTX2 transcoder path to " + o), $.setTranscoderPath(j), $.init()) : console.debug("Setting KTX2 transcoder path to " + o);
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
return
|
|
29
|
+
function Le(o) {
|
|
30
|
+
return Ce(), o ? $.detectSupport(o) : o !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: C, ktx2Loader: $, meshoptDecoder: ne };
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
32
|
+
function Te(o) {
|
|
33
|
+
o.dracoLoader || o.setDRACOLoader(C), o.ktx2Loader || o.setKTX2Loader($), o.meshoptDecoder || o.setMeshoptDecoder(ne);
|
|
34
34
|
}
|
|
35
|
-
const
|
|
36
|
-
let
|
|
37
|
-
function
|
|
38
|
-
|
|
35
|
+
const me = /* @__PURE__ */ Symbol("dracoDecoderPath");
|
|
36
|
+
let C, ne, $;
|
|
37
|
+
function Ce() {
|
|
38
|
+
C || (C = new Xe(), C[me] = I, C.setDecoderPath(I), C.setDecoderConfig({ type: "js" }), C.preload()), $ || ($ = new je(), $.setTranscoderPath(j), $.init()), ne || (ne = Ke);
|
|
39
39
|
}
|
|
40
|
-
const
|
|
41
|
-
function Ae(
|
|
42
|
-
let e =
|
|
43
|
-
e ? e = Object.assign(e, t) : e = t,
|
|
40
|
+
const ye = /* @__PURE__ */ new WeakMap();
|
|
41
|
+
function Ae(o, t) {
|
|
42
|
+
let e = ye.get(o);
|
|
43
|
+
e ? e = Object.assign(e, t) : e = t, ye.set(o, e);
|
|
44
44
|
}
|
|
45
|
-
const
|
|
46
|
-
function
|
|
47
|
-
const t =
|
|
48
|
-
let e =
|
|
45
|
+
const tt = we.prototype.load;
|
|
46
|
+
function st(...o) {
|
|
47
|
+
const t = ye.get(this);
|
|
48
|
+
let e = o[0];
|
|
49
49
|
const s = new URL(e, window.location.href);
|
|
50
50
|
if (s.hostname.endsWith("needle.tools")) {
|
|
51
|
-
const
|
|
52
|
-
|
|
51
|
+
const i = t?.progressive !== void 0 ? t.progressive : !0, n = t?.usecase ? t.usecase : "default";
|
|
52
|
+
i ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${n}` : this.requestHeader.Accept = `*/*;usecase=${n}`, e = s.toString();
|
|
53
53
|
}
|
|
54
|
-
return
|
|
54
|
+
return o[0] = e, tt?.call(this, ...o);
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
function
|
|
56
|
+
we.prototype.load = st;
|
|
57
|
+
N("debugprogressive");
|
|
58
|
+
function N(o) {
|
|
59
59
|
if (typeof window > "u") return !1;
|
|
60
|
-
const e = new URL(window.location.href).searchParams.get(
|
|
60
|
+
const e = new URL(window.location.href).searchParams.get(o);
|
|
61
61
|
return e == null || e === "0" || e === "false" ? !1 : e === "" ? !0 : e;
|
|
62
62
|
}
|
|
63
|
-
function
|
|
64
|
-
if (t === void 0 ||
|
|
63
|
+
function rt(o, t) {
|
|
64
|
+
if (t === void 0 || o === void 0 || t.startsWith("./") || t.startsWith("http") || t.startsWith("data:") || t.startsWith("blob:"))
|
|
65
65
|
return t;
|
|
66
|
-
const e =
|
|
66
|
+
const e = o.lastIndexOf("/");
|
|
67
67
|
if (e >= 0) {
|
|
68
|
-
const s =
|
|
68
|
+
const s = o.substring(0, e + 1);
|
|
69
69
|
for (; s.endsWith("/") && t.startsWith("/"); ) t = t.substring(1);
|
|
70
70
|
return s + t;
|
|
71
71
|
}
|
|
72
72
|
return t;
|
|
73
73
|
}
|
|
74
|
-
function
|
|
75
|
-
return
|
|
74
|
+
function ke() {
|
|
75
|
+
return H !== void 0 || (H = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", H)), H;
|
|
76
76
|
}
|
|
77
|
-
let
|
|
78
|
-
function
|
|
77
|
+
let H;
|
|
78
|
+
function ve() {
|
|
79
79
|
if (typeof window > "u") return !1;
|
|
80
|
-
const
|
|
81
|
-
return
|
|
80
|
+
const o = new URL(window.location.href), t = o.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o.hostname);
|
|
81
|
+
return o.hostname === "127.0.0.1" || t;
|
|
82
82
|
}
|
|
83
|
-
class
|
|
83
|
+
class it {
|
|
84
84
|
constructor(t = 100, e = {}) {
|
|
85
85
|
this.maxConcurrent = t, this.debug = e.debug ?? !1, window.requestAnimationFrame(this.tick);
|
|
86
86
|
}
|
|
@@ -107,87 +107,99 @@ class rt {
|
|
|
107
107
|
const t = this.maxConcurrent - this._running.size;
|
|
108
108
|
for (let e = 0; e < t && this._queue.length > 0; e++) {
|
|
109
109
|
this.debug && console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);
|
|
110
|
-
const { key: s, resolve:
|
|
111
|
-
|
|
112
|
-
use: (
|
|
110
|
+
const { key: s, resolve: r } = this._queue.shift();
|
|
111
|
+
r({
|
|
112
|
+
use: (i) => this.add(s, i)
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
return
|
|
117
|
+
function nt(o) {
|
|
118
|
+
const t = o.image?.width ?? 0, e = o.image?.height ?? 0, s = o.image?.depth ?? 1, r = Math.floor(Math.log2(Math.max(t, e, s))) + 1, i = ot(o);
|
|
119
|
+
return t * e * s * i * (1 - Math.pow(0.25, r)) / (1 - 0.25);
|
|
120
|
+
}
|
|
121
|
+
function ot(o) {
|
|
122
|
+
let t = 4;
|
|
123
|
+
const e = o.format;
|
|
124
|
+
e === 1024 || e === 1025 ? t = 1 : e === 1026 || e === 1027 ? t = 2 : e === 1022 || e === 1029 ? t = 3 : (e === 1023 || e === 1033) && (t = 4);
|
|
125
|
+
let s = 1;
|
|
126
|
+
const r = o.type;
|
|
127
|
+
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;
|
|
120
128
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
const at = typeof window > "u" && typeof document > "u", xe = /* @__PURE__ */ Symbol("needle:raycast-mesh");
|
|
130
|
+
function ee(o) {
|
|
131
|
+
return o?.[xe] instanceof V ? o[xe] : null;
|
|
132
|
+
}
|
|
133
|
+
function lt(o, t) {
|
|
134
|
+
if ((o.type === "Mesh" || o.type === "SkinnedMesh") && !ee(o)) {
|
|
135
|
+
const s = ct(t);
|
|
136
|
+
s.userData = { isRaycastMesh: !0 }, o[xe] = s;
|
|
125
137
|
}
|
|
126
138
|
}
|
|
127
|
-
function
|
|
128
|
-
if (
|
|
129
|
-
if (
|
|
130
|
-
const t =
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
let
|
|
134
|
-
|
|
139
|
+
function ut(o = !0) {
|
|
140
|
+
if (o) {
|
|
141
|
+
if (Q) return;
|
|
142
|
+
const t = Q = X.prototype.raycast;
|
|
143
|
+
X.prototype.raycast = function(e, s) {
|
|
144
|
+
const r = this, i = ee(r);
|
|
145
|
+
let n;
|
|
146
|
+
i && r.isMesh && (n = r.geometry, r.geometry = i), t.call(this, e, s), n && (r.geometry = n);
|
|
135
147
|
};
|
|
136
148
|
} else {
|
|
137
|
-
if (!
|
|
138
|
-
|
|
149
|
+
if (!Q) return;
|
|
150
|
+
X.prototype.raycast = Q, Q = null;
|
|
139
151
|
}
|
|
140
152
|
}
|
|
141
|
-
let
|
|
142
|
-
function
|
|
143
|
-
const t = new
|
|
144
|
-
for (const e in
|
|
145
|
-
t.setAttribute(e,
|
|
146
|
-
return t.setIndex(
|
|
153
|
+
let Q = null;
|
|
154
|
+
function ct(o) {
|
|
155
|
+
const t = new V();
|
|
156
|
+
for (const e in o.attributes)
|
|
157
|
+
t.setAttribute(e, o.getAttribute(e));
|
|
158
|
+
return t.setIndex(o.getIndex()), t;
|
|
147
159
|
}
|
|
148
|
-
const z = new Array(),
|
|
149
|
-
let
|
|
150
|
-
if (
|
|
151
|
-
let
|
|
160
|
+
const z = new Array(), f = N("debugprogressive");
|
|
161
|
+
let Z, E = -1;
|
|
162
|
+
if (f) {
|
|
163
|
+
let o = function() {
|
|
152
164
|
E += 1, E >= t && (E = -1), console.log(`Toggle LOD level [${E}]`);
|
|
153
165
|
}, t = 6;
|
|
154
166
|
window.addEventListener("keyup", (e) => {
|
|
155
|
-
e.key === "p" &&
|
|
167
|
+
e.key === "p" && o(), e.key === "w" && (Z = !Z, console.log(`Toggle wireframe [${Z}]`));
|
|
156
168
|
const s = parseInt(e.key);
|
|
157
169
|
!isNaN(s) && s >= 0 && (E = s, console.log(`Set LOD level to [${E}]`));
|
|
158
170
|
});
|
|
159
171
|
}
|
|
160
|
-
function
|
|
161
|
-
if (
|
|
162
|
-
if (Array.isArray(
|
|
163
|
-
for (const t of
|
|
164
|
-
|
|
165
|
-
else
|
|
172
|
+
function Re(o) {
|
|
173
|
+
if (f && Z !== void 0)
|
|
174
|
+
if (Array.isArray(o))
|
|
175
|
+
for (const t of o)
|
|
176
|
+
Re(t);
|
|
177
|
+
else o && "wireframe" in o && (o.wireframe = Z === !0);
|
|
166
178
|
}
|
|
167
|
-
const
|
|
168
|
-
let
|
|
169
|
-
const
|
|
170
|
-
function
|
|
171
|
-
if (
|
|
172
|
-
const s =
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
const t =
|
|
178
|
-
return
|
|
179
|
+
const J = new Array();
|
|
180
|
+
let dt = 0;
|
|
181
|
+
const ft = ke() ? 2 : 10;
|
|
182
|
+
function ht(o) {
|
|
183
|
+
if (J.length < ft) {
|
|
184
|
+
const s = J.length;
|
|
185
|
+
f && console.warn(`[Worker] Creating new worker #${s}`);
|
|
186
|
+
const r = _e.createWorker(o || {});
|
|
187
|
+
return J.push(r), r;
|
|
188
|
+
}
|
|
189
|
+
const t = dt++ % J.length;
|
|
190
|
+
return J[t];
|
|
179
191
|
}
|
|
180
|
-
class
|
|
192
|
+
class _e {
|
|
181
193
|
constructor(t, e) {
|
|
182
194
|
this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
|
|
183
|
-
const
|
|
184
|
-
switch (this._debug && console.log("[Worker] EVENT",
|
|
195
|
+
const r = s.data;
|
|
196
|
+
switch (this._debug && console.log("[Worker] EVENT", r), r.type) {
|
|
185
197
|
case "loaded-gltf":
|
|
186
|
-
for (const
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
198
|
+
for (const i of this._running)
|
|
199
|
+
if (i.url === r.result.url) {
|
|
200
|
+
gt(r.result), i.resolve(r.result);
|
|
201
|
+
const n = i.url;
|
|
202
|
+
n.startsWith("blob:") && URL.revokeObjectURL(n);
|
|
191
203
|
}
|
|
192
204
|
}
|
|
193
205
|
}, t.onerror = (s) => {
|
|
@@ -200,18 +212,18 @@ class Le {
|
|
|
200
212
|
const e = /* new-worker */ new Worker(URL.createObjectURL(new Blob(["import '" + `${new URL('./loader.worker-C1GG9A7C.js', import.meta.url).toString()}` + "';"], { type: 'text/javascript' })), {
|
|
201
213
|
type: "module"
|
|
202
214
|
});
|
|
203
|
-
return new
|
|
215
|
+
return new _e(e, t);
|
|
204
216
|
}
|
|
205
217
|
_running = [];
|
|
206
218
|
_webglRenderer = null;
|
|
207
219
|
async load(t, e) {
|
|
208
|
-
const s =
|
|
209
|
-
let
|
|
210
|
-
|
|
211
|
-
const { WebGLRenderer: u } = await import("./three-VvRoMeIN.js").then((
|
|
220
|
+
const s = Je();
|
|
221
|
+
let r = e?.renderer;
|
|
222
|
+
r || (this._webglRenderer ??= (async () => {
|
|
223
|
+
const { WebGLRenderer: u } = await import("./three-VvRoMeIN.js").then((c) => c.THREE);
|
|
212
224
|
return new u();
|
|
213
|
-
})(),
|
|
214
|
-
const l =
|
|
225
|
+
})(), r = await this._webglRenderer);
|
|
226
|
+
const l = Le(r).ktx2Loader.workerConfig;
|
|
215
227
|
t instanceof URL ? t = t.toString() : t.startsWith("file:") ? t = URL.createObjectURL(new Blob([t])) : !t.startsWith("blob:") && !t.startsWith("http:") && !t.startsWith("https:") && (t = new URL(t, window.location.href).toString());
|
|
216
228
|
const a = {
|
|
217
229
|
type: "load",
|
|
@@ -229,51 +241,51 @@ class Le {
|
|
|
229
241
|
}
|
|
230
242
|
_debug = !1;
|
|
231
243
|
}
|
|
232
|
-
function
|
|
233
|
-
for (const t of
|
|
234
|
-
const e = t.geometry, s = new
|
|
244
|
+
function gt(o) {
|
|
245
|
+
for (const t of o.geometries) {
|
|
246
|
+
const e = t.geometry, s = new V();
|
|
235
247
|
if (s.name = e.name || "", e.index) {
|
|
236
|
-
const
|
|
237
|
-
s.setIndex(
|
|
248
|
+
const r = e.index;
|
|
249
|
+
s.setIndex(ue(r));
|
|
238
250
|
}
|
|
239
|
-
for (const
|
|
240
|
-
const
|
|
241
|
-
s.setAttribute(
|
|
251
|
+
for (const r in e.attributes) {
|
|
252
|
+
const i = e.attributes[r], n = ue(i);
|
|
253
|
+
s.setAttribute(r, n);
|
|
242
254
|
}
|
|
243
255
|
if (e.morphAttributes)
|
|
244
|
-
for (const
|
|
245
|
-
const
|
|
246
|
-
s.morphAttributes[
|
|
256
|
+
for (const r in e.morphAttributes) {
|
|
257
|
+
const n = e.morphAttributes[r].map((l) => ue(l));
|
|
258
|
+
s.morphAttributes[r] = n;
|
|
247
259
|
}
|
|
248
|
-
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new
|
|
260
|
+
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new pe(), s.boundingBox.min = new A(
|
|
249
261
|
e.boundingBox?.min.x,
|
|
250
262
|
e.boundingBox?.min.y,
|
|
251
263
|
e.boundingBox?.min.z
|
|
252
|
-
), s.boundingBox.max = new
|
|
264
|
+
), s.boundingBox.max = new A(
|
|
253
265
|
e.boundingBox?.max.x,
|
|
254
266
|
e.boundingBox?.max.y,
|
|
255
267
|
e.boundingBox?.max.z
|
|
256
|
-
), s.boundingSphere = new
|
|
257
|
-
new
|
|
268
|
+
), s.boundingSphere = new Se(
|
|
269
|
+
new A(
|
|
258
270
|
e.boundingSphere?.center.x,
|
|
259
271
|
e.boundingSphere?.center.y,
|
|
260
272
|
e.boundingSphere?.center.z
|
|
261
273
|
),
|
|
262
274
|
e.boundingSphere?.radius
|
|
263
275
|
), e.groups)
|
|
264
|
-
for (const
|
|
265
|
-
s.addGroup(
|
|
276
|
+
for (const r of e.groups)
|
|
277
|
+
s.addGroup(r.start, r.count, r.materialIndex);
|
|
266
278
|
e.userData && (s.userData = e.userData), t.geometry = s;
|
|
267
279
|
}
|
|
268
|
-
for (const t of
|
|
280
|
+
for (const t of o.textures) {
|
|
269
281
|
const e = t.texture;
|
|
270
282
|
let s = null;
|
|
271
283
|
if (e.isCompressedTexture) {
|
|
272
|
-
const
|
|
273
|
-
s = new
|
|
274
|
-
n,
|
|
284
|
+
const r = e.mipmaps, i = e.image?.width || e.source?.data?.width || -1, n = e.image?.height || e.source?.data?.height || -1;
|
|
285
|
+
s = new Fe(
|
|
275
286
|
r,
|
|
276
|
-
|
|
287
|
+
i,
|
|
288
|
+
n,
|
|
277
289
|
e.format,
|
|
278
290
|
e.type,
|
|
279
291
|
e.mapping,
|
|
@@ -296,25 +308,27 @@ function ct(i) {
|
|
|
296
308
|
e.type,
|
|
297
309
|
e.anisotropy,
|
|
298
310
|
e.colorSpace
|
|
299
|
-
), 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
|
|
311
|
+
), 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 We(...e.matrix.elements);
|
|
300
312
|
if (!s) {
|
|
301
313
|
console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");
|
|
302
314
|
continue;
|
|
303
315
|
}
|
|
304
316
|
t.texture = s;
|
|
305
317
|
}
|
|
306
|
-
return
|
|
318
|
+
return o;
|
|
307
319
|
}
|
|
308
|
-
function
|
|
309
|
-
let t =
|
|
310
|
-
if ("isInterleavedBufferAttribute" in
|
|
311
|
-
const e =
|
|
312
|
-
t = new
|
|
313
|
-
} else "isBufferAttribute" in
|
|
320
|
+
function ue(o) {
|
|
321
|
+
let t = o;
|
|
322
|
+
if ("isInterleavedBufferAttribute" in o && o.isInterleavedBufferAttribute) {
|
|
323
|
+
const e = o.data, s = e.array, r = new Ue(s, e.stride);
|
|
324
|
+
t = new ze(r, o.itemSize, s.byteOffset, o.normalized), t.offset = o.offset;
|
|
325
|
+
} else "isBufferAttribute" in o && o.isBufferAttribute && (t = new Ne(o.array, o.itemSize, o.normalized), t.usage = o.usage, t.gpuType = o.gpuType, t.updateRanges = o.updateRanges);
|
|
314
326
|
return t;
|
|
315
327
|
}
|
|
316
|
-
const
|
|
317
|
-
|
|
328
|
+
const pt = N("gltf-progressive-worker");
|
|
329
|
+
N("gltf-progressive-reduce-mipmaps");
|
|
330
|
+
const K = N("gltf-progressive-gc"), ce = /* @__PURE__ */ Symbol("needle-progressive-texture"), W = "NEEDLE_progressive";
|
|
331
|
+
class y {
|
|
318
332
|
/** The name of the extension */
|
|
319
333
|
get name() {
|
|
320
334
|
return W;
|
|
@@ -329,8 +343,8 @@ class m {
|
|
|
329
343
|
return e ?? -1;
|
|
330
344
|
}
|
|
331
345
|
static getMaterialMinMaxLODsCount(t, e) {
|
|
332
|
-
const s = this,
|
|
333
|
-
if (
|
|
346
|
+
const s = this, r = "LODS:minmax", i = t[r];
|
|
347
|
+
if (i != null) return i;
|
|
334
348
|
if (e || (e = {
|
|
335
349
|
min_count: 1 / 0,
|
|
336
350
|
max_count: 0,
|
|
@@ -338,31 +352,31 @@ class m {
|
|
|
338
352
|
}), Array.isArray(t)) {
|
|
339
353
|
for (const l of t)
|
|
340
354
|
this.getMaterialMinMaxLODsCount(l, e);
|
|
341
|
-
return t[
|
|
355
|
+
return t[r] = e, e;
|
|
342
356
|
}
|
|
343
|
-
if (
|
|
357
|
+
if (f === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
|
|
344
358
|
const l = t;
|
|
345
359
|
for (const a of Object.keys(l.uniforms)) {
|
|
346
360
|
const u = l.uniforms[a].value;
|
|
347
|
-
u?.isTexture === !0 &&
|
|
361
|
+
u?.isTexture === !0 && n(u, e);
|
|
348
362
|
}
|
|
349
363
|
} else if (t.isMaterial)
|
|
350
364
|
for (const l of Object.keys(t)) {
|
|
351
365
|
const a = t[l];
|
|
352
|
-
a?.isTexture === !0 &&
|
|
366
|
+
a?.isTexture === !0 && n(a, e);
|
|
353
367
|
}
|
|
354
368
|
else
|
|
355
|
-
|
|
356
|
-
return t[
|
|
357
|
-
function
|
|
369
|
+
f && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
|
|
370
|
+
return t[r] = e, e;
|
|
371
|
+
function n(l, a) {
|
|
358
372
|
const u = s.getAssignedLODInformation(l);
|
|
359
373
|
if (u) {
|
|
360
|
-
const
|
|
361
|
-
if (
|
|
362
|
-
a.min_count = Math.min(a.min_count,
|
|
363
|
-
for (let
|
|
364
|
-
const w =
|
|
365
|
-
w.width && (a.lods[
|
|
374
|
+
const c = s.lodInfos.get(u.key);
|
|
375
|
+
if (c && c.lods) {
|
|
376
|
+
a.min_count = Math.min(a.min_count, c.lods.length), a.max_count = Math.max(a.max_count, c.lods.length);
|
|
377
|
+
for (let m = 0; m < c.lods.length; m++) {
|
|
378
|
+
const w = c.lods[m];
|
|
379
|
+
w.width && (a.lods[m] = a.lods[m] || { min_height: 1 / 0, max_height: 0 }, a.lods[m].min_height = Math.min(a.lods[m].min_height, w.height), a.lods[m].max_height = Math.max(a.lods[m].max_height, w.height));
|
|
366
380
|
}
|
|
367
381
|
}
|
|
368
382
|
}
|
|
@@ -375,28 +389,28 @@ class m {
|
|
|
375
389
|
*/
|
|
376
390
|
static hasLODLevelAvailable(t, e) {
|
|
377
391
|
if (Array.isArray(t)) {
|
|
378
|
-
for (const
|
|
379
|
-
if (this.hasLODLevelAvailable(
|
|
392
|
+
for (const i of t)
|
|
393
|
+
if (this.hasLODLevelAvailable(i, e)) return !0;
|
|
380
394
|
return !1;
|
|
381
395
|
}
|
|
382
396
|
if (t.isMaterial === !0) {
|
|
383
|
-
for (const
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
397
|
+
for (const i of Object.keys(t)) {
|
|
398
|
+
const n = t[i];
|
|
399
|
+
if (n && n.isTexture && this.hasLODLevelAvailable(n, e))
|
|
386
400
|
return !0;
|
|
387
401
|
}
|
|
388
402
|
return !1;
|
|
389
403
|
} else if (t.isGroup === !0) {
|
|
390
|
-
for (const
|
|
391
|
-
if (
|
|
404
|
+
for (const i of t.children)
|
|
405
|
+
if (i.isMesh === !0 && this.hasLODLevelAvailable(i, e))
|
|
392
406
|
return !0;
|
|
393
407
|
}
|
|
394
|
-
let s,
|
|
408
|
+
let s, r;
|
|
395
409
|
if (t.isMesh ? s = t.geometry : (t.isBufferGeometry || t.isTexture) && (s = t), s && s?.userData?.LODS) {
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
398
|
-
if (
|
|
399
|
-
return Array.isArray(
|
|
410
|
+
const i = s.userData.LODS;
|
|
411
|
+
if (r = this.lodInfos.get(i.key), e === void 0) return r != null;
|
|
412
|
+
if (r)
|
|
413
|
+
return Array.isArray(r.lods) ? e < r.lods.length : e === 0;
|
|
400
414
|
}
|
|
401
415
|
return !1;
|
|
402
416
|
}
|
|
@@ -416,20 +430,20 @@ class m {
|
|
|
416
430
|
*/
|
|
417
431
|
static assignMeshLOD(t, e) {
|
|
418
432
|
if (!t) return Promise.resolve(null);
|
|
419
|
-
if (t instanceof
|
|
420
|
-
const s = t.geometry,
|
|
421
|
-
if (!
|
|
433
|
+
if (t instanceof X || t.isMesh === !0) {
|
|
434
|
+
const s = t.geometry, r = this.getAssignedLODInformation(s);
|
|
435
|
+
if (!r)
|
|
422
436
|
return Promise.resolve(null);
|
|
423
|
-
for (const
|
|
424
|
-
|
|
425
|
-
return t["LOD:requested level"] = e,
|
|
426
|
-
if (Array.isArray(
|
|
427
|
-
const
|
|
428
|
-
|
|
437
|
+
for (const i of z)
|
|
438
|
+
i.onBeforeGetLODMesh?.(t, e);
|
|
439
|
+
return t["LOD:requested level"] = e, y.getOrLoadLOD(s, e).then((i) => {
|
|
440
|
+
if (Array.isArray(i)) {
|
|
441
|
+
const n = r.index || 0;
|
|
442
|
+
i = i[n];
|
|
429
443
|
}
|
|
430
|
-
return t["LOD:requested level"] === e && (delete t["LOD:requested level"],
|
|
431
|
-
}).catch((
|
|
432
|
-
} else
|
|
444
|
+
return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i : f && console.error("Invalid LOD geometry", i))), i;
|
|
445
|
+
}).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
|
|
446
|
+
} else f && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
433
447
|
return Promise.resolve(null);
|
|
434
448
|
}
|
|
435
449
|
static assignTextureLOD(t, e = 0) {
|
|
@@ -437,44 +451,44 @@ class m {
|
|
|
437
451
|
if (t.isMesh === !0) {
|
|
438
452
|
const s = t;
|
|
439
453
|
if (Array.isArray(s.material)) {
|
|
440
|
-
const
|
|
441
|
-
for (const
|
|
442
|
-
const
|
|
443
|
-
|
|
454
|
+
const r = new Array();
|
|
455
|
+
for (const i of s.material) {
|
|
456
|
+
const n = this.assignTextureLOD(i, e);
|
|
457
|
+
r.push(n);
|
|
444
458
|
}
|
|
445
|
-
return Promise.all(
|
|
446
|
-
const
|
|
447
|
-
for (const l of
|
|
448
|
-
Array.isArray(l) &&
|
|
449
|
-
return
|
|
459
|
+
return Promise.all(r).then((i) => {
|
|
460
|
+
const n = new Array();
|
|
461
|
+
for (const l of i)
|
|
462
|
+
Array.isArray(l) && n.push(...l);
|
|
463
|
+
return n;
|
|
450
464
|
});
|
|
451
465
|
} else
|
|
452
466
|
return this.assignTextureLOD(s.material, e);
|
|
453
467
|
}
|
|
454
468
|
if (t.isMaterial === !0) {
|
|
455
|
-
const s = t,
|
|
469
|
+
const s = t, r = [], i = new Array();
|
|
456
470
|
if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
|
457
|
-
const
|
|
458
|
-
for (const l of Object.keys(
|
|
459
|
-
const a =
|
|
471
|
+
const n = s;
|
|
472
|
+
for (const l of Object.keys(n.uniforms)) {
|
|
473
|
+
const a = n.uniforms[l].value;
|
|
460
474
|
if (a?.isTexture === !0) {
|
|
461
|
-
const u = this.assignTextureLODForSlot(a, e, s, l).then((
|
|
462
|
-
|
|
475
|
+
const u = this.assignTextureLODForSlot(a, e, s, l).then((c) => (c && n.uniforms[l].value != c && (n.uniforms[l].value = c, n.uniformsNeedUpdate = !0), c));
|
|
476
|
+
r.push(u), i.push(l);
|
|
463
477
|
}
|
|
464
478
|
}
|
|
465
479
|
} else
|
|
466
|
-
for (const
|
|
467
|
-
const l = s[
|
|
480
|
+
for (const n of Object.keys(s)) {
|
|
481
|
+
const l = s[n];
|
|
468
482
|
if (l?.isTexture === !0) {
|
|
469
|
-
const a = this.assignTextureLODForSlot(l, e, s,
|
|
470
|
-
|
|
483
|
+
const a = this.assignTextureLODForSlot(l, e, s, n);
|
|
484
|
+
r.push(a), i.push(n);
|
|
471
485
|
}
|
|
472
486
|
}
|
|
473
|
-
return Promise.all(
|
|
487
|
+
return Promise.all(r).then((n) => {
|
|
474
488
|
const l = new Array();
|
|
475
|
-
for (let a = 0; a <
|
|
476
|
-
const u =
|
|
477
|
-
u && u.isTexture === !0 ? l.push({ material: s, slot:
|
|
489
|
+
for (let a = 0; a < n.length; a++) {
|
|
490
|
+
const u = n[a], c = i[a];
|
|
491
|
+
u && u.isTexture === !0 ? l.push({ material: s, slot: c, texture: u, level: e }) : l.push({ material: s, slot: c, texture: null, level: e });
|
|
478
492
|
}
|
|
479
493
|
return l;
|
|
480
494
|
});
|
|
@@ -486,40 +500,40 @@ class m {
|
|
|
486
500
|
return Promise.resolve(null);
|
|
487
501
|
}
|
|
488
502
|
// #region INTERNAL
|
|
489
|
-
static assignTextureLODForSlot(t, e, s,
|
|
490
|
-
return t?.isTexture !== !0 ? Promise.resolve(null) :
|
|
491
|
-
if (Array.isArray(
|
|
503
|
+
static assignTextureLODForSlot(t, e, s, r) {
|
|
504
|
+
return t?.isTexture !== !0 ? Promise.resolve(null) : r === "glyphMap" ? Promise.resolve(t) : y.getOrLoadLOD(t, e).then((i) => {
|
|
505
|
+
if (Array.isArray(i))
|
|
492
506
|
return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."), null;
|
|
493
|
-
if (
|
|
494
|
-
if (
|
|
495
|
-
const
|
|
496
|
-
if (
|
|
497
|
-
const l = this.getAssignedLODInformation(
|
|
507
|
+
if (i?.isTexture === !0) {
|
|
508
|
+
if (i != t && s && r) {
|
|
509
|
+
const n = s[r];
|
|
510
|
+
if (n && !f) {
|
|
511
|
+
const l = this.getAssignedLODInformation(n);
|
|
498
512
|
if (l && l?.level < e)
|
|
499
|
-
return
|
|
513
|
+
return f === "verbose" && console.warn("Assigned texture level is already higher: ", l.level, e, s, n, i), i && i !== n && ((f || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${l.level})`, i.uuid), i.dispose()), null;
|
|
500
514
|
}
|
|
501
|
-
if (
|
|
502
|
-
const
|
|
503
|
-
|
|
515
|
+
if (this.trackTextureUsage(i), n && n !== i && this.untrackTextureUsage(n) && (f || K)) {
|
|
516
|
+
const a = this.getAssignedLODInformation(n);
|
|
517
|
+
console.log(`[gltf-progressive] Disposed old texture LOD ${a?.level ?? "?"} → ${e} for ${s.name || s.type}.${r}`, n.uuid);
|
|
504
518
|
}
|
|
505
|
-
s[
|
|
519
|
+
s[r] = i;
|
|
506
520
|
}
|
|
507
|
-
return
|
|
508
|
-
} else
|
|
521
|
+
return i;
|
|
522
|
+
} else f == "verbose" && console.warn("No LOD found for", t, e);
|
|
509
523
|
return null;
|
|
510
|
-
}).catch((
|
|
524
|
+
}).catch((i) => (console.error("Error loading LOD", t, i), null));
|
|
511
525
|
}
|
|
512
526
|
parser;
|
|
513
527
|
url;
|
|
514
528
|
constructor(t) {
|
|
515
529
|
const e = t.options.path;
|
|
516
|
-
|
|
530
|
+
f && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
|
|
517
531
|
}
|
|
518
532
|
_isLoadingMesh;
|
|
519
533
|
loadMesh = (t) => {
|
|
520
534
|
if (this._isLoadingMesh) return null;
|
|
521
535
|
const e = this.parser.json.meshes[t]?.extensions?.[W];
|
|
522
|
-
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s &&
|
|
536
|
+
return e ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", t).then((s) => (this._isLoadingMesh = !1, s && y.registerMesh(this.url, e.guid, s, e.lods?.length, 0, e), s))) : null;
|
|
523
537
|
};
|
|
524
538
|
// private _isLoadingTexture;
|
|
525
539
|
// loadTexture = (textureIndex: number) => {
|
|
@@ -536,30 +550,30 @@ class m {
|
|
|
536
550
|
// });
|
|
537
551
|
// }
|
|
538
552
|
afterRoot(t) {
|
|
539
|
-
return
|
|
553
|
+
return f && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
|
|
540
554
|
if (e?.extensions) {
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
543
|
-
if (!
|
|
544
|
-
|
|
555
|
+
const r = e?.extensions[W];
|
|
556
|
+
if (r) {
|
|
557
|
+
if (!r.lods) {
|
|
558
|
+
f && console.warn("Texture has no LODs", r);
|
|
545
559
|
return;
|
|
546
560
|
}
|
|
547
|
-
let
|
|
548
|
-
for (const
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
561
|
+
let i = !1;
|
|
562
|
+
for (const n of this.parser.associations.keys())
|
|
563
|
+
n.isTexture === !0 && this.parser.associations.get(n)?.textures === s && (i = !0, y.registerTexture(this.url, n, r.lods?.length, s, r));
|
|
564
|
+
i || this.parser.getDependency("texture", s).then((n) => {
|
|
565
|
+
n && y.registerTexture(this.url, n, r.lods?.length, s, r);
|
|
552
566
|
});
|
|
553
567
|
}
|
|
554
568
|
}
|
|
555
569
|
}), this.parser.json.meshes?.forEach((e, s) => {
|
|
556
570
|
if (e?.extensions) {
|
|
557
|
-
const
|
|
558
|
-
if (
|
|
559
|
-
for (const
|
|
560
|
-
if (
|
|
561
|
-
const
|
|
562
|
-
|
|
571
|
+
const r = e?.extensions[W];
|
|
572
|
+
if (r && r.lods) {
|
|
573
|
+
for (const i of this.parser.associations.keys())
|
|
574
|
+
if (i.isMesh) {
|
|
575
|
+
const n = this.parser.associations.get(i);
|
|
576
|
+
n?.meshes === s && y.registerMesh(this.url, r.guid, i, r.lods.length, n.primitives, r);
|
|
563
577
|
}
|
|
564
578
|
}
|
|
565
579
|
}
|
|
@@ -568,38 +582,39 @@ class m {
|
|
|
568
582
|
/**
|
|
569
583
|
* Register a texture with LOD information
|
|
570
584
|
*/
|
|
571
|
-
static registerTexture = (t, e, s,
|
|
585
|
+
static registerTexture = (t, e, s, r, i) => {
|
|
572
586
|
if (!e) {
|
|
573
|
-
|
|
587
|
+
f && console.error("!! gltf-progressive: Called register texture without texture");
|
|
574
588
|
return;
|
|
575
589
|
}
|
|
576
|
-
if (
|
|
590
|
+
if (f) {
|
|
577
591
|
const l = e.image?.width || e.source?.data?.width || 0, a = e.image?.height || e.source?.data?.height || 0;
|
|
578
|
-
console.log(`> gltf-progressive: register texture[${
|
|
592
|
+
console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${l}x${a}, Max: ${i.lods[0]?.width}x${i.lods[0]?.height}, uuid: ${e.uuid}`, i, e);
|
|
579
593
|
}
|
|
580
|
-
e.source && (e.source[
|
|
581
|
-
const
|
|
582
|
-
|
|
594
|
+
e.source && (e.source[ce] = i);
|
|
595
|
+
const n = i.guid;
|
|
596
|
+
y.assignLODInformation(t, e, n, s, r), y.lodInfos.set(n, i), y.lowresCache.set(n, new WeakRef(e));
|
|
583
597
|
};
|
|
584
598
|
/**
|
|
585
599
|
* Register a mesh with LOD information
|
|
586
600
|
*/
|
|
587
|
-
static registerMesh = (t, e, s,
|
|
601
|
+
static registerMesh = (t, e, s, r, i, n) => {
|
|
588
602
|
const l = s.geometry;
|
|
589
603
|
if (!l) {
|
|
590
|
-
|
|
604
|
+
f && console.warn("gltf-progressive: Register mesh without geometry");
|
|
591
605
|
return;
|
|
592
606
|
}
|
|
593
|
-
l.userData || (l.userData = {}),
|
|
594
|
-
let u =
|
|
595
|
-
u ? u.push(s.geometry) : u = [s.geometry],
|
|
596
|
-
for (const
|
|
597
|
-
|
|
607
|
+
l.userData || (l.userData = {}), f && console.log("> Progressive: register mesh " + s.name, { index: i, uuid: s.uuid }, n, s), y.assignLODInformation(t, l, e, r, i), y.lodInfos.set(e, n);
|
|
608
|
+
let u = y.lowresCache.get(e)?.deref();
|
|
609
|
+
u ? u.push(s.geometry) : u = [s.geometry], y.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && lt(s, l);
|
|
610
|
+
for (const c of z)
|
|
611
|
+
c.onRegisteredNewMesh?.(s, n);
|
|
598
612
|
};
|
|
599
613
|
/**
|
|
600
614
|
* Dispose cached resources to free memory.
|
|
601
615
|
* Call this when a model is removed from the scene to allow garbage collection of its LOD resources.
|
|
602
616
|
* Calls three.js `.dispose()` on cached Textures and BufferGeometries to free GPU memory.
|
|
617
|
+
* Also clears reference counts for disposed textures.
|
|
603
618
|
* @param guid Optional GUID to dispose resources for a specific model. If omitted, all cached resources are cleared.
|
|
604
619
|
*/
|
|
605
620
|
static dispose(t) {
|
|
@@ -609,42 +624,48 @@ class m {
|
|
|
609
624
|
if (e) {
|
|
610
625
|
const s = e.deref();
|
|
611
626
|
if (s) {
|
|
612
|
-
if (s.isTexture)
|
|
613
|
-
s
|
|
614
|
-
|
|
615
|
-
|
|
627
|
+
if (s.isTexture) {
|
|
628
|
+
const r = s;
|
|
629
|
+
this.textureRefCounts.delete(r.uuid), r.dispose();
|
|
630
|
+
} else if (Array.isArray(s))
|
|
631
|
+
for (const r of s) r.dispose();
|
|
616
632
|
}
|
|
617
633
|
this.lowresCache.delete(t);
|
|
618
634
|
}
|
|
619
|
-
for (const [s,
|
|
620
|
-
s.includes(t) && (this._disposeCacheEntry(
|
|
635
|
+
for (const [s, r] of this.cache)
|
|
636
|
+
s.includes(t) && (this._disposeCacheEntry(r), this.cache.delete(s));
|
|
621
637
|
} else {
|
|
622
638
|
this.lodInfos.clear();
|
|
623
639
|
for (const [, e] of this.lowresCache) {
|
|
624
640
|
const s = e.deref();
|
|
625
641
|
if (s) {
|
|
626
|
-
if (s.isTexture)
|
|
627
|
-
s
|
|
628
|
-
|
|
629
|
-
|
|
642
|
+
if (s.isTexture) {
|
|
643
|
+
const r = s;
|
|
644
|
+
this.textureRefCounts.delete(r.uuid), r.dispose();
|
|
645
|
+
} else if (Array.isArray(s))
|
|
646
|
+
for (const r of s) r.dispose();
|
|
630
647
|
}
|
|
631
648
|
}
|
|
632
649
|
this.lowresCache.clear();
|
|
633
650
|
for (const [, e] of this.cache)
|
|
634
651
|
this._disposeCacheEntry(e);
|
|
635
|
-
this.cache.clear();
|
|
652
|
+
this.cache.clear(), this.textureRefCounts.clear();
|
|
636
653
|
}
|
|
637
654
|
}
|
|
638
655
|
/** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
|
|
639
656
|
static _disposeCacheEntry(t) {
|
|
640
|
-
t instanceof WeakRef
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
657
|
+
if (t instanceof WeakRef) {
|
|
658
|
+
const e = t.deref();
|
|
659
|
+
e && (e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose());
|
|
660
|
+
} else
|
|
661
|
+
t.then((e) => {
|
|
662
|
+
if (e)
|
|
663
|
+
if (Array.isArray(e))
|
|
664
|
+
for (const s of e) s.dispose();
|
|
665
|
+
else
|
|
666
|
+
e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose();
|
|
667
|
+
}).catch(() => {
|
|
668
|
+
});
|
|
648
669
|
}
|
|
649
670
|
/** A map of key = asset uuid and value = LOD information */
|
|
650
671
|
static lodInfos = /* @__PURE__ */ new Map();
|
|
@@ -652,107 +673,137 @@ class m {
|
|
|
652
673
|
static cache = /* @__PURE__ */ new Map();
|
|
653
674
|
/** this contains the geometry/textures that were originally loaded. Uses WeakRef to allow garbage collection when unused. */
|
|
654
675
|
static lowresCache = /* @__PURE__ */ new Map();
|
|
676
|
+
/** Reference counting for textures to track usage across multiple materials/objects */
|
|
677
|
+
static textureRefCounts = /* @__PURE__ */ new Map();
|
|
655
678
|
/**
|
|
656
679
|
* FinalizationRegistry to automatically clean up `previouslyLoaded` cache entries
|
|
657
680
|
* when their associated three.js resources are garbage collected by the browser.
|
|
658
681
|
* The held value is the cache key string used in `previouslyLoaded`.
|
|
659
682
|
*/
|
|
660
683
|
static _resourceRegistry = new FinalizationRegistry((t) => {
|
|
661
|
-
const e =
|
|
662
|
-
|
|
663
|
-
${t}`), e instanceof WeakRef && (e.deref() || (
|
|
684
|
+
const e = y.cache.get(t);
|
|
685
|
+
(f || K) && console.debug(`[gltf-progressive] Memory: Resource GC'd
|
|
686
|
+
${t}`), e instanceof WeakRef && (e.deref() || (y.cache.delete(t), (f || K) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
|
|
664
687
|
});
|
|
688
|
+
/**
|
|
689
|
+
* Track texture usage by incrementing reference count
|
|
690
|
+
*/
|
|
691
|
+
static trackTextureUsage(t) {
|
|
692
|
+
const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
|
|
693
|
+
this.textureRefCounts.set(e, s + 1), f === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Untrack texture usage by decrementing reference count.
|
|
697
|
+
* Automatically disposes the texture when reference count reaches zero.
|
|
698
|
+
* @returns true if the texture was disposed, false otherwise
|
|
699
|
+
*/
|
|
700
|
+
static untrackTextureUsage(t) {
|
|
701
|
+
const e = t.uuid, s = this.textureRefCounts.get(e);
|
|
702
|
+
if (!s)
|
|
703
|
+
return (f === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
|
|
704
|
+
const r = s - 1;
|
|
705
|
+
if (r <= 0)
|
|
706
|
+
return this.textureRefCounts.delete(e), (f || K) && i("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
|
|
707
|
+
return this.textureRefCounts.set(e, r), f === "verbose" && i("[gltf-progressive] Memory: Untrack texture", r), !1;
|
|
708
|
+
function i(n, l) {
|
|
709
|
+
let a = t.image?.width || t.source?.data?.width || 0, u = t.image?.height || t.source?.data?.height || 0;
|
|
710
|
+
const c = a && u ? `${a}x${u}` : "N/A";
|
|
711
|
+
let m = "N/A";
|
|
712
|
+
a && u && (m = `~${(nt(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${n} — ${t.name} ${c} (${m}), refCount: ${s} → ${l}
|
|
713
|
+
${e}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
665
716
|
static workers = [];
|
|
666
717
|
static _workersIndex = 0;
|
|
667
718
|
static async getOrLoadLOD(t, e) {
|
|
668
|
-
const s =
|
|
669
|
-
if (!
|
|
670
|
-
return
|
|
671
|
-
const
|
|
672
|
-
let
|
|
719
|
+
const s = f == "verbose", r = this.getAssignedLODInformation(t);
|
|
720
|
+
if (!r)
|
|
721
|
+
return f && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
|
|
722
|
+
const i = r?.key;
|
|
723
|
+
let n;
|
|
673
724
|
if (t.isTexture === !0) {
|
|
674
725
|
const a = t;
|
|
675
|
-
a.source && a.source[
|
|
726
|
+
a.source && a.source[ce] && (n = a.source[ce]);
|
|
676
727
|
}
|
|
677
|
-
if (
|
|
678
|
-
|
|
728
|
+
if (n || (n = y.lodInfos.get(i)), !n)
|
|
729
|
+
f && console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`, t.type, y.lodInfos);
|
|
679
730
|
else {
|
|
680
731
|
if (e > 0) {
|
|
681
|
-
let
|
|
682
|
-
const
|
|
683
|
-
if (
|
|
684
|
-
const w = this.lowresCache.get(
|
|
732
|
+
let c = !1;
|
|
733
|
+
const m = Array.isArray(n.lods);
|
|
734
|
+
if (m && e >= n.lods.length ? c = !0 : m || (c = !0), c) {
|
|
735
|
+
const w = this.lowresCache.get(i);
|
|
685
736
|
if (w) {
|
|
686
737
|
const L = w.deref();
|
|
687
738
|
if (L) return L;
|
|
688
|
-
this.lowresCache.delete(
|
|
739
|
+
this.lowresCache.delete(i), f && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${i}`);
|
|
689
740
|
}
|
|
690
741
|
return null;
|
|
691
742
|
}
|
|
692
743
|
}
|
|
693
|
-
const a = Array.isArray(
|
|
744
|
+
const a = Array.isArray(n.lods) ? n.lods[e]?.path : n.lods;
|
|
694
745
|
if (!a)
|
|
695
|
-
return
|
|
696
|
-
const u =
|
|
746
|
+
return f && !n["missing:uri"] && (n["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, n)), null;
|
|
747
|
+
const u = rt(r.url, a);
|
|
697
748
|
if (u.endsWith(".glb") || u.endsWith(".gltf")) {
|
|
698
|
-
if (!
|
|
699
|
-
return console.warn("missing pointer for glb/gltf texture",
|
|
700
|
-
const
|
|
749
|
+
if (!n.guid)
|
|
750
|
+
return console.warn("missing pointer for glb/gltf texture", n), null;
|
|
751
|
+
const c = u + "_" + n.guid, m = await this.queue.slot(u), w = this.cache.get(c);
|
|
701
752
|
if (w !== void 0)
|
|
702
|
-
if (s && console.log(`LOD ${e} was already loading/loaded: ${
|
|
703
|
-
const
|
|
704
|
-
if (
|
|
705
|
-
let g =
|
|
706
|
-
if (g instanceof F && t instanceof F ? g.image?.data || g.source?.data ? g = this.copySettings(t, g) : M = !0 : g instanceof
|
|
753
|
+
if (s && console.log(`LOD ${e} was already loading/loaded: ${c}`), w instanceof WeakRef) {
|
|
754
|
+
const d = w.deref();
|
|
755
|
+
if (d) {
|
|
756
|
+
let g = d, M = !1;
|
|
757
|
+
if (g instanceof F && t instanceof F ? g.image?.data || g.source?.data ? g = this.copySettings(t, g) : M = !0 : g instanceof V && t instanceof V && (g.attributes.position?.array || (M = !0)), !M)
|
|
707
758
|
return g;
|
|
708
759
|
}
|
|
709
|
-
this.cache.delete(
|
|
760
|
+
this.cache.delete(c), f && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${c}`);
|
|
710
761
|
} else {
|
|
711
|
-
let
|
|
762
|
+
let d = await w.catch((M) => (console.error(`Error loading LOD ${e} from ${u}
|
|
712
763
|
`, M), null)), g = !1;
|
|
713
|
-
if (
|
|
714
|
-
return
|
|
764
|
+
if (d == null || (d instanceof F && t instanceof F ? d.image?.data || d.source?.data ? d = this.copySettings(t, d) : (g = !0, this.cache.delete(c)) : d instanceof V && t instanceof V && (d.attributes.position?.array || (g = !0, this.cache.delete(c)))), !g)
|
|
765
|
+
return d;
|
|
715
766
|
}
|
|
716
|
-
if (!
|
|
717
|
-
return
|
|
718
|
-
const L =
|
|
719
|
-
if (
|
|
720
|
-
const x = await (await
|
|
767
|
+
if (!m.use)
|
|
768
|
+
return f && console.log(`LOD ${e} was aborted: ${u}`), null;
|
|
769
|
+
const L = n, k = new Promise(async (d, g) => {
|
|
770
|
+
if (pt) {
|
|
771
|
+
const x = await (await ht({})).load(u);
|
|
721
772
|
if (x.textures.length > 0)
|
|
722
|
-
for (const
|
|
723
|
-
let p =
|
|
724
|
-
return
|
|
773
|
+
for (const h of x.textures) {
|
|
774
|
+
let p = h.texture;
|
|
775
|
+
return y.assignLODInformation(r.url, p, i, e, void 0), t instanceof F && (p = this.copySettings(t, p)), p && (p.guid = L.guid), d(p);
|
|
725
776
|
}
|
|
726
777
|
if (x.geometries.length > 0) {
|
|
727
|
-
const
|
|
778
|
+
const h = new Array();
|
|
728
779
|
for (const p of x.geometries) {
|
|
729
|
-
const
|
|
730
|
-
|
|
780
|
+
const b = p.geometry;
|
|
781
|
+
y.assignLODInformation(r.url, b, i, e, p.primitiveIndex), h.push(b);
|
|
731
782
|
}
|
|
732
|
-
return
|
|
783
|
+
return d(h);
|
|
733
784
|
}
|
|
734
|
-
return
|
|
785
|
+
return d(null);
|
|
735
786
|
}
|
|
736
|
-
const M = new
|
|
737
|
-
|
|
787
|
+
const M = new we();
|
|
788
|
+
Te(M), f && (await new Promise((_) => setTimeout(_, 1e3)), s && console.warn("Start loading (delayed) " + u, L.guid));
|
|
738
789
|
let B = u;
|
|
739
790
|
if (L && Array.isArray(L.lods)) {
|
|
740
791
|
const _ = L.lods[e];
|
|
741
792
|
_.hash && (B += "?v=" + _.hash);
|
|
742
793
|
}
|
|
743
|
-
const
|
|
744
|
-
`, _),
|
|
745
|
-
if (!
|
|
746
|
-
return
|
|
747
|
-
const
|
|
794
|
+
const D = await M.loadAsync(B).catch((_) => (console.error(`Error loading LOD ${e} from ${u}
|
|
795
|
+
`, _), d(null)));
|
|
796
|
+
if (!D)
|
|
797
|
+
return d(null);
|
|
798
|
+
const q = D.parser;
|
|
748
799
|
s && console.log("Loading finished " + u, L.guid);
|
|
749
800
|
let P = 0;
|
|
750
|
-
if (
|
|
801
|
+
if (D.parser.json.textures) {
|
|
751
802
|
let _ = !1;
|
|
752
|
-
for (const x of
|
|
803
|
+
for (const x of D.parser.json.textures) {
|
|
753
804
|
if (x?.extensions) {
|
|
754
|
-
const
|
|
755
|
-
if (
|
|
805
|
+
const h = x?.extensions[W];
|
|
806
|
+
if (h?.guid && h.guid === L.guid) {
|
|
756
807
|
_ = !0;
|
|
757
808
|
break;
|
|
758
809
|
}
|
|
@@ -760,16 +811,16 @@ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), h && console.l
|
|
|
760
811
|
P++;
|
|
761
812
|
}
|
|
762
813
|
if (_) {
|
|
763
|
-
let x = await
|
|
764
|
-
return x &&
|
|
765
|
-
} else
|
|
814
|
+
let x = await q.getDependency("texture", P);
|
|
815
|
+
return x && y.assignLODInformation(r.url, x, i, e, void 0), s && console.log('change "' + t.name + '" → "' + x.name + '"', u, P, x, c), t instanceof F && (x = this.copySettings(t, x)), x && (x.guid = L.guid), d(x);
|
|
816
|
+
} else f && console.warn("Could not find texture with guid", L.guid, D.parser.json);
|
|
766
817
|
}
|
|
767
|
-
if (P = 0,
|
|
818
|
+
if (P = 0, D.parser.json.meshes) {
|
|
768
819
|
let _ = !1;
|
|
769
|
-
for (const x of
|
|
820
|
+
for (const x of D.parser.json.meshes) {
|
|
770
821
|
if (x?.extensions) {
|
|
771
|
-
const
|
|
772
|
-
if (
|
|
822
|
+
const h = x?.extensions[W];
|
|
823
|
+
if (h?.guid && h.guid === L.guid) {
|
|
773
824
|
_ = !0;
|
|
774
825
|
break;
|
|
775
826
|
}
|
|
@@ -777,69 +828,69 @@ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), h && console.l
|
|
|
777
828
|
P++;
|
|
778
829
|
}
|
|
779
830
|
if (_) {
|
|
780
|
-
const x = await
|
|
781
|
-
if (s && console.log(`Loaded Mesh "${x.name}"`, u, P, x,
|
|
782
|
-
const
|
|
783
|
-
return
|
|
831
|
+
const x = await q.getDependency("mesh", P);
|
|
832
|
+
if (s && console.log(`Loaded Mesh "${x.name}"`, u, P, x, c), x.isMesh === !0) {
|
|
833
|
+
const h = x.geometry;
|
|
834
|
+
return y.assignLODInformation(r.url, h, i, e, 0), d(h);
|
|
784
835
|
} else {
|
|
785
|
-
const
|
|
836
|
+
const h = new Array();
|
|
786
837
|
for (let p = 0; p < x.children.length; p++) {
|
|
787
|
-
const
|
|
788
|
-
if (
|
|
789
|
-
const S =
|
|
790
|
-
|
|
838
|
+
const b = x.children[p];
|
|
839
|
+
if (b.isMesh === !0) {
|
|
840
|
+
const S = b.geometry;
|
|
841
|
+
y.assignLODInformation(r.url, S, i, e, p), h.push(S);
|
|
791
842
|
}
|
|
792
843
|
}
|
|
793
|
-
return
|
|
844
|
+
return d(h);
|
|
794
845
|
}
|
|
795
|
-
} else
|
|
846
|
+
} else f && console.warn("Could not find mesh with guid", L.guid, D.parser.json);
|
|
796
847
|
}
|
|
797
|
-
return
|
|
848
|
+
return d(null);
|
|
798
849
|
});
|
|
799
|
-
this.cache.set(
|
|
850
|
+
this.cache.set(c, k), m.use(k);
|
|
800
851
|
const v = await k;
|
|
801
|
-
return v != null ? v instanceof F ? (this.cache.set(
|
|
852
|
+
return v != null ? v instanceof F ? (this.cache.set(c, new WeakRef(v)), y._resourceRegistry.register(v, c)) : Array.isArray(v) ? this.cache.set(c, Promise.resolve(v)) : this.cache.set(c, Promise.resolve(v)) : this.cache.set(c, Promise.resolve(null)), v;
|
|
802
853
|
} else if (t instanceof F) {
|
|
803
854
|
s && console.log("Load texture from uri: " + u);
|
|
804
|
-
const
|
|
805
|
-
return
|
|
855
|
+
const m = await new qe().loadAsync(u);
|
|
856
|
+
return m ? (m.guid = n.guid, m.flipY = !1, m.needsUpdate = !0, m.colorSpace = t.colorSpace, s && console.log(n, m)) : f && console.warn("failed loading", u), m;
|
|
806
857
|
}
|
|
807
858
|
}
|
|
808
859
|
return null;
|
|
809
860
|
}
|
|
810
861
|
static maxConcurrent = 50;
|
|
811
|
-
static queue = new
|
|
812
|
-
static assignLODInformation(t, e, s,
|
|
862
|
+
static queue = new it(y.maxConcurrent, { debug: f != !1 });
|
|
863
|
+
static assignLODInformation(t, e, s, r, i) {
|
|
813
864
|
if (!e) return;
|
|
814
865
|
e.userData || (e.userData = {});
|
|
815
|
-
const
|
|
816
|
-
e.userData.LODS =
|
|
866
|
+
const n = new mt(t, s, r, i);
|
|
867
|
+
e.userData.LODS = n, "source" in e && typeof e.source == "object" && (e.source.LODS = n);
|
|
817
868
|
}
|
|
818
869
|
static getAssignedLODInformation(t) {
|
|
819
870
|
return t ? t.userData?.LODS ? t.userData.LODS : "source" in t && t.source?.LODS ? t.source.LODS : null : null;
|
|
820
871
|
}
|
|
821
872
|
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
822
873
|
static copySettings(t, e) {
|
|
823
|
-
return e ? (
|
|
874
|
+
return e ? (f === "verbose" && console.debug(`Copy texture settings
|
|
824
875
|
`, t.uuid, `
|
|
825
876
|
`, 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;
|
|
826
877
|
}
|
|
827
878
|
}
|
|
828
|
-
class
|
|
879
|
+
class mt {
|
|
829
880
|
url;
|
|
830
881
|
/** the key to lookup the LOD information */
|
|
831
882
|
key;
|
|
832
883
|
level;
|
|
833
884
|
/** For multi objects (e.g. a group of meshes) this is the index of the object */
|
|
834
885
|
index;
|
|
835
|
-
constructor(t, e, s,
|
|
836
|
-
this.url = t, this.key = e, this.level = s,
|
|
886
|
+
constructor(t, e, s, r) {
|
|
887
|
+
this.url = t, this.key = e, this.level = s, r != null && (this.index = r);
|
|
837
888
|
}
|
|
838
889
|
}
|
|
839
890
|
class de {
|
|
840
|
-
static addPromise = (t, e, s,
|
|
841
|
-
|
|
842
|
-
|
|
891
|
+
static addPromise = (t, e, s, r) => {
|
|
892
|
+
r.forEach((i) => {
|
|
893
|
+
i.add(t, e, s);
|
|
843
894
|
});
|
|
844
895
|
};
|
|
845
896
|
ready;
|
|
@@ -869,9 +920,9 @@ class de {
|
|
|
869
920
|
_awaiting = [];
|
|
870
921
|
_maxPromisesPerObject = 1;
|
|
871
922
|
constructor(t, e) {
|
|
872
|
-
const
|
|
873
|
-
this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture =
|
|
874
|
-
this._resolve =
|
|
923
|
+
const r = Math.max(e.frames ?? 2, 2);
|
|
924
|
+
this._frame_start = e.waitForFirstCapture ? void 0 : t, this._frames_to_capture = r, this.ready = new Promise((i) => {
|
|
925
|
+
this._resolve = i;
|
|
875
926
|
}), this.ready.finally(() => {
|
|
876
927
|
this._resolved = !0, this._awaiting.length = 0;
|
|
877
928
|
}), this._signal = e.signal, this._signal?.addEventListener("abort", () => {
|
|
@@ -885,18 +936,18 @@ class de {
|
|
|
885
936
|
_seen = /* @__PURE__ */ new WeakMap();
|
|
886
937
|
add(t, e, s) {
|
|
887
938
|
if (this._resolved) {
|
|
888
|
-
|
|
939
|
+
f && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
|
|
889
940
|
return;
|
|
890
941
|
}
|
|
891
942
|
if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
|
|
892
943
|
if (this._maxPromisesPerObject >= 1)
|
|
893
944
|
if (this._seen.has(e)) {
|
|
894
|
-
let
|
|
895
|
-
if (
|
|
896
|
-
|
|
945
|
+
let r = this._seen.get(e);
|
|
946
|
+
if (r >= this._maxPromisesPerObject) {
|
|
947
|
+
f && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
|
|
897
948
|
return;
|
|
898
949
|
}
|
|
899
|
-
this._seen.set(e,
|
|
950
|
+
this._seen.set(e, r + 1);
|
|
900
951
|
} else
|
|
901
952
|
this._seen.set(e, 1);
|
|
902
953
|
this._awaiting.push(s), this._addedCount++, s.finally(() => {
|
|
@@ -912,7 +963,7 @@ class de {
|
|
|
912
963
|
});
|
|
913
964
|
}
|
|
914
965
|
}
|
|
915
|
-
const
|
|
966
|
+
const R = N("debugprogressive"), yt = N("noprogressive"), fe = /* @__PURE__ */ Symbol("Needle:LODSManager"), he = /* @__PURE__ */ Symbol("Needle:LODState"), U = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), T = { mesh_lod: -1, texture_lod: -1 };
|
|
916
967
|
let oe = class O {
|
|
917
968
|
/**
|
|
918
969
|
* 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.
|
|
@@ -920,7 +971,7 @@ let oe = class O {
|
|
|
920
971
|
static debugDrawLine;
|
|
921
972
|
/** @internal */
|
|
922
973
|
static getObjectLODState(t) {
|
|
923
|
-
return t[
|
|
974
|
+
return t[he];
|
|
924
975
|
}
|
|
925
976
|
static addPlugin(t) {
|
|
926
977
|
z.push(t);
|
|
@@ -935,17 +986,17 @@ let oe = class O {
|
|
|
935
986
|
* @returns The LODsManager instance.
|
|
936
987
|
*/
|
|
937
988
|
static get(t, e) {
|
|
938
|
-
if (t[
|
|
939
|
-
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[
|
|
989
|
+
if (t[fe])
|
|
990
|
+
return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), t[fe];
|
|
940
991
|
const s = new O(t, {
|
|
941
992
|
engine: "unknown",
|
|
942
993
|
...e
|
|
943
994
|
});
|
|
944
|
-
return t[
|
|
995
|
+
return t[fe] = s, s;
|
|
945
996
|
}
|
|
946
997
|
renderer;
|
|
947
998
|
context;
|
|
948
|
-
projectionScreenMatrix = new
|
|
999
|
+
projectionScreenMatrix = new Me();
|
|
949
1000
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
950
1001
|
get plugins() {
|
|
951
1002
|
return z;
|
|
@@ -991,11 +1042,11 @@ let oe = class O {
|
|
|
991
1042
|
awaitLoading(t) {
|
|
992
1043
|
const e = this._promiseGroupIds++, s = new de(this.#r, { ...t });
|
|
993
1044
|
this._newPromiseGroups.push(s);
|
|
994
|
-
const
|
|
1045
|
+
const r = performance.now();
|
|
995
1046
|
return s.ready.finally(() => {
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
start:
|
|
1047
|
+
const i = this._newPromiseGroups.indexOf(s);
|
|
1048
|
+
i >= 0 && (this._newPromiseGroups.splice(i, 1), ve() && performance.measure("LODsManager:awaitLoading", {
|
|
1049
|
+
start: r,
|
|
999
1050
|
detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
|
|
1000
1051
|
}));
|
|
1001
1052
|
}), s.ready;
|
|
@@ -1020,10 +1071,10 @@ let oe = class O {
|
|
|
1020
1071
|
this.renderer = t, this.context = { ...e };
|
|
1021
1072
|
}
|
|
1022
1073
|
#t;
|
|
1023
|
-
#
|
|
1074
|
+
#n = new Ee();
|
|
1024
1075
|
#r = 0;
|
|
1025
|
-
#n = 0;
|
|
1026
1076
|
#i = 0;
|
|
1077
|
+
#o = 0;
|
|
1027
1078
|
#s = 0;
|
|
1028
1079
|
_fpsBuffer = [60, 60, 60, 60, 60];
|
|
1029
1080
|
/**
|
|
@@ -1035,11 +1086,11 @@ let oe = class O {
|
|
|
1035
1086
|
let t = 0;
|
|
1036
1087
|
this.#t = this.renderer.render;
|
|
1037
1088
|
const e = this;
|
|
1038
|
-
|
|
1039
|
-
const
|
|
1040
|
-
(
|
|
1041
|
-
const
|
|
1042
|
-
e.#t.call(this, s,
|
|
1089
|
+
Le(this.renderer), this.renderer.render = function(s, r) {
|
|
1090
|
+
const i = e.renderer.getRenderTarget();
|
|
1091
|
+
(i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#n.getDelta(), e.#o += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((l, a) => l + a) / e._fpsBuffer.length, R && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
|
|
1092
|
+
const n = t++;
|
|
1093
|
+
e.#t.call(this, s, r), e.onAfterRender(s, r, n);
|
|
1043
1094
|
};
|
|
1044
1095
|
}
|
|
1045
1096
|
disable() {
|
|
@@ -1050,14 +1101,14 @@ let oe = class O {
|
|
|
1050
1101
|
}
|
|
1051
1102
|
onAfterRender(t, e, s) {
|
|
1052
1103
|
if (this.pause) return;
|
|
1053
|
-
const
|
|
1054
|
-
let
|
|
1055
|
-
if (
|
|
1056
|
-
const l =
|
|
1057
|
-
(l.name === "EffectMaterial" || l.name === "CopyShader") && (
|
|
1104
|
+
const i = this.renderer.renderLists.get(t, 0).opaque;
|
|
1105
|
+
let n = !0;
|
|
1106
|
+
if (i.length === 1) {
|
|
1107
|
+
const l = i[0].material;
|
|
1108
|
+
(l.name === "EffectMaterial" || l.name === "CopyShader") && (n = !1);
|
|
1058
1109
|
}
|
|
1059
|
-
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (
|
|
1060
|
-
if (
|
|
1110
|
+
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (n = !1), n) {
|
|
1111
|
+
if (yt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, R && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, R && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
|
|
1061
1112
|
return;
|
|
1062
1113
|
this.internalUpdate(t, e), this._postprocessPromiseGroups();
|
|
1063
1114
|
}
|
|
@@ -1066,12 +1117,12 @@ let oe = class O {
|
|
|
1066
1117
|
* Update LODs in a scene
|
|
1067
1118
|
*/
|
|
1068
1119
|
internalUpdate(t, e) {
|
|
1069
|
-
const s = this.renderer.renderLists.get(t, 0),
|
|
1120
|
+
const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
|
|
1070
1121
|
this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
|
|
1071
|
-
const
|
|
1072
|
-
for (const a of
|
|
1122
|
+
const i = this.targetTriangleDensity;
|
|
1123
|
+
for (const a of r) {
|
|
1073
1124
|
if (a.material && (a.geometry?.type === "BoxGeometry" || a.geometry?.type === "BufferGeometry") && (a.material.name === "SphericalGaussianBlur" || a.material.name == "BackgroundCubeMaterial" || a.material.name === "CubemapFromEquirect" || a.material.name === "EquirectangularToCubeUV")) {
|
|
1074
|
-
|
|
1125
|
+
R && (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", a, a.material.name, a.material.type)));
|
|
1075
1126
|
continue;
|
|
1076
1127
|
}
|
|
1077
1128
|
switch (a.material.type) {
|
|
@@ -1083,38 +1134,38 @@ let oe = class O {
|
|
|
1083
1134
|
case "MeshDepthMaterial":
|
|
1084
1135
|
continue;
|
|
1085
1136
|
}
|
|
1086
|
-
if (
|
|
1137
|
+
if (R === "color" && a.material && !a.object.progressive_debug_color) {
|
|
1087
1138
|
a.object.progressive_debug_color = !0;
|
|
1088
|
-
const
|
|
1089
|
-
a.object.material =
|
|
1139
|
+
const c = Math.random() * 16777215, m = new Ve({ color: c });
|
|
1140
|
+
a.object.material = m;
|
|
1090
1141
|
}
|
|
1091
1142
|
const u = a.object;
|
|
1092
|
-
(u instanceof
|
|
1143
|
+
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1093
1144
|
}
|
|
1094
|
-
const
|
|
1095
|
-
for (const a of
|
|
1145
|
+
const n = s.transparent;
|
|
1146
|
+
for (const a of n) {
|
|
1096
1147
|
const u = a.object;
|
|
1097
|
-
(u instanceof
|
|
1148
|
+
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1098
1149
|
}
|
|
1099
1150
|
const l = s.transmissive;
|
|
1100
1151
|
for (const a of l) {
|
|
1101
1152
|
const u = a.object;
|
|
1102
|
-
(u instanceof
|
|
1153
|
+
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1103
1154
|
}
|
|
1104
1155
|
}
|
|
1105
1156
|
/** Update the LOD levels for the renderer. */
|
|
1106
|
-
updateLODs(t, e, s,
|
|
1157
|
+
updateLODs(t, e, s, r) {
|
|
1107
1158
|
s.userData || (s.userData = {});
|
|
1108
|
-
let
|
|
1109
|
-
if (
|
|
1159
|
+
let i = s[he];
|
|
1160
|
+
if (i || (i = new xt(), s[he] = i), i.frames++ < 2)
|
|
1110
1161
|
return;
|
|
1111
1162
|
for (const l of z)
|
|
1112
1163
|
l.onBeforeUpdateLOD?.(this.renderer, t, e, s);
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1164
|
+
const n = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : E;
|
|
1165
|
+
n >= 0 ? (T.mesh_lod = n, T.texture_lod = n) : (this.calculateLodLevel(e, s, i, r, T), T.mesh_lod = Math.round(T.mesh_lod), T.texture_lod = Math.round(T.texture_lod)), T.mesh_lod >= 0 && this.loadProgressiveMeshes(s, T.mesh_lod), s.material && T.texture_lod >= 0 && this.loadProgressiveTextures(s.material, T.texture_lod, n), f && s.material && !s.isGizmo && Re(s.material);
|
|
1115
1166
|
for (const l of z)
|
|
1116
1167
|
l.onAfterUpdatedLOD?.(this.renderer, t, e, s, T);
|
|
1117
|
-
|
|
1168
|
+
i.lastLodLevel_Mesh = T.mesh_lod, i.lastLodLevel_Texture = T.texture_lod;
|
|
1118
1169
|
}
|
|
1119
1170
|
/** Load progressive textures for the given material
|
|
1120
1171
|
* @param material the material to load the textures for
|
|
@@ -1124,17 +1175,17 @@ let oe = class O {
|
|
|
1124
1175
|
loadProgressiveTextures(t, e, s) {
|
|
1125
1176
|
if (!t) return;
|
|
1126
1177
|
if (Array.isArray(t)) {
|
|
1127
|
-
for (const
|
|
1128
|
-
this.loadProgressiveTextures(
|
|
1178
|
+
for (const i of t)
|
|
1179
|
+
this.loadProgressiveTextures(i, e);
|
|
1129
1180
|
return;
|
|
1130
1181
|
}
|
|
1131
|
-
let
|
|
1132
|
-
if ((t[U] === void 0 || e < t[U]) && (
|
|
1182
|
+
let r = !1;
|
|
1183
|
+
if ((t[U] === void 0 || e < t[U]) && (r = !0), s !== void 0 && s >= 0 && (r = t[U] != s, e = s), r) {
|
|
1133
1184
|
t[U] = e;
|
|
1134
|
-
const
|
|
1185
|
+
const i = y.assignTextureLOD(t, e).then((n) => {
|
|
1135
1186
|
this._lodchangedlisteners.forEach((l) => l({ type: "texture", level: e, object: t }));
|
|
1136
1187
|
});
|
|
1137
|
-
de.addPromise("texture", t,
|
|
1188
|
+
de.addPromise("texture", t, i, this._newPromiseGroups);
|
|
1138
1189
|
}
|
|
1139
1190
|
}
|
|
1140
1191
|
/** Load progressive meshes for the given mesh
|
|
@@ -1146,142 +1197,142 @@ let oe = class O {
|
|
|
1146
1197
|
loadProgressiveMeshes(t, e) {
|
|
1147
1198
|
if (!t) return Promise.resolve(null);
|
|
1148
1199
|
let s = t[U] !== e;
|
|
1149
|
-
const
|
|
1150
|
-
if (
|
|
1200
|
+
const r = t["DEBUG:LOD"];
|
|
1201
|
+
if (r != null && (s = t[U] != r, e = r), s) {
|
|
1151
1202
|
t[U] = e;
|
|
1152
|
-
const
|
|
1153
|
-
return de.addPromise("mesh", t,
|
|
1203
|
+
const i = t.geometry, n = y.assignMeshLOD(t, e).then((l) => (l && t[U] == e && i != t.geometry && this._lodchangedlisteners.forEach((a) => a({ type: "mesh", level: e, object: t })), l));
|
|
1204
|
+
return de.addPromise("mesh", t, n, this._newPromiseGroups), n;
|
|
1154
1205
|
}
|
|
1155
1206
|
return Promise.resolve(null);
|
|
1156
1207
|
}
|
|
1157
1208
|
// private testIfLODLevelsAreAvailable() {
|
|
1158
|
-
_sphere = new
|
|
1159
|
-
_tempBox = new
|
|
1160
|
-
_tempBox2 = new
|
|
1161
|
-
tempMatrix = new
|
|
1162
|
-
_tempWorldPosition = new
|
|
1163
|
-
_tempBoxSize = new
|
|
1164
|
-
_tempBox2Size = new
|
|
1165
|
-
static corner0 = new
|
|
1166
|
-
static corner1 = new
|
|
1167
|
-
static corner2 = new
|
|
1168
|
-
static corner3 = new
|
|
1169
|
-
static _tempPtInside = new
|
|
1209
|
+
_sphere = new Se();
|
|
1210
|
+
_tempBox = new pe();
|
|
1211
|
+
_tempBox2 = new pe();
|
|
1212
|
+
tempMatrix = new Me();
|
|
1213
|
+
_tempWorldPosition = new A();
|
|
1214
|
+
_tempBoxSize = new A();
|
|
1215
|
+
_tempBox2Size = new A();
|
|
1216
|
+
static corner0 = new A();
|
|
1217
|
+
static corner1 = new A();
|
|
1218
|
+
static corner2 = new A();
|
|
1219
|
+
static corner3 = new A();
|
|
1220
|
+
static _tempPtInside = new A();
|
|
1170
1221
|
static isInside(t, e) {
|
|
1171
|
-
const s = t.min,
|
|
1172
|
-
return this._tempPtInside.set(
|
|
1222
|
+
const s = t.min, r = t.max, i = (s.x + r.x) * 0.5, n = (s.y + r.y) * 0.5;
|
|
1223
|
+
return this._tempPtInside.set(i, n, s.z).applyMatrix4(e).z < 0;
|
|
1173
1224
|
}
|
|
1174
1225
|
static skinnedMeshBoundsFrameOffsetCounter = 0;
|
|
1175
1226
|
static $skinnedMeshBoundsOffset = /* @__PURE__ */ Symbol("gltf-progressive-skinnedMeshBoundsOffset");
|
|
1176
1227
|
// #region calculateLodLevel
|
|
1177
|
-
calculateLodLevel(t, e, s,
|
|
1228
|
+
calculateLodLevel(t, e, s, r, i) {
|
|
1178
1229
|
if (!e) {
|
|
1179
|
-
|
|
1230
|
+
i.mesh_lod = -1, i.texture_lod = -1;
|
|
1180
1231
|
return;
|
|
1181
1232
|
}
|
|
1182
1233
|
if (!t) {
|
|
1183
|
-
|
|
1234
|
+
i.mesh_lod = -1, i.texture_lod = -1;
|
|
1184
1235
|
return;
|
|
1185
1236
|
}
|
|
1186
1237
|
let l = 10 + 1, a = !1;
|
|
1187
|
-
if (
|
|
1238
|
+
if (R && e["DEBUG:LOD"] != null)
|
|
1188
1239
|
return e["DEBUG:LOD"];
|
|
1189
|
-
const u =
|
|
1190
|
-
if (!
|
|
1191
|
-
|
|
1240
|
+
const u = y.getMeshLODExtension(e.geometry)?.lods, c = y.getPrimitiveIndex(e.geometry), m = u && u.length > 0, w = y.getMaterialMinMaxLODsCount(e.material), L = w.min_count !== 1 / 0 && w.min_count >= 0 && w.max_count >= 0;
|
|
1241
|
+
if (!m && !L) {
|
|
1242
|
+
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1192
1243
|
return;
|
|
1193
1244
|
}
|
|
1194
|
-
|
|
1245
|
+
m || (a = !0, l = 0);
|
|
1195
1246
|
const k = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
|
|
1196
1247
|
let v = e.geometry.boundingBox;
|
|
1197
1248
|
if (e.type === "SkinnedMesh") {
|
|
1198
|
-
const
|
|
1199
|
-
if (!
|
|
1200
|
-
|
|
1249
|
+
const d = e;
|
|
1250
|
+
if (!d.boundingBox)
|
|
1251
|
+
d.computeBoundingBox();
|
|
1201
1252
|
else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
|
|
1202
|
-
if (!
|
|
1253
|
+
if (!d[O.$skinnedMeshBoundsOffset]) {
|
|
1203
1254
|
const M = O.skinnedMeshBoundsFrameOffsetCounter++;
|
|
1204
|
-
|
|
1255
|
+
d[O.$skinnedMeshBoundsOffset] = M;
|
|
1205
1256
|
}
|
|
1206
|
-
const g =
|
|
1257
|
+
const g = d[O.$skinnedMeshBoundsOffset];
|
|
1207
1258
|
if ((s.frames + g) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
|
|
1208
|
-
const M =
|
|
1209
|
-
M && (
|
|
1259
|
+
const M = ee(d), B = d.geometry;
|
|
1260
|
+
M && (d.geometry = M), d.computeBoundingBox(), d.geometry = B;
|
|
1210
1261
|
}
|
|
1211
1262
|
}
|
|
1212
|
-
v =
|
|
1263
|
+
v = d.boundingBox;
|
|
1213
1264
|
}
|
|
1214
1265
|
if (v) {
|
|
1215
|
-
const
|
|
1266
|
+
const d = t;
|
|
1216
1267
|
if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
|
|
1217
1268
|
this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
|
|
1218
|
-
const
|
|
1219
|
-
if (this._sphere.containsPoint(
|
|
1220
|
-
|
|
1269
|
+
const h = t.getWorldPosition(this._tempWorldPosition);
|
|
1270
|
+
if (this._sphere.containsPoint(h)) {
|
|
1271
|
+
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1221
1272
|
return;
|
|
1222
1273
|
}
|
|
1223
1274
|
}
|
|
1224
|
-
if (this._tempBox.copy(v), this._tempBox.applyMatrix4(e.matrixWorld),
|
|
1225
|
-
|
|
1275
|
+
if (this._tempBox.copy(v), this._tempBox.applyMatrix4(e.matrixWorld), d.isPerspectiveCamera && O.isInside(this._tempBox, this.projectionScreenMatrix)) {
|
|
1276
|
+
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1226
1277
|
return;
|
|
1227
1278
|
}
|
|
1228
|
-
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled &&
|
|
1229
|
-
const
|
|
1230
|
-
let
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
const
|
|
1234
|
-
s.lastCentrality = (
|
|
1279
|
+
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && d.isPerspectiveCamera && d.fov > 70) {
|
|
1280
|
+
const h = this._tempBox.min, p = this._tempBox.max;
|
|
1281
|
+
let b = h.x, S = h.y, G = p.x, Y = p.y;
|
|
1282
|
+
const te = 2, ae = 1.5, se = (h.x + p.x) * 0.5, re = (h.y + p.y) * 0.5;
|
|
1283
|
+
b = (b - se) * te + se, S = (S - re) * te + re, G = (G - se) * te + se, Y = (Y - re) * te + re;
|
|
1284
|
+
const Be = b < 0 && G > 0 ? 0 : Math.min(Math.abs(h.x), Math.abs(p.x)), Ge = S < 0 && Y > 0 ? 0 : Math.min(Math.abs(h.y), Math.abs(p.y)), le = Math.max(Be, Ge);
|
|
1285
|
+
s.lastCentrality = (ae - le) * (ae - le) * (ae - le);
|
|
1235
1286
|
} else
|
|
1236
1287
|
s.lastCentrality = 1;
|
|
1237
1288
|
const g = this._tempBox.getSize(this._tempBoxSize);
|
|
1238
1289
|
g.multiplyScalar(0.5), screen.availHeight > 0 && k > 0 && g.multiplyScalar(k / screen.availHeight), t.isPerspectiveCamera ? g.x *= t.aspect : t.isOrthographicCamera;
|
|
1239
1290
|
const M = t.matrixWorldInverse, B = this._tempBox2;
|
|
1240
1291
|
B.copy(v), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(M);
|
|
1241
|
-
const
|
|
1242
|
-
if (Math.max(g.x, g.y) != 0 &&
|
|
1243
|
-
const
|
|
1244
|
-
|
|
1245
|
-
const p = O.corner0,
|
|
1246
|
-
p.copy(this._tempBox.min),
|
|
1247
|
-
const
|
|
1248
|
-
p.z =
|
|
1292
|
+
const D = B.getSize(this._tempBox2Size), q = Math.max(D.x, D.y);
|
|
1293
|
+
if (Math.max(g.x, g.y) != 0 && q != 0 && (g.z = D.z / Math.max(D.x, D.y) * Math.max(g.x, g.y)), s.lastScreenCoverage = Math.max(g.x, g.y, g.z), s.lastScreenspaceVolume.copy(g), s.lastScreenCoverage *= s.lastCentrality, R && O.debugDrawLine) {
|
|
1294
|
+
const h = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
1295
|
+
h.invert();
|
|
1296
|
+
const p = O.corner0, b = O.corner1, S = O.corner2, G = O.corner3;
|
|
1297
|
+
p.copy(this._tempBox.min), b.copy(this._tempBox.max), b.x = p.x, S.copy(this._tempBox.max), S.y = p.y, G.copy(this._tempBox.max);
|
|
1298
|
+
const Y = (p.z + G.z) * 0.5;
|
|
1299
|
+
p.z = b.z = S.z = G.z = Y, p.applyMatrix4(h), b.applyMatrix4(h), S.applyMatrix4(h), G.applyMatrix4(h), O.debugDrawLine(p, b, 255), O.debugDrawLine(p, S, 255), O.debugDrawLine(b, G, 255), O.debugDrawLine(S, G, 255);
|
|
1249
1300
|
}
|
|
1250
1301
|
let _ = 999;
|
|
1251
1302
|
if (u && s.lastScreenCoverage > 0)
|
|
1252
|
-
for (let
|
|
1253
|
-
const p = u[
|
|
1254
|
-
if (
|
|
1255
|
-
_ =
|
|
1303
|
+
for (let h = 0; h < u.length; h++) {
|
|
1304
|
+
const p = u[h], S = (p.densities?.[c] || p.density || 1e-5) / s.lastScreenCoverage;
|
|
1305
|
+
if (c > 0 && ve() && !p.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["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.")), S < r) {
|
|
1306
|
+
_ = h;
|
|
1256
1307
|
break;
|
|
1257
1308
|
}
|
|
1258
1309
|
}
|
|
1259
1310
|
_ < l && (l = _, a = !0);
|
|
1260
1311
|
}
|
|
1261
|
-
if (a ?
|
|
1262
|
-
const g = u?.[
|
|
1263
|
-
g && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${
|
|
1312
|
+
if (a ? i.mesh_lod = l : i.mesh_lod = s.lastLodLevel_Mesh, R && i.mesh_lod != s.lastLodLevel_Mesh) {
|
|
1313
|
+
const g = u?.[i.mesh_lod];
|
|
1314
|
+
g && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${g.densities?.[c].toFixed(0)}) | ${e.name}`);
|
|
1264
1315
|
}
|
|
1265
1316
|
if (L) {
|
|
1266
|
-
const
|
|
1317
|
+
const d = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
1267
1318
|
if (s.lastLodLevel_Texture < 0) {
|
|
1268
|
-
if (
|
|
1319
|
+
if (i.texture_lod = w.max_count - 1, R) {
|
|
1269
1320
|
const g = w.lods[w.max_count - 1];
|
|
1270
|
-
|
|
1321
|
+
R && console.log(`First Texture LOD ${i.texture_lod} (${g.max_height}px) - ${e.name}`);
|
|
1271
1322
|
}
|
|
1272
1323
|
} else {
|
|
1273
1324
|
const g = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
1274
1325
|
let M = s.lastScreenCoverage * 4;
|
|
1275
1326
|
this.context?.engine === "model-viewer" && (M *= 1.5);
|
|
1276
|
-
const
|
|
1277
|
-
let
|
|
1327
|
+
const D = k / window.devicePixelRatio * M;
|
|
1328
|
+
let q = !1;
|
|
1278
1329
|
for (let P = w.lods.length - 1; P >= 0; P--) {
|
|
1279
1330
|
const _ = w.lods[P];
|
|
1280
|
-
if (!(
|
|
1281
|
-
if (
|
|
1331
|
+
if (!(d && _.max_height >= 2048) && !(ke() && _.max_height > 4096) && (_.max_height > D || !q && P === 0)) {
|
|
1332
|
+
if (q = !0, i.texture_lod = P, R && i.texture_lod < s.lastLodLevel_Texture) {
|
|
1282
1333
|
const x = _.max_height;
|
|
1283
|
-
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${
|
|
1284
|
-
Screensize: ${
|
|
1334
|
+
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${x}px
|
|
1335
|
+
Screensize: ${D.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${g.toFixed(1)}
|
|
1285
1336
|
${e.name}`);
|
|
1286
1337
|
}
|
|
1287
1338
|
break;
|
|
@@ -1289,86 +1340,86 @@ ${e.name}`);
|
|
|
1289
1340
|
}
|
|
1290
1341
|
}
|
|
1291
1342
|
} else
|
|
1292
|
-
|
|
1343
|
+
i.texture_lod = 0;
|
|
1293
1344
|
}
|
|
1294
1345
|
};
|
|
1295
|
-
class
|
|
1346
|
+
class xt {
|
|
1296
1347
|
frames = 0;
|
|
1297
1348
|
lastLodLevel_Mesh = -1;
|
|
1298
1349
|
lastLodLevel_Texture = -1;
|
|
1299
1350
|
lastScreenCoverage = 0;
|
|
1300
|
-
lastScreenspaceVolume = new
|
|
1351
|
+
lastScreenspaceVolume = new A();
|
|
1301
1352
|
lastCentrality = 0;
|
|
1302
1353
|
}
|
|
1303
|
-
const
|
|
1304
|
-
let
|
|
1354
|
+
const De = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
|
|
1355
|
+
let ge = null;
|
|
1305
1356
|
function Ie() {
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1357
|
+
const o = wt();
|
|
1358
|
+
o && (o.mapURLs(function(t) {
|
|
1308
1359
|
return be(), t;
|
|
1309
|
-
}), be(),
|
|
1360
|
+
}), be(), ge?.disconnect(), ge = new MutationObserver((t) => {
|
|
1310
1361
|
t.forEach((e) => {
|
|
1311
1362
|
e.addedNodes.forEach((s) => {
|
|
1312
|
-
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" &&
|
|
1363
|
+
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && $e(s);
|
|
1313
1364
|
});
|
|
1314
1365
|
});
|
|
1315
|
-
}),
|
|
1366
|
+
}), ge.observe(document, { childList: !0, subtree: !0 }));
|
|
1316
1367
|
}
|
|
1317
|
-
function
|
|
1368
|
+
function wt() {
|
|
1318
1369
|
if (typeof customElements > "u") return null;
|
|
1319
|
-
const
|
|
1320
|
-
return
|
|
1370
|
+
const o = customElements.get("model-viewer");
|
|
1371
|
+
return o || (customElements.whenDefined("model-viewer").then(() => {
|
|
1321
1372
|
console.debug("[gltf-progressive] model-viewer defined"), Ie();
|
|
1322
1373
|
}), null);
|
|
1323
1374
|
}
|
|
1324
1375
|
function be() {
|
|
1325
1376
|
if (typeof document > "u") return;
|
|
1326
1377
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
1327
|
-
|
|
1378
|
+
$e(t);
|
|
1328
1379
|
});
|
|
1329
1380
|
}
|
|
1330
|
-
const
|
|
1331
|
-
let
|
|
1332
|
-
function
|
|
1333
|
-
if (!
|
|
1381
|
+
const Oe = /* @__PURE__ */ new WeakSet();
|
|
1382
|
+
let Lt = 0;
|
|
1383
|
+
function $e(o) {
|
|
1384
|
+
if (!o || Oe.has(o))
|
|
1334
1385
|
return null;
|
|
1335
|
-
|
|
1336
|
-
`,
|
|
1386
|
+
Oe.add(o), console.debug("[gltf-progressive] found new model-viewer..." + ++Lt + `
|
|
1387
|
+
`, o.getAttribute("src"));
|
|
1337
1388
|
let t = null, e = null, s = null;
|
|
1338
|
-
for (let
|
|
1339
|
-
const
|
|
1340
|
-
!t &&
|
|
1389
|
+
for (let r = o; r != null; r = Object.getPrototypeOf(r)) {
|
|
1390
|
+
const i = Object.getOwnPropertySymbols(r), n = i.find((u) => u.toString() == "Symbol(renderer)"), l = i.find((u) => u.toString() == "Symbol(scene)"), a = i.find((u) => u.toString() == "Symbol(needsRender)");
|
|
1391
|
+
!t && n != null && (t = o[n].threeRenderer), !e && l != null && (e = o[l]), !s && a != null && (s = o[a]);
|
|
1341
1392
|
}
|
|
1342
1393
|
if (t && e) {
|
|
1343
|
-
let
|
|
1394
|
+
let r = function() {
|
|
1344
1395
|
if (s) {
|
|
1345
|
-
let
|
|
1346
|
-
if (
|
|
1396
|
+
let n = 0, l = setInterval(() => {
|
|
1397
|
+
if (n++ > 5) {
|
|
1347
1398
|
clearInterval(l);
|
|
1348
1399
|
return;
|
|
1349
1400
|
}
|
|
1350
|
-
s?.call(
|
|
1401
|
+
s?.call(o);
|
|
1351
1402
|
}, 300);
|
|
1352
1403
|
}
|
|
1353
1404
|
};
|
|
1354
1405
|
console.debug("[gltf-progressive] setup model-viewer");
|
|
1355
|
-
const
|
|
1356
|
-
return oe.addPlugin(new
|
|
1357
|
-
s?.call(
|
|
1358
|
-
}),
|
|
1359
|
-
|
|
1360
|
-
}),
|
|
1361
|
-
|
|
1406
|
+
const i = oe.get(t, { engine: "model-viewer" });
|
|
1407
|
+
return oe.addPlugin(new _t()), i.enable(), i.addEventListener("changed", () => {
|
|
1408
|
+
s?.call(o);
|
|
1409
|
+
}), o.addEventListener("model-visibility", (n) => {
|
|
1410
|
+
n.detail.visible && s?.call(o);
|
|
1411
|
+
}), o.addEventListener("load", () => {
|
|
1412
|
+
r();
|
|
1362
1413
|
}), () => {
|
|
1363
|
-
|
|
1414
|
+
i.disable();
|
|
1364
1415
|
};
|
|
1365
1416
|
}
|
|
1366
1417
|
return null;
|
|
1367
1418
|
}
|
|
1368
|
-
class
|
|
1419
|
+
class _t {
|
|
1369
1420
|
_didWarnAboutMissingUrl = !1;
|
|
1370
|
-
onBeforeUpdateLOD(t, e, s,
|
|
1371
|
-
this.tryParseMeshLOD(e,
|
|
1421
|
+
onBeforeUpdateLOD(t, e, s, r) {
|
|
1422
|
+
this.tryParseMeshLOD(e, r), this.tryParseTextureLOD(e, r);
|
|
1372
1423
|
}
|
|
1373
1424
|
getUrl(t) {
|
|
1374
1425
|
if (!t)
|
|
@@ -1383,16 +1434,16 @@ class wt {
|
|
|
1383
1434
|
return t.element;
|
|
1384
1435
|
}
|
|
1385
1436
|
tryParseTextureLOD(t, e) {
|
|
1386
|
-
if (e[
|
|
1387
|
-
e[
|
|
1388
|
-
const s = this.tryGetCurrentGLTF(t),
|
|
1389
|
-
if (
|
|
1390
|
-
let
|
|
1391
|
-
if (a[
|
|
1392
|
-
a[
|
|
1437
|
+
if (e[ie] == !0) return;
|
|
1438
|
+
e[ie] = !0;
|
|
1439
|
+
const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
|
|
1440
|
+
if (i && s && e.material) {
|
|
1441
|
+
let n = function(a) {
|
|
1442
|
+
if (a[ie] == !0) return;
|
|
1443
|
+
a[ie] = !0, a.userData && (a.userData.LOD = -1);
|
|
1393
1444
|
const u = Object.keys(a);
|
|
1394
|
-
for (let
|
|
1395
|
-
const
|
|
1445
|
+
for (let c = 0; c < u.length; c++) {
|
|
1446
|
+
const m = u[c], w = a[m];
|
|
1396
1447
|
if (w?.isTexture === !0) {
|
|
1397
1448
|
const L = w.userData?.associations?.textures;
|
|
1398
1449
|
if (L == null) continue;
|
|
@@ -1403,75 +1454,75 @@ class wt {
|
|
|
1403
1454
|
}
|
|
1404
1455
|
if (k?.extensions?.[W]) {
|
|
1405
1456
|
const v = k.extensions[W];
|
|
1406
|
-
v &&
|
|
1457
|
+
v && i && y.registerTexture(i, w, v.lods.length, L, v);
|
|
1407
1458
|
}
|
|
1408
1459
|
}
|
|
1409
1460
|
}
|
|
1410
1461
|
};
|
|
1411
1462
|
const l = e.material;
|
|
1412
|
-
if (Array.isArray(l)) for (const a of l)
|
|
1413
|
-
else
|
|
1463
|
+
if (Array.isArray(l)) for (const a of l) n(a);
|
|
1464
|
+
else n(l);
|
|
1414
1465
|
}
|
|
1415
1466
|
}
|
|
1416
1467
|
tryParseMeshLOD(t, e) {
|
|
1417
|
-
if (e[
|
|
1418
|
-
e[
|
|
1419
|
-
const s = this.tryGetCurrentModelViewer(t),
|
|
1420
|
-
if (!
|
|
1468
|
+
if (e[De] == !0) return;
|
|
1469
|
+
e[De] = !0;
|
|
1470
|
+
const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
|
|
1471
|
+
if (!r)
|
|
1421
1472
|
return;
|
|
1422
|
-
const
|
|
1423
|
-
if (
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1473
|
+
const i = e.userData?.gltfExtensions?.[W];
|
|
1474
|
+
if (i && r) {
|
|
1475
|
+
const n = e.uuid;
|
|
1476
|
+
y.registerMesh(r, n, e, 0, i.lods.length, i);
|
|
1426
1477
|
}
|
|
1427
1478
|
}
|
|
1428
1479
|
}
|
|
1429
|
-
function
|
|
1430
|
-
let t, e, s,
|
|
1431
|
-
switch (
|
|
1480
|
+
function Mt(...o) {
|
|
1481
|
+
let t, e, s, r;
|
|
1482
|
+
switch (o.length) {
|
|
1432
1483
|
case 2:
|
|
1433
|
-
[s, e] =
|
|
1484
|
+
[s, e] = o, r = {};
|
|
1434
1485
|
break;
|
|
1435
1486
|
case 3:
|
|
1436
|
-
[s, e,
|
|
1487
|
+
[s, e, r] = o;
|
|
1437
1488
|
break;
|
|
1438
1489
|
case 4:
|
|
1439
|
-
[t, e, s,
|
|
1490
|
+
[t, e, s, r] = o;
|
|
1440
1491
|
break;
|
|
1441
1492
|
default:
|
|
1442
1493
|
throw new Error("Invalid arguments");
|
|
1443
1494
|
}
|
|
1444
|
-
|
|
1495
|
+
Le(e), Te(s), Ae(s, {
|
|
1445
1496
|
progressive: !0,
|
|
1446
|
-
...
|
|
1447
|
-
}), s.register((
|
|
1448
|
-
const
|
|
1449
|
-
return
|
|
1497
|
+
...r?.hints
|
|
1498
|
+
}), s.register((n) => new y(n));
|
|
1499
|
+
const i = oe.get(e);
|
|
1500
|
+
return r?.enableLODsManager !== !1 && i.enable(), i;
|
|
1450
1501
|
}
|
|
1451
1502
|
Ie();
|
|
1452
|
-
if (!
|
|
1453
|
-
const
|
|
1503
|
+
if (!at) {
|
|
1504
|
+
const o = {
|
|
1454
1505
|
gltfProgressive: {
|
|
1455
|
-
useNeedleProgressive:
|
|
1506
|
+
useNeedleProgressive: Mt,
|
|
1456
1507
|
LODsManager: oe,
|
|
1457
1508
|
configureLoader: Ae,
|
|
1458
|
-
getRaycastMesh:
|
|
1459
|
-
useRaycastMeshes:
|
|
1509
|
+
getRaycastMesh: ee,
|
|
1510
|
+
useRaycastMeshes: ut
|
|
1460
1511
|
}
|
|
1461
1512
|
};
|
|
1462
1513
|
if (!globalThis.Needle)
|
|
1463
|
-
globalThis.Needle =
|
|
1514
|
+
globalThis.Needle = o;
|
|
1464
1515
|
else
|
|
1465
|
-
for (const t in
|
|
1466
|
-
globalThis.Needle[t] =
|
|
1516
|
+
for (const t in o)
|
|
1517
|
+
globalThis.Needle[t] = o[t];
|
|
1467
1518
|
}
|
|
1468
1519
|
export {
|
|
1469
1520
|
oe as LODsManager,
|
|
1470
|
-
|
|
1471
|
-
|
|
1521
|
+
y as NEEDLE_progressive,
|
|
1522
|
+
Te as addDracoAndKTX2Loaders,
|
|
1472
1523
|
Ae as configureLoader,
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1524
|
+
Le as createLoaders,
|
|
1525
|
+
ee as getRaycastMesh,
|
|
1526
|
+
Ze as setDracoDecoderLocation,
|
|
1527
|
+
et as setKTX2TranscoderLocation
|
|
1477
1528
|
};
|