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