@needle-tools/gltf-progressive 1.2.0-alpha.7 → 1.2.0-alpha.8
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 +2 -1
- package/gltf-progressive.js +121 -117
- package/gltf-progressive.min.js +4 -4
- package/gltf-progressive.umd.cjs +4 -4
- package/lib/lods_manager.js +7 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,9 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [1.2.0-alpha.
|
|
7
|
+
## [1.2.0-alpha.8] - 2023-06-13
|
|
8
8
|
- fix: issue where skinned mesh matrix was falsely applied to calculate screen size
|
|
9
|
+
- fix: use bounding box from SkinnedMesh object
|
|
9
10
|
|
|
10
11
|
## [1.2.0-alpha.6] - 2023-06-12
|
|
11
12
|
- fix: minor bug where opened glTF has `NEEDLE_progressive` extension but no lods array because the glTF is a LOD variant
|
package/gltf-progressive.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var c = (l, e, t) => (
|
|
1
|
+
var xe = Object.defineProperty;
|
|
2
|
+
var me = (l, e, t) => e in l ? xe(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
|
|
3
|
+
var c = (l, e, t) => (me(l, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import { MeshoptDecoder as Le } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
5
5
|
import { DRACOLoader as De } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
6
6
|
import { KTX2Loader as Me } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
@@ -76,8 +76,8 @@ function Pe(l) {
|
|
|
76
76
|
e.setAttribute(t, l.getAttribute(t));
|
|
77
77
|
return e.setIndex(l.getIndex()), e;
|
|
78
78
|
}
|
|
79
|
-
const I = new Array(),
|
|
80
|
-
if (
|
|
79
|
+
const I = new Array(), R = "NEEDLE_progressive", M = j("debugprogressive"), se = Symbol("needle-progressive-texture"), V = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Set();
|
|
80
|
+
if (M) {
|
|
81
81
|
let l = function() {
|
|
82
82
|
e += 1, console.log("Toggle LOD level", e, V), V.forEach((i, n) => {
|
|
83
83
|
for (const s of i.keys) {
|
|
@@ -100,7 +100,7 @@ if (D) {
|
|
|
100
100
|
}
|
|
101
101
|
function ue(l, e, t) {
|
|
102
102
|
var i;
|
|
103
|
-
if (!
|
|
103
|
+
if (!M)
|
|
104
104
|
return;
|
|
105
105
|
V.has(l) || V.set(l, { keys: [], sourceId: t });
|
|
106
106
|
const r = V.get(l);
|
|
@@ -115,14 +115,14 @@ const _ = class {
|
|
|
115
115
|
var r, i;
|
|
116
116
|
if (this._isLoadingMesh)
|
|
117
117
|
return null;
|
|
118
|
-
const t = (i = (r = this.parser.json.meshes[e]) == null ? void 0 : r.extensions) == null ? void 0 : i[
|
|
118
|
+
const t = (i = (r = this.parser.json.meshes[e]) == null ? void 0 : r.extensions) == null ? void 0 : i[R];
|
|
119
119
|
return t ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", e).then((n) => (this._isLoadingMesh = !1, n && _.registerMesh(this.url, t.guid, n, t.lods.length, void 0, t), n))) : null;
|
|
120
120
|
});
|
|
121
|
-
|
|
121
|
+
M && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
|
|
122
122
|
}
|
|
123
123
|
/** The name of the extension */
|
|
124
124
|
get name() {
|
|
125
|
-
return
|
|
125
|
+
return R;
|
|
126
126
|
}
|
|
127
127
|
static getMeshLODInformation(e) {
|
|
128
128
|
const t = this.getAssignedLODInformation(e);
|
|
@@ -141,7 +141,7 @@ const _ = class {
|
|
|
141
141
|
this.getMaterialMinMaxLODsCount(o, t);
|
|
142
142
|
return e[i] = t, t;
|
|
143
143
|
}
|
|
144
|
-
if (
|
|
144
|
+
if (M === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
|
|
145
145
|
const o = e;
|
|
146
146
|
for (const a of Object.keys(o.uniforms)) {
|
|
147
147
|
const h = o.uniforms[a].value;
|
|
@@ -232,12 +232,12 @@ const _ = class {
|
|
|
232
232
|
const o = n.index || 0;
|
|
233
233
|
s = s[o];
|
|
234
234
|
}
|
|
235
|
-
s && i != s && s instanceof Y && (e.geometry = s,
|
|
235
|
+
s && i != s && s instanceof Y && (e.geometry = s, M && ue(e, "geometry", n.url));
|
|
236
236
|
}
|
|
237
237
|
return s;
|
|
238
238
|
}).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
|
|
239
239
|
} else
|
|
240
|
-
|
|
240
|
+
M && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
|
|
241
241
|
return Promise.resolve(null);
|
|
242
242
|
}
|
|
243
243
|
/** Load a different resolution of a texture (if available)
|
|
@@ -252,7 +252,7 @@ const _ = class {
|
|
|
252
252
|
return Promise.resolve(null);
|
|
253
253
|
if (e instanceof we || e.isMaterial === !0) {
|
|
254
254
|
const r = e, i = [], n = new Array();
|
|
255
|
-
if (
|
|
255
|
+
if (M && ne.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
|
|
256
256
|
const s = r;
|
|
257
257
|
for (const o of Object.keys(s.uniforms)) {
|
|
258
258
|
const a = s.uniforms[o].value;
|
|
@@ -295,29 +295,29 @@ const _ = class {
|
|
|
295
295
|
if (s) {
|
|
296
296
|
const o = this.getAssignedLODInformation(s);
|
|
297
297
|
if (o && (o == null ? void 0 : o.level) < t)
|
|
298
|
-
return
|
|
298
|
+
return M === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, t, r, s, n), null;
|
|
299
299
|
}
|
|
300
300
|
r[i] = n;
|
|
301
301
|
}
|
|
302
|
-
if (
|
|
302
|
+
if (M && i && r) {
|
|
303
303
|
const s = this.getAssignedLODInformation(e);
|
|
304
304
|
s && ue(r, i, s.url);
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
return n;
|
|
308
308
|
} else
|
|
309
|
-
|
|
309
|
+
M == "verbose" && console.warn("No LOD found for", e, t);
|
|
310
310
|
return null;
|
|
311
311
|
}).catch((n) => (console.error("Error loading LOD", e, n), null));
|
|
312
312
|
}
|
|
313
313
|
afterRoot(e) {
|
|
314
314
|
var t, r;
|
|
315
|
-
return
|
|
315
|
+
return M && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
|
|
316
316
|
if (i != null && i.extensions) {
|
|
317
|
-
const s = i == null ? void 0 : i.extensions[
|
|
317
|
+
const s = i == null ? void 0 : i.extensions[R];
|
|
318
318
|
if (s) {
|
|
319
319
|
if (!s.lods) {
|
|
320
|
-
|
|
320
|
+
M && console.warn("Texture has no LODs", s);
|
|
321
321
|
return;
|
|
322
322
|
}
|
|
323
323
|
let o = !1;
|
|
@@ -330,7 +330,7 @@ const _ = class {
|
|
|
330
330
|
}
|
|
331
331
|
}), (r = this.parser.json.meshes) == null || r.forEach((i, n) => {
|
|
332
332
|
if (i != null && i.extensions) {
|
|
333
|
-
const s = i == null ? void 0 : i.extensions[
|
|
333
|
+
const s = i == null ? void 0 : i.extensions[R];
|
|
334
334
|
if (s && s.lods) {
|
|
335
335
|
for (const o of this.parser.associations.keys())
|
|
336
336
|
if (o.isMesh) {
|
|
@@ -343,7 +343,7 @@ const _ = class {
|
|
|
343
343
|
}
|
|
344
344
|
static async getOrLoadLOD(e, t) {
|
|
345
345
|
var o, a, h, d;
|
|
346
|
-
const r =
|
|
346
|
+
const r = M == "verbose", i = e.userData.LODS;
|
|
347
347
|
if (!i)
|
|
348
348
|
return null;
|
|
349
349
|
const n = i == null ? void 0 : i.key;
|
|
@@ -354,32 +354,32 @@ const _ = class {
|
|
|
354
354
|
}
|
|
355
355
|
if (s || (s = _.lodInfos.get(n)), s) {
|
|
356
356
|
if (t > 0) {
|
|
357
|
-
let
|
|
358
|
-
const
|
|
359
|
-
if (
|
|
357
|
+
let y = !1;
|
|
358
|
+
const w = Array.isArray(s.lods);
|
|
359
|
+
if (w && t >= s.lods.length ? y = !0 : w || (y = !0), y)
|
|
360
360
|
return this.lowresCache.get(n);
|
|
361
361
|
}
|
|
362
362
|
const g = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
|
|
363
363
|
if (!g)
|
|
364
|
-
return
|
|
364
|
+
return M && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
|
|
365
365
|
const f = Te(i.url, g);
|
|
366
366
|
if (f.endsWith(".glb") || f.endsWith(".gltf")) {
|
|
367
367
|
if (!s.guid)
|
|
368
368
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
369
|
-
const
|
|
370
|
-
if (
|
|
371
|
-
r && console.log(`LOD ${t} was already loading/loaded: ${
|
|
372
|
-
let
|
|
369
|
+
const y = f + "_" + s.guid, w = this.previouslyLoaded.get(y);
|
|
370
|
+
if (w !== void 0) {
|
|
371
|
+
r && console.log(`LOD ${t} was already loading/loaded: ${y}`);
|
|
372
|
+
let L = await w.catch((z) => (console.error(`Error loading LOD ${t} from ${f}
|
|
373
373
|
`, z), null)), T = !1;
|
|
374
|
-
if (
|
|
375
|
-
return
|
|
374
|
+
if (L == null || (L instanceof N && e instanceof N ? (a = L.image) != null && a.data || (h = L.source) != null && h.data ? L = this.copySettings(e, L) : (T = !0, this.previouslyLoaded.delete(y)) : L instanceof Y && e instanceof Y && ((d = L.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(y)))), !T)
|
|
375
|
+
return L;
|
|
376
376
|
}
|
|
377
|
-
const
|
|
377
|
+
const m = s, O = new Promise(async (L, T) => {
|
|
378
378
|
const z = new Se();
|
|
379
|
-
ge(z),
|
|
379
|
+
ge(z), M && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, m.guid));
|
|
380
380
|
let ee = f;
|
|
381
|
-
if (
|
|
382
|
-
const p =
|
|
381
|
+
if (m && Array.isArray(m.lods)) {
|
|
382
|
+
const p = m.lods[t];
|
|
383
383
|
p.hash && (ee += "?v=" + p.hash);
|
|
384
384
|
}
|
|
385
385
|
const E = await z.loadAsync(ee).catch((p) => (console.error(`Error loading LOD ${t} from ${f}
|
|
@@ -387,66 +387,66 @@ const _ = class {
|
|
|
387
387
|
if (!E)
|
|
388
388
|
return null;
|
|
389
389
|
const te = E.parser;
|
|
390
|
-
r && console.log("Loading finished " + f,
|
|
391
|
-
let
|
|
390
|
+
r && console.log("Loading finished " + f, m.guid);
|
|
391
|
+
let x = 0;
|
|
392
392
|
if (E.parser.json.textures) {
|
|
393
393
|
let p = !1;
|
|
394
394
|
for (const u of E.parser.json.textures) {
|
|
395
395
|
if (u != null && u.extensions) {
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
396
|
+
const D = u == null ? void 0 : u.extensions[R];
|
|
397
|
+
if (D != null && D.guid && D.guid === m.guid) {
|
|
398
398
|
p = !0;
|
|
399
399
|
break;
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
|
-
|
|
402
|
+
x++;
|
|
403
403
|
}
|
|
404
404
|
if (p) {
|
|
405
|
-
let u = await te.getDependency("texture",
|
|
406
|
-
return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f,
|
|
405
|
+
let u = await te.getDependency("texture", x);
|
|
406
|
+
return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, x, u, y), e instanceof N && (u = this.copySettings(e, u)), u && (u.guid = m.guid), L(u);
|
|
407
407
|
} else
|
|
408
|
-
|
|
408
|
+
M && console.warn("Could not find texture with guid", m.guid);
|
|
409
409
|
}
|
|
410
|
-
if (
|
|
410
|
+
if (x = 0, E.parser.json.meshes) {
|
|
411
411
|
let p = !1;
|
|
412
412
|
for (const u of E.parser.json.meshes) {
|
|
413
413
|
if (u != null && u.extensions) {
|
|
414
|
-
const
|
|
415
|
-
if (
|
|
414
|
+
const D = u == null ? void 0 : u.extensions[R];
|
|
415
|
+
if (D != null && D.guid && D.guid === m.guid) {
|
|
416
416
|
p = !0;
|
|
417
417
|
break;
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
|
-
|
|
420
|
+
x++;
|
|
421
421
|
}
|
|
422
422
|
if (p) {
|
|
423
|
-
const u = await te.getDependency("mesh",
|
|
424
|
-
if (r && console.log(`Loaded Mesh "${u.name}"`, f,
|
|
423
|
+
const u = await te.getDependency("mesh", x), D = m;
|
|
424
|
+
if (r && console.log(`Loaded Mesh "${u.name}"`, f, x, u, y), u.isMesh === !0) {
|
|
425
425
|
const S = u.geometry;
|
|
426
|
-
return _.assignLODInformation(i.url, S, n, t, void 0,
|
|
426
|
+
return _.assignLODInformation(i.url, S, n, t, void 0, D.density), L(S);
|
|
427
427
|
} else {
|
|
428
428
|
const S = new Array();
|
|
429
|
-
for (let
|
|
430
|
-
const G = u.children[
|
|
429
|
+
for (let B = 0; B < u.children.length; B++) {
|
|
430
|
+
const G = u.children[B];
|
|
431
431
|
if (G instanceof F) {
|
|
432
432
|
const $ = G.geometry;
|
|
433
|
-
_.assignLODInformation(i.url, $, n, t,
|
|
433
|
+
_.assignLODInformation(i.url, $, n, t, B, D.density), S.push($);
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
|
-
return
|
|
436
|
+
return L(S);
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
return
|
|
440
|
+
return L(null);
|
|
441
441
|
});
|
|
442
|
-
return this.previouslyLoaded.set(
|
|
442
|
+
return this.previouslyLoaded.set(y, O), await O;
|
|
443
443
|
} else if (e instanceof N) {
|
|
444
444
|
r && console.log("Load texture from uri: " + f);
|
|
445
|
-
const
|
|
446
|
-
return
|
|
445
|
+
const w = await new Oe().loadAsync(f);
|
|
446
|
+
return w ? (w.guid = s.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = e.colorSpace, r && console.log(s, w)) : M && console.warn("failed loading", f), w;
|
|
447
447
|
}
|
|
448
448
|
} else
|
|
449
|
-
|
|
449
|
+
M && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
450
450
|
return null;
|
|
451
451
|
}
|
|
452
452
|
static assignLODInformation(e, t, r, i, n, s) {
|
|
@@ -462,7 +462,7 @@ const _ = class {
|
|
|
462
462
|
}
|
|
463
463
|
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
464
464
|
static copySettings(e, t) {
|
|
465
|
-
return t = t.clone(),
|
|
465
|
+
return t = t.clone(), M && console.warn(`Copying texture settings
|
|
466
466
|
`, e.uuid, `
|
|
467
467
|
`, t.uuid), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t.magFilter = e.magFilter, t.minFilter = e.minFilter, t.wrapS = e.wrapS, t.wrapT = e.wrapT, t.flipY = e.flipY, t.anisotropy = e.anisotropy, t.mipmaps || (t.generateMipmaps = e.generateMipmaps), t;
|
|
468
468
|
}
|
|
@@ -472,8 +472,8 @@ let v = _;
|
|
|
472
472
|
* Register a texture with LOD information
|
|
473
473
|
*/
|
|
474
474
|
c(v, "registerTexture", (e, t, r, i, n) => {
|
|
475
|
-
if (
|
|
476
|
-
|
|
475
|
+
if (M && console.log("> Progressive: register texture", i, t.name, t.uuid, t, n), !t) {
|
|
476
|
+
M && console.error("gltf-progressive: Register texture without texture");
|
|
477
477
|
return;
|
|
478
478
|
}
|
|
479
479
|
t.source && (t.source[se] = n);
|
|
@@ -484,10 +484,10 @@ c(v, "registerTexture", (e, t, r, i, n) => {
|
|
|
484
484
|
*/
|
|
485
485
|
c(v, "registerMesh", (e, t, r, i, n, s) => {
|
|
486
486
|
var h;
|
|
487
|
-
|
|
487
|
+
M && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
|
|
488
488
|
const o = r.geometry;
|
|
489
489
|
if (!o) {
|
|
490
|
-
|
|
490
|
+
M && console.warn("gltf-progressive: Register mesh without geometry");
|
|
491
491
|
return;
|
|
492
492
|
}
|
|
493
493
|
o.userData || (o.userData = {}), _.assignLODInformation(e, o, t, i, n, s.density), _.lodInfos.set(t, s);
|
|
@@ -512,7 +512,7 @@ class Ee {
|
|
|
512
512
|
this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
|
-
const U = j("debugprogressive"),
|
|
515
|
+
const U = j("debugprogressive"), Be = j("noprogressive"), fe = Symbol("Needle:LODSManager"), b = { mesh_lod: -1, texture_lod: -1 }, A = class {
|
|
516
516
|
// readonly plugins: NEEDLE_progressive_plugin[] = [];
|
|
517
517
|
constructor(e) {
|
|
518
518
|
c(this, "renderer");
|
|
@@ -598,7 +598,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
598
598
|
(d.name === "EffectMaterial" || d.name === "CopyShader") && (o = !1);
|
|
599
599
|
}
|
|
600
600
|
if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
|
|
601
|
-
if (
|
|
601
|
+
if (Be || this.updateInterval > 0 && i % this.updateInterval != 0)
|
|
602
602
|
return;
|
|
603
603
|
this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
604
604
|
const d = this.targetTriangleDensity;
|
|
@@ -616,13 +616,13 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
616
616
|
case "MeshDepthMaterial":
|
|
617
617
|
continue;
|
|
618
618
|
}
|
|
619
|
-
const
|
|
620
|
-
(
|
|
619
|
+
const y = f.object;
|
|
620
|
+
(y instanceof F || y.isMesh) && this.updateLODs(e, t, y, d, i);
|
|
621
621
|
}
|
|
622
622
|
const g = n.transparent;
|
|
623
623
|
for (const f of g) {
|
|
624
|
-
const
|
|
625
|
-
(
|
|
624
|
+
const y = f.object;
|
|
625
|
+
(y instanceof F || y.isMesh) && this.updateLODs(e, t, y, d, i);
|
|
626
626
|
}
|
|
627
627
|
}
|
|
628
628
|
}
|
|
@@ -631,7 +631,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
631
631
|
var a, h;
|
|
632
632
|
r.userData || (r.userData = {});
|
|
633
633
|
let s = r.userData.LOD_state;
|
|
634
|
-
if (s || (s = new
|
|
634
|
+
if (s || (s = new Ce(), r.userData.LOD_state = s), s.frames++ < 2)
|
|
635
635
|
return;
|
|
636
636
|
for (const d of I)
|
|
637
637
|
(a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
|
|
@@ -683,7 +683,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
683
683
|
return this._tempPtInside.set(n, s, r.z).applyMatrix4(t).z < 0;
|
|
684
684
|
}
|
|
685
685
|
calculateLodLevel(e, t, r, i, n) {
|
|
686
|
-
var
|
|
686
|
+
var w;
|
|
687
687
|
if (!t) {
|
|
688
688
|
n.mesh_lod = -1, n.texture_lod = -1;
|
|
689
689
|
return;
|
|
@@ -700,52 +700,56 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
700
700
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
701
701
|
return;
|
|
702
702
|
}
|
|
703
|
-
if (d || (o = 0), !((
|
|
703
|
+
if (d || (o = 0), !((w = this.cameraFrustrum) != null && w.intersectsObject(t))) {
|
|
704
704
|
n.mesh_lod = 99, n.texture_lod = 99;
|
|
705
705
|
return;
|
|
706
706
|
}
|
|
707
|
-
|
|
708
|
-
if (
|
|
709
|
-
const
|
|
707
|
+
let y = t.geometry.boundingBox;
|
|
708
|
+
if (t.type === "SkinnedMesh") {
|
|
709
|
+
const m = t;
|
|
710
|
+
m.boundingBox || m.computeBoundingBox(), y = m.boundingBox;
|
|
711
|
+
}
|
|
712
|
+
if (y && e.isPerspectiveCamera) {
|
|
713
|
+
const m = e;
|
|
710
714
|
if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
|
|
711
715
|
this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
|
|
712
|
-
const
|
|
713
|
-
if (this._sphere.containsPoint(
|
|
716
|
+
const x = e.getWorldPosition(this._tempWorldPosition);
|
|
717
|
+
if (this._sphere.containsPoint(x)) {
|
|
714
718
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
715
719
|
return;
|
|
716
720
|
}
|
|
717
721
|
}
|
|
718
|
-
if (this._tempBox.copy(
|
|
722
|
+
if (this._tempBox.copy(y), t.type === "SkinnedMesh" ? t.parent && this._tempBox.applyMatrix4(t.parent.matrixWorld) : this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
|
|
719
723
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
720
724
|
return;
|
|
721
725
|
}
|
|
722
|
-
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled &&
|
|
723
|
-
const
|
|
724
|
-
let u =
|
|
725
|
-
const G = 2, $ = 1.5, H = (
|
|
726
|
-
u = (u - H) * G + H,
|
|
727
|
-
const pe = u < 0 && S > 0 ? 0 : Math.min(Math.abs(
|
|
726
|
+
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && m.fov > 70) {
|
|
727
|
+
const x = this._tempBox.min, p = this._tempBox.max;
|
|
728
|
+
let u = x.x, D = x.y, S = p.x, B = p.y;
|
|
729
|
+
const G = 2, $ = 1.5, H = (x.x + p.x) * 0.5, J = (x.y + p.y) * 0.5;
|
|
730
|
+
u = (u - H) * G + H, D = (D - J) * G + J, S = (S - H) * G + H, B = (B - J) * G + J;
|
|
731
|
+
const pe = u < 0 && S > 0 ? 0 : Math.min(Math.abs(x.x), Math.abs(p.x)), ye = D < 0 && B > 0 ? 0 : Math.min(Math.abs(x.y), Math.abs(p.y)), re = Math.max(pe, ye);
|
|
728
732
|
r.lastCentrality = ($ - re) * ($ - re) * ($ - re);
|
|
729
733
|
} else
|
|
730
734
|
r.lastCentrality = 1;
|
|
731
735
|
const O = this._tempBox.getSize(this._tempBoxSize);
|
|
732
|
-
O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *=
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
const T =
|
|
736
|
+
O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= m.aspect;
|
|
737
|
+
const C = e.matrixWorldInverse, L = this._tempBox2;
|
|
738
|
+
L.copy(y), L.applyMatrix4(t.matrixWorld), L.applyMatrix4(C);
|
|
739
|
+
const T = L.getSize(this._tempBox2Size), z = Math.max(T.x, T.y);
|
|
736
740
|
if (Math.max(O.x, O.y) != 0 && z != 0 && (O.z = T.z / Math.max(T.x, T.y) * Math.max(O.x, O.y)), r.lastScreenCoverage = Math.max(O.x, O.y, O.z), r.lastScreenspaceVolume.copy(O), r.lastScreenCoverage *= r.lastCentrality, U && A.debugDrawLine) {
|
|
737
|
-
const
|
|
738
|
-
|
|
739
|
-
const p = A.corner0, u = A.corner1,
|
|
740
|
-
p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x,
|
|
741
|
-
const
|
|
742
|
-
p.z = u.z =
|
|
741
|
+
const x = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
742
|
+
x.invert();
|
|
743
|
+
const p = A.corner0, u = A.corner1, D = A.corner2, S = A.corner3;
|
|
744
|
+
p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x, D.copy(this._tempBox.max), D.y = p.y, S.copy(this._tempBox.max);
|
|
745
|
+
const B = (p.z + S.z) * 0.5;
|
|
746
|
+
p.z = u.z = D.z = S.z = B, p.applyMatrix4(x), u.applyMatrix4(x), D.applyMatrix4(x), S.applyMatrix4(x), A.debugDrawLine(p, u, 255), A.debugDrawLine(p, D, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(D, S, 255);
|
|
743
747
|
}
|
|
744
748
|
let E = 999;
|
|
745
749
|
if (h && r.lastScreenCoverage > 0) {
|
|
746
|
-
for (let
|
|
747
|
-
if (h[
|
|
748
|
-
E =
|
|
750
|
+
for (let x = 0; x < h.length; x++)
|
|
751
|
+
if (h[x].density / r.lastScreenCoverage < i) {
|
|
752
|
+
E = x;
|
|
749
753
|
break;
|
|
750
754
|
}
|
|
751
755
|
}
|
|
@@ -754,15 +758,15 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
754
758
|
if (n.mesh_lod = o, f)
|
|
755
759
|
if (r.lastLodLevel_Texture < 0) {
|
|
756
760
|
if (n.texture_lod = g.max_count - 1, U) {
|
|
757
|
-
const
|
|
758
|
-
U && console.log(`First Texture LOD ${n.texture_lod} (${
|
|
761
|
+
const m = g.lods[g.max_count - 1];
|
|
762
|
+
U && console.log(`First Texture LOD ${n.texture_lod} (${m.max_height}px) - ${t.name}`);
|
|
759
763
|
}
|
|
760
764
|
} else {
|
|
761
|
-
const
|
|
762
|
-
for (let
|
|
763
|
-
const T = g.lods[
|
|
764
|
-
if (!(Ae() && T.max_height > 4096) && T.max_height >
|
|
765
|
-
n.texture_lod =
|
|
765
|
+
const m = r.lastScreenCoverage * 1.5, C = this.renderer.domElement.clientHeight / window.devicePixelRatio * m;
|
|
766
|
+
for (let L = g.lods.length - 1; L >= 0; L--) {
|
|
767
|
+
const T = g.lods[L];
|
|
768
|
+
if (!(Ae() && T.max_height > 4096) && T.max_height > C) {
|
|
769
|
+
n.texture_lod = L, n.texture_lod < r.lastLodLevel_Texture && U && console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${n.texture_lod} (${T.max_height}px: ${(100 * r.lastScreenCoverage).toFixed(2)} % = ${C.toFixed(0)}px) - ${t.name}`);
|
|
766
770
|
break;
|
|
767
771
|
}
|
|
768
772
|
}
|
|
@@ -775,7 +779,7 @@ let P = A;
|
|
|
775
779
|
/** 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.
|
|
776
780
|
*/
|
|
777
781
|
c(P, "debugDrawLine"), c(P, "corner0", new k()), c(P, "corner1", new k()), c(P, "corner2", new k()), c(P, "corner3", new k()), c(P, "_tempPtInside", new k());
|
|
778
|
-
class
|
|
782
|
+
class Ce {
|
|
779
783
|
constructor() {
|
|
780
784
|
c(this, "frames", 0);
|
|
781
785
|
c(this, "lastLodLevel_Mesh", -1);
|
|
@@ -797,7 +801,7 @@ function ke(l) {
|
|
|
797
801
|
if (e) {
|
|
798
802
|
console.log("Adding Needle LODs to modelviewer");
|
|
799
803
|
const r = P.get(e);
|
|
800
|
-
if (P.addPlugin(new
|
|
804
|
+
if (P.addPlugin(new Re(l)), r.enable(), t) {
|
|
801
805
|
const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
|
|
802
806
|
i && e.render(t, i);
|
|
803
807
|
}
|
|
@@ -807,7 +811,7 @@ function ke(l) {
|
|
|
807
811
|
}
|
|
808
812
|
return null;
|
|
809
813
|
}
|
|
810
|
-
class
|
|
814
|
+
class Re {
|
|
811
815
|
constructor(e) {
|
|
812
816
|
c(this, "modelviewer");
|
|
813
817
|
c(this, "_didWarnAboutMissingUrl", !1);
|
|
@@ -836,16 +840,16 @@ class Be {
|
|
|
836
840
|
o[Q] = !0, o.userData && (o.userData.LOD = -1);
|
|
837
841
|
const a = Object.keys(o);
|
|
838
842
|
for (let f = 0; f < a.length; f++) {
|
|
839
|
-
const
|
|
840
|
-
if ((
|
|
841
|
-
const
|
|
843
|
+
const y = a[f], w = o[y];
|
|
844
|
+
if ((w == null ? void 0 : w.isTexture) === !0) {
|
|
845
|
+
const m = (d = (h = w.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[m];
|
|
842
846
|
if (!O) {
|
|
843
|
-
console.warn("Texture data not found for texture index " +
|
|
847
|
+
console.warn("Texture data not found for texture index " + m);
|
|
844
848
|
continue;
|
|
845
849
|
}
|
|
846
|
-
if ((g = O == null ? void 0 : O.extensions) != null && g[
|
|
847
|
-
const
|
|
848
|
-
|
|
850
|
+
if ((g = O == null ? void 0 : O.extensions) != null && g[R]) {
|
|
851
|
+
const C = O.extensions[R];
|
|
852
|
+
C && i && v.registerTexture(i, w, C.lods.length, m, C);
|
|
849
853
|
}
|
|
850
854
|
}
|
|
851
855
|
}
|
|
@@ -866,7 +870,7 @@ class Be {
|
|
|
866
870
|
const r = this.getUrl();
|
|
867
871
|
if (!r)
|
|
868
872
|
return;
|
|
869
|
-
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[
|
|
873
|
+
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
|
|
870
874
|
if (i && r) {
|
|
871
875
|
const o = t.uuid;
|
|
872
876
|
v.registerMesh(r, o, t, 0, i.lods.length, i);
|
|
@@ -882,7 +886,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
882
886
|
ke(document.querySelector("model-viewer"));
|
|
883
887
|
});
|
|
884
888
|
export {
|
|
885
|
-
|
|
889
|
+
R as EXTENSION_NAME,
|
|
886
890
|
P as LODsManager,
|
|
887
891
|
v as NEEDLE_progressive,
|
|
888
892
|
ge as addDracoAndKTX2Loaders,
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as
|
|
2
|
-
`,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new _e;se(N),
|
|
3
|
-
`,y),null));if(!x)return null;const
|
|
1
|
+
var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ve}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as $,Mesh as G,Material as De,Texture as z,TextureLoader as Le,Matrix4 as ie,Frustum as Me,Sphere as Oe,Box3 as ae,Vector3 as I}from"three";import{GLTFLoader as _e}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",ee="./include/ktx2/"});function we(t){X=t}function be(t){ee=t}let U,te,q;function re(t){U||(U=new ye,U.setDecoderPath(X),U.setDecoderConfig({type:"js"})),q||(q=new ve,q.setTranscoderPath(ee)),te||(te=xe),t?q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function se(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(q),t.meshoptDecoder||t.setMeshoptDecoder(te)}function H(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Se(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let Y;function Te(){return Y!==void 0||(Y=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),H("debugprogressive")&&console.log("isMobileDevice",Y)),Y}function J(t){var e;return((e=t?.userData)==null?void 0:e["needle:raycast-mesh"])instanceof $?t.userData["needle:raycast-mesh"]:null}function le(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!J(t)){const r=Ae(e);r.userData={isRaycastMesh:!0},t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=r}}function Ee(t=!0){if(t){if(V)return;const e=V=G.prototype.raycast;G.prototype.raycast=function(r,n){const o=this,s=J(o);let a;s&&o.isMesh&&(a=o.geometry,o.geometry=s),e.call(this,r,n),a&&(o.geometry=a)}}else{if(!V)return;G.prototype.raycast=V,V=null}}let V=null;function Ae(t){const e=new $;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const R=new Array,P="NEEDLE_progressive",v=H("debugprogressive"),oe=Symbol("needle-progressive-texture"),K=new Map,ne=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const u=w.getMeshLODInformation(i),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",o=>{o.key==="p"&&t(),o.key==="w"&&(n=!n,ne&&ne.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ue(t,e,r){var n;if(!v)return;K.has(t)||K.set(t,{keys:[],sourceId:r});const o=K.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const O=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,o;if(this._isLoadingMesh)return null;const s=(o=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:o[P];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(a=>(this._isLoadingMesh=!1,a&&O.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return P}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",o=t[n];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const i of Object.keys(a.uniforms)){const u=a.uniforms[i].value;u?.isTexture===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const i=t[a];i?.isTexture===!0&&s(i,e)}return t[n]=e,e;function s(a,i){const u=r.getAssignedLODInformation(a);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){i.min_count=Math.min(i.min_count,l.lods.length),i.max_count=Math.max(i.max_count,l.lods.length);for(let g=0;g<l.lods.length;g++){const d=l.lods[g];d.width&&(i.lods[g]=i.lods[g]||{min_height:1/0,max_height:0},i.lods[g].min_height=Math.min(i.lods[g].min_height,d.height),i.lods[g].max_height=Math.max(i.lods[g].max_height,d.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let n,o;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const s=n.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof G||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of R)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,O.getOrLoadLOD(n,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const a=o.index||0;s=s[a]}s&&n!=s&&s instanceof $&&(t.geometry=s,v&&ue(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof De||t.isMaterial===!0){const r=t,n=[],o=new Array;if(v&&ne.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const u=this.assignTextureLODForSlot(i,e,r,a);n.push(u),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,r,s);n.push(i),o.push(s)}}return Promise.all(n).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const u=s[i],l=o[i];u&&u.isTexture===!0?a.push({material:r,slot:l,texture:u,level:e}):a.push({material:r,slot:l,texture:null,level:e})}return a})}if(t instanceof z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t){if(r&&n){const s=r[n];if(s){const a=this.getAssignedLODInformation(s);if(a&&a?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(v&&n&&r){const s=this.getAssignedLODInformation(t);s&&ue(r,n,s.url)}}return o}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[P];if(s){if(!s.lods){v&&console.warn("Texture has no LODs",s);return}let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,O.registerTexture(this.url,i,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&O.registerTexture(this.url,i,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[P];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===o&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const a=v=="verbose",i=t.userData.LODS;if(!i)return null;const u=i?.key;let l;if(t.isTexture===!0){const g=t;g.source&&g.source[oe]&&(l=g.source[oe])}if(l||(l=O.lodInfos.get(u)),l){if(e>0){let f=!1;const D=Array.isArray(l.lods);if(D&&e>=l.lods.length?f=!0:D||(f=!0),f)return this.lowresCache.get(u)}const g=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!g)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const d=Se(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=d+"_"+l.guid,D=this.previouslyLoaded.get(f);if(D!==void 0){a&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let p=await D.catch(N=>(console.error(`Error loading LOD ${e} from ${d}
|
|
2
|
+
`,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new _e;se(N),v&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let F=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(F+="?v="+y.hash)}const x=await N.loadAsync(F).catch(y=>(console.error(`Error loading LOD ${e} from ${d}
|
|
3
|
+
`,y),null));if(!x)return null;const L=x.parser;a&&console.log("Loading finished "+d,m.guid);let M=0;if(x.parser.json.textures){let y=!1;for(const h of x.parser.json.textures){if(h!=null&&h.extensions){const _=h?.extensions[P];if(_!=null&&_.guid&&_.guid===m.guid){y=!0;break}}M++}if(y){let h=await L.getDependency("texture",M);return h&&O.assignLODInformation(i.url,h,u,e,void 0,void 0),a&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',d,M,h,f),t instanceof z&&(h=this.copySettings(t,h)),h&&(h.guid=m.guid),p(h)}else v&&console.warn("Could not find texture with guid",m.guid)}if(M=0,x.parser.json.meshes){let y=!1;for(const h of x.parser.json.meshes){if(h!=null&&h.extensions){const _=h?.extensions[P];if(_!=null&&_.guid&&_.guid===m.guid){y=!0;break}}M++}if(y){const h=await L.getDependency("mesh",M),_=m;if(a&&console.log(`Loaded Mesh "${h.name}"`,d,M,h,f),h.isMesh===!0){const A=h.geometry;return O.assignLODInformation(i.url,A,u,e,void 0,_.density),p(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const k=h.children[C];if(k instanceof G){const j=k.geometry;O.assignLODInformation(i.url,j,u,e,C,_.density),A.push(j)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof z){a&&console.log("Load texture from uri: "+d);const f=await new Le().loadAsync(d);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,a&&console.log(l,f)):v&&console.warn("failed loading",d),f}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new Pe(t,r,n,o,s);e.userData.LODS=a,e.userData.LOD=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),v&&console.warn(`Copying texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),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}};let _=M;c(_,"registerTexture",(t,e,r,n,o)=>{if(L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;M.assignLODInformation(t,e,s,r,n,void 0),M.lodInfos.set(s,o),M.lowresCache.set(s,e)}),c(_,"registerMesh",(t,e,r,n,o,s)=>{var a;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){L&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class Pe{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const W=H("debugprogressive"),Ie=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),c(this,"cameraFrustrum",new Me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new Oe),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Ie||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Be,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,_.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return _.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=_.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=_.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const f=e.geometry.boundingBox;if(f&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const x=this._tempBox.min,v=this._tempBox.max;let D=x.x,y=x.y,h=v.x,O=v.y;const A=2,C=1.5,k=(x.x+v.x)*.5,j=(x.y+v.y)*.5;D=(D-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,O=(O-j)*A+j;const fe=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(v.x)),ge=y<0&&O>0?0:Math.min(Math.abs(x.y),Math.abs(v.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=w.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const v=T.corner0,D=T.corner1,y=T.corner2,h=T.corner3;v.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=v.x,y.copy(this._tempBox.max),y.y=v.y,h.copy(this._tempBox.max);const O=(v.z+h.z)*.5;v.z=D.z=y.z=h.z=O,v.applyMatrix4(x),D.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(v,D,255),T.debugDrawLine(v,y,255),T.debugDrawLine(D,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const w=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let I=T;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B),c(I,"_tempPtInside",new B);class Be{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=I.get(e);if(I.addPlugin(new Ce(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class Ce{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[Q]==!0)return;r[Q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const w=d[f],m=i[w];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&_.registerTexture(o,m,b.lods.length,S,b)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;_.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
|
|
5
|
+
`,e.uuid),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}};let w=O;c(w,"registerTexture",(t,e,r,n,o)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;O.assignLODInformation(t,e,s,r,n,void 0),O.lodInfos.set(s,o),O.lowresCache.set(s,e)}),c(w,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){v&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),O.assignLODInformation(t,i,e,n,o,s.density),O.lodInfos.set(e,s);let u=O.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],O.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map);class Pe{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const W=H("debugprogressive"),Be=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),c(this,"cameraFrustrum",new Me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new Oe),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),c(this,"_tempWorldPosition",new I),c(this,"_tempBoxSize",new I),c(this,"_tempBox2Size",new I),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Be||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Ie,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,w.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return w.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=w.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=w.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}let f=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const D=e;D.boundingBox||D.computeBoundingBox(),f=D.boundingBox}if(f&&t.isPerspectiveCamera){const D=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&D.fov>70){const x=this._tempBox.min,L=this._tempBox.max;let M=x.x,y=x.y,h=L.x,_=L.y;const A=2,C=1.5,k=(x.x+L.x)*.5,j=(x.y+L.y)*.5;M=(M-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,_=(_-j)*A+j;const fe=M<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(L.x)),ge=y<0&&_>0?0:Math.min(Math.abs(x.y),Math.abs(L.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=D.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const L=T.corner0,M=T.corner1,y=T.corner2,h=T.corner3;L.copy(this._tempBox.min),M.copy(this._tempBox.max),M.x=L.x,y.copy(this._tempBox.max),y.y=L.y,h.copy(this._tempBox.max);const _=(L.z+h.z)*.5;L.z=M.z=y.z=h.z=_,L.applyMatrix4(x),M.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(L,M,255),T.debugDrawLine(L,y,255),T.debugDrawLine(M,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const D=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${D.max_height}px) - ${e.name}`)}}else{const D=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*D;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let B=T;c(B,"debugDrawLine"),c(B,"corner0",new I),c(B,"corner1",new I),c(B,"corner2",new I),c(B,"corner3",new I),c(B,"_tempPtInside",new I);class Ie{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new I),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=B.get(e);if(B.addPlugin(new Ce(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class Ce{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[Q]==!0)return;r[Q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const D=d[f],m=i[D];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&w.registerTexture(o,m,b.lods.length,S,b)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;w.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new w(s,t));const o=B.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,B as LODsManager,w as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),
|
|
2
|
-
`,F),null)),A=!1;if(
|
|
3
|
-
`,y),null));if(!B)return null;const j=B.parser;r&&console.log("Loading finished "+f,
|
|
1
|
+
"use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),xe=require("three/examples/jsm/loaders/DRACOLoader.js"),Le=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),me=require("three/examples/jsm/loaders/GLTFLoader.js");let H="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ie="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(H+"draco_decoder.js",{method:"head"}).catch(l=>{H="./include/draco/",ie="./include/ktx2/"});function De(l){H=l}function Me(l){ie=l}let W,re,V;function oe(l){W||(W=new xe.DRACOLoader,W.setDecoderPath(H),W.setDecoderConfig({type:"js"})),V||(V=new Le.KTX2Loader,V.setTranscoderPath(ie)),re||(re=ye.MeshoptDecoder),l?V.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ne(l){l.dracoLoader||l.setDRACOLoader(W),l.ktx2Loader||l.setKTX2Loader(V),l.meshoptDecoder||l.setMeshoptDecoder(re)}function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function _e(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let $;function Oe(){return $!==void 0||($=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",$)),$}function Q(l){var e;return((e=l==null?void 0:l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function ue(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!Q(l)){const r=ve(e);r.userData={isRaycastMesh:!0},l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=r}}function we(l=!0){if(l){if(U)return;const e=U=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=Q(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!U)return;g.Mesh.prototype.raycast=U,U=null}}let U=null;function ve(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const I=new Array,C="NEEDLE_progressive",_=J("debugprogressive"),te=Symbol("needle-progressive-texture"),q=new Map,se=new Set;if(_){let l=function(){e+=1,console.log("Toggle LOD level",e,q),q.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),h=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,h),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,se&&se.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ae(l,e,t){var i;if(!_)return;q.has(l)||q.set(l,{keys:[],sourceId:t});const r=q.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const v=class{constructor(e,t){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[C];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>(this._isLoadingMesh=!1,o&&v.registerMesh(this.url,t.guid,o,t.lods.length,void 0,t),o))):null});_&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(_==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const h=n.uniforms[a].value;(h==null?void 0:h.isTexture)===!0&&s(h,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const h=r.getAssignedLODInformation(n);if(h){const d=r.lodInfos.get(h.key);if(d&&d.lods){a.min_count=Math.min(a.min_count,d.lods.length),a.max_count=Math.max(a.max_count,d.lods.length);for(let p=0;p<d.lods.length;p++){const f=d.lods[p];f.width&&(a.lods[p]=a.lods[p]||{min_height:1/0,max_height:0},a.lods[p].min_height=Math.min(a.lods[p].min_height,f.height),a.lods[p].max_height=Math.max(a.lods[p].max_height,f.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof g.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of I)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,v.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,_&&ae(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else _&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof g.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(_&&se.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const h=this.assignTextureLODForSlot(a,t,r,n);i.push(h),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const h=s[a],d=o[a];h&&h.isTexture===!0?n.push({material:r,slot:d,texture:h,level:t}):n.push({material:r,slot:d,texture:null,level:t})}return n})}if(e instanceof g.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(e):v.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return _==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(_&&i&&r){const s=this.getAssignedLODInformation(e);s&&ae(r,i,s.url)}}return o}else _=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return _&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){if(!s.lods){_&&console.warn("Texture has no LODs",s);return}let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,v.registerTexture(this.url,a,s.lods.length,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&v.registerTexture(this.url,a,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&v.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,h,d;const r=_=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const p=e;p.source&&p.source[te]&&(s=p.source[te])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const O=Array.isArray(s.lods);if(O&&t>=s.lods.length?x=!0:O||(x=!0),x)return this.lowresCache.get(o)}const p=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!p)return _&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const f=_e(i.url,p);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=f+"_"+s.guid,O=this.previouslyLoaded.get(x);if(O!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let D=await O.catch(F=>(console.error(`Error loading LOD ${t} from ${f}
|
|
2
|
+
`,F),null)),A=!1;if(D==null||(D instanceof g.Texture&&e instanceof g.Texture?(a=D.image)!=null&&a.data||(h=D.source)!=null&&h.data?D=this.copySettings(e,D):(A=!0,this.previouslyLoaded.delete(x)):D instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((d=D.attributes.position)!=null&&d.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return D}const m=s,w=new Promise(async(D,A)=>{const F=new me.GLTFLoader;ne(F),_&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+f,m.guid));let Z=f;if(m&&Array.isArray(m.lods)){const y=m.lods[t];y.hash&&(Z+="?v="+y.hash)}const B=await F.loadAsync(Z).catch(y=>(console.error(`Error loading LOD ${t} from ${f}
|
|
3
|
+
`,y),null));if(!B)return null;const j=B.parser;r&&console.log("Loading finished "+f,m.guid);let L=0;if(B.parser.json.textures){let y=!1;for(const u of B.parser.json.textures){if(u!=null&&u.extensions){const M=u==null?void 0:u.extensions[C];if(M!=null&&M.guid&&M.guid===m.guid){y=!0;break}}L++}if(y){let u=await j.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,L,u,x),e instanceof g.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=m.guid),D(u)}else _&&console.warn("Could not find texture with guid",m.guid)}if(L=0,B.parser.json.meshes){let y=!1;for(const u of B.parser.json.meshes){if(u!=null&&u.extensions){const M=u==null?void 0:u.extensions[C];if(M!=null&&M.guid&&M.guid===m.guid){y=!0;break}}L++}if(y){const u=await j.getDependency("mesh",L),M=m;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,L,u,x),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,M.density),D(T)}else{const T=new Array;for(let R=0;R<u.children.length;R++){const G=u.children[R];if(G instanceof g.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,R,M.density),T.push(N)}}return D(T)}}}return D(null)});return this.previouslyLoaded.set(x,w),await w}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+f);const O=await new g.TextureLoader().loadAsync(f);return O?(O.guid=s.guid,O.flipY=!1,O.needsUpdate=!0,O.colorSpace=e.colorSpace,r&&console.log(s,O)):_&&console.warn("failed loading",f),O}}else _&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new Se(e,r,i,o,s);t.userData.LODS=n,t.userData.LOD=i}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){return t=t.clone(),_&&console.warn(`Copying texture settings
|
|
4
4
|
`,e.uuid,`
|
|
5
|
-
`,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){M&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),c(S,"registerMesh",(e,t,r,i,o,s)=>{var h;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const d=s[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new Ae,r.userData.LOD_state=s),s.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let i=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(i=!0),i&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var _;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((_=this.cameraFrustrum)!=null&&_.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const x=t.geometry.boundingBox;if(x&&e.isPerspectiveCamera){const O=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&O.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,D=L.y,T=y.x,R=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,D=(D-X)*G+X,T=(T-K)*G+K,R=(R-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=D<0&&R>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&w.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),w.x*=O.aspect;const k=e.matrixWorldInverse,m=this._tempBox2;m.copy(x),m.applyMatrix4(t.matrixWorld),m.applyMatrix4(k);const A=m.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(w.x,w.y)!=0&&F!=0&&(w.z=A.z/Math.max(A.x,A.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,D=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,D.copy(this._tempBox.max),D.y=y.y,T.copy(this._tempBox.max);const R=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=R,y.applyMatrix4(L),u.applyMatrix4(L),D.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,D,255),b.debugDrawLine(u,T,255),b.debugDrawLine(D,T,255)}let B=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<i){B=L;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const O=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${O.max_height}px) - ${t.name}`)}}else{const O=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*O;for(let m=p.lods.length-1;m>=0;m--){const A=p.lods[m];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=m,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],_=n[x];if((_==null?void 0:_.isTexture)===!0){const O=(d=(h=_.userData)==null?void 0:h.associations)==null?void 0:d.textures,w=r.parser.json.textures[O];if(!w){console.warn("Texture data not found for texture index "+O);continue}if((p=w==null?void 0:w.extensions)!=null&&p[C]){const k=w.extensions[C];k&&i&&S.registerTexture(i,_,k.lods.length,O,k)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const i=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
|
|
5
|
+
`,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,i,o)=>{if(_&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){_&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),c(S,"registerMesh",(e,t,r,i,o,s)=>{var h;_&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){_&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const d=s[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new Ae,r.userData.LOD_state=s),s.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let i=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(i=!0),i&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var O;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((O=this.cameraFrustrum)!=null&&O.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}let x=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const m=t;m.boundingBox||m.computeBoundingBox(),x=m.boundingBox}if(x&&e.isPerspectiveCamera){const m=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,M=L.y,T=y.x,R=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,M=(M-X)*G+X,T=(T-K)*G+K,R=(R-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=M<0&&R>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&w.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),w.x*=m.aspect;const k=e.matrixWorldInverse,D=this._tempBox2;D.copy(x),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(k);const A=D.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(w.x,w.y)!=0&&F!=0&&(w.z=A.z/Math.max(A.x,A.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,M=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,M.copy(this._tempBox.max),M.y=y.y,T.copy(this._tempBox.max);const R=(y.z+T.z)*.5;y.z=u.z=M.z=T.z=R,y.applyMatrix4(L),u.applyMatrix4(L),M.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,M,255),b.debugDrawLine(u,T,255),b.debugDrawLine(M,T,255)}let B=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<i){B=L;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const m=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${m.max_height}px) - ${t.name}`)}}else{const m=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*m;for(let D=p.lods.length-1;D>=0;D--){const A=p.lods[D];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=D,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],O=n[x];if((O==null?void 0:O.isTexture)===!0){const m=(d=(h=O.userData)==null?void 0:h.associations)==null?void 0:d.textures,w=r.parser.json.textures[m];if(!w){console.warn("Texture data not found for texture index "+m);continue}if((p=w==null?void 0:w.extensions)!=null&&p[C]){const k=w.extensions[C];k&&i&&S.registerTexture(i,O,k.lods.length,m,k)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const i=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
|
package/lib/lods_manager.js
CHANGED
|
@@ -357,7 +357,13 @@ export class LODsManager {
|
|
|
357
357
|
result.texture_lod = 99;
|
|
358
358
|
return;
|
|
359
359
|
}
|
|
360
|
-
|
|
360
|
+
let boundingBox = mesh.geometry.boundingBox;
|
|
361
|
+
if (mesh.type === "SkinnedMesh") {
|
|
362
|
+
const skinnedMesh = mesh;
|
|
363
|
+
if (!skinnedMesh.boundingBox)
|
|
364
|
+
skinnedMesh.computeBoundingBox();
|
|
365
|
+
boundingBox = skinnedMesh.boundingBox;
|
|
366
|
+
}
|
|
361
367
|
if (boundingBox && camera.isPerspectiveCamera) {
|
|
362
368
|
const cam = camera;
|
|
363
369
|
// hack: if the mesh has vertex colors, has less than 100 vertices we always select the highest LOD
|
package/package.json
CHANGED