@needle-tools/gltf-progressive 1.2.0-alpha → 1.2.0-alpha.2
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/gltf-progressive.js +140 -140
- package/gltf-progressive.min.js +4 -4
- package/gltf-progressive.umd.cjs +4 -4
- package/lib/extension.js +21 -20
- package/lib/lods_manager.js +3 -0
- package/package.json +1 -1
package/gltf-progressive.js
CHANGED
|
@@ -2,8 +2,8 @@ var ge = Object.defineProperty;
|
|
|
2
2
|
var pe = (l, e, t) => e in l ? ge(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
|
|
3
3
|
var c = (l, e, t) => (pe(l, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import { MeshoptDecoder as ye } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
5
|
-
import { DRACOLoader as
|
|
6
|
-
import { KTX2Loader as
|
|
5
|
+
import { DRACOLoader as Le } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
6
|
+
import { KTX2Loader as me } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
7
7
|
import { BufferGeometry as V, Mesh as H, Material as xe, Texture as U, TextureLoader as De, Matrix4 as ne, Frustum as Me, Sphere as Oe, Box3 as oe, Vector3 as k } from "three";
|
|
8
8
|
import { GLTFLoader as we } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
9
9
|
let J = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", se = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
|
|
@@ -18,7 +18,7 @@ function ze(l) {
|
|
|
18
18
|
}
|
|
19
19
|
let N, te, W;
|
|
20
20
|
function ue(l) {
|
|
21
|
-
N || (N = new
|
|
21
|
+
N || (N = new Le(), N.setDecoderPath(J), N.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(se)), te || (te = ye), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
|
|
22
22
|
}
|
|
23
23
|
function fe(l) {
|
|
24
24
|
l.dracoLoader || l.setDRACOLoader(N), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(te);
|
|
@@ -53,8 +53,8 @@ if (w) {
|
|
|
53
53
|
for (const s of i.keys) {
|
|
54
54
|
const o = n[s];
|
|
55
55
|
if (o.isBufferGeometry === !0) {
|
|
56
|
-
const a = v.getMeshLODInformation(o),
|
|
57
|
-
n["DEBUG:LOD"] = e, v.assignMeshLOD(n,
|
|
56
|
+
const a = v.getMeshLODInformation(o), h = a ? Math.min(e, a.lods.length) : 0;
|
|
57
|
+
n["DEBUG:LOD"] = e, v.assignMeshLOD(n, h), a && (t = Math.max(t, a.lods.length - 1));
|
|
58
58
|
} else if (n.isMaterial === !0) {
|
|
59
59
|
n["DEBUG:LOD"] = e, v.assignTextureLOD(n, e);
|
|
60
60
|
break;
|
|
@@ -99,44 +99,43 @@ const _ = class {
|
|
|
99
99
|
return t != null && t.key ? this.lodInfos.get(t.key) : null;
|
|
100
100
|
}
|
|
101
101
|
static getMaterialMinMaxLODsCount(e, t) {
|
|
102
|
-
const r = "LODS:minmax",
|
|
103
|
-
if (
|
|
104
|
-
return
|
|
102
|
+
const r = this, i = "LODS:minmax", n = e[i];
|
|
103
|
+
if (n != null)
|
|
104
|
+
return n;
|
|
105
105
|
if (t || (t = {
|
|
106
106
|
min_count: 1 / 0,
|
|
107
107
|
max_count: 0,
|
|
108
108
|
lods: []
|
|
109
109
|
}), Array.isArray(e)) {
|
|
110
|
-
for (const
|
|
111
|
-
this.getMaterialMinMaxLODsCount(
|
|
112
|
-
return e[
|
|
110
|
+
for (const o of e)
|
|
111
|
+
this.getMaterialMinMaxLODsCount(o, t);
|
|
112
|
+
return e[i] = t, t;
|
|
113
113
|
}
|
|
114
|
-
w === "verbose" && console.log("getMaterialMinMaxLODsCount", e)
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (a && a.lods) {
|
|
120
|
-
t.min_count = Math.min(t.min_count, a.lods.length), t.max_count = Math.max(t.max_count, a.lods.length);
|
|
121
|
-
for (let f = 0; f < a.lods.length; f++) {
|
|
122
|
-
const h = a.lods[f];
|
|
123
|
-
h.width && (t.lods[f] = t.lods[f] || { min_height: 1 / 0, max_height: 0 }, t.lods[f].min_height = Math.min(t.lods[f].min_height, h.height), t.lods[f].max_height = Math.max(t.lods[f].max_height, h.height));
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
if (e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
|
|
129
|
-
const s = e;
|
|
130
|
-
for (const o of Object.keys(s.uniforms)) {
|
|
131
|
-
const a = s.uniforms[o].value;
|
|
132
|
-
(a == null ? void 0 : a.isTexture) === !0 && n(a);
|
|
114
|
+
if (w === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
|
|
115
|
+
const o = e;
|
|
116
|
+
for (const a of Object.keys(o.uniforms)) {
|
|
117
|
+
const h = o.uniforms[a].value;
|
|
118
|
+
(h == null ? void 0 : h.isTexture) === !0 && s(h, t);
|
|
133
119
|
}
|
|
134
120
|
} else if (e.isMaterial)
|
|
135
|
-
for (const
|
|
136
|
-
const
|
|
137
|
-
(
|
|
121
|
+
for (const o of Object.keys(e)) {
|
|
122
|
+
const a = e[o];
|
|
123
|
+
(a == null ? void 0 : a.isTexture) === !0 && s(a, t);
|
|
138
124
|
}
|
|
139
|
-
return e[
|
|
125
|
+
return e[i] = t, t;
|
|
126
|
+
function s(o, a) {
|
|
127
|
+
const h = r.getAssignedLODInformation(o);
|
|
128
|
+
if (h) {
|
|
129
|
+
const d = r.lodInfos.get(h.key);
|
|
130
|
+
if (d && d.lods) {
|
|
131
|
+
a.min_count = Math.min(a.min_count, d.lods.length), a.max_count = Math.max(a.max_count, d.lods.length);
|
|
132
|
+
for (let g = 0; g < d.lods.length; g++) {
|
|
133
|
+
const f = d.lods[g];
|
|
134
|
+
f.width && (a.lods[g] = a.lods[g] || { min_height: 1 / 0, max_height: 0 }, a.lods[g].min_height = Math.min(a.lods[g].min_height, f.height), a.lods[g].max_height = Math.max(a.lods[g].max_height, f.height));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
140
139
|
}
|
|
141
140
|
/** Check if a LOD level is available for a mesh or a texture
|
|
142
141
|
* @param obj the mesh or texture to check
|
|
@@ -228,8 +227,8 @@ const _ = class {
|
|
|
228
227
|
for (const o of Object.keys(s.uniforms)) {
|
|
229
228
|
const a = s.uniforms[o].value;
|
|
230
229
|
if ((a == null ? void 0 : a.isTexture) === !0) {
|
|
231
|
-
const
|
|
232
|
-
i.push(
|
|
230
|
+
const h = this.assignTextureLODForSlot(a, t, r, o);
|
|
231
|
+
i.push(h), n.push(o);
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
} else
|
|
@@ -243,8 +242,8 @@ const _ = class {
|
|
|
243
242
|
return Promise.all(i).then((s) => {
|
|
244
243
|
const o = new Array();
|
|
245
244
|
for (let a = 0; a < s.length; a++) {
|
|
246
|
-
const
|
|
247
|
-
|
|
245
|
+
const h = s[a], d = n[a];
|
|
246
|
+
h && h.isTexture === !0 ? o.push({ material: r, slot: d, texture: h, level: t }) : o.push({ material: r, slot: d, texture: null, level: t });
|
|
248
247
|
}
|
|
249
248
|
return o;
|
|
250
249
|
});
|
|
@@ -309,95 +308,95 @@ const _ = class {
|
|
|
309
308
|
}), null;
|
|
310
309
|
}
|
|
311
310
|
static async getOrLoadLOD(e, t) {
|
|
312
|
-
var o, a,
|
|
311
|
+
var o, a, h, d;
|
|
313
312
|
const r = w == "verbose", i = e.userData.LODS;
|
|
314
313
|
if (!i)
|
|
315
314
|
return null;
|
|
316
315
|
const n = i == null ? void 0 : i.key;
|
|
317
316
|
let s;
|
|
318
317
|
if (e.isTexture === !0) {
|
|
319
|
-
const
|
|
320
|
-
|
|
318
|
+
const g = e;
|
|
319
|
+
g.source && g.source[ee] && (s = g.source[ee]);
|
|
321
320
|
}
|
|
322
321
|
if (s || (s = _.lodInfos.get(n)), s) {
|
|
323
322
|
if (t > 0) {
|
|
324
|
-
let
|
|
323
|
+
let L = !1;
|
|
325
324
|
const D = Array.isArray(s.lods);
|
|
326
|
-
if (D && t >= s.lods.length ?
|
|
325
|
+
if (D && t >= s.lods.length ? L = !0 : D || (L = !0), L)
|
|
327
326
|
return this.lowresCache.get(n);
|
|
328
327
|
}
|
|
329
|
-
const
|
|
330
|
-
if (!
|
|
328
|
+
const g = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
|
|
329
|
+
if (!g)
|
|
331
330
|
return w && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
|
|
332
|
-
const
|
|
333
|
-
if (
|
|
331
|
+
const f = _e(i.url, g);
|
|
332
|
+
if (f.endsWith(".glb") || f.endsWith(".gltf")) {
|
|
334
333
|
if (!s.guid)
|
|
335
334
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
336
|
-
const
|
|
335
|
+
const L = f + "_" + s.guid, D = this.previouslyLoaded.get(L);
|
|
337
336
|
if (D !== void 0) {
|
|
338
|
-
r && console.log(`LOD ${t} was already loading/loaded: ${
|
|
339
|
-
let m = await D.catch((G) => (console.error(`Error loading LOD ${t} from ${
|
|
337
|
+
r && console.log(`LOD ${t} was already loading/loaded: ${L}`);
|
|
338
|
+
let m = await D.catch((G) => (console.error(`Error loading LOD ${t} from ${f}
|
|
340
339
|
`, G), null)), T = !1;
|
|
341
|
-
if (m == null || (m instanceof U && e instanceof U ? (a = m.image) != null && a.data || (
|
|
340
|
+
if (m == null || (m instanceof U && e instanceof U ? (a = m.image) != null && a.data || (h = m.source) != null && h.data ? m = this.copySettings(e, m) : (T = !0, this.previouslyLoaded.delete(L)) : m instanceof V && e instanceof V && ((d = m.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(L)))), !T)
|
|
342
341
|
return m;
|
|
343
342
|
}
|
|
344
343
|
const M = s, O = new Promise(async (m, T) => {
|
|
345
344
|
const G = new we();
|
|
346
|
-
fe(G), w && (await new Promise((
|
|
347
|
-
let Q =
|
|
345
|
+
fe(G), w && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, M.guid));
|
|
346
|
+
let Q = f;
|
|
348
347
|
if (M && Array.isArray(M.lods)) {
|
|
349
|
-
const
|
|
350
|
-
|
|
348
|
+
const p = M.lods[t];
|
|
349
|
+
p.hash && (Q += "?v=" + p.hash);
|
|
351
350
|
}
|
|
352
|
-
const E = await G.loadAsync(Q).catch((
|
|
353
|
-
`,
|
|
351
|
+
const E = await G.loadAsync(Q).catch((p) => (console.error(`Error loading LOD ${t} from ${f}
|
|
352
|
+
`, p), null));
|
|
354
353
|
if (!E)
|
|
355
354
|
return null;
|
|
356
355
|
const Z = E.parser;
|
|
357
|
-
r && console.log("Loading finished " +
|
|
358
|
-
let
|
|
356
|
+
r && console.log("Loading finished " + f, M.guid);
|
|
357
|
+
let y = 0;
|
|
359
358
|
if (E.parser.json.textures) {
|
|
360
|
-
let
|
|
359
|
+
let p = !1;
|
|
361
360
|
for (const u of E.parser.json.textures) {
|
|
362
361
|
if (u != null && u.extensions) {
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
|
|
362
|
+
const x = u == null ? void 0 : u.extensions[R];
|
|
363
|
+
if (x != null && x.guid && x.guid === M.guid) {
|
|
364
|
+
p = !0;
|
|
366
365
|
break;
|
|
367
366
|
}
|
|
368
367
|
}
|
|
369
|
-
|
|
368
|
+
y++;
|
|
370
369
|
}
|
|
371
|
-
if (
|
|
372
|
-
let u = await Z.getDependency("texture",
|
|
373
|
-
return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"',
|
|
370
|
+
if (p) {
|
|
371
|
+
let u = await Z.getDependency("texture", y);
|
|
372
|
+
return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, y, u, L), e instanceof U && (u = this.copySettings(e, u)), u && (u.guid = M.guid), m(u);
|
|
374
373
|
} else
|
|
375
374
|
w && console.warn("Could not find texture with guid", M.guid);
|
|
376
375
|
}
|
|
377
|
-
if (
|
|
378
|
-
let
|
|
376
|
+
if (y = 0, E.parser.json.meshes) {
|
|
377
|
+
let p = !1;
|
|
379
378
|
for (const u of E.parser.json.meshes) {
|
|
380
379
|
if (u != null && u.extensions) {
|
|
381
|
-
const
|
|
382
|
-
if (
|
|
383
|
-
|
|
380
|
+
const x = u == null ? void 0 : u.extensions[R];
|
|
381
|
+
if (x != null && x.guid && x.guid === M.guid) {
|
|
382
|
+
p = !0;
|
|
384
383
|
break;
|
|
385
384
|
}
|
|
386
385
|
}
|
|
387
|
-
|
|
386
|
+
y++;
|
|
388
387
|
}
|
|
389
|
-
if (
|
|
390
|
-
const u = await Z.getDependency("mesh",
|
|
391
|
-
if (r && console.log(`Loaded Mesh "${u.name}"`,
|
|
388
|
+
if (p) {
|
|
389
|
+
const u = await Z.getDependency("mesh", y), x = M;
|
|
390
|
+
if (r && console.log(`Loaded Mesh "${u.name}"`, f, y, u, L), u.isMesh === !0) {
|
|
392
391
|
const S = u.geometry;
|
|
393
|
-
return _.assignLODInformation(i.url, S, n, t, void 0,
|
|
392
|
+
return _.assignLODInformation(i.url, S, n, t, void 0, x.density), m(S);
|
|
394
393
|
} else {
|
|
395
394
|
const S = new Array();
|
|
396
395
|
for (let C = 0; C < u.children.length; C++) {
|
|
397
396
|
const F = u.children[C];
|
|
398
397
|
if (F instanceof H) {
|
|
399
398
|
const z = F.geometry;
|
|
400
|
-
_.assignLODInformation(i.url, z, n, t, C,
|
|
399
|
+
_.assignLODInformation(i.url, z, n, t, C, x.density), S.push(z);
|
|
401
400
|
}
|
|
402
401
|
}
|
|
403
402
|
return m(S);
|
|
@@ -406,11 +405,11 @@ const _ = class {
|
|
|
406
405
|
}
|
|
407
406
|
return m(null);
|
|
408
407
|
});
|
|
409
|
-
return this.previouslyLoaded.set(
|
|
408
|
+
return this.previouslyLoaded.set(L, O), await O;
|
|
410
409
|
} else if (e instanceof U) {
|
|
411
|
-
r && console.log("Load texture from uri: " +
|
|
412
|
-
const D = await new De().loadAsync(
|
|
413
|
-
return D ? (D.guid = s.guid, D.flipY = !1, D.needsUpdate = !0, D.colorSpace = e.colorSpace, r && console.log(s, D)) : w && console.warn("failed loading",
|
|
410
|
+
r && console.log("Load texture from uri: " + f);
|
|
411
|
+
const D = await new De().loadAsync(f);
|
|
412
|
+
return D ? (D.guid = s.guid, D.flipY = !1, D.needsUpdate = !0, D.colorSpace = e.colorSpace, r && console.log(s, D)) : w && console.warn("failed loading", f), D;
|
|
414
413
|
}
|
|
415
414
|
} else
|
|
416
415
|
w && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
@@ -446,14 +445,14 @@ c(v, "registerTexture", (e, t, r, i, n) => {
|
|
|
446
445
|
* Register a mesh with LOD information
|
|
447
446
|
*/
|
|
448
447
|
c(v, "registerMesh", (e, t, r, i, n, s) => {
|
|
449
|
-
var
|
|
448
|
+
var h;
|
|
450
449
|
w && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
|
|
451
450
|
const o = r.geometry;
|
|
452
451
|
o.userData || (o.userData = {}), _.assignLODInformation(e, o, t, i, n, s.density), _.lodInfos.set(t, s);
|
|
453
452
|
let a = _.lowresCache.get(t);
|
|
454
453
|
a ? a.push(r.geometry) : a = [r.geometry], _.lowresCache.set(t, a), i > 0 && !ve(r) && Se(r, o);
|
|
455
|
-
for (const
|
|
456
|
-
(
|
|
454
|
+
for (const d of I)
|
|
455
|
+
(h = d.onRegisteredNewMesh) == null || h.call(d, r, s);
|
|
457
456
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
458
457
|
c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
459
458
|
c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
@@ -547,26 +546,26 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
|
|
|
547
546
|
onBeforeRender(e, t, r, i) {
|
|
548
547
|
}
|
|
549
548
|
onAfterRender(e, t, r, i) {
|
|
550
|
-
var a,
|
|
549
|
+
var a, h;
|
|
551
550
|
if (this.pause)
|
|
552
551
|
return;
|
|
553
552
|
const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
|
|
554
553
|
let o = !0;
|
|
555
554
|
if (s.length === 1) {
|
|
556
|
-
const
|
|
557
|
-
(
|
|
555
|
+
const d = s[0].material;
|
|
556
|
+
(d.name === "EffectMaterial" || d.name === "CopyShader") && (o = !1);
|
|
558
557
|
}
|
|
559
558
|
if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
|
|
560
559
|
if (Ae || this.updateInterval > 0 && i % this.updateInterval != 0)
|
|
561
560
|
return;
|
|
562
561
|
this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
563
|
-
const
|
|
564
|
-
for (const
|
|
565
|
-
if (
|
|
566
|
-
$ && (
|
|
562
|
+
const d = this.targetTriangleDensity;
|
|
563
|
+
for (const f of s) {
|
|
564
|
+
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")) {
|
|
565
|
+
$ && (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)));
|
|
567
566
|
continue;
|
|
568
567
|
}
|
|
569
|
-
switch (
|
|
568
|
+
switch (f.material.type) {
|
|
570
569
|
case "LineBasicMaterial":
|
|
571
570
|
case "LineDashedMaterial":
|
|
572
571
|
case "PointsMaterial":
|
|
@@ -575,32 +574,33 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
|
|
|
575
574
|
case "MeshDepthMaterial":
|
|
576
575
|
continue;
|
|
577
576
|
}
|
|
578
|
-
const
|
|
579
|
-
(
|
|
577
|
+
const L = f.object;
|
|
578
|
+
(L instanceof H || L.isMesh) && this.updateLODs(e, t, L, d, i);
|
|
580
579
|
}
|
|
581
|
-
const
|
|
582
|
-
for (const
|
|
583
|
-
const
|
|
584
|
-
(
|
|
580
|
+
const g = n.transparent;
|
|
581
|
+
for (const f of g) {
|
|
582
|
+
const L = f.object;
|
|
583
|
+
(L instanceof H || L.isMesh) && this.updateLODs(e, t, L, d, i);
|
|
585
584
|
}
|
|
586
585
|
}
|
|
587
586
|
}
|
|
588
587
|
/** Update the LOD levels for the renderer. */
|
|
589
588
|
updateLODs(e, t, r, i, n) {
|
|
590
|
-
var a,
|
|
589
|
+
var a, h;
|
|
590
|
+
r.userData || (r.userData = {});
|
|
591
591
|
let s = r.userData.LOD_state;
|
|
592
592
|
if (s || (s = new be(), r.userData.LOD_state = s), s.frames++ < 2)
|
|
593
593
|
return;
|
|
594
|
-
for (const
|
|
595
|
-
(a =
|
|
594
|
+
for (const d of I)
|
|
595
|
+
(a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
|
|
596
596
|
this.calculateLodLevel(t, r, s, i, b), b.mesh_lod = Math.round(b.mesh_lod), b.texture_lod = Math.round(b.texture_lod), b.mesh_lod >= 0 && this.loadProgressiveMeshes(r, b.mesh_lod);
|
|
597
597
|
let o = b.texture_lod;
|
|
598
598
|
if (r.material && o >= 0) {
|
|
599
|
-
const
|
|
600
|
-
|
|
599
|
+
const d = r["DEBUG:LOD"];
|
|
600
|
+
d != null && (o = d), this.loadProgressiveTextures(r.material, o);
|
|
601
601
|
}
|
|
602
|
-
for (const
|
|
603
|
-
(
|
|
602
|
+
for (const d of I)
|
|
603
|
+
(h = d.onAfterUpdatedLOD) == null || h.call(d, this.renderer, e, t, r, b);
|
|
604
604
|
s.lastLodLevel_Mesh = b.mesh_lod, s.lastLodLevel_Texture = b.texture_lod;
|
|
605
605
|
}
|
|
606
606
|
/** Load progressive textures for the given material
|
|
@@ -653,72 +653,72 @@ const $ = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:
|
|
|
653
653
|
let o = 10 + 1;
|
|
654
654
|
if ($ && t["DEBUG:LOD"] != null)
|
|
655
655
|
return t["DEBUG:LOD"];
|
|
656
|
-
const a = v.getMeshLODInformation(t.geometry),
|
|
657
|
-
if (!
|
|
656
|
+
const a = v.getMeshLODInformation(t.geometry), h = a == null ? void 0 : a.lods, d = h && h.length > 0, g = v.getMaterialMinMaxLODsCount(t.material), f = (g == null ? void 0 : g.min_count) != 1 / 0 && g.min_count > 0 && g.max_count > 0;
|
|
657
|
+
if (!d && !f) {
|
|
658
658
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
659
659
|
return;
|
|
660
660
|
}
|
|
661
|
-
if (
|
|
661
|
+
if (d || (o = 0), !((D = this.cameraFrustrum) != null && D.intersectsObject(t))) {
|
|
662
662
|
n.mesh_lod = 99, n.texture_lod = 99;
|
|
663
663
|
return;
|
|
664
664
|
}
|
|
665
|
-
const
|
|
666
|
-
if (
|
|
665
|
+
const L = t.geometry.boundingBox;
|
|
666
|
+
if (L && e.isPerspectiveCamera) {
|
|
667
667
|
const M = e;
|
|
668
668
|
if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
|
|
669
669
|
this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
|
|
670
|
-
const
|
|
671
|
-
if (this._sphere.containsPoint(
|
|
670
|
+
const y = e.getWorldPosition(this._tempWorldPosition);
|
|
671
|
+
if (this._sphere.containsPoint(y)) {
|
|
672
672
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
673
673
|
return;
|
|
674
674
|
}
|
|
675
675
|
}
|
|
676
|
-
if (this._tempBox.copy(
|
|
676
|
+
if (this._tempBox.copy(L), this._tempBox.applyMatrix4(t.matrixWorld), A.isInside(this._tempBox, this.projectionScreenMatrix)) {
|
|
677
677
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
678
678
|
return;
|
|
679
679
|
}
|
|
680
680
|
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && M.fov > 70) {
|
|
681
|
-
const
|
|
682
|
-
let u =
|
|
683
|
-
const F = 2, z = 1.5, q = (
|
|
684
|
-
u = (u - q) * F + q,
|
|
685
|
-
const de = u < 0 && S > 0 ? 0 : Math.min(Math.abs(
|
|
681
|
+
const y = this._tempBox.min, p = this._tempBox.max;
|
|
682
|
+
let u = y.x, x = y.y, S = p.x, C = p.y;
|
|
683
|
+
const F = 2, z = 1.5, q = (y.x + p.x) * 0.5, X = (y.y + p.y) * 0.5;
|
|
684
|
+
u = (u - q) * F + q, x = (x - X) * F + X, S = (S - q) * F + q, C = (C - X) * F + X;
|
|
685
|
+
const de = u < 0 && S > 0 ? 0 : Math.min(Math.abs(y.x), Math.abs(p.x)), he = x < 0 && C > 0 ? 0 : Math.min(Math.abs(y.y), Math.abs(p.y)), j = Math.max(de, he);
|
|
686
686
|
r.lastCentrality = (z - j) * (z - j) * (z - j);
|
|
687
687
|
} else
|
|
688
688
|
r.lastCentrality = 1;
|
|
689
689
|
const O = this._tempBox.getSize(this._tempBoxSize);
|
|
690
690
|
O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= M.aspect;
|
|
691
691
|
const B = e.matrixWorldInverse, m = this._tempBox2;
|
|
692
|
-
m.copy(
|
|
692
|
+
m.copy(L), m.applyMatrix4(t.matrixWorld), m.applyMatrix4(B);
|
|
693
693
|
const T = m.getSize(this._tempBox2Size), G = Math.max(T.x, T.y);
|
|
694
694
|
if (Math.max(O.x, O.y) != 0 && G != 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, $ && A.debugDrawLine) {
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
const C = (
|
|
700
|
-
|
|
695
|
+
const y = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
696
|
+
y.invert();
|
|
697
|
+
const p = A.corner0, u = A.corner1, x = A.corner2, S = A.corner3;
|
|
698
|
+
p.copy(this._tempBox.min), u.copy(this._tempBox.max), u.x = p.x, x.copy(this._tempBox.max), x.y = p.y, S.copy(this._tempBox.max);
|
|
699
|
+
const C = (p.z + S.z) * 0.5;
|
|
700
|
+
p.z = u.z = x.z = S.z = C, p.applyMatrix4(y), u.applyMatrix4(y), x.applyMatrix4(y), S.applyMatrix4(y), A.debugDrawLine(p, u, 255), A.debugDrawLine(p, x, 255), A.debugDrawLine(u, S, 255), A.debugDrawLine(x, S, 255);
|
|
701
701
|
}
|
|
702
702
|
let E = 999;
|
|
703
|
-
if (
|
|
704
|
-
for (let
|
|
705
|
-
if (
|
|
706
|
-
E =
|
|
703
|
+
if (h && r.lastScreenCoverage > 0) {
|
|
704
|
+
for (let y = 0; y < h.length; y++)
|
|
705
|
+
if (h[y].density / r.lastScreenCoverage < i) {
|
|
706
|
+
E = y;
|
|
707
707
|
break;
|
|
708
708
|
}
|
|
709
709
|
}
|
|
710
710
|
E < o && (o = E);
|
|
711
711
|
}
|
|
712
|
-
if (n.mesh_lod = o,
|
|
712
|
+
if (n.mesh_lod = o, f)
|
|
713
713
|
if (r.lastLodLevel_Texture < 0) {
|
|
714
|
-
if (n.texture_lod =
|
|
715
|
-
const M =
|
|
714
|
+
if (n.texture_lod = g.max_count - 1, $) {
|
|
715
|
+
const M = g.lods[g.max_count - 1];
|
|
716
716
|
$ && console.log(`First Texture LOD ${n.texture_lod} (${M.max_height}px) - ${t.name}`);
|
|
717
717
|
}
|
|
718
718
|
} else {
|
|
719
719
|
const M = r.lastScreenCoverage * 1.5, B = this.renderer.domElement.clientHeight / window.devicePixelRatio * M;
|
|
720
|
-
for (let m =
|
|
721
|
-
const T =
|
|
720
|
+
for (let m = g.lods.length - 1; m >= 0; m--) {
|
|
721
|
+
const T = g.lods[m];
|
|
722
722
|
if (T.max_height > B) {
|
|
723
723
|
n.texture_lod = m, n.texture_lod < r.lastLodLevel_Texture && $ && console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${n.texture_lod} (${T.max_height}px: ${(100 * r.lastScreenCoverage).toFixed(2)} % = ${B.toFixed(0)}px) - ${t.name}`);
|
|
724
724
|
break;
|
|
@@ -788,20 +788,20 @@ class Ee {
|
|
|
788
788
|
const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
|
|
789
789
|
if (i && r && t.material) {
|
|
790
790
|
let n = function(o) {
|
|
791
|
-
var
|
|
791
|
+
var h, d, g;
|
|
792
792
|
if (o[Y] == !0)
|
|
793
793
|
return;
|
|
794
794
|
o[Y] = !0, o.userData && (o.userData.LOD = -1);
|
|
795
795
|
const a = Object.keys(o);
|
|
796
|
-
for (let
|
|
797
|
-
const
|
|
796
|
+
for (let f = 0; f < a.length; f++) {
|
|
797
|
+
const L = a[f], D = o[L];
|
|
798
798
|
if ((D == null ? void 0 : D.isTexture) === !0) {
|
|
799
|
-
const M = (
|
|
799
|
+
const M = (d = (h = D.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[M];
|
|
800
800
|
if (!O) {
|
|
801
801
|
console.warn("Texture data not found for texture index " + M);
|
|
802
802
|
continue;
|
|
803
803
|
}
|
|
804
|
-
if ((
|
|
804
|
+
if ((g = O == null ? void 0 : O.extensions) != null && g[R]) {
|
|
805
805
|
const B = O.extensions[R];
|
|
806
806
|
B && i && v.registerTexture(i, D, B.lods.length, M, B);
|
|
807
807
|
}
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var fe=Object.defineProperty,ge=(t,e,r)=>e in t?fe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ge(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as me}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as xe}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as q,Mesh as V,Material as ye,Texture as $,TextureLoader as Le,Matrix4 as se,Frustum as ve,Sphere as De,Box3 as oe,Vector3 as B}from"three";import{GLTFLoader as Me}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",Y="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",Y="./include/ktx2/"});function Oe(t){X=t}function _e(t){Y=t}let z,J,W;function Q(t){z||(z=new pe,z.setDecoderPath(X),z.setDecoderConfig({type:"js"})),W||(W=new xe,W.setTranscoderPath(Y)),J||(J=me),t?W.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(t){t.dracoLoader||t.setDRACOLoader(z),t.ktx2Loader||t.setKTX2Loader(W),t.meshoptDecoder||t.setMeshoptDecoder(J)}function ee(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function we(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}function ne(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof q?t.userData["needle:raycast-mesh"]:null}function ie(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const k=new Array,P="NEEDLE_progressive",L=ee("debugprogressive"),te=Symbol("needle-progressive-texture"),U=new Map,re=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,U),U.forEach((o,s)=>{for(const
|
|
2
|
-
`,G),null)),b=!1;if(
|
|
3
|
-
`,
|
|
1
|
+
var fe=Object.defineProperty,ge=(t,e,r)=>e in t?fe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ge(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as me}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as xe}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as q,Mesh as V,Material as ye,Texture as $,TextureLoader as Le,Matrix4 as se,Frustum as ve,Sphere as De,Box3 as oe,Vector3 as B}from"three";import{GLTFLoader as Me}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",Y="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",Y="./include/ktx2/"});function Oe(t){X=t}function _e(t){Y=t}let z,J,W;function Q(t){z||(z=new pe,z.setDecoderPath(X),z.setDecoderConfig({type:"js"})),W||(W=new xe,W.setTranscoderPath(Y)),J||(J=me),t?W.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(t){t.dracoLoader||t.setDRACOLoader(z),t.ktx2Loader||t.setKTX2Loader(W),t.meshoptDecoder||t.setMeshoptDecoder(J)}function ee(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function we(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}function ne(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof q?t.userData["needle:raycast-mesh"]:null}function ie(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const k=new Array,P="NEEDLE_progressive",L=ee("debugprogressive"),te=Symbol("needle-progressive-texture"),U=new Map,re=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,U),U.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const u=_.getMeshLODInformation(i),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,_.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,_.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,re&&re.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ae(t,e,r){var n;if(!L)return;U.has(t)||U.set(t,{keys:[],sourceId:r});const o=U.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const M=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&&M.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),L&&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(L==="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 V||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of k)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,M.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 q&&(t.geometry=s,L&&ae(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else L&&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 ye||t.isMaterial===!0){const r=t,n=[],o=new Array;if(L&&re.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 $||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):M.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 L==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(L&&n&&r){const s=this.getAssignedLODInformation(t);s&&ae(r,n,s.url)}}return o}else L=="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 L&&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){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,M.registerTexture(this.url,i,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&M.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&&M.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=L=="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[te]&&(l=g.source[te])}if(l||(l=M.lodInfos.get(u)),l){if(e>0){let f=!1;const w=Array.isArray(l.lods);if(w&&e>=l.lods.length?f=!0:w||(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 L&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const d=we(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,w=this.previouslyLoaded.get(f);if(w!==void 0){a&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let p=await w.catch(G=>(console.error(`Error loading LOD ${e} from ${d}
|
|
2
|
+
`,G),null)),b=!1;if(p==null||(p instanceof $&&t instanceof $?(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 q&&t instanceof q&&((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 G=new Me;Z(G),L&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let N=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(N+="?v="+y.hash)}const x=await G.loadAsync(N).catch(y=>(console.error(`Error loading LOD ${e} from ${d}
|
|
3
|
+
`,y),null));if(!x)return null;const v=x.parser;a&&console.log("Loading finished "+d,m.guid);let D=0;if(x.parser.json.textures){let y=!1;for(const h of x.parser.json.textures){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){let h=await v.getDependency("texture",D);return h&&M.assignLODInformation(i.url,h,u,e,void 0,void 0),a&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',d,D,h,f),t instanceof $&&(h=this.copySettings(t,h)),h&&(h.guid=m.guid),p(h)}else L&&console.warn("Could not find texture with guid",m.guid)}if(D=0,x.parser.json.meshes){let y=!1;for(const h of x.parser.json.meshes){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){const h=await v.getDependency("mesh",D),O=m;if(a&&console.log(`Loaded Mesh "${h.name}"`,d,D,h,f),h.isMesh===!0){const A=h.geometry;return M.assignLODInformation(i.url,A,u,e,void 0,O.density),p(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const j=h.children[C];if(j instanceof V){const R=j.geometry;M.assignLODInformation(i.url,R,u,e,C,O.density),A.push(R)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof $){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)):L&&console.warn("failed loading",d),f}}else L&&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 be(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(),L&&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)=>{L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),e.source&&(e.source[te]=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 i;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const a=r.geometry;a.userData||(a.userData={}),M.assignLODInformation(t,a,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&&!ne(r)&&ie(r,a);for(const l of k)(i=l.onRegisteredNewMesh)==null||i.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class be{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 F=ee("debugprogressive"),Se=ee("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new se),c(this,"cameraFrustrum",new ve),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new De),c(this,"_tempBox",new oe),c(this,"_tempBox2",new oe),c(this,"tempMatrix",new se),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){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t){return t[le]?t[le]:new T(t)}get plugins(){return k}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;Q(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 i=this.renderer.renderLists.get(t,0),a=i.opaque;let u=!0;if(a.length===1){const l=a[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Se||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 h of a){if(h.material&&(((o=h.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=h.geometry)==null?void 0:s.type)==="BufferGeometry")&&(h.material.name==="SphericalGaussianBlur"||h.material.name=="BackgroundCubeMaterial"||h.material.name==="CubemapFromEquirect"||h.material.name==="EquirectangularToCubeUV")){F&&(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",h,h.material.name,h.material.type)));continue}switch(h.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=h.object;(f instanceof V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const y=i.transparent;for(const h of y){const f=h.object;(f instanceof V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,i;let a=r.userData.LOD_state;if(a||(a=new Te,r.userData.LOD_state=a),a.frames++<2)return;for(const l of k)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,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 k)(i=l.onAfterUpdatedLOD)==null||i.call(l,this.renderer,t,e,r,E);a.lastLodLevel_Mesh=E.mesh_lod,a.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 i=10+1;if(F&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=_.getMeshLODInformation(e.geometry),u=a?.lods,l=u&&u.length>0,y=_.getMaterialMinMaxLODsCount(e.material),h=y?.min_count!=1/0&&y.min_count>0&&y.max_count>0;if(!l&&!h){o.mesh_lod=0,o.texture_lod=0;return}if(l||(i=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 p=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(p)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),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 p=this._tempBox.min,v=this._tempBox.max;let D=p.x,x=p.y,d=v.x,O=v.y;const A=2,C=1.5,j=(p.x+v.x)*.5,R=(p.y+v.y)*.5;D=(D-j)*A+j,x=(x-R)*A+R,d=(d-j)*A+j,O=(O-R)*A+R;const de=D<0&&d>0?0:Math.min(Math.abs(p.x),Math.abs(v.x)),he=x<0&&O>0?0:Math.min(Math.abs(p.y),Math.abs(v.y)),H=Math.max(de,he);r.lastCentrality=(C-H)*(C-H)*(C-H)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&g.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),g.x*=w.aspect;const S=t.matrixWorldInverse,m=this._tempBox2;m.copy(f),m.applyMatrix4(e.matrixWorld),m.applyMatrix4(S);const b=m.getSize(this._tempBox2Size),G=Math.max(b.x,b.y);if(Math.max(g.x,g.y)!=0&&G!=0&&(g.z=b.z/Math.max(b.x,b.y)*Math.max(g.x,g.y)),r.lastScreenCoverage=Math.max(g.x,g.y,g.z),r.lastScreenspaceVolume.copy(g),r.lastScreenCoverage*=r.lastCentrality,F&&T.debugDrawLine){const p=this.tempMatrix.copy(this.projectionScreenMatrix);p.invert();const v=T.corner0,D=T.corner1,x=T.corner2,d=T.corner3;v.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=v.x,x.copy(this._tempBox.max),x.y=v.y,d.copy(this._tempBox.max);const O=(v.z+d.z)*.5;v.z=D.z=x.z=d.z=O,v.applyMatrix4(p),D.applyMatrix4(p),x.applyMatrix4(p),d.applyMatrix4(p),T.debugDrawLine(v,D,255),T.debugDrawLine(v,x,255),T.debugDrawLine(D,d,255),T.debugDrawLine(x,d,255)}let N=999;if(u&&r.lastScreenCoverage>0){for(let p=0;p<u.length;p++)if(u[p].density/r.lastScreenCoverage<n){N=p;break}}N<i&&(i=N)}if(o.mesh_lod=i,h)if(r.lastLodLevel_Texture<0){if(o.texture_lod=y.max_count-1,F){const w=y.lods[y.max_count-1];F&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,g=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=y.lods.length-1;S>=0;S--){const m=y.lods[S];if(m.max_height>g){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&F&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${m.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${g.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 Te{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 ue=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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(a=>a.toString()=="Symbol(renderer)"),i=o.find(a=>a.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&i!=null&&(r=t[i])}if(e){console.log("Adding Needle LODs to modelviewer");const n=I.get(e);if(I.addPlugin(new Ee(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 Ee{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[K]==!0)return;r[K]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(a){var u,l,y;if(a[K]==!0)return;a[K]=!0,a.userData&&(a.userData.LOD=-1);const h=Object.keys(a);for(let f=0;f<h.length;f++){const w=h[f],g=a[w];if(g?.isTexture===!0){const S=(l=(u=g.userData)==null?void 0:u.associations)==null?void 0:l.textures,m=n.parser.json.textures[S];if(!m){console.warn("Texture data not found for texture index "+S);continue}if((y=m?.extensions)!=null&&y[P]){const b=m.extensions[P];b&&o&&_.registerTexture(o,g,b.lods.length,S,b)}}}};const i=r.material;if(Array.isArray(i))for(const a of i)s(a);else s(i)}}tryParseMeshLOD(e,r){var n,o;if(r[ue]==!0)return;r[ue]=!0;const s=this.getUrl();if(!s)return;const i=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(i&&s){const a=r.uuid;_.registerMesh(s,a,r,0,i.lods.length,i)}}}function Ae(t,e,r,n){Q(e),Z(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ce(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,Z as addDracoAndKTX2Loaders,Q as createLoaders,ne as getRaycastMesh,ce as patchModelViewer,Oe as setDracoDecoderLocation,_e as setKTX2TranscoderLocation,ie as setRaycastMesh,Ae as useNeedleProgressive};
|
|
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)=>{L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),e.source&&(e.source[te]=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;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&&!ne(r)&&ie(r,i);for(const l of k)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class be{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 F=ee("debugprogressive"),Se=ee("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new se),c(this,"cameraFrustrum",new ve),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new De),c(this,"_tempBox",new oe),c(this,"_tempBox2",new oe),c(this,"tempMatrix",new se),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){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t){return t[le]?t[le]:new T(t)}get plugins(){return k}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;Q(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(Se||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")){F&&(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 V||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof V||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 Te,r.userData.LOD_state=i),i.frames++<2)return;for(const l of k)(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 k)(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(F&&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),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,j=(x.x+v.x)*.5,R=(x.y+v.y)*.5;D=(D-j)*A+j,y=(y-R)*A+R,h=(h-j)*A+j,O=(O-R)*A+R;const de=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(v.x)),he=y<0&&O>0?0:Math.min(Math.abs(x.y),Math.abs(v.y)),H=Math.max(de,he);r.lastCentrality=(C-H)*(C-H)*(C-H)}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),G=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&G!=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,F&&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 N=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){N=x;break}}N<a&&(a=N)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,F){const w=g.lods[g.max_count-1];F&&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(p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&F&&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 Te{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 ue=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 Ee(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 Ee{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[K]==!0)return;r[K]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[K]==!0)return;i[K]=!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[ue]==!0)return;r[ue]=!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 Ae(t,e,r,n){Q(e),Z(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ce(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,Z as addDracoAndKTX2Loaders,Q as createLoaders,ne as getRaycastMesh,ce as patchModelViewer,Oe as setDracoDecoderLocation,_e as setKTX2TranscoderLocation,ie as setRaycastMesh,Ae as useNeedleProgressive};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var fe=Object.defineProperty;var he=(l,e,t)=>e in l?fe(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(he(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ge=require("three/examples/jsm/libs/meshopt_decoder.module.js"),pe=require("three/examples/jsm/loaders/DRACOLoader.js"),ye=require("three/examples/jsm/loaders/KTX2Loader.js"),
|
|
2
|
-
`,F),null)),A=!1;if(
|
|
3
|
-
`,
|
|
1
|
+
"use strict";var fe=Object.defineProperty;var he=(l,e,t)=>e in l?fe(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(he(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ge=require("three/examples/jsm/libs/meshopt_decoder.module.js"),pe=require("three/examples/jsm/loaders/DRACOLoader.js"),ye=require("three/examples/jsm/loaders/KTX2Loader.js"),p=require("three"),Le=require("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(l=>{X="./include/draco/",ee="./include/ktx2/"});function xe(l){X=l}function me(l){ee=l}let $,Z,U;function te(l){$||($=new pe.DRACOLoader,$.setDecoderPath(X),$.setDecoderConfig({type:"js"})),U||(U=new ye.KTX2Loader,U.setTranscoderPath(ee)),Z||(Z=ge.MeshoptDecoder),l?U.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function re(l){l.dracoLoader||l.setDRACOLoader($),l.ktx2Loader||l.setKTX2Loader(U),l.meshoptDecoder||l.setMeshoptDecoder(Z)}function se(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function De(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}function ae(l){var e;return((e=l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof p.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function le(l,e){(l.type==="Mesh"||l.type==="SkinnedMesh")&&(l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=e)}const I=new Array,R="NEEDLE_progressive",w=se("debugprogressive"),Q=Symbol("needle-progressive-texture"),W=new Map,j=new Set;if(w){let l=function(){e+=1,console.log("Toggle LOD level",e,W),W.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,j&&j.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ie(l,e,t){var i;if(!w)return;W.has(l)||W.set(l,{keys:[],sourceId:t});const r=W.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[R];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});w&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return R}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(w==="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 f=r.lodInfos.get(h.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let g=0;g<f.lods.length;g++){const d=f.lods[g];d.width&&(a.lods[g]=a.lods[g]||{min_height:1/0,max_height:0},a.lods[g].min_height=Math.min(a.lods[g].min_height,d.height),a.lods[g].max_height=Math.max(a.lods[g].max_height,d.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 p.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 p.BufferGeometry&&(e.geometry=s,w&&ie(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else w&&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 p.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(w&&j.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],f=o[a];h&&h.isTexture===!0?n.push({material:r,slot:f,texture:h,level:t}):n.push({material:r,slot:f,texture:null,level:t})}return n})}if(e instanceof p.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 w==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(w&&i&&r){const s=this.getAssignedLODInformation(e);s&&ie(r,i,s.url)}}return o}else w=="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 w&&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[R];if(s){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[R];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,f;const r=w=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const g=e;g.source&&g.source[Q]&&(s=g.source[Q])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const M=Array.isArray(s.lods);if(M&&t>=s.lods.length?x=!0:M||(x=!0),x)return this.lowresCache.get(o)}const g=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!g)return w&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const d=De(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=d+"_"+s.guid,M=this.previouslyLoaded.get(x);if(M!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let m=await M.catch(F=>(console.error(`Error loading LOD ${t} from ${d}
|
|
2
|
+
`,F),null)),A=!1;if(m==null||(m instanceof p.Texture&&e instanceof p.Texture?(a=m.image)!=null&&a.data||(h=m.source)!=null&&h.data?m=this.copySettings(e,m):(A=!0,this.previouslyLoaded.delete(x)):m instanceof p.BufferGeometry&&e instanceof p.BufferGeometry&&((f=m.attributes.position)!=null&&f.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return m}const O=s,_=new Promise(async(m,A)=>{const F=new Le.GLTFLoader;re(F),w&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+d,O.guid));let Y=d;if(O&&Array.isArray(O.lods)){const y=O.lods[t];y.hash&&(Y+="?v="+y.hash)}const B=await F.loadAsync(Y).catch(y=>(console.error(`Error loading LOD ${t} from ${d}
|
|
3
|
+
`,y),null));if(!B)return null;const H=B.parser;r&&console.log("Loading finished "+d,O.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 D=u==null?void 0:u.extensions[R];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){let u=await H.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',d,L,u,x),e instanceof p.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=O.guid),m(u)}else w&&console.warn("Could not find texture with guid",O.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 D=u==null?void 0:u.extensions[R];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){const u=await H.getDependency("mesh",L),D=O;if(r&&console.log(`Loaded Mesh "${u.name}"`,d,L,u,x),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,D.density),m(T)}else{const T=new Array;for(let C=0;C<u.children.length;C++){const G=u.children[C];if(G instanceof p.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,C,D.density),T.push(N)}}return m(T)}}}return m(null)});return this.previouslyLoaded.set(x,_),await _}else if(e instanceof p.Texture){r&&console.log("Load texture from uri: "+d);const M=await new p.TextureLoader().loadAsync(d);return M?(M.guid=s.guid,M.flipY=!1,M.needsUpdate=!0,M.colorSpace=e.colorSpace,r&&console.log(s,M)):w&&console.warn("failed loading",d),M}}else w&&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 Me(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(),w&&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)=>{w&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),t.source&&(t.source[Q]=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 d;w&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;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&&!ae(r)&&le(r,n);for(const h of I)(d=h.onRegisteredNewMesh)==null||d.call(h,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Me{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=se("debugprogressive"),Oe=se("noprogressive"),oe=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[oe]?e[oe]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;te(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,d;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const h=s[0].material;(h.name==="EffectMaterial"||h.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Oe||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const h=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((d=f.geometry)==null?void 0:d.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 L=f.object;(L instanceof g.Mesh||L.isMesh)&&this.updateLODs(e,t,L,h,i)}const D=o.transparent;for(const f of D){const L=f.object;(L instanceof g.Mesh||L.isMesh)&&this.updateLODs(e,t,L,h,i)}}}updateLODs(e,t,r,i,o){var a,d;let s=r.userData.LOD_state;if(s||(s=new _e,r.userData.LOD_state=s),s.frames++<2)return;for(const h of I)(a=h.onBeforeUpdateLOD)==null||a.call(h,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 h=r["DEBUG:LOD"];h!=null&&(n=h),this.loadProgressiveTextures(r.material,n)}for(const h of I)(d=h.onAfterUpdatedLOD)==null||d.call(h,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 M;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),d=a==null?void 0:a.lods,h=d&&d.length>0,D=S.getMaterialMinMaxLODsCount(t.material),f=(D==null?void 0:D.min_count)!=1/0&&D.min_count>0&&D.max_count>0;if(!h&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(h||(n=0),!((M=this.cameraFrustrum)!=null&&M.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const L=t.geometry.boundingBox;if(L&&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 y=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(L),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 y=this._tempBox.min,p=this._tempBox.max;let u=y.x,m=y.y,T=p.x,C=p.y;const G=2,N=1.5,V=(y.x+p.x)*.5,q=(y.y+p.y)*.5;u=(u-V)*G+V,m=(m-q)*G+q,T=(T-V)*G+V,C=(C-q)*G+q;const ue=u<0&&T>0?0:Math.min(Math.abs(y.x),Math.abs(p.x)),de=m<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(p.y)),J=Math.max(ue,de);r.lastCentrality=(N-J)*(N-J)*(N-J)}else r.lastCentrality=1;const _=this._tempBox.getSize(this._tempBoxSize);_.multiplyScalar(.5),screen.availHeight>0&&_.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),_.x*=O.aspect;const k=e.matrixWorldInverse,x=this._tempBox2;x.copy(L),x.applyMatrix4(t.matrixWorld),x.applyMatrix4(k);const A=x.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(_.x,_.y)!=0&&F!=0&&(_.z=A.z/Math.max(A.x,A.y)*Math.max(_.x,_.y)),r.lastScreenCoverage=Math.max(_.x,_.y,_.z),r.lastScreenspaceVolume.copy(_),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const p=b.corner0,u=b.corner1,m=b.corner2,T=b.corner3;p.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=p.x,m.copy(this._tempBox.max),m.y=p.y,T.copy(this._tempBox.max);const C=(p.z+T.z)*.5;p.z=u.z=m.z=T.z=C,p.applyMatrix4(y),u.applyMatrix4(y),m.applyMatrix4(y),T.applyMatrix4(y),b.debugDrawLine(p,u,255),b.debugDrawLine(p,m,255),b.debugDrawLine(u,T,255),b.debugDrawLine(m,T,255)}let B=999;if(d&&r.lastScreenCoverage>0){for(let y=0;y<d.length;y++)if(d[y].density/r.lastScreenCoverage<i){B=y;break}}B<n&&(n=B)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=D.max_count-1,z){const O=D.lods[D.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 x=D.lods.length-1;x>=0;x--){const A=D.lods[x];if(A.max_height>k){o.texture_lod=x,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 _e{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 ne=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 we(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 we{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[K]==!0)return;t[K]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var d,h,D;if(n[K]==!0)return;n[K]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const L=a[f],M=n[L];if((M==null?void 0:M.isTexture)===!0){const O=(h=(d=M.userData)==null?void 0:d.associations)==null?void 0:h.textures,_=r.parser.json.textures[O];if(!_){console.warn("Texture data not found for texture index "+O);continue}if((D=_==null?void 0:_.extensions)!=null&&D[R]){const k=_.extensions[R];k&&i&&S.registerTexture(i,M,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[ne]==!0)return;t[ne]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function ve(l,e,t,r){te(e),re(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",()=>{ce(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=re;exports.createLoaders=te;exports.getRaycastMesh=ae;exports.patchModelViewer=ce;exports.setDracoDecoderLocation=xe;exports.setKTX2TranscoderLocation=me;exports.setRaycastMesh=le;exports.useNeedleProgressive=ve;
|
|
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)=>{w&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),t.source&&(t.source[Q]=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;w&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;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&&!ae(r)&&le(r,n);for(const f of I)(h=f.onRegisteredNewMesh)==null||h.call(f,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Me{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=se("debugprogressive"),Oe=se("noprogressive"),oe=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new p.Matrix4);c(this,"cameraFrustrum",new p.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new p.Sphere);c(this,"_tempBox",new p.Box3);c(this,"_tempBox2",new p.Box3);c(this,"tempMatrix",new p.Matrix4);c(this,"_tempWorldPosition",new p.Vector3);c(this,"_tempBoxSize",new p.Vector3);c(this,"_tempBox2Size",new p.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[oe]?e[oe]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;te(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 f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Oe||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const d of s){if(d.material&&(((a=d.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=d.geometry)==null?void 0:h.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){z&&(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 x=d.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,f,i)}const g=o.transparent;for(const d of g){const x=d.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,f,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new _e,r.userData.LOD_state=s),s.frames++<2)return;for(const f of I)(a=f.onBeforeUpdateLOD)==null||a.call(f,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 f=r["DEBUG:LOD"];f!=null&&(n=f),this.loadProgressiveTextures(r.material,n)}for(const f of I)(h=f.onAfterUpdatedLOD)==null||h.call(f,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 M;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,f=h&&h.length>0,g=S.getMaterialMinMaxLODsCount(t.material),d=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(f||(n=0),!((M=this.cameraFrustrum)!=null&&M.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),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,C=y.y;const G=2,N=1.5,V=(L.x+y.x)*.5,q=(L.y+y.y)*.5;u=(u-V)*G+V,D=(D-q)*G+q,T=(T-V)*G+V,C=(C-q)*G+q;const ue=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),de=D<0&&C>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),J=Math.max(ue,de);r.lastCentrality=(N-J)*(N-J)*(N-J)}else r.lastCentrality=1;const _=this._tempBox.getSize(this._tempBoxSize);_.multiplyScalar(.5),screen.availHeight>0&&_.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),_.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(_.x,_.y)!=0&&F!=0&&(_.z=A.z/Math.max(A.x,A.y)*Math.max(_.x,_.y)),r.lastScreenCoverage=Math.max(_.x,_.y,_.z),r.lastScreenspaceVolume.copy(_),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 C=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=C,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,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,z){const O=g.lods[g.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=g.lods.length-1;m>=0;m--){const A=g.lods[m];if(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 p.Vector3),c(P,"corner1",new p.Vector3),c(P,"corner2",new p.Vector3),c(P,"corner3",new p.Vector3),c(P,"_tempPtInside",new p.Vector3);class _e{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new p.Vector3);c(this,"lastCentrality",0)}}const ne=Symbol("NEEDLE_mesh_lod"),K=Symbol("NEEDLE_texture_lod");function ce(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 we(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 we{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[K]==!0)return;t[K]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,f,g;if(n[K]==!0)return;n[K]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let d=0;d<a.length;d++){const x=a[d],M=n[x];if((M==null?void 0:M.isTexture)===!0){const O=(f=(h=M.userData)==null?void 0:h.associations)==null?void 0:f.textures,_=r.parser.json.textures[O];if(!_){console.warn("Texture data not found for texture index "+O);continue}if((g=_==null?void 0:_.extensions)!=null&&g[R]){const k=_.extensions[R];k&&i&&S.registerTexture(i,M,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[ne]==!0)return;t[ne]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[R];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function ve(l,e,t,r){te(e),re(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",()=>{ce(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=re;exports.createLoaders=te;exports.getRaycastMesh=ae;exports.patchModelViewer=ce;exports.setDracoDecoderLocation=xe;exports.setKTX2TranscoderLocation=me;exports.setRaycastMesh=le;exports.useNeedleProgressive=ve;
|
package/lib/extension.js
CHANGED
|
@@ -96,6 +96,7 @@ export class NEEDLE_progressive {
|
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
98
|
static getMaterialMinMaxLODsCount(material, minmax) {
|
|
99
|
+
const self = this;
|
|
99
100
|
// we can cache this material min max data because it wont change at runtime
|
|
100
101
|
const cacheKey = "LODS:minmax";
|
|
101
102
|
const cached = material[cacheKey];
|
|
@@ -117,30 +118,12 @@ export class NEEDLE_progressive {
|
|
|
117
118
|
}
|
|
118
119
|
if (debug === "verbose")
|
|
119
120
|
console.log("getMaterialMinMaxLODsCount", material);
|
|
120
|
-
const processTexture = (tex) => {
|
|
121
|
-
const info = this.getAssignedLODInformation(tex);
|
|
122
|
-
if (info) {
|
|
123
|
-
const model = this.lodInfos.get(info.key);
|
|
124
|
-
if (model && model.lods) {
|
|
125
|
-
minmax.min_count = Math.min(minmax.min_count, model.lods.length);
|
|
126
|
-
minmax.max_count = Math.max(minmax.max_count, model.lods.length);
|
|
127
|
-
for (let i = 0; i < model.lods.length; i++) {
|
|
128
|
-
const lod = model.lods[i];
|
|
129
|
-
if (lod.width) {
|
|
130
|
-
minmax.lods[i] = minmax.lods[i] || { min_height: Infinity, max_height: 0 };
|
|
131
|
-
minmax.lods[i].min_height = Math.min(minmax.lods[i].min_height, lod.height);
|
|
132
|
-
minmax.lods[i].max_height = Math.max(minmax.lods[i].max_height, lod.height);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
121
|
if (material.type === "ShaderMaterial" || material.type === "RawShaderMaterial") {
|
|
139
122
|
const mat = material;
|
|
140
123
|
for (const slot of Object.keys(mat.uniforms)) {
|
|
141
124
|
const val = mat.uniforms[slot].value;
|
|
142
125
|
if (val?.isTexture === true) {
|
|
143
|
-
processTexture(val);
|
|
126
|
+
processTexture(val, minmax);
|
|
144
127
|
}
|
|
145
128
|
}
|
|
146
129
|
}
|
|
@@ -148,12 +131,30 @@ export class NEEDLE_progressive {
|
|
|
148
131
|
for (const slot of Object.keys(material)) {
|
|
149
132
|
const val = material[slot];
|
|
150
133
|
if (val?.isTexture === true) {
|
|
151
|
-
processTexture(val);
|
|
134
|
+
processTexture(val, minmax);
|
|
152
135
|
}
|
|
153
136
|
}
|
|
154
137
|
}
|
|
155
138
|
material[cacheKey] = minmax;
|
|
156
139
|
return minmax;
|
|
140
|
+
function processTexture(tex, minmax) {
|
|
141
|
+
const info = self.getAssignedLODInformation(tex);
|
|
142
|
+
if (info) {
|
|
143
|
+
const model = self.lodInfos.get(info.key);
|
|
144
|
+
if (model && model.lods) {
|
|
145
|
+
minmax.min_count = Math.min(minmax.min_count, model.lods.length);
|
|
146
|
+
minmax.max_count = Math.max(minmax.max_count, model.lods.length);
|
|
147
|
+
for (let i = 0; i < model.lods.length; i++) {
|
|
148
|
+
const lod = model.lods[i];
|
|
149
|
+
if (lod.width) {
|
|
150
|
+
minmax.lods[i] = minmax.lods[i] || { min_height: Infinity, max_height: 0 };
|
|
151
|
+
minmax.lods[i].min_height = Math.min(minmax.lods[i].min_height, lod.height);
|
|
152
|
+
minmax.lods[i].max_height = Math.max(minmax.lods[i].max_height, lod.height);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
157
158
|
}
|
|
158
159
|
/** Check if a LOD level is available for a mesh or a texture
|
|
159
160
|
* @param obj the mesh or texture to check
|
package/lib/lods_manager.js
CHANGED
|
@@ -201,6 +201,9 @@ export class LODsManager {
|
|
|
201
201
|
}
|
|
202
202
|
/** Update the LOD levels for the renderer. */
|
|
203
203
|
updateLODs(scene, camera, object, desiredDensity, _frame) {
|
|
204
|
+
if (!object.userData) {
|
|
205
|
+
object.userData = {};
|
|
206
|
+
}
|
|
204
207
|
let state = object.userData.LOD_state;
|
|
205
208
|
if (!state) {
|
|
206
209
|
state = new LOD_state();
|
package/package.json
CHANGED