@needle-tools/gltf-progressive 3.4.0-beta.2 → 3.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/gltf-progressive.js +382 -376
- package/gltf-progressive.min.js +9 -9
- package/gltf-progressive.umd.cjs +9 -9
- package/lib/extension.d.ts +3 -1
- package/lib/extension.js +21 -3
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/gltf-progressive.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BufferGeometry as E, Mesh as X, Box3 as ge, Vector3 as
|
|
1
|
+
import { BufferGeometry as E, Mesh as X, Box3 as ge, Vector3 as R, Sphere as Se, CompressedTexture as Ge, Texture as F, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as qe, Matrix4 as ve, Clock as Ne, MeshStandardMaterial as Ve } from "three";
|
|
2
2
|
import { GLTFLoader as xe } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
3
3
|
import { MeshoptDecoder as Ee } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
4
4
|
import { DRACOLoader as Xe } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
@@ -6,42 +6,42 @@ import { KTX2Loader as je } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
|
6
6
|
const Ke = "";
|
|
7
7
|
globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
|
|
8
8
|
console.debug("[gltf-progressive] version -");
|
|
9
|
-
let
|
|
10
|
-
const Ye =
|
|
11
|
-
|
|
12
|
-
fetch(
|
|
9
|
+
let B = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", j = "https://cdn.needle.tools/static/three/0.179.1/basis2/";
|
|
10
|
+
const Ye = B, He = j, Pe = new URL(B + "draco_decoder.js");
|
|
11
|
+
Pe.searchParams.append("range", "true");
|
|
12
|
+
fetch(Pe, {
|
|
13
13
|
method: "GET",
|
|
14
14
|
headers: {
|
|
15
15
|
Range: "bytes=0-1"
|
|
16
16
|
}
|
|
17
17
|
}).catch((n) => {
|
|
18
|
-
console.debug(`Failed to fetch remote Draco decoder from ${
|
|
18
|
+
console.debug(`Failed to fetch remote Draco decoder from ${B} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), B === Ye && Je("./include/draco/"), j === He && Ze("./include/ktx2/");
|
|
19
19
|
}).finally(() => {
|
|
20
|
-
|
|
20
|
+
Ce();
|
|
21
21
|
});
|
|
22
22
|
const Qe = () => ({
|
|
23
|
-
dracoDecoderPath:
|
|
23
|
+
dracoDecoderPath: B,
|
|
24
24
|
ktx2TranscoderPath: j
|
|
25
25
|
});
|
|
26
26
|
function Je(n) {
|
|
27
|
-
|
|
27
|
+
B = n, k && k[pe] != B ? (console.debug("Updating Draco decoder path to " + n), k[pe] = B, k.setDecoderPath(B), k.preload()) : console.debug("Setting Draco decoder path to " + n);
|
|
28
28
|
}
|
|
29
29
|
function Ze(n) {
|
|
30
|
-
j = n,
|
|
30
|
+
j = n, G && G.transcoderPath != j ? (console.debug("Updating KTX2 transcoder path to " + n), G.setTranscoderPath(j), G.init()) : console.debug("Setting KTX2 transcoder path to " + n);
|
|
31
31
|
}
|
|
32
32
|
function we(n) {
|
|
33
|
-
return
|
|
33
|
+
return Ce(), n ? G.detectSupport(n) : n !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: k, ktx2Loader: G, meshoptDecoder: oe };
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
n.dracoLoader || n.setDRACOLoader(
|
|
35
|
+
function Te(n) {
|
|
36
|
+
n.dracoLoader || n.setDRACOLoader(k), n.ktx2Loader || n.setKTX2Loader(G), n.meshoptDecoder || n.setMeshoptDecoder(oe);
|
|
37
37
|
}
|
|
38
38
|
const pe = /* @__PURE__ */ Symbol("dracoDecoderPath");
|
|
39
|
-
let
|
|
40
|
-
function
|
|
41
|
-
|
|
39
|
+
let k, oe, G;
|
|
40
|
+
function Ce() {
|
|
41
|
+
k || (k = new Xe(), k[pe] = B, k.setDecoderPath(B), k.setDecoderConfig({ type: "js" }), k.preload()), G || (G = new je(), G.setTranscoderPath(j), G.init()), oe || (oe = Ee);
|
|
42
42
|
}
|
|
43
43
|
const me = /* @__PURE__ */ new WeakMap();
|
|
44
|
-
function
|
|
44
|
+
function Ae(n, t) {
|
|
45
45
|
let e = me.get(n);
|
|
46
46
|
e ? e = Object.assign(e, t) : e = t, me.set(n, e);
|
|
47
47
|
}
|
|
@@ -74,11 +74,11 @@ function st(n, t) {
|
|
|
74
74
|
}
|
|
75
75
|
return t;
|
|
76
76
|
}
|
|
77
|
-
function
|
|
77
|
+
function _e() {
|
|
78
78
|
return H !== void 0 || (H = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), N("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", H)), H;
|
|
79
79
|
}
|
|
80
80
|
let H;
|
|
81
|
-
function
|
|
81
|
+
function be() {
|
|
82
82
|
if (typeof window > "u") return !1;
|
|
83
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
84
|
return n.hostname === "127.0.0.1" || t;
|
|
@@ -160,9 +160,9 @@ function ut(n) {
|
|
|
160
160
|
t.setAttribute(e, n.getAttribute(e));
|
|
161
161
|
return t.setIndex(n.getIndex()), t;
|
|
162
162
|
}
|
|
163
|
-
const
|
|
163
|
+
const q = new Array(), h = N("debugprogressive");
|
|
164
164
|
let Z, V = -1;
|
|
165
|
-
if (
|
|
165
|
+
if (h) {
|
|
166
166
|
let n = function() {
|
|
167
167
|
V += 1, V >= t && (V = -1), console.log(`Toggle LOD level [${V}]`);
|
|
168
168
|
}, t = 6;
|
|
@@ -173,7 +173,7 @@ if (f) {
|
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
function ke(n) {
|
|
176
|
-
if (
|
|
176
|
+
if (h && Z !== void 0)
|
|
177
177
|
if (Array.isArray(n))
|
|
178
178
|
for (const t of n)
|
|
179
179
|
ke(t);
|
|
@@ -181,18 +181,18 @@ function ke(n) {
|
|
|
181
181
|
}
|
|
182
182
|
const J = new Array();
|
|
183
183
|
let ct = 0;
|
|
184
|
-
const dt =
|
|
184
|
+
const dt = _e() ? 2 : 10;
|
|
185
185
|
function ft(n) {
|
|
186
186
|
if (J.length < dt) {
|
|
187
187
|
const s = J.length;
|
|
188
|
-
|
|
189
|
-
const r =
|
|
188
|
+
h && console.warn(`[Worker] Creating new worker #${s}`);
|
|
189
|
+
const r = Le.createWorker(n || {});
|
|
190
190
|
return J.push(r), r;
|
|
191
191
|
}
|
|
192
192
|
const t = ct++ % J.length;
|
|
193
193
|
return J[t];
|
|
194
194
|
}
|
|
195
|
-
class
|
|
195
|
+
class Le {
|
|
196
196
|
constructor(t, e) {
|
|
197
197
|
this.worker = t, this._debug = e.debug ?? !1, t.onmessage = (s) => {
|
|
198
198
|
const r = s.data;
|
|
@@ -219,7 +219,7 @@ class _e {
|
|
|
219
219
|
), {
|
|
220
220
|
type: "module"
|
|
221
221
|
});
|
|
222
|
-
return new
|
|
222
|
+
return new Le(e, t);
|
|
223
223
|
}
|
|
224
224
|
_running = [];
|
|
225
225
|
_webglRenderer = null;
|
|
@@ -230,16 +230,16 @@ class _e {
|
|
|
230
230
|
const { WebGLRenderer: u } = await import("three");
|
|
231
231
|
return new u();
|
|
232
232
|
})(), r = await this._webglRenderer);
|
|
233
|
-
const
|
|
233
|
+
const a = we(r).ktx2Loader.workerConfig;
|
|
234
234
|
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());
|
|
235
|
-
const
|
|
235
|
+
const l = {
|
|
236
236
|
type: "load",
|
|
237
237
|
url: t,
|
|
238
238
|
dracoDecoderPath: s.dracoDecoderPath,
|
|
239
239
|
ktx2TranscoderPath: s.ktx2TranscoderPath,
|
|
240
|
-
ktx2LoaderConfig:
|
|
240
|
+
ktx2LoaderConfig: a
|
|
241
241
|
};
|
|
242
|
-
return this._debug && console.debug("[Worker] Sending load request",
|
|
242
|
+
return this._debug && console.debug("[Worker] Sending load request", l), this.worker.postMessage(l), new Promise((u) => {
|
|
243
243
|
this._running.push({
|
|
244
244
|
url: t.toString(),
|
|
245
245
|
resolve: u
|
|
@@ -261,19 +261,19 @@ function ht(n) {
|
|
|
261
261
|
}
|
|
262
262
|
if (e.morphAttributes)
|
|
263
263
|
for (const r in e.morphAttributes) {
|
|
264
|
-
const o = e.morphAttributes[r].map((
|
|
264
|
+
const o = e.morphAttributes[r].map((a) => le(a));
|
|
265
265
|
s.morphAttributes[r] = o;
|
|
266
266
|
}
|
|
267
|
-
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new
|
|
267
|
+
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new R(
|
|
268
268
|
e.boundingBox?.min.x,
|
|
269
269
|
e.boundingBox?.min.y,
|
|
270
270
|
e.boundingBox?.min.z
|
|
271
|
-
), s.boundingBox.max = new
|
|
271
|
+
), s.boundingBox.max = new R(
|
|
272
272
|
e.boundingBox?.max.x,
|
|
273
273
|
e.boundingBox?.max.y,
|
|
274
274
|
e.boundingBox?.max.z
|
|
275
|
-
), s.boundingSphere = new
|
|
276
|
-
new
|
|
275
|
+
), s.boundingSphere = new Se(
|
|
276
|
+
new R(
|
|
277
277
|
e.boundingSphere?.center.x,
|
|
278
278
|
e.boundingSphere?.center.y,
|
|
279
279
|
e.boundingSphere?.center.z
|
|
@@ -334,11 +334,11 @@ function le(n) {
|
|
|
334
334
|
}
|
|
335
335
|
const gt = N("gltf-progressive-worker");
|
|
336
336
|
N("gltf-progressive-reduce-mipmaps");
|
|
337
|
-
const K = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"),
|
|
337
|
+
const K = N("gltf-progressive-gc"), ue = /* @__PURE__ */ Symbol("needle-progressive-texture"), U = "NEEDLE_progressive";
|
|
338
338
|
class m {
|
|
339
339
|
/** The name of the extension */
|
|
340
340
|
get name() {
|
|
341
|
-
return
|
|
341
|
+
return U;
|
|
342
342
|
}
|
|
343
343
|
// #region PUBLIC API
|
|
344
344
|
static getMeshLODExtension(t) {
|
|
@@ -357,33 +357,33 @@ class m {
|
|
|
357
357
|
max_count: 0,
|
|
358
358
|
lods: []
|
|
359
359
|
}), Array.isArray(t)) {
|
|
360
|
-
for (const
|
|
361
|
-
this.getMaterialMinMaxLODsCount(
|
|
360
|
+
for (const a of t)
|
|
361
|
+
this.getMaterialMinMaxLODsCount(a, e);
|
|
362
362
|
return t[r] = e, e;
|
|
363
363
|
}
|
|
364
|
-
if (
|
|
365
|
-
const
|
|
366
|
-
for (const
|
|
367
|
-
const u =
|
|
364
|
+
if (h === "verbose" && console.log("getMaterialMinMaxLODsCount", t), t.type === "ShaderMaterial" || t.type === "RawShaderMaterial") {
|
|
365
|
+
const a = t;
|
|
366
|
+
for (const l of Object.keys(a.uniforms)) {
|
|
367
|
+
const u = a.uniforms[l].value;
|
|
368
368
|
u?.isTexture === !0 && o(u, e);
|
|
369
369
|
}
|
|
370
370
|
} else if (t.isMaterial)
|
|
371
|
-
for (const
|
|
372
|
-
const
|
|
373
|
-
|
|
371
|
+
for (const a of Object.keys(t)) {
|
|
372
|
+
const l = t[a];
|
|
373
|
+
l?.isTexture === !0 && o(l, e);
|
|
374
374
|
}
|
|
375
375
|
else
|
|
376
|
-
|
|
376
|
+
h && console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);
|
|
377
377
|
return t[r] = e, e;
|
|
378
|
-
function o(
|
|
379
|
-
const u = s.getAssignedLODInformation(
|
|
378
|
+
function o(a, l) {
|
|
379
|
+
const u = s.getAssignedLODInformation(a);
|
|
380
380
|
if (u) {
|
|
381
|
-
const
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
for (let
|
|
385
|
-
const
|
|
386
|
-
|
|
381
|
+
const d = s.lodInfos.get(u.key);
|
|
382
|
+
if (d && d.lods) {
|
|
383
|
+
l.min_count = Math.min(l.min_count, d.lods.length), l.max_count = Math.max(l.max_count, d.lods.length);
|
|
384
|
+
for (let g = 0; g < d.lods.length; g++) {
|
|
385
|
+
const y = d.lods[g];
|
|
386
|
+
y.width && (l.lods[g] = l.lods[g] || { min_height: 1 / 0, max_height: 0 }, l.lods[g].min_height = Math.min(l.lods[g].min_height, y.height), l.lods[g].max_height = Math.max(l.lods[g].max_height, y.height));
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
}
|
|
@@ -441,16 +441,16 @@ class m {
|
|
|
441
441
|
const s = t.geometry, r = this.getAssignedLODInformation(s);
|
|
442
442
|
if (!r)
|
|
443
443
|
return Promise.resolve(null);
|
|
444
|
-
for (const i of
|
|
444
|
+
for (const i of q)
|
|
445
445
|
i.onBeforeGetLODMesh?.(t, e);
|
|
446
446
|
return t["LOD:requested level"] = e, m.getOrLoadLOD(s, e).then((i) => {
|
|
447
447
|
if (Array.isArray(i)) {
|
|
448
448
|
const o = r.index || 0;
|
|
449
449
|
i = i[o];
|
|
450
450
|
}
|
|
451
|
-
return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i :
|
|
451
|
+
return t["LOD:requested level"] === e && (delete t["LOD:requested level"], i && s != i && (i?.isBufferGeometry ? t.geometry = i : h && console.error("Invalid LOD geometry", i))), i;
|
|
452
452
|
}).catch((i) => (console.error("Error loading mesh LOD", t, i), null));
|
|
453
|
-
} else
|
|
453
|
+
} else h && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
454
454
|
return Promise.resolve(null);
|
|
455
455
|
}
|
|
456
456
|
static assignTextureLOD(t, e = 0) {
|
|
@@ -465,8 +465,8 @@ class m {
|
|
|
465
465
|
}
|
|
466
466
|
return Promise.all(r).then((i) => {
|
|
467
467
|
const o = new Array();
|
|
468
|
-
for (const
|
|
469
|
-
Array.isArray(
|
|
468
|
+
for (const a of i)
|
|
469
|
+
Array.isArray(a) && o.push(...a);
|
|
470
470
|
return o;
|
|
471
471
|
});
|
|
472
472
|
} else
|
|
@@ -476,28 +476,28 @@ class m {
|
|
|
476
476
|
const s = t, r = [], i = new Array();
|
|
477
477
|
if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
|
478
478
|
const o = s;
|
|
479
|
-
for (const
|
|
480
|
-
const
|
|
481
|
-
if (
|
|
482
|
-
const u = this.assignTextureLODForSlot(
|
|
483
|
-
r.push(u), i.push(
|
|
479
|
+
for (const a of Object.keys(o.uniforms)) {
|
|
480
|
+
const l = o.uniforms[a].value;
|
|
481
|
+
if (l?.isTexture === !0) {
|
|
482
|
+
const u = this.assignTextureLODForSlot(l, e, s, a).then((d) => (d && o.uniforms[a].value != d && (o.uniforms[a].value = d, o.uniformsNeedUpdate = !0), d));
|
|
483
|
+
r.push(u), i.push(a);
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
} else
|
|
487
487
|
for (const o of Object.keys(s)) {
|
|
488
|
-
const
|
|
489
|
-
if (
|
|
490
|
-
const
|
|
491
|
-
r.push(
|
|
488
|
+
const a = s[o];
|
|
489
|
+
if (a?.isTexture === !0) {
|
|
490
|
+
const l = this.assignTextureLODForSlot(a, e, s, o);
|
|
491
|
+
r.push(l), i.push(o);
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
494
|
return Promise.all(r).then((o) => {
|
|
495
|
-
const
|
|
496
|
-
for (let
|
|
497
|
-
const u = o[
|
|
498
|
-
u && u.isTexture === !0 ?
|
|
495
|
+
const a = new Array();
|
|
496
|
+
for (let l = 0; l < o.length; l++) {
|
|
497
|
+
const u = o[l], d = i[l];
|
|
498
|
+
u && u.isTexture === !0 ? a.push({ material: s, slot: d, texture: u, level: e }) : a.push({ material: s, slot: d, texture: null, level: e });
|
|
499
499
|
}
|
|
500
|
-
return
|
|
500
|
+
return a;
|
|
501
501
|
});
|
|
502
502
|
}
|
|
503
503
|
if (t instanceof F || t.isTexture === !0) {
|
|
@@ -508,7 +508,7 @@ class m {
|
|
|
508
508
|
}
|
|
509
509
|
/**
|
|
510
510
|
* Set the maximum number of concurrent loading tasks for LOD resources. This limits how many LOD resources (meshes or textures) can be loaded at the same time to prevent overloading the network or GPU. If the limit is reached, additional loading requests will be queued and processed as previous ones finish.
|
|
511
|
-
* @default 50
|
|
511
|
+
* @default 50 on desktop, 20 on mobile devices
|
|
512
512
|
*/
|
|
513
513
|
static set maxConcurrentLoadingTasks(t) {
|
|
514
514
|
m.queue.maxConcurrent = t;
|
|
@@ -524,19 +524,19 @@ class m {
|
|
|
524
524
|
if (i?.isTexture === !0) {
|
|
525
525
|
if (i != t && s && r) {
|
|
526
526
|
const o = s[r];
|
|
527
|
-
if (o && !
|
|
528
|
-
const l = this.getAssignedLODInformation(o);
|
|
529
|
-
if (l && l?.level < e)
|
|
530
|
-
return f === "verbose" && console.warn("Assigned texture level is already higher: ", l.level, e, s, o, i), i && i !== o && ((f || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${l.level})`, i.uuid), i.dispose()), null;
|
|
531
|
-
}
|
|
532
|
-
if (this.trackTextureUsage(i), o && o !== i && this.untrackTextureUsage(o) && (f || K)) {
|
|
527
|
+
if (o && !h) {
|
|
533
528
|
const a = this.getAssignedLODInformation(o);
|
|
534
|
-
|
|
529
|
+
if (a && a?.level < e)
|
|
530
|
+
return h === "verbose" && console.warn("Assigned texture level is already higher: ", a.level, e, s, o, i), i && i !== o && ((h || K) && console.log(`[gltf-progressive] Disposing rejected lower-quality texture LOD ${e} (assigned is ${a.level})`, i.uuid), i.dispose()), null;
|
|
531
|
+
}
|
|
532
|
+
if (this.trackTextureUsage(i), o && o !== i && this.untrackTextureUsage(o) && (h || K)) {
|
|
533
|
+
const l = this.getAssignedLODInformation(o);
|
|
534
|
+
console.log(`[gltf-progressive] Disposed old texture LOD ${l?.level ?? "?"} → ${e} for ${s.name || s.type}.${r}`, o.uuid);
|
|
535
535
|
}
|
|
536
536
|
s[r] = i;
|
|
537
537
|
}
|
|
538
538
|
return i;
|
|
539
|
-
} else
|
|
539
|
+
} else h == "verbose" && console.warn("No LOD found for", t, e);
|
|
540
540
|
return null;
|
|
541
541
|
}).catch((i) => (console.error("Error loading LOD", t, i), null));
|
|
542
542
|
}
|
|
@@ -544,12 +544,12 @@ class m {
|
|
|
544
544
|
url;
|
|
545
545
|
constructor(t) {
|
|
546
546
|
const e = t.options.path;
|
|
547
|
-
|
|
547
|
+
h && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
|
|
548
548
|
}
|
|
549
549
|
_isLoadingMesh;
|
|
550
550
|
loadMesh = (t) => {
|
|
551
551
|
if (this._isLoadingMesh) return null;
|
|
552
|
-
const e = this.parser.json.meshes[t]?.extensions?.[
|
|
552
|
+
const e = this.parser.json.meshes[t]?.extensions?.[U];
|
|
553
553
|
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;
|
|
554
554
|
};
|
|
555
555
|
// private _isLoadingTexture;
|
|
@@ -567,12 +567,12 @@ class m {
|
|
|
567
567
|
// });
|
|
568
568
|
// }
|
|
569
569
|
afterRoot(t) {
|
|
570
|
-
return
|
|
570
|
+
return h && console.log("AFTER", this.url, t), this.parser.json.textures?.forEach((e, s) => {
|
|
571
571
|
if (e?.extensions) {
|
|
572
|
-
const r = e?.extensions[
|
|
572
|
+
const r = e?.extensions[U];
|
|
573
573
|
if (r) {
|
|
574
574
|
if (!r.lods) {
|
|
575
|
-
|
|
575
|
+
h && console.warn("Texture has no LODs", r);
|
|
576
576
|
return;
|
|
577
577
|
}
|
|
578
578
|
let i = !1;
|
|
@@ -585,7 +585,7 @@ class m {
|
|
|
585
585
|
}
|
|
586
586
|
}), this.parser.json.meshes?.forEach((e, s) => {
|
|
587
587
|
if (e?.extensions) {
|
|
588
|
-
const r = e?.extensions[
|
|
588
|
+
const r = e?.extensions[U];
|
|
589
589
|
if (r && r.lods) {
|
|
590
590
|
for (const i of this.parser.associations.keys())
|
|
591
591
|
if (i.isMesh) {
|
|
@@ -601,12 +601,12 @@ class m {
|
|
|
601
601
|
*/
|
|
602
602
|
static registerTexture = (t, e, s, r, i) => {
|
|
603
603
|
if (!e) {
|
|
604
|
-
|
|
604
|
+
h && console.error("!! gltf-progressive: Called register texture without texture");
|
|
605
605
|
return;
|
|
606
606
|
}
|
|
607
|
-
if (
|
|
608
|
-
const
|
|
609
|
-
console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${
|
|
607
|
+
if (h) {
|
|
608
|
+
const a = e.image?.width || e.source?.data?.width || 0, l = e.image?.height || e.source?.data?.height || 0;
|
|
609
|
+
console.log(`> gltf-progressive: register texture[${r}] "${e.name || e.uuid}", Current: ${a}x${l}, Max: ${i.lods[0]?.width}x${i.lods[0]?.height}, uuid: ${e.uuid}`, i, e);
|
|
610
610
|
}
|
|
611
611
|
e.source && (e.source[ue] = i);
|
|
612
612
|
const o = i.guid;
|
|
@@ -616,16 +616,16 @@ class m {
|
|
|
616
616
|
* Register a mesh with LOD information
|
|
617
617
|
*/
|
|
618
618
|
static registerMesh = (t, e, s, r, i, o) => {
|
|
619
|
-
const
|
|
620
|
-
if (!
|
|
621
|
-
|
|
619
|
+
const a = s.geometry;
|
|
620
|
+
if (!a) {
|
|
621
|
+
h && console.warn("gltf-progressive: Register mesh without geometry");
|
|
622
622
|
return;
|
|
623
623
|
}
|
|
624
|
-
|
|
624
|
+
a.userData || (a.userData = {}), h && console.log("> Progressive: register mesh " + s.name, { index: i, uuid: s.uuid }, o, s), m.assignLODInformation(t, a, e, r, i), m.lodInfos.set(e, o);
|
|
625
625
|
let u = m.lowresCache.get(e)?.deref();
|
|
626
|
-
u ? u.push(s.geometry) : u = [s.geometry], m.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && at(s,
|
|
627
|
-
for (const
|
|
628
|
-
|
|
626
|
+
u ? u.push(s.geometry) : u = [s.geometry], m.lowresCache.set(e, new WeakRef(u)), r > 0 && !ee(s) && at(s, a);
|
|
627
|
+
for (const d of q)
|
|
628
|
+
d.onRegisteredNewMesh?.(s, o);
|
|
629
629
|
};
|
|
630
630
|
/**
|
|
631
631
|
* Dispose cached resources to free memory.
|
|
@@ -652,7 +652,7 @@ class m {
|
|
|
652
652
|
for (const [s, r] of this.cache)
|
|
653
653
|
s.includes(t) && (this._disposeCacheEntry(r), this.cache.delete(s));
|
|
654
654
|
} else {
|
|
655
|
-
this.lodInfos.clear();
|
|
655
|
+
this.cacheGeneration++, this.lodInfos.clear();
|
|
656
656
|
for (const [, e] of this.lowresCache) {
|
|
657
657
|
const s = e.deref();
|
|
658
658
|
if (s) {
|
|
@@ -675,7 +675,7 @@ class m {
|
|
|
675
675
|
const e = t.deref();
|
|
676
676
|
e && (e.isTexture && this.textureRefCounts.delete(e.uuid), e.dispose());
|
|
677
677
|
} else
|
|
678
|
-
t.then((e) => {
|
|
678
|
+
this.disposedRequests.add(t), t.then((e) => {
|
|
679
679
|
if (e)
|
|
680
680
|
if (Array.isArray(e))
|
|
681
681
|
for (const s of e) s.dispose();
|
|
@@ -699,15 +699,15 @@ class m {
|
|
|
699
699
|
*/
|
|
700
700
|
static _resourceRegistry = new FinalizationRegistry((t) => {
|
|
701
701
|
const e = m.cache.get(t);
|
|
702
|
-
(
|
|
703
|
-
${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (
|
|
702
|
+
(h || K) && console.debug(`[gltf-progressive] Memory: Resource GC'd
|
|
703
|
+
${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (h || K) && console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")));
|
|
704
704
|
});
|
|
705
705
|
/**
|
|
706
706
|
* Track texture usage by incrementing reference count
|
|
707
707
|
*/
|
|
708
708
|
static trackTextureUsage(t) {
|
|
709
709
|
const e = t.uuid, s = this.textureRefCounts.get(e) || 0;
|
|
710
|
-
this.textureRefCounts.set(e, s + 1),
|
|
710
|
+
this.textureRefCounts.set(e, s + 1), h === "verbose" && console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s + 1}`);
|
|
711
711
|
}
|
|
712
712
|
/**
|
|
713
713
|
* Untrack texture usage by decrementing reference count.
|
|
@@ -717,165 +717,171 @@ ${t}`), e instanceof WeakRef && (e.deref() || (m.cache.delete(t), (f || K) && co
|
|
|
717
717
|
static untrackTextureUsage(t) {
|
|
718
718
|
const e = t.uuid, s = this.textureRefCounts.get(e);
|
|
719
719
|
if (!s)
|
|
720
|
-
return (
|
|
720
|
+
return (h === "verbose" || K) && i("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)", 0), t.dispose(), !0;
|
|
721
721
|
const r = s - 1;
|
|
722
722
|
if (r <= 0)
|
|
723
|
-
return this.textureRefCounts.delete(e), (
|
|
724
|
-
return this.textureRefCounts.set(e, r),
|
|
725
|
-
function i(o,
|
|
726
|
-
let
|
|
727
|
-
const
|
|
728
|
-
let
|
|
729
|
-
|
|
723
|
+
return this.textureRefCounts.delete(e), (h || K) && i("[gltf-progressive] Memory: Dispose texture", r), t.dispose(), !0;
|
|
724
|
+
return this.textureRefCounts.set(e, r), h === "verbose" && i("[gltf-progressive] Memory: Untrack texture", r), !1;
|
|
725
|
+
function i(o, a) {
|
|
726
|
+
let l = t.image?.width || t.source?.data?.width || 0, u = t.image?.height || t.source?.data?.height || 0;
|
|
727
|
+
const d = l && u ? `${l}x${u}` : "N/A";
|
|
728
|
+
let g = "N/A";
|
|
729
|
+
l && u && (g = `~${(it(t) / (1024 * 1024)).toFixed(2)} MB`), console.log(`${o} — ${t.name} ${d} (${g}), refCount: ${s} → ${a}
|
|
730
730
|
${e}`);
|
|
731
731
|
}
|
|
732
732
|
}
|
|
733
733
|
static workers = [];
|
|
734
|
+
static cacheGeneration = 0;
|
|
735
|
+
static disposedRequests = /* @__PURE__ */ new WeakSet();
|
|
734
736
|
static _workersIndex = 0;
|
|
735
737
|
static async getOrLoadLOD(t, e) {
|
|
736
|
-
const s =
|
|
737
|
-
if (!
|
|
738
|
-
return
|
|
739
|
-
const
|
|
740
|
-
let
|
|
738
|
+
const s = this.cacheGeneration, r = h == "verbose", i = this.getAssignedLODInformation(t);
|
|
739
|
+
if (!i)
|
|
740
|
+
return h && console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`, t), null;
|
|
741
|
+
const o = i?.key;
|
|
742
|
+
let a;
|
|
741
743
|
if (t.isTexture === !0) {
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
+
const u = t;
|
|
745
|
+
u.source && u.source[ue] && (a = u.source[ue]);
|
|
744
746
|
}
|
|
745
|
-
if (
|
|
746
|
-
|
|
747
|
+
if (a || (a = m.lodInfos.get(o)), !a)
|
|
748
|
+
h && console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`, t.type, m.lodInfos);
|
|
747
749
|
else {
|
|
748
750
|
if (e > 0) {
|
|
749
|
-
let
|
|
750
|
-
const y = Array.isArray(
|
|
751
|
-
if (y && e >=
|
|
752
|
-
const
|
|
753
|
-
if (
|
|
754
|
-
const
|
|
755
|
-
if (
|
|
756
|
-
this.lowresCache.delete(
|
|
751
|
+
let g = !1;
|
|
752
|
+
const y = Array.isArray(a.lods);
|
|
753
|
+
if (y && e >= a.lods.length ? g = !0 : y || (g = !0), g) {
|
|
754
|
+
const M = this.lowresCache.get(o);
|
|
755
|
+
if (M) {
|
|
756
|
+
const L = M.deref();
|
|
757
|
+
if (L) return L;
|
|
758
|
+
this.lowresCache.delete(o), h && console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${o}`);
|
|
757
759
|
}
|
|
758
760
|
return null;
|
|
759
761
|
}
|
|
760
762
|
}
|
|
761
|
-
const
|
|
762
|
-
if (!
|
|
763
|
-
return
|
|
764
|
-
const
|
|
765
|
-
if (
|
|
766
|
-
if (!
|
|
767
|
-
return console.warn("missing pointer for glb/gltf texture",
|
|
768
|
-
const
|
|
769
|
-
if (
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
763
|
+
const u = Array.isArray(a.lods) ? a.lods[e]?.path : a.lods;
|
|
764
|
+
if (!u)
|
|
765
|
+
return h && !a["missing:uri"] && (a["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + e, a)), null;
|
|
766
|
+
const d = st(i.url, u);
|
|
767
|
+
if (d.endsWith(".glb") || d.endsWith(".gltf")) {
|
|
768
|
+
if (!a.guid)
|
|
769
|
+
return console.warn("missing pointer for glb/gltf texture", a), null;
|
|
770
|
+
const g = d + "_" + a.guid, y = await this.queue.slot(d);
|
|
771
|
+
if (s !== this.cacheGeneration) return null;
|
|
772
|
+
const M = this.cache.get(g);
|
|
773
|
+
if (M !== void 0)
|
|
774
|
+
if (r && console.log(`LOD ${e} was already loading/loaded: ${g}`), M instanceof WeakRef) {
|
|
775
|
+
const f = M.deref();
|
|
776
|
+
if (f) {
|
|
777
|
+
let _ = f, D = !1;
|
|
778
|
+
if (_ instanceof F && t instanceof F ? _.image?.data || _.source?.data ? _ = this.copySettings(t, _) : D = !0 : _ instanceof E && t instanceof E && (_.attributes.position?.array || (D = !0)), !D)
|
|
779
|
+
return _;
|
|
776
780
|
}
|
|
777
|
-
this.cache.delete(
|
|
781
|
+
this.cache.delete(g), h && console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${g}`);
|
|
778
782
|
} else {
|
|
779
|
-
let
|
|
780
|
-
`,
|
|
781
|
-
if (
|
|
782
|
-
|
|
783
|
+
let f = await M.catch((D) => (console.error(`Error loading LOD ${e} from ${d}
|
|
784
|
+
`, D), null));
|
|
785
|
+
if (s !== this.cacheGeneration || this.disposedRequests.has(M)) return null;
|
|
786
|
+
let _ = !1;
|
|
787
|
+
if (f == null || (f instanceof F && t instanceof F ? f.image?.data || f.source?.data ? f = this.copySettings(t, f) : (_ = !0, this.cache.delete(g)) : f instanceof E && t instanceof E && (f.attributes.position?.array || (_ = !0, this.cache.delete(g)))), !_)
|
|
788
|
+
return f;
|
|
783
789
|
}
|
|
784
790
|
if (!y.use)
|
|
785
|
-
return
|
|
786
|
-
const
|
|
791
|
+
return h && console.log(`LOD ${e} was aborted: ${d}`), null;
|
|
792
|
+
const L = a, T = new Promise(async (f, _) => {
|
|
787
793
|
if (gt) {
|
|
788
|
-
const
|
|
789
|
-
if (
|
|
790
|
-
for (const
|
|
791
|
-
let
|
|
792
|
-
return m.assignLODInformation(
|
|
794
|
+
const c = await (await ft({})).load(d);
|
|
795
|
+
if (c.textures.length > 0)
|
|
796
|
+
for (const p of c.textures) {
|
|
797
|
+
let w = p.texture;
|
|
798
|
+
return m.assignLODInformation(i.url, w, o, e, void 0), t instanceof F && (w = this.copySettings(t, w)), w && (w.guid = L.guid), f(w);
|
|
793
799
|
}
|
|
794
|
-
if (
|
|
795
|
-
const
|
|
796
|
-
for (const
|
|
797
|
-
const
|
|
798
|
-
m.assignLODInformation(
|
|
800
|
+
if (c.geometries.length > 0) {
|
|
801
|
+
const p = new Array();
|
|
802
|
+
for (const w of c.geometries) {
|
|
803
|
+
const b = w.geometry;
|
|
804
|
+
m.assignLODInformation(i.url, b, o, e, w.primitiveIndex), p.push(b);
|
|
799
805
|
}
|
|
800
|
-
return
|
|
806
|
+
return f(p);
|
|
801
807
|
}
|
|
802
|
-
return
|
|
808
|
+
return f(null);
|
|
803
809
|
}
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
let
|
|
807
|
-
if (
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
+
const D = new xe();
|
|
811
|
+
Te(D), h && (await new Promise((S) => setTimeout(S, 1e3)), r && console.warn("Start loading (delayed) " + d, L.guid));
|
|
812
|
+
let I = d;
|
|
813
|
+
if (L && Array.isArray(L.lods)) {
|
|
814
|
+
const S = L.lods[e];
|
|
815
|
+
S.hash && (I += "?v=" + S.hash);
|
|
810
816
|
}
|
|
811
|
-
const
|
|
812
|
-
`,
|
|
813
|
-
if (!
|
|
814
|
-
return
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
let
|
|
818
|
-
if (
|
|
819
|
-
let
|
|
820
|
-
for (const
|
|
821
|
-
if (
|
|
822
|
-
const
|
|
823
|
-
if (
|
|
824
|
-
|
|
817
|
+
const C = await D.loadAsync(I).catch((S) => (console.error(`Error loading LOD ${e} from ${d}
|
|
818
|
+
`, S), f(null)));
|
|
819
|
+
if (!C)
|
|
820
|
+
return f(null);
|
|
821
|
+
const W = C.parser;
|
|
822
|
+
r && console.log("Loading finished " + d, L.guid);
|
|
823
|
+
let O = 0;
|
|
824
|
+
if (C.parser.json.textures) {
|
|
825
|
+
let S = !1;
|
|
826
|
+
for (const c of C.parser.json.textures) {
|
|
827
|
+
if (c?.extensions) {
|
|
828
|
+
const p = c?.extensions[U];
|
|
829
|
+
if (p?.guid && p.guid === L.guid) {
|
|
830
|
+
S = !0;
|
|
825
831
|
break;
|
|
826
832
|
}
|
|
827
833
|
}
|
|
828
|
-
|
|
834
|
+
O++;
|
|
829
835
|
}
|
|
830
|
-
if (
|
|
831
|
-
let
|
|
832
|
-
return
|
|
833
|
-
} else
|
|
836
|
+
if (S) {
|
|
837
|
+
let c = await W.getDependency("texture", O);
|
|
838
|
+
return c && m.assignLODInformation(i.url, c, o, e, void 0), r && console.log('change "' + t.name + '" → "' + c.name + '"', d, O, c, g), t instanceof F && (c = this.copySettings(t, c)), c && (c.guid = L.guid), f(c);
|
|
839
|
+
} else h && console.warn("Could not find texture with guid", L.guid, C.parser.json);
|
|
834
840
|
}
|
|
835
|
-
if (
|
|
836
|
-
let
|
|
837
|
-
for (const
|
|
838
|
-
if (
|
|
839
|
-
const
|
|
840
|
-
if (
|
|
841
|
-
|
|
841
|
+
if (O = 0, C.parser.json.meshes) {
|
|
842
|
+
let S = !1;
|
|
843
|
+
for (const c of C.parser.json.meshes) {
|
|
844
|
+
if (c?.extensions) {
|
|
845
|
+
const p = c?.extensions[U];
|
|
846
|
+
if (p?.guid && p.guid === L.guid) {
|
|
847
|
+
S = !0;
|
|
842
848
|
break;
|
|
843
849
|
}
|
|
844
850
|
}
|
|
845
|
-
|
|
851
|
+
O++;
|
|
846
852
|
}
|
|
847
|
-
if (
|
|
848
|
-
const
|
|
849
|
-
if (
|
|
850
|
-
const
|
|
851
|
-
return m.assignLODInformation(
|
|
853
|
+
if (S) {
|
|
854
|
+
const c = await W.getDependency("mesh", O);
|
|
855
|
+
if (r && console.log(`Loaded Mesh "${c.name}"`, d, O, c, g), c.isMesh === !0) {
|
|
856
|
+
const p = c.geometry;
|
|
857
|
+
return m.assignLODInformation(i.url, p, o, e, 0), f(p);
|
|
852
858
|
} else {
|
|
853
|
-
const
|
|
854
|
-
for (let
|
|
855
|
-
const
|
|
856
|
-
if (
|
|
857
|
-
const
|
|
858
|
-
m.assignLODInformation(
|
|
859
|
+
const p = new Array();
|
|
860
|
+
for (let w = 0; w < c.children.length; w++) {
|
|
861
|
+
const b = c.children[w];
|
|
862
|
+
if (b.isMesh === !0) {
|
|
863
|
+
const A = b.geometry;
|
|
864
|
+
m.assignLODInformation(i.url, A, o, e, w), p.push(A);
|
|
859
865
|
}
|
|
860
866
|
}
|
|
861
|
-
return
|
|
867
|
+
return f(p);
|
|
862
868
|
}
|
|
863
|
-
} else
|
|
869
|
+
} else h && console.warn("Could not find mesh with guid", L.guid, C.parser.json);
|
|
864
870
|
}
|
|
865
|
-
return
|
|
871
|
+
return f(null);
|
|
866
872
|
});
|
|
867
|
-
this.cache.set(
|
|
868
|
-
const
|
|
869
|
-
return
|
|
873
|
+
this.cache.set(g, T), y.use(T);
|
|
874
|
+
const x = await T;
|
|
875
|
+
return s !== this.cacheGeneration || this.cache.get(g) !== T ? null : (x != null ? x instanceof F ? (this.cache.set(g, new WeakRef(x)), m._resourceRegistry.register(x, g)) : Array.isArray(x) ? this.cache.set(g, Promise.resolve(x)) : this.cache.set(g, Promise.resolve(x)) : this.cache.set(g, Promise.resolve(null)), x);
|
|
870
876
|
} else if (t instanceof F) {
|
|
871
|
-
|
|
872
|
-
const y = await new
|
|
873
|
-
return y ? (y.guid =
|
|
877
|
+
r && console.log("Load texture from uri: " + d);
|
|
878
|
+
const y = await new qe().loadAsync(d);
|
|
879
|
+
return s !== this.cacheGeneration ? (y?.dispose(), null) : (y ? (y.guid = a.guid, y.flipY = !1, y.needsUpdate = !0, y.colorSpace = t.colorSpace, r && console.log(a, y)) : h && console.warn("failed loading", d), y);
|
|
874
880
|
}
|
|
875
881
|
}
|
|
876
882
|
return null;
|
|
877
883
|
}
|
|
878
|
-
static queue = new rt(50, { debug:
|
|
884
|
+
static queue = new rt(_e() ? 20 : 50, { debug: h != !1 });
|
|
879
885
|
static assignLODInformation(t, e, s, r, i) {
|
|
880
886
|
if (!e) return;
|
|
881
887
|
e.userData || (e.userData = {});
|
|
@@ -887,7 +893,7 @@ ${e}`);
|
|
|
887
893
|
}
|
|
888
894
|
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
889
895
|
static copySettings(t, e) {
|
|
890
|
-
return e ? (
|
|
896
|
+
return e ? (h === "verbose" && console.debug(`Copy texture settings
|
|
891
897
|
`, t.uuid, `
|
|
892
898
|
`, 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;
|
|
893
899
|
}
|
|
@@ -952,7 +958,7 @@ class ce {
|
|
|
952
958
|
_seen = /* @__PURE__ */ new WeakMap();
|
|
953
959
|
add(t, e, s) {
|
|
954
960
|
if (this._resolved) {
|
|
955
|
-
|
|
961
|
+
h && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
|
|
956
962
|
return;
|
|
957
963
|
}
|
|
958
964
|
if (!(this._frame_start !== void 0 && this._currentFrame > this._frame_start + this._frames_to_capture)) {
|
|
@@ -960,7 +966,7 @@ class ce {
|
|
|
960
966
|
if (this._seen.has(e)) {
|
|
961
967
|
let r = this._seen.get(e);
|
|
962
968
|
if (r >= this._maxPromisesPerObject) {
|
|
963
|
-
|
|
969
|
+
h && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
|
|
964
970
|
return;
|
|
965
971
|
}
|
|
966
972
|
this._seen.set(e, r + 1);
|
|
@@ -979,7 +985,7 @@ class ce {
|
|
|
979
985
|
});
|
|
980
986
|
}
|
|
981
987
|
}
|
|
982
|
-
const
|
|
988
|
+
const $ = N("debugprogressive"), mt = N("noprogressive"), de = /* @__PURE__ */ Symbol("Needle:LODSManager"), fe = /* @__PURE__ */ Symbol("Needle:LODState"), z = /* @__PURE__ */ Symbol("Needle:CurrentLOD"), P = { mesh_lod: -1, texture_lod: -1 };
|
|
983
989
|
class v {
|
|
984
990
|
/**
|
|
985
991
|
* 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.
|
|
@@ -990,11 +996,11 @@ class v {
|
|
|
990
996
|
return t[fe];
|
|
991
997
|
}
|
|
992
998
|
static addPlugin(t) {
|
|
993
|
-
|
|
999
|
+
q.push(t);
|
|
994
1000
|
}
|
|
995
1001
|
static removePlugin(t) {
|
|
996
|
-
const e =
|
|
997
|
-
e >= 0 &&
|
|
1002
|
+
const e = q.indexOf(t);
|
|
1003
|
+
e >= 0 && q.splice(e, 1);
|
|
998
1004
|
}
|
|
999
1005
|
/**
|
|
1000
1006
|
* Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
|
|
@@ -1012,10 +1018,10 @@ class v {
|
|
|
1012
1018
|
}
|
|
1013
1019
|
renderer;
|
|
1014
1020
|
context;
|
|
1015
|
-
projectionScreenMatrix = new
|
|
1021
|
+
projectionScreenMatrix = new ve();
|
|
1016
1022
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
1017
1023
|
get plugins() {
|
|
1018
|
-
return
|
|
1024
|
+
return q;
|
|
1019
1025
|
}
|
|
1020
1026
|
/**
|
|
1021
1027
|
* Force override the LOD level for all objects (meshes + textures) rendered in the scene
|
|
@@ -1061,7 +1067,7 @@ class v {
|
|
|
1061
1067
|
const r = performance.now();
|
|
1062
1068
|
return s.ready.finally(() => {
|
|
1063
1069
|
const i = this._newPromiseGroups.indexOf(s);
|
|
1064
|
-
i >= 0 && (this._newPromiseGroups.splice(i, 1),
|
|
1070
|
+
i >= 0 && (this._newPromiseGroups.splice(i, 1), be() && performance.measure("LODsManager:awaitLoading", {
|
|
1065
1071
|
start: r,
|
|
1066
1072
|
detail: { id: e, name: t?.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
|
|
1067
1073
|
}));
|
|
@@ -1087,7 +1093,7 @@ class v {
|
|
|
1087
1093
|
this.renderer = t, this.context = { ...e };
|
|
1088
1094
|
}
|
|
1089
1095
|
#t;
|
|
1090
|
-
#o = new
|
|
1096
|
+
#o = new Ne();
|
|
1091
1097
|
#r = 0;
|
|
1092
1098
|
#i = 0;
|
|
1093
1099
|
#n = 0;
|
|
@@ -1104,7 +1110,7 @@ class v {
|
|
|
1104
1110
|
const e = this;
|
|
1105
1111
|
we(this.renderer), this.renderer.render = function(s, r) {
|
|
1106
1112
|
const i = e.renderer.getRenderTarget();
|
|
1107
|
-
(i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#o.getDelta(), e.#n += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((
|
|
1113
|
+
(i == null || "isXRRenderTarget" in i && i.isXRRenderTarget) && (t = 0, e.#r += 1, e.#i = e.#o.getDelta(), e.#n += e.#i, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#i), e.#s = e._fpsBuffer.reduce((a, l) => a + l) / e._fpsBuffer.length, $ && e.#r % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
|
|
1108
1114
|
const o = t++;
|
|
1109
1115
|
e.#t.call(this, s, r), e.onAfterRender(s, r, o);
|
|
1110
1116
|
};
|
|
@@ -1120,11 +1126,11 @@ class v {
|
|
|
1120
1126
|
const i = this.renderer.renderLists.get(t, 0).opaque;
|
|
1121
1127
|
let o = !0;
|
|
1122
1128
|
if (i.length === 1) {
|
|
1123
|
-
const
|
|
1124
|
-
(
|
|
1129
|
+
const a = i[0].material;
|
|
1130
|
+
(a.name === "EffectMaterial" || a.name === "CopyShader") && (o = !1);
|
|
1125
1131
|
}
|
|
1126
1132
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (o = !1), o) {
|
|
1127
|
-
if (mt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1,
|
|
1133
|
+
if (mt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, $ && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, $ && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#r % this.#e != 0))
|
|
1128
1134
|
return;
|
|
1129
1135
|
this.internalUpdate(t, e), this._postprocessPromiseGroups();
|
|
1130
1136
|
}
|
|
@@ -1136,12 +1142,12 @@ class v {
|
|
|
1136
1142
|
const s = this.renderer.renderLists.get(t, 0), r = s.opaque;
|
|
1137
1143
|
this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix, e.matrixWorldInverse);
|
|
1138
1144
|
const i = this.targetTriangleDensity;
|
|
1139
|
-
for (const
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1145
|
+
for (const l of r) {
|
|
1146
|
+
if (l.material && (l.geometry?.type === "BoxGeometry" || l.geometry?.type === "BufferGeometry") && (l.material.name === "SphericalGaussianBlur" || l.material.name == "BackgroundCubeMaterial" || l.material.name === "CubemapFromEquirect" || l.material.name === "EquirectangularToCubeUV")) {
|
|
1147
|
+
$ && (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", l, l.material.name, l.material.type)));
|
|
1142
1148
|
continue;
|
|
1143
1149
|
}
|
|
1144
|
-
switch (
|
|
1150
|
+
switch (l.material.type) {
|
|
1145
1151
|
case "LineBasicMaterial":
|
|
1146
1152
|
case "LineDashedMaterial":
|
|
1147
1153
|
case "PointsMaterial":
|
|
@@ -1150,22 +1156,22 @@ class v {
|
|
|
1150
1156
|
case "MeshDepthMaterial":
|
|
1151
1157
|
continue;
|
|
1152
1158
|
}
|
|
1153
|
-
if (
|
|
1154
|
-
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1159
|
+
if ($ === "color" && l.material && !l.object.progressive_debug_color) {
|
|
1160
|
+
l.object.progressive_debug_color = !0;
|
|
1161
|
+
const d = Math.random() * 16777215, g = new Ve({ color: d });
|
|
1162
|
+
l.object.material = g;
|
|
1157
1163
|
}
|
|
1158
|
-
const u =
|
|
1164
|
+
const u = l.object;
|
|
1159
1165
|
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1160
1166
|
}
|
|
1161
1167
|
const o = s.transparent;
|
|
1162
|
-
for (const
|
|
1163
|
-
const u =
|
|
1168
|
+
for (const l of o) {
|
|
1169
|
+
const u = l.object;
|
|
1164
1170
|
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1165
1171
|
}
|
|
1166
|
-
const
|
|
1167
|
-
for (const
|
|
1168
|
-
const u =
|
|
1172
|
+
const a = s.transmissive;
|
|
1173
|
+
for (const l of a) {
|
|
1174
|
+
const u = l.object;
|
|
1169
1175
|
(u instanceof X || u.isMesh) && this.updateLODs(t, e, u, i);
|
|
1170
1176
|
}
|
|
1171
1177
|
}
|
|
@@ -1175,13 +1181,13 @@ class v {
|
|
|
1175
1181
|
let i = s[fe];
|
|
1176
1182
|
if (i || (i = new yt(), s[fe] = i), i.frames++ < 2)
|
|
1177
1183
|
return;
|
|
1178
|
-
for (const
|
|
1179
|
-
|
|
1184
|
+
for (const a of q)
|
|
1185
|
+
a.onBeforeUpdateLOD?.(this.renderer, t, e, s);
|
|
1180
1186
|
const o = this.overrideLodLevel !== void 0 ? this.overrideLodLevel : V;
|
|
1181
|
-
o >= 0 ? (
|
|
1182
|
-
for (const
|
|
1183
|
-
|
|
1184
|
-
i.lastLodLevel_Mesh =
|
|
1187
|
+
o >= 0 ? (P.mesh_lod = o, P.texture_lod = o) : (this.calculateLodLevel(e, s, i, r, P), P.mesh_lod = Math.round(P.mesh_lod), P.texture_lod = Math.round(P.texture_lod)), P.mesh_lod >= 0 && this.loadProgressiveMeshes(s, P.mesh_lod), s.material && P.texture_lod >= 0 && this.loadProgressiveTextures(s.material, P.texture_lod, o), h && s.material && !s.isGizmo && ke(s.material);
|
|
1188
|
+
for (const a of q)
|
|
1189
|
+
a.onAfterUpdatedLOD?.(this.renderer, t, e, s, P);
|
|
1190
|
+
i.lastLodLevel_Mesh = P.mesh_lod, i.lastLodLevel_Texture = P.texture_lod;
|
|
1185
1191
|
}
|
|
1186
1192
|
/** Load progressive textures for the given material
|
|
1187
1193
|
* @param material the material to load the textures for
|
|
@@ -1196,10 +1202,10 @@ class v {
|
|
|
1196
1202
|
return;
|
|
1197
1203
|
}
|
|
1198
1204
|
let r = !1;
|
|
1199
|
-
if ((t[
|
|
1200
|
-
t[
|
|
1205
|
+
if ((t[z] === void 0 || e < t[z]) && (r = !0), s !== void 0 && s >= 0 && (r = t[z] != s, e = s), r) {
|
|
1206
|
+
t[z] = e;
|
|
1201
1207
|
const i = m.assignTextureLOD(t, e).then((o) => {
|
|
1202
|
-
this._lodchangedlisteners.forEach((
|
|
1208
|
+
this._lodchangedlisteners.forEach((a) => a({ type: "texture", level: e, object: t }));
|
|
1203
1209
|
});
|
|
1204
1210
|
ce.addPromise("texture", t, i, this._newPromiseGroups);
|
|
1205
1211
|
}
|
|
@@ -1212,28 +1218,28 @@ class v {
|
|
|
1212
1218
|
*/
|
|
1213
1219
|
loadProgressiveMeshes(t, e) {
|
|
1214
1220
|
if (!t) return Promise.resolve(null);
|
|
1215
|
-
let s = t[
|
|
1221
|
+
let s = t[z] !== e;
|
|
1216
1222
|
const r = t["DEBUG:LOD"];
|
|
1217
|
-
if (r != null && (s = t[
|
|
1218
|
-
t[
|
|
1219
|
-
const i = t.geometry, o = m.assignMeshLOD(t, e).then((
|
|
1223
|
+
if (r != null && (s = t[z] != r, e = r), s) {
|
|
1224
|
+
t[z] = e;
|
|
1225
|
+
const i = t.geometry, o = m.assignMeshLOD(t, e).then((a) => (a && t[z] == e && i != t.geometry && this._lodchangedlisteners.forEach((l) => l({ type: "mesh", level: e, object: t })), a));
|
|
1220
1226
|
return ce.addPromise("mesh", t, o, this._newPromiseGroups), o;
|
|
1221
1227
|
}
|
|
1222
1228
|
return Promise.resolve(null);
|
|
1223
1229
|
}
|
|
1224
1230
|
// private testIfLODLevelsAreAvailable() {
|
|
1225
|
-
_sphere = new
|
|
1231
|
+
_sphere = new Se();
|
|
1226
1232
|
_tempBox = new ge();
|
|
1227
1233
|
_tempBox2 = new ge();
|
|
1228
|
-
tempMatrix = new
|
|
1229
|
-
_tempWorldPosition = new
|
|
1230
|
-
_tempBoxSize = new
|
|
1231
|
-
_tempBox2Size = new
|
|
1232
|
-
static corner0 = new
|
|
1233
|
-
static corner1 = new
|
|
1234
|
-
static corner2 = new
|
|
1235
|
-
static corner3 = new
|
|
1236
|
-
static _tempPtInside = new
|
|
1234
|
+
tempMatrix = new ve();
|
|
1235
|
+
_tempWorldPosition = new R();
|
|
1236
|
+
_tempBoxSize = new R();
|
|
1237
|
+
_tempBox2Size = new R();
|
|
1238
|
+
static corner0 = new R();
|
|
1239
|
+
static corner1 = new R();
|
|
1240
|
+
static corner2 = new R();
|
|
1241
|
+
static corner3 = new R();
|
|
1242
|
+
static _tempPtInside = new R();
|
|
1237
1243
|
static isInside(t, e) {
|
|
1238
1244
|
const s = t.min, r = t.max, i = (s.x + r.x) * 0.5, o = (s.y + r.y) * 0.5;
|
|
1239
1245
|
return this._tempPtInside.set(i, o, s.z).applyMatrix4(e).z < 0;
|
|
@@ -1250,105 +1256,105 @@ class v {
|
|
|
1250
1256
|
i.mesh_lod = -1, i.texture_lod = -1;
|
|
1251
1257
|
return;
|
|
1252
1258
|
}
|
|
1253
|
-
let
|
|
1254
|
-
if (
|
|
1259
|
+
let a = 10 + 1, l = !1;
|
|
1260
|
+
if ($ && e["DEBUG:LOD"] != null)
|
|
1255
1261
|
return e["DEBUG:LOD"];
|
|
1256
|
-
const u = m.getMeshLODExtension(e.geometry)?.lods,
|
|
1257
|
-
if (!
|
|
1262
|
+
const u = m.getMeshLODExtension(e.geometry)?.lods, d = m.getPrimitiveIndex(e.geometry), g = u && u.length > 0, y = m.getMaterialMinMaxLODsCount(e.material), M = y.min_count !== 1 / 0 && y.min_count >= 0 && y.max_count >= 0;
|
|
1263
|
+
if (!g && !M) {
|
|
1258
1264
|
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1259
1265
|
return;
|
|
1260
1266
|
}
|
|
1261
|
-
|
|
1262
|
-
const
|
|
1263
|
-
let
|
|
1267
|
+
g || (l = !0, a = 0);
|
|
1268
|
+
const L = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
|
|
1269
|
+
let T = e.geometry.boundingBox;
|
|
1264
1270
|
if (e.type === "SkinnedMesh") {
|
|
1265
|
-
const
|
|
1266
|
-
if (!
|
|
1267
|
-
|
|
1271
|
+
const x = e;
|
|
1272
|
+
if (!x.boundingBox)
|
|
1273
|
+
x.computeBoundingBox();
|
|
1268
1274
|
else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
|
|
1269
|
-
if (!
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1275
|
+
if (!x[v.$skinnedMeshBoundsOffset]) {
|
|
1276
|
+
const _ = v.skinnedMeshBoundsFrameOffsetCounter++;
|
|
1277
|
+
x[v.$skinnedMeshBoundsOffset] = _;
|
|
1272
1278
|
}
|
|
1273
|
-
const
|
|
1274
|
-
if ((s.frames +
|
|
1275
|
-
const
|
|
1276
|
-
|
|
1279
|
+
const f = x[v.$skinnedMeshBoundsOffset];
|
|
1280
|
+
if ((s.frames + f) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
|
|
1281
|
+
const _ = ee(x), D = x.geometry;
|
|
1282
|
+
_ && (x.geometry = _), x.computeBoundingBox(), x.geometry = D;
|
|
1277
1283
|
}
|
|
1278
1284
|
}
|
|
1279
|
-
|
|
1285
|
+
T = x.boundingBox;
|
|
1280
1286
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
const
|
|
1287
|
+
if (T) {
|
|
1288
|
+
const x = t;
|
|
1283
1289
|
if (e.geometry.attributes.color && e.geometry.attributes.color.count < 100 && e.geometry.boundingSphere) {
|
|
1284
1290
|
this._sphere.copy(e.geometry.boundingSphere), this._sphere.applyMatrix4(e.matrixWorld);
|
|
1285
|
-
const
|
|
1286
|
-
if (this._sphere.containsPoint(
|
|
1291
|
+
const c = t.getWorldPosition(this._tempWorldPosition);
|
|
1292
|
+
if (this._sphere.containsPoint(c)) {
|
|
1287
1293
|
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1288
1294
|
return;
|
|
1289
1295
|
}
|
|
1290
1296
|
}
|
|
1291
|
-
if (this._tempBox.copy(
|
|
1297
|
+
if (this._tempBox.copy(T), this._tempBox.applyMatrix4(e.matrixWorld), x.isPerspectiveCamera && v.isInside(this._tempBox, this.projectionScreenMatrix)) {
|
|
1292
1298
|
i.mesh_lod = 0, i.texture_lod = 0;
|
|
1293
1299
|
return;
|
|
1294
1300
|
}
|
|
1295
|
-
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled &&
|
|
1296
|
-
const
|
|
1297
|
-
let
|
|
1298
|
-
const te = 2, ne = 1.5, se = (
|
|
1299
|
-
|
|
1300
|
-
const $e =
|
|
1301
|
+
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && x.isPerspectiveCamera && x.fov > 70) {
|
|
1302
|
+
const c = this._tempBox.min, p = this._tempBox.max;
|
|
1303
|
+
let w = c.x, b = c.y, A = p.x, Y = p.y;
|
|
1304
|
+
const te = 2, ne = 1.5, se = (c.x + p.x) * 0.5, re = (c.y + p.y) * 0.5;
|
|
1305
|
+
w = (w - se) * te + se, b = (b - re) * te + re, A = (A - se) * te + se, Y = (Y - re) * te + re;
|
|
1306
|
+
const $e = w < 0 && A > 0 ? 0 : Math.min(Math.abs(c.x), Math.abs(p.x)), Be = b < 0 && Y > 0 ? 0 : Math.min(Math.abs(c.y), Math.abs(p.y)), ae = Math.max($e, Be);
|
|
1301
1307
|
s.lastCentrality = (ne - ae) * (ne - ae) * (ne - ae);
|
|
1302
1308
|
} else
|
|
1303
1309
|
s.lastCentrality = 1;
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1308
|
-
const
|
|
1309
|
-
if (Math.max(
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
const p = v.corner0,
|
|
1313
|
-
p.copy(this._tempBox.min),
|
|
1314
|
-
const Y = (p.z +
|
|
1315
|
-
p.z =
|
|
1310
|
+
const f = this._tempBox.getSize(this._tempBoxSize);
|
|
1311
|
+
f.multiplyScalar(0.5), screen.availHeight > 0 && L > 0 && f.multiplyScalar(L / screen.availHeight), t.isPerspectiveCamera ? f.x *= t.aspect : t.isOrthographicCamera;
|
|
1312
|
+
const _ = t.matrixWorldInverse, D = this._tempBox2;
|
|
1313
|
+
D.copy(T), D.applyMatrix4(e.matrixWorld), D.applyMatrix4(_);
|
|
1314
|
+
const I = D.getSize(this._tempBox2Size), C = Math.max(I.x, I.y);
|
|
1315
|
+
if (Math.max(f.x, f.y) != 0 && C != 0 && (f.z = I.z / Math.max(I.x, I.y) * Math.max(f.x, f.y)), s.lastScreenCoverage = Math.max(f.x, f.y, f.z), s.lastScreenspaceVolume.copy(f), s.lastScreenCoverage *= s.lastCentrality, $ && v.debugDrawLine) {
|
|
1316
|
+
const c = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
1317
|
+
c.invert();
|
|
1318
|
+
const p = v.corner0, w = v.corner1, b = v.corner2, A = v.corner3;
|
|
1319
|
+
p.copy(this._tempBox.min), w.copy(this._tempBox.max), w.x = p.x, b.copy(this._tempBox.max), b.y = p.y, A.copy(this._tempBox.max);
|
|
1320
|
+
const Y = (p.z + A.z) * 0.5;
|
|
1321
|
+
p.z = w.z = b.z = A.z = Y, p.applyMatrix4(c), w.applyMatrix4(c), b.applyMatrix4(c), A.applyMatrix4(c), v.debugDrawLine(p, w, 255), v.debugDrawLine(p, b, 255), v.debugDrawLine(w, A, 255), v.debugDrawLine(b, A, 255);
|
|
1316
1322
|
}
|
|
1317
|
-
let
|
|
1323
|
+
let O = 999;
|
|
1318
1324
|
if (u && s.lastScreenCoverage > 0)
|
|
1319
|
-
for (let
|
|
1320
|
-
const p = u[
|
|
1321
|
-
if (
|
|
1322
|
-
|
|
1325
|
+
for (let c = 0; c < u.length; c++) {
|
|
1326
|
+
const p = u[c], b = (p.densities?.[d] || p.density || 1e-5) / s.lastScreenCoverage;
|
|
1327
|
+
if (d > 0 && be() && !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.")), b < r) {
|
|
1328
|
+
O = c;
|
|
1323
1329
|
break;
|
|
1324
1330
|
}
|
|
1325
1331
|
}
|
|
1326
|
-
|
|
1332
|
+
O < a && (a = O, l = !0);
|
|
1327
1333
|
}
|
|
1328
|
-
if (
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1334
|
+
if (l ? i.mesh_lod = a : i.mesh_lod = s.lastLodLevel_Mesh, $ && i.mesh_lod != s.lastLodLevel_Mesh) {
|
|
1335
|
+
const f = u?.[i.mesh_lod];
|
|
1336
|
+
f && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${i.mesh_lod} (density: ${f.densities?.[d].toFixed(0)}) | ${e.name}`);
|
|
1331
1337
|
}
|
|
1332
|
-
if (
|
|
1333
|
-
const
|
|
1338
|
+
if (M) {
|
|
1339
|
+
const x = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
1334
1340
|
if (s.lastLodLevel_Texture < 0) {
|
|
1335
|
-
if (i.texture_lod =
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1341
|
+
if (i.texture_lod = y.max_count - 1, $) {
|
|
1342
|
+
const f = y.lods[y.max_count - 1];
|
|
1343
|
+
$ && console.log(`First Texture LOD ${i.texture_lod} (${f.max_height}px) - ${e.name}`);
|
|
1338
1344
|
}
|
|
1339
1345
|
} else {
|
|
1340
|
-
const
|
|
1341
|
-
let
|
|
1342
|
-
this.context?.engine === "model-viewer" && (
|
|
1343
|
-
const
|
|
1344
|
-
let
|
|
1345
|
-
for (let
|
|
1346
|
-
const
|
|
1347
|
-
if (!(
|
|
1348
|
-
if (
|
|
1349
|
-
const
|
|
1350
|
-
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${
|
|
1351
|
-
Screensize: ${
|
|
1346
|
+
const f = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
1347
|
+
let _ = s.lastScreenCoverage * 4;
|
|
1348
|
+
this.context?.engine === "model-viewer" && (_ *= 1.5);
|
|
1349
|
+
const I = L / window.devicePixelRatio * _;
|
|
1350
|
+
let C = !1;
|
|
1351
|
+
for (let W = y.lods.length - 1; W >= 0; W--) {
|
|
1352
|
+
const O = y.lods[W];
|
|
1353
|
+
if (!(x && O.max_height >= 2048) && !(_e() && O.max_height > 4096) && (O.max_height > I || !C && W === 0)) {
|
|
1354
|
+
if (C = !0, i.texture_lod = W, $ && i.texture_lod < s.lastLodLevel_Texture) {
|
|
1355
|
+
const S = O.max_height;
|
|
1356
|
+
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${i.texture_lod} = ${S}px
|
|
1357
|
+
Screensize: ${I.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${f.toFixed(1)}
|
|
1352
1358
|
${e.name}`);
|
|
1353
1359
|
}
|
|
1354
1360
|
break;
|
|
@@ -1364,16 +1370,16 @@ class yt {
|
|
|
1364
1370
|
lastLodLevel_Mesh = -1;
|
|
1365
1371
|
lastLodLevel_Texture = -1;
|
|
1366
1372
|
lastScreenCoverage = 0;
|
|
1367
|
-
lastScreenspaceVolume = new
|
|
1373
|
+
lastScreenspaceVolume = new R();
|
|
1368
1374
|
lastCentrality = 0;
|
|
1369
1375
|
}
|
|
1370
|
-
const
|
|
1376
|
+
const Me = /* @__PURE__ */ Symbol("NEEDLE_mesh_lod"), ie = /* @__PURE__ */ Symbol("NEEDLE_texture_lod");
|
|
1371
1377
|
let he = null;
|
|
1372
1378
|
function Re() {
|
|
1373
1379
|
const n = xt();
|
|
1374
1380
|
n && (n.mapURLs(function(t) {
|
|
1375
|
-
return
|
|
1376
|
-
}),
|
|
1381
|
+
return De(), t;
|
|
1382
|
+
}), De(), he?.disconnect(), he = new MutationObserver((t) => {
|
|
1377
1383
|
t.forEach((e) => {
|
|
1378
1384
|
e.addedNodes.forEach((s) => {
|
|
1379
1385
|
s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Ie(s);
|
|
@@ -1388,30 +1394,30 @@ function xt() {
|
|
|
1388
1394
|
console.debug("[gltf-progressive] model-viewer defined"), Re();
|
|
1389
1395
|
}), null);
|
|
1390
1396
|
}
|
|
1391
|
-
function
|
|
1397
|
+
function De() {
|
|
1392
1398
|
if (typeof document > "u") return;
|
|
1393
1399
|
document.querySelectorAll("model-viewer").forEach((t) => {
|
|
1394
1400
|
Ie(t);
|
|
1395
1401
|
});
|
|
1396
1402
|
}
|
|
1397
|
-
const
|
|
1403
|
+
const Oe = /* @__PURE__ */ new WeakSet();
|
|
1398
1404
|
let wt = 0;
|
|
1399
1405
|
function Ie(n) {
|
|
1400
|
-
if (!n ||
|
|
1406
|
+
if (!n || Oe.has(n))
|
|
1401
1407
|
return null;
|
|
1402
|
-
|
|
1408
|
+
Oe.add(n), console.debug("[gltf-progressive] found new model-viewer..." + ++wt + `
|
|
1403
1409
|
`, n.getAttribute("src"));
|
|
1404
1410
|
let t = null, e = null, s = null;
|
|
1405
1411
|
for (let r = n; r != null; r = Object.getPrototypeOf(r)) {
|
|
1406
|
-
const i = Object.getOwnPropertySymbols(r), o = i.find((u) => u.toString() == "Symbol(renderer)"),
|
|
1407
|
-
!t && o != null && (t = n[o].threeRenderer), !e &&
|
|
1412
|
+
const i = Object.getOwnPropertySymbols(r), o = i.find((u) => u.toString() == "Symbol(renderer)"), a = i.find((u) => u.toString() == "Symbol(scene)"), l = i.find((u) => u.toString() == "Symbol(needsRender)");
|
|
1413
|
+
!t && o != null && (t = n[o].threeRenderer), !e && a != null && (e = n[a]), !s && l != null && (s = n[l]);
|
|
1408
1414
|
}
|
|
1409
1415
|
if (t && e) {
|
|
1410
1416
|
let r = function() {
|
|
1411
1417
|
if (s) {
|
|
1412
|
-
let o = 0,
|
|
1418
|
+
let o = 0, a = setInterval(() => {
|
|
1413
1419
|
if (o++ > 5) {
|
|
1414
|
-
clearInterval(
|
|
1420
|
+
clearInterval(a);
|
|
1415
1421
|
return;
|
|
1416
1422
|
}
|
|
1417
1423
|
s?.call(n);
|
|
@@ -1454,39 +1460,39 @@ class _t {
|
|
|
1454
1460
|
e[ie] = !0;
|
|
1455
1461
|
const s = this.tryGetCurrentGLTF(t), r = this.tryGetCurrentModelViewer(t), i = this.getUrl(r);
|
|
1456
1462
|
if (i && s && e.material) {
|
|
1457
|
-
let o = function(
|
|
1458
|
-
if (
|
|
1459
|
-
|
|
1460
|
-
const u = Object.keys(
|
|
1461
|
-
for (let
|
|
1462
|
-
const
|
|
1463
|
-
if (
|
|
1464
|
-
const
|
|
1465
|
-
if (
|
|
1466
|
-
const
|
|
1467
|
-
if (!
|
|
1468
|
-
console.warn("Texture data not found for texture index " +
|
|
1463
|
+
let o = function(l) {
|
|
1464
|
+
if (l[ie] == !0) return;
|
|
1465
|
+
l[ie] = !0, l.userData && (l.userData.LOD = -1);
|
|
1466
|
+
const u = Object.keys(l);
|
|
1467
|
+
for (let d = 0; d < u.length; d++) {
|
|
1468
|
+
const g = u[d], y = l[g];
|
|
1469
|
+
if (y?.isTexture === !0) {
|
|
1470
|
+
const M = y.userData?.associations?.textures;
|
|
1471
|
+
if (M == null) continue;
|
|
1472
|
+
const L = s.parser.json.textures[M];
|
|
1473
|
+
if (!L) {
|
|
1474
|
+
console.warn("Texture data not found for texture index " + M);
|
|
1469
1475
|
continue;
|
|
1470
1476
|
}
|
|
1471
|
-
if (
|
|
1472
|
-
const
|
|
1473
|
-
|
|
1477
|
+
if (L?.extensions?.[U]) {
|
|
1478
|
+
const T = L.extensions[U];
|
|
1479
|
+
T && i && m.registerTexture(i, y, T.lods.length, M, T);
|
|
1474
1480
|
}
|
|
1475
1481
|
}
|
|
1476
1482
|
}
|
|
1477
1483
|
};
|
|
1478
|
-
const
|
|
1479
|
-
if (Array.isArray(
|
|
1480
|
-
else o(
|
|
1484
|
+
const a = e.material;
|
|
1485
|
+
if (Array.isArray(a)) for (const l of a) o(l);
|
|
1486
|
+
else o(a);
|
|
1481
1487
|
}
|
|
1482
1488
|
}
|
|
1483
1489
|
tryParseMeshLOD(t, e) {
|
|
1484
|
-
if (e[
|
|
1485
|
-
e[
|
|
1490
|
+
if (e[Me] == !0) return;
|
|
1491
|
+
e[Me] = !0;
|
|
1486
1492
|
const s = this.tryGetCurrentModelViewer(t), r = this.getUrl(s);
|
|
1487
1493
|
if (!r)
|
|
1488
1494
|
return;
|
|
1489
|
-
const i = e.userData?.gltfExtensions?.[
|
|
1495
|
+
const i = e.userData?.gltfExtensions?.[U];
|
|
1490
1496
|
if (i && r) {
|
|
1491
1497
|
const o = e.uuid;
|
|
1492
1498
|
m.registerMesh(r, o, e, 0, i.lods.length, i);
|
|
@@ -1508,7 +1514,7 @@ function Lt(...n) {
|
|
|
1508
1514
|
default:
|
|
1509
1515
|
throw new Error("Invalid arguments");
|
|
1510
1516
|
}
|
|
1511
|
-
we(e),
|
|
1517
|
+
we(e), Te(s), Ae(s, {
|
|
1512
1518
|
progressive: !0,
|
|
1513
1519
|
...r?.hints
|
|
1514
1520
|
}), s.register((o) => new m(o));
|
|
@@ -1521,7 +1527,7 @@ if (!nt) {
|
|
|
1521
1527
|
gltfProgressive: {
|
|
1522
1528
|
useNeedleProgressive: Lt,
|
|
1523
1529
|
LODsManager: v,
|
|
1524
|
-
configureLoader:
|
|
1530
|
+
configureLoader: Ae,
|
|
1525
1531
|
getRaycastMesh: ee,
|
|
1526
1532
|
useRaycastMeshes: lt
|
|
1527
1533
|
}
|
|
@@ -1533,12 +1539,12 @@ if (!nt) {
|
|
|
1533
1539
|
globalThis.Needle[t] = n[t];
|
|
1534
1540
|
}
|
|
1535
1541
|
export {
|
|
1536
|
-
|
|
1542
|
+
U as EXTENSION_NAME,
|
|
1537
1543
|
v as LODsManager,
|
|
1538
1544
|
m as NEEDLE_progressive,
|
|
1539
1545
|
Ke as VERSION,
|
|
1540
|
-
|
|
1541
|
-
|
|
1546
|
+
Te as addDracoAndKTX2Loaders,
|
|
1547
|
+
Ae as configureLoader,
|
|
1542
1548
|
we as createLoaders,
|
|
1543
1549
|
ee as getRaycastMesh,
|
|
1544
1550
|
Re as patchModelViewer,
|