@needle-tools/gltf-progressive 1.0.0-alpha.10 → 1.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/gltf-progressive.js +228 -209
- package/gltf-progressive.min.js +3 -3
- package/gltf-progressive.umd.cjs +3 -3
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/loaders.d.ts +10 -0
- package/lib/loaders.js +21 -2
- package/lib/lods_manager.js +17 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.0.0-alpha.12] - 2023-05-19
|
|
8
|
+
- fix: update LODs when using postprocessing
|
|
9
|
+
|
|
10
|
+
## [1.0.0-alpha.11] - 2023-05-17
|
|
11
|
+
- add: expose `setDracoDecoderLocation` and `setKTX2TranscoderLocation`
|
|
12
|
+
- fix: allow using draco decoder and ktx2 transcoder from local filepath
|
|
13
|
+
|
|
7
14
|
## [1.0.0-alpha.10] - 2023-05-07
|
|
8
15
|
- fix: progressive assets are now only updated during the main canvas render call and not e.g. when rendering to a texture
|
|
9
16
|
|
package/gltf-progressive.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { Mesh as q, BufferGeometry as
|
|
5
|
-
import { GLTFLoader as
|
|
6
|
-
import { MeshoptDecoder as
|
|
7
|
-
import { DRACOLoader as
|
|
8
|
-
import { KTX2Loader as
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
var le = Object.defineProperty;
|
|
2
|
+
var ue = (l, e, t) => e in l ? le(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
|
|
3
|
+
var c = (l, e, t) => (ue(l, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import { Mesh as q, BufferGeometry as V, Material as ce, Texture as U, TextureLoader as fe, Matrix4 as te, Frustum as de, Sphere as ge, Box3 as re, Vector3 as C } from "three";
|
|
5
|
+
import { GLTFLoader as he } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
6
|
+
import { MeshoptDecoder as pe } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
7
|
+
import { DRACOLoader as ye } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
8
|
+
import { KTX2Loader as me } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
9
|
+
let K = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", j = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
|
|
10
|
+
fetch(K + "draco_decoder.js", { method: "head" }).catch((l) => {
|
|
11
|
+
K = "./include/draco/", j = "./include/ktx2/";
|
|
12
|
+
});
|
|
13
|
+
function _e(l) {
|
|
14
|
+
K = l;
|
|
15
|
+
}
|
|
16
|
+
function Be(l) {
|
|
17
|
+
j = l;
|
|
18
|
+
}
|
|
19
|
+
let F, J, W;
|
|
20
|
+
function ne(l) {
|
|
21
|
+
F || (F = new ye(), F.setDecoderPath(K), F.setDecoderConfig({ type: "js" })), W || (W = new me(), W.setTranscoderPath(j)), J || (J = pe), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
|
|
13
22
|
}
|
|
14
|
-
function
|
|
15
|
-
l.dracoLoader || l.setDRACOLoader(F), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(
|
|
23
|
+
function oe(l) {
|
|
24
|
+
l.dracoLoader || l.setDRACOLoader(F), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(J);
|
|
16
25
|
}
|
|
17
|
-
function
|
|
26
|
+
function ee(l) {
|
|
18
27
|
const t = new URL(window.location.href).searchParams.get(l);
|
|
19
28
|
return t == null || t === "0" || t === "false" ? !1 : t === "" ? !0 : t;
|
|
20
29
|
}
|
|
@@ -30,19 +39,19 @@ function Le(l, e) {
|
|
|
30
39
|
}
|
|
31
40
|
return e;
|
|
32
41
|
}
|
|
33
|
-
const
|
|
34
|
-
function
|
|
35
|
-
|
|
42
|
+
const Q = new Array();
|
|
43
|
+
function ke(l) {
|
|
44
|
+
Q.push(l);
|
|
36
45
|
}
|
|
37
|
-
const
|
|
46
|
+
const R = "NEEDLE_progressive", S = ee("debugprogressive"), Y = Symbol("needle-progressive-texture"), z = /* @__PURE__ */ new Map(), Z = /* @__PURE__ */ new Set();
|
|
38
47
|
if (S) {
|
|
39
48
|
let l = function() {
|
|
40
49
|
e += 1, console.log("Toggle LOD level", e, z), z.forEach((i, n) => {
|
|
41
50
|
for (const s of i.keys) {
|
|
42
51
|
const o = n[s];
|
|
43
52
|
if (o.isBufferGeometry === !0) {
|
|
44
|
-
const a = v.getMeshLODInformation(o),
|
|
45
|
-
n["DEBUG:LOD"] = e, v.assignMeshLOD(n,
|
|
53
|
+
const a = v.getMeshLODInformation(o), g = a ? Math.min(e, a.lods.length) : 0;
|
|
54
|
+
n["DEBUG:LOD"] = e, v.assignMeshLOD(n, g), a && (t = Math.max(t, a.lods.length - 1));
|
|
46
55
|
} else if (n.isMaterial === !0) {
|
|
47
56
|
n["DEBUG:LOD"] = e, v.assignTextureLOD(n, e);
|
|
48
57
|
break;
|
|
@@ -51,12 +60,12 @@ if (S) {
|
|
|
51
60
|
}), e >= t && (e = -1);
|
|
52
61
|
}, e = -1, t = 2, r = !1;
|
|
53
62
|
window.addEventListener("keyup", (i) => {
|
|
54
|
-
i.key === "p" && l(), i.key === "w" && (r = !r,
|
|
63
|
+
i.key === "p" && l(), i.key === "w" && (r = !r, Z && Z.forEach((n) => {
|
|
55
64
|
n.name != "BackgroundCubeMaterial" && "wireframe" in n && (n.wireframe = r);
|
|
56
65
|
}));
|
|
57
66
|
});
|
|
58
67
|
}
|
|
59
|
-
function
|
|
68
|
+
function se(l, e, t) {
|
|
60
69
|
var i;
|
|
61
70
|
if (!S)
|
|
62
71
|
return;
|
|
@@ -66,13 +75,13 @@ function te(l, e, t) {
|
|
|
66
75
|
}
|
|
67
76
|
const M = class {
|
|
68
77
|
constructor(e, t) {
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
c(this, "parser");
|
|
79
|
+
c(this, "url");
|
|
71
80
|
S && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
|
|
72
81
|
}
|
|
73
82
|
/** The name of the extension */
|
|
74
83
|
get name() {
|
|
75
|
-
return
|
|
84
|
+
return R;
|
|
76
85
|
}
|
|
77
86
|
static getMeshLODInformation(e) {
|
|
78
87
|
const t = this.getAssignedLODInformation(e);
|
|
@@ -129,7 +138,7 @@ const M = class {
|
|
|
129
138
|
const i = e.geometry, n = this.getAssignedLODInformation(i);
|
|
130
139
|
if (!n)
|
|
131
140
|
return Promise.resolve(null);
|
|
132
|
-
for (const s of
|
|
141
|
+
for (const s of Q)
|
|
133
142
|
(r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
|
|
134
143
|
return e["LOD:requested level"] = t, M.getOrLoadLOD(i, t).then((s) => {
|
|
135
144
|
if (e["LOD:requested level"] === t) {
|
|
@@ -137,7 +146,7 @@ const M = class {
|
|
|
137
146
|
const o = n.index || 0;
|
|
138
147
|
s = s[o];
|
|
139
148
|
}
|
|
140
|
-
s && i != s && s instanceof
|
|
149
|
+
s && i != s && s instanceof V && (e.geometry = s, S && se(e, "geometry", n.url));
|
|
141
150
|
}
|
|
142
151
|
return s;
|
|
143
152
|
}).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
|
|
@@ -155,15 +164,15 @@ const M = class {
|
|
|
155
164
|
static assignTextureLOD(e, t = 0) {
|
|
156
165
|
if (!e)
|
|
157
166
|
return Promise.resolve(null);
|
|
158
|
-
if (e instanceof
|
|
167
|
+
if (e instanceof ce || e.isMaterial === !0) {
|
|
159
168
|
const r = e, i = [], n = new Array();
|
|
160
|
-
if (S &&
|
|
169
|
+
if (S && Z.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
|
|
161
170
|
const s = r;
|
|
162
171
|
for (const o of Object.keys(s.uniforms)) {
|
|
163
172
|
const a = s.uniforms[o].value;
|
|
164
173
|
if ((a == null ? void 0 : a.isTexture) === !0) {
|
|
165
|
-
const
|
|
166
|
-
i.push(
|
|
174
|
+
const g = this.assignTextureLODForSlot(a, t, r, o);
|
|
175
|
+
i.push(g), n.push(o);
|
|
167
176
|
}
|
|
168
177
|
}
|
|
169
178
|
} else
|
|
@@ -177,8 +186,8 @@ const M = class {
|
|
|
177
186
|
return Promise.all(i).then((s) => {
|
|
178
187
|
const o = new Array();
|
|
179
188
|
for (let a = 0; a < s.length; a++) {
|
|
180
|
-
const
|
|
181
|
-
|
|
189
|
+
const g = s[a], f = n[a];
|
|
190
|
+
g && g.isTexture === !0 ? o.push({ material: r, slot: f, texture: g, level: t }) : o.push({ material: r, slot: f, texture: null, level: t });
|
|
182
191
|
}
|
|
183
192
|
return o;
|
|
184
193
|
});
|
|
@@ -196,7 +205,7 @@ const M = class {
|
|
|
196
205
|
if ((n == null ? void 0 : n.isTexture) === !0) {
|
|
197
206
|
if (n != e && (r && i && (r[i] = n), S && i && r)) {
|
|
198
207
|
const s = this.getAssignedLODInformation(e);
|
|
199
|
-
s &&
|
|
208
|
+
s && se(r, i, s.url);
|
|
200
209
|
}
|
|
201
210
|
return n;
|
|
202
211
|
} else
|
|
@@ -208,7 +217,7 @@ const M = class {
|
|
|
208
217
|
var t, r;
|
|
209
218
|
return S && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
|
|
210
219
|
if (i != null && i.extensions) {
|
|
211
|
-
const s = i == null ? void 0 : i.extensions[
|
|
220
|
+
const s = i == null ? void 0 : i.extensions[R];
|
|
212
221
|
if (s) {
|
|
213
222
|
let o = !1;
|
|
214
223
|
for (const a of this.parser.associations.keys())
|
|
@@ -220,7 +229,7 @@ const M = class {
|
|
|
220
229
|
}
|
|
221
230
|
}), (r = this.parser.json.meshes) == null || r.forEach((i, n) => {
|
|
222
231
|
if (i != null && i.extensions) {
|
|
223
|
-
const s = i == null ? void 0 : i.extensions[
|
|
232
|
+
const s = i == null ? void 0 : i.extensions[R];
|
|
224
233
|
if (s && s.lods) {
|
|
225
234
|
for (const o of this.parser.associations.keys())
|
|
226
235
|
if (o.isMesh) {
|
|
@@ -232,107 +241,107 @@ const M = class {
|
|
|
232
241
|
}), null;
|
|
233
242
|
}
|
|
234
243
|
static async getOrLoadLOD(e, t) {
|
|
235
|
-
var o, a,
|
|
244
|
+
var o, a, g;
|
|
236
245
|
const r = S == "verbose", i = e.userData.LODS;
|
|
237
246
|
if (!i)
|
|
238
247
|
return null;
|
|
239
248
|
const n = i == null ? void 0 : i.key;
|
|
240
249
|
let s;
|
|
241
250
|
if (e.isTexture === !0) {
|
|
242
|
-
const
|
|
243
|
-
|
|
251
|
+
const f = e;
|
|
252
|
+
f.source && f.source[Y] && (s = f.source[Y]);
|
|
244
253
|
}
|
|
245
254
|
if (s || (s = M.lodInfos.get(n)), s) {
|
|
246
255
|
if (t > 0) {
|
|
247
|
-
let
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
256
|
+
let u = !1;
|
|
257
|
+
const h = Array.isArray(s.lods);
|
|
258
|
+
if (h && t >= s.lods.length ? u = !0 : h || (u = !0), u)
|
|
250
259
|
return this.lowresCache.get(n);
|
|
251
260
|
}
|
|
252
|
-
const
|
|
253
|
-
if (!
|
|
261
|
+
const f = Array.isArray(s.lods) ? s.lods[t].path : s.lods;
|
|
262
|
+
if (!f)
|
|
254
263
|
return S && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
|
|
255
|
-
const
|
|
256
|
-
if (
|
|
264
|
+
const p = Le(i.url, f);
|
|
265
|
+
if (p.endsWith(".glb") || p.endsWith(".gltf")) {
|
|
257
266
|
if (!s.guid)
|
|
258
267
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
r && console.log(`LOD ${t} was already loading/loaded: ${
|
|
262
|
-
let
|
|
263
|
-
`, I), null)),
|
|
264
|
-
if (
|
|
265
|
-
return
|
|
268
|
+
const u = p + "_" + s.guid, h = this.previouslyLoaded.get(u);
|
|
269
|
+
if (h !== void 0) {
|
|
270
|
+
r && console.log(`LOD ${t} was already loading/loaded: ${u}`);
|
|
271
|
+
let x = await h.catch((I) => (console.error(`Error loading LOD ${t} from ${p}
|
|
272
|
+
`, I), null)), k = !1;
|
|
273
|
+
if (x == null || (x instanceof U && e instanceof U ? (o = x.image) != null && o.data || (a = x.source) != null && a.data ? x = this.copySettings(e, x) : (k = !0, this.previouslyLoaded.delete(u)) : x instanceof V && e instanceof V && ((g = x.attributes.position) != null && g.array || (k = !0, this.previouslyLoaded.delete(u)))), !k)
|
|
274
|
+
return x;
|
|
266
275
|
}
|
|
267
|
-
const
|
|
268
|
-
const I = new
|
|
269
|
-
|
|
270
|
-
let
|
|
271
|
-
if (
|
|
272
|
-
const
|
|
273
|
-
|
|
276
|
+
const D = s, A = new Promise(async (x, k) => {
|
|
277
|
+
const I = new he();
|
|
278
|
+
oe(I), S && (await new Promise((m) => setTimeout(m, 1e3)), r && console.warn("Start loading (delayed) " + p, D.guid));
|
|
279
|
+
let L = p;
|
|
280
|
+
if (D && Array.isArray(D.lods)) {
|
|
281
|
+
const m = D.lods[t];
|
|
282
|
+
m.hash && (L += "?v=" + m.hash);
|
|
274
283
|
}
|
|
275
|
-
const
|
|
276
|
-
`,
|
|
277
|
-
if (!
|
|
284
|
+
const y = await I.loadAsync(L).catch((m) => (console.error(`Error loading LOD ${t} from ${p}
|
|
285
|
+
`, m), null));
|
|
286
|
+
if (!y)
|
|
278
287
|
return null;
|
|
279
|
-
const
|
|
280
|
-
r && console.log("Loading finished " +
|
|
281
|
-
let
|
|
282
|
-
if (
|
|
283
|
-
let
|
|
284
|
-
for (const d of
|
|
288
|
+
const T = y.parser;
|
|
289
|
+
r && console.log("Loading finished " + p, D.guid);
|
|
290
|
+
let O = 0;
|
|
291
|
+
if (y.parser.json.textures) {
|
|
292
|
+
let m = !1;
|
|
293
|
+
for (const d of y.parser.json.textures) {
|
|
285
294
|
if (d != null && d.extensions) {
|
|
286
|
-
const
|
|
287
|
-
if (
|
|
288
|
-
|
|
295
|
+
const w = d == null ? void 0 : d.extensions[R];
|
|
296
|
+
if (w != null && w.guid && w.guid === D.guid) {
|
|
297
|
+
m = !0;
|
|
289
298
|
break;
|
|
290
299
|
}
|
|
291
300
|
}
|
|
292
|
-
|
|
301
|
+
O++;
|
|
293
302
|
}
|
|
294
|
-
if (
|
|
295
|
-
let d = await
|
|
296
|
-
return r && console.log('change "' + e.name + '" → "' + d.name + '"',
|
|
303
|
+
if (m) {
|
|
304
|
+
let d = await T.getDependency("texture", O);
|
|
305
|
+
return r && console.log('change "' + e.name + '" → "' + d.name + '"', p, O, d, u), e instanceof U && (d = this.copySettings(e, d)), d && (d.guid = D.guid), x(d);
|
|
297
306
|
}
|
|
298
307
|
}
|
|
299
|
-
if (
|
|
300
|
-
let
|
|
301
|
-
for (const d of
|
|
308
|
+
if (O = 0, y.parser.json.meshes) {
|
|
309
|
+
let m = !1;
|
|
310
|
+
for (const d of y.parser.json.meshes) {
|
|
302
311
|
if (d != null && d.extensions) {
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
|
|
312
|
+
const w = d == null ? void 0 : d.extensions[R];
|
|
313
|
+
if (w != null && w.guid && w.guid === D.guid) {
|
|
314
|
+
m = !0;
|
|
306
315
|
break;
|
|
307
316
|
}
|
|
308
317
|
}
|
|
309
|
-
|
|
318
|
+
O++;
|
|
310
319
|
}
|
|
311
|
-
if (
|
|
312
|
-
const d = await
|
|
313
|
-
if (r && console.log(`Loaded Mesh "${d.name}"`,
|
|
320
|
+
if (m) {
|
|
321
|
+
const d = await T.getDependency("mesh", O), w = D;
|
|
322
|
+
if (r && console.log(`Loaded Mesh "${d.name}"`, p, O, d, u), d.isMesh === !0) {
|
|
314
323
|
const P = d.geometry;
|
|
315
|
-
return M.assignLODInformation(i.url, P, n, t, void 0,
|
|
324
|
+
return M.assignLODInformation(i.url, P, n, t, void 0, w.density), x(P);
|
|
316
325
|
} else {
|
|
317
326
|
const P = new Array();
|
|
318
327
|
for (let _ = 0; _ < d.children.length; _++) {
|
|
319
328
|
const E = d.children[_];
|
|
320
329
|
if (E instanceof q) {
|
|
321
330
|
const N = E.geometry;
|
|
322
|
-
M.assignLODInformation(i.url, N, n, t, _,
|
|
331
|
+
M.assignLODInformation(i.url, N, n, t, _, w.density), P.push(N);
|
|
323
332
|
}
|
|
324
333
|
}
|
|
325
|
-
return
|
|
334
|
+
return x(P);
|
|
326
335
|
}
|
|
327
336
|
}
|
|
328
337
|
}
|
|
329
|
-
return
|
|
338
|
+
return x(null);
|
|
330
339
|
});
|
|
331
|
-
return this.previouslyLoaded.set(
|
|
340
|
+
return this.previouslyLoaded.set(u, A), await A;
|
|
332
341
|
} else if (e instanceof U) {
|
|
333
|
-
r && console.log("Load texture from uri: " +
|
|
334
|
-
const
|
|
335
|
-
return
|
|
342
|
+
r && console.log("Load texture from uri: " + p);
|
|
343
|
+
const h = await new fe().loadAsync(p);
|
|
344
|
+
return h ? (h.guid = s.guid, h.flipY = !1, h.needsUpdate = !0, h.colorSpace = e.colorSpace, r && console.log(s, h)) : S && console.warn("failed loading", p), h;
|
|
336
345
|
}
|
|
337
346
|
} else
|
|
338
347
|
S && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
@@ -358,62 +367,62 @@ let v = M;
|
|
|
358
367
|
/**
|
|
359
368
|
* Register a texture with LOD information
|
|
360
369
|
*/
|
|
361
|
-
|
|
362
|
-
S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[
|
|
370
|
+
c(v, "registerTexture", (e, t, r, i) => {
|
|
371
|
+
S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[Y] = i);
|
|
363
372
|
const n = i.guid;
|
|
364
373
|
M.assignLODInformation(e, t, n, 0, 0, void 0), M.lodInfos.set(n, i), M.lowresCache.set(n, t);
|
|
365
374
|
}), /**
|
|
366
375
|
* Register a mesh with LOD information
|
|
367
376
|
*/
|
|
368
|
-
|
|
369
|
-
var
|
|
377
|
+
c(v, "registerMesh", (e, t, r, i, n, s) => {
|
|
378
|
+
var g;
|
|
370
379
|
S && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
|
|
371
380
|
const o = r.geometry;
|
|
372
381
|
o.userData || (o.userData = {}), M.assignLODInformation(e, o, t, i, n, s.density), M.lodInfos.set(t, s);
|
|
373
382
|
let a = M.lowresCache.get(t);
|
|
374
383
|
a ? a.push(r.geometry) : a = [r.geometry], M.lowresCache.set(t, a);
|
|
375
|
-
for (const
|
|
376
|
-
(
|
|
384
|
+
for (const f of Q)
|
|
385
|
+
(g = f.onRegisteredNewMesh) == null || g.call(f, r, s);
|
|
377
386
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
387
|
+
c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
388
|
+
c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
389
|
+
c(v, "lowresCache", /* @__PURE__ */ new Map()), c(v, "_copiedTextures", /* @__PURE__ */ new Map());
|
|
381
390
|
class De {
|
|
382
391
|
constructor(e, t, r, i, n) {
|
|
383
|
-
|
|
392
|
+
c(this, "url");
|
|
384
393
|
/** the key to lookup the LOD information */
|
|
385
|
-
|
|
386
|
-
|
|
394
|
+
c(this, "key");
|
|
395
|
+
c(this, "level");
|
|
387
396
|
/** For multi objects (e.g. a group of meshes) this is the index of the object */
|
|
388
|
-
|
|
397
|
+
c(this, "index");
|
|
389
398
|
/** the mesh density */
|
|
390
|
-
|
|
399
|
+
c(this, "density");
|
|
391
400
|
this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
|
|
392
401
|
}
|
|
393
402
|
}
|
|
394
|
-
const
|
|
403
|
+
const H = ee("debugprogressive"), xe = ee("noprogressive"), b = class {
|
|
395
404
|
constructor(e) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
405
|
+
c(this, "renderer");
|
|
406
|
+
c(this, "projectionScreenMatrix", new te());
|
|
407
|
+
c(this, "cameraFrustrum", new de());
|
|
399
408
|
/**
|
|
400
409
|
* The update interval in frames. If set to 0, the LODs will be updated every frame. If set to 1, the LODs will be updated every second frame, etc.
|
|
401
410
|
*/
|
|
402
|
-
|
|
411
|
+
c(this, "updateInterval", 0);
|
|
403
412
|
/**
|
|
404
413
|
* If set to true, the LODsManager will not update the LODs.
|
|
405
414
|
*/
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
415
|
+
c(this, "pause", !1);
|
|
416
|
+
c(this, "plugins", []);
|
|
417
|
+
c(this, "_frame", 0);
|
|
418
|
+
c(this, "_originalRender");
|
|
410
419
|
// private testIfLODLevelsAreAvailable() {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
420
|
+
c(this, "_sphere", new ge());
|
|
421
|
+
c(this, "_tempBox", new re());
|
|
422
|
+
c(this, "tempMatrix", new te());
|
|
423
|
+
c(this, "_tempWorldPosition", new C());
|
|
424
|
+
c(this, "_tempBoxSize", new C());
|
|
425
|
+
c(this, "_tempBox2Size", new C());
|
|
417
426
|
this.renderer = e;
|
|
418
427
|
}
|
|
419
428
|
/** @internal */
|
|
@@ -430,7 +439,7 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
430
439
|
let e = 0;
|
|
431
440
|
this._originalRender = this.renderer.render;
|
|
432
441
|
const t = this;
|
|
433
|
-
|
|
442
|
+
ne(this.renderer), this.renderer.render = function(r, i) {
|
|
434
443
|
t.renderer.getRenderTarget() == null && (e = 0, t._frame += 1);
|
|
435
444
|
const s = t._frame, o = e++;
|
|
436
445
|
t.onBeforeRender(r, i, o, s), t._originalRender.call(this, r, i), t.onAfterRender(r, i, o, s);
|
|
@@ -442,47 +451,55 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
442
451
|
onBeforeRender(e, t, r, i) {
|
|
443
452
|
}
|
|
444
453
|
onAfterRender(e, t, r, i) {
|
|
445
|
-
var
|
|
446
|
-
if (
|
|
454
|
+
var a, g;
|
|
455
|
+
if (this.pause)
|
|
456
|
+
return;
|
|
457
|
+
const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
|
|
458
|
+
let o = !0;
|
|
459
|
+
if (s.length === 1) {
|
|
460
|
+
const f = s[0].material;
|
|
461
|
+
(f.name === "EffectMaterial" || f.name === "CopyShader") && (o = !1);
|
|
462
|
+
}
|
|
463
|
+
if (o) {
|
|
447
464
|
if (xe || this.updateInterval > 0 && i % this.updateInterval != 0)
|
|
448
465
|
return;
|
|
449
466
|
this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
450
|
-
const
|
|
451
|
-
for (const
|
|
452
|
-
if (
|
|
453
|
-
|
|
467
|
+
const f = 1e5;
|
|
468
|
+
for (const u of s) {
|
|
469
|
+
if (u.material && (((a = u.geometry) == null ? void 0 : a.type) === "BoxGeometry" || ((g = u.geometry) == null ? void 0 : g.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
|
|
470
|
+
H && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
|
|
454
471
|
continue;
|
|
455
472
|
}
|
|
456
|
-
const
|
|
457
|
-
(
|
|
473
|
+
const h = u.object;
|
|
474
|
+
(h instanceof q || h.isMesh) && this.updateLODs(e, t, h, f);
|
|
458
475
|
}
|
|
459
|
-
const
|
|
460
|
-
for (const
|
|
461
|
-
const
|
|
462
|
-
(
|
|
476
|
+
const p = n.transparent;
|
|
477
|
+
for (const u of p) {
|
|
478
|
+
const h = u.object;
|
|
479
|
+
(h instanceof q || h.isMesh) && this.updateLODs(e, t, h, f);
|
|
463
480
|
}
|
|
464
481
|
}
|
|
465
482
|
}
|
|
466
483
|
/** Update the LOD levels for the renderer. */
|
|
467
484
|
updateLODs(e, t, r, i) {
|
|
468
|
-
var a,
|
|
469
|
-
for (const
|
|
470
|
-
(a =
|
|
485
|
+
var a, g;
|
|
486
|
+
for (const f of this.plugins)
|
|
487
|
+
(a = f.onBeforeUpdateLOD) == null || a.call(f, this.renderer, e, t, r);
|
|
471
488
|
let n = r.userData.LOD_state;
|
|
472
|
-
n || (n = new
|
|
489
|
+
n || (n = new Oe(), r.userData.LOD_state = n);
|
|
473
490
|
let s = this.calculateLodLevel(t, r, n, i);
|
|
474
491
|
s = Math.round(s), s >= 0 && this.loadProgressiveMeshes(r, s);
|
|
475
492
|
let o = 0;
|
|
476
493
|
if (r.material) {
|
|
477
|
-
const
|
|
478
|
-
if (
|
|
479
|
-
for (const
|
|
480
|
-
this.loadProgressiveTextures(
|
|
494
|
+
const f = r["DEBUG:LOD"];
|
|
495
|
+
if (f != null && (o = f), Array.isArray(r.material))
|
|
496
|
+
for (const p of r.material)
|
|
497
|
+
this.loadProgressiveTextures(p, o);
|
|
481
498
|
else
|
|
482
499
|
this.loadProgressiveTextures(r.material, o);
|
|
483
500
|
}
|
|
484
|
-
for (const
|
|
485
|
-
(
|
|
501
|
+
for (const f of this.plugins)
|
|
502
|
+
(g = f.onAfterUpdatedLOD) == null || g.call(f, this.renderer, e, t, r, s);
|
|
486
503
|
n.lastLodLevel = s;
|
|
487
504
|
}
|
|
488
505
|
/** Load progressive textures for the given material
|
|
@@ -515,70 +532,70 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
515
532
|
return -1;
|
|
516
533
|
let s = 10 + 1;
|
|
517
534
|
if (e) {
|
|
518
|
-
if (
|
|
535
|
+
if (H && t["DEBUG:LOD"] != null)
|
|
519
536
|
return t["DEBUG:LOD"];
|
|
520
|
-
const a = v.getMeshLODInformation(t.geometry),
|
|
521
|
-
if (!
|
|
537
|
+
const a = v.getMeshLODInformation(t.geometry), g = a == null ? void 0 : a.lods;
|
|
538
|
+
if (!g || g.length <= 0 || !((o = this.cameraFrustrum) != null && o.intersectsObject(t)))
|
|
522
539
|
return 99;
|
|
523
|
-
const
|
|
524
|
-
if (
|
|
525
|
-
const
|
|
540
|
+
const f = t.geometry.boundingBox;
|
|
541
|
+
if (f && e.isPerspectiveCamera) {
|
|
542
|
+
const p = e;
|
|
526
543
|
if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
|
|
527
544
|
this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
|
|
528
|
-
const
|
|
529
|
-
if (this._sphere.containsPoint(
|
|
545
|
+
const L = e.getWorldPosition(this._tempWorldPosition);
|
|
546
|
+
if (this._sphere.containsPoint(L))
|
|
530
547
|
return 0;
|
|
531
548
|
}
|
|
532
|
-
if (this._tempBox.copy(
|
|
533
|
-
const
|
|
534
|
-
let
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
const N =
|
|
538
|
-
r.lastCentrality = (P -
|
|
549
|
+
if (this._tempBox.copy(f), this._tempBox.applyMatrix4(t.matrixWorld), this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && p.fov > 70) {
|
|
550
|
+
const L = this._tempBox.min, y = this._tempBox.max;
|
|
551
|
+
let T = L.x, O = L.y, m = y.x, d = y.y;
|
|
552
|
+
const w = 2, P = 1.5, _ = (L.x + y.x) * 0.5, E = (L.y + y.y) * 0.5;
|
|
553
|
+
T = (T - _) * w + _, O = (O - E) * w + E, m = (m - _) * w + _, d = (d - E) * w + E;
|
|
554
|
+
const N = T < 0 && m > 0 ? 0 : Math.min(Math.abs(L.x), Math.abs(y.x)), ae = O < 0 && d > 0 ? 0 : Math.min(Math.abs(L.y), Math.abs(y.y)), X = Math.max(N, ae);
|
|
555
|
+
r.lastCentrality = (P - X) * (P - X) * (P - X);
|
|
539
556
|
} else
|
|
540
557
|
r.lastCentrality = 1;
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
const A =
|
|
546
|
-
if (Math.max(
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
const d = (
|
|
552
|
-
|
|
558
|
+
const u = this._tempBox.getSize(this._tempBoxSize);
|
|
559
|
+
u.multiplyScalar(0.5), screen.availHeight > 0 && u.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), u.x *= p.aspect;
|
|
560
|
+
const h = e.matrixWorldInverse, D = new re();
|
|
561
|
+
D.copy(f), D.applyMatrix4(t.matrixWorld), D.applyMatrix4(h);
|
|
562
|
+
const A = D.getSize(this._tempBox2Size), G = Math.max(A.x, A.y);
|
|
563
|
+
if (Math.max(u.x, u.y) != 0 && G != 0 && (u.z = A.z / Math.max(A.x, A.y) * Math.max(u.x, u.y)), r.lastScreenCoverage = Math.max(u.x, u.y, u.z), r.lastScreenspaceVolume.copy(u), r.lastScreenCoverage *= r.lastCentrality, H && b.debugDrawLine) {
|
|
564
|
+
const L = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
565
|
+
L.invert();
|
|
566
|
+
const y = b.corner0, T = b.corner1, O = b.corner2, m = b.corner3;
|
|
567
|
+
y.copy(this._tempBox.min), T.copy(this._tempBox.max), T.x = y.x, O.copy(this._tempBox.max), O.y = y.y, m.copy(this._tempBox.max);
|
|
568
|
+
const d = (y.z + m.z) * 0.5;
|
|
569
|
+
y.z = T.z = O.z = m.z = d, y.applyMatrix4(L), T.applyMatrix4(L), O.applyMatrix4(L), m.applyMatrix4(L), b.debugDrawLine(y, T, 255), b.debugDrawLine(y, O, 255), b.debugDrawLine(T, m, 255), b.debugDrawLine(O, m, 255);
|
|
553
570
|
}
|
|
554
|
-
let
|
|
555
|
-
if (
|
|
556
|
-
for (let
|
|
557
|
-
if (
|
|
558
|
-
|
|
571
|
+
let k = 999;
|
|
572
|
+
if (g && r.lastScreenCoverage > 0) {
|
|
573
|
+
for (let L = 0; L < g.length; L++)
|
|
574
|
+
if (g[L].density / r.lastScreenCoverage < i) {
|
|
575
|
+
k = L;
|
|
559
576
|
break;
|
|
560
577
|
}
|
|
561
578
|
}
|
|
562
|
-
|
|
579
|
+
k < s && (s = k);
|
|
563
580
|
}
|
|
564
581
|
}
|
|
565
582
|
return s;
|
|
566
583
|
}
|
|
567
584
|
};
|
|
568
|
-
let B =
|
|
585
|
+
let B = b;
|
|
569
586
|
/** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
|
|
570
587
|
*/
|
|
571
|
-
|
|
572
|
-
class
|
|
588
|
+
c(B, "debugDrawLine"), c(B, "corner0", new C()), c(B, "corner1", new C()), c(B, "corner2", new C()), c(B, "corner3", new C());
|
|
589
|
+
class Oe {
|
|
573
590
|
constructor() {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
591
|
+
c(this, "lastLodLevel", 0);
|
|
592
|
+
c(this, "lastScreenCoverage", 0);
|
|
593
|
+
c(this, "lastScreenspaceVolume", new C());
|
|
594
|
+
c(this, "lastCentrality", 0);
|
|
578
595
|
}
|
|
579
596
|
}
|
|
580
|
-
const
|
|
581
|
-
function
|
|
597
|
+
const ie = Symbol("NEEDLE_mesh_lod"), $ = Symbol("NEEDLE_texture_lod");
|
|
598
|
+
function we(l) {
|
|
582
599
|
if (!l)
|
|
583
600
|
return null;
|
|
584
601
|
let e = null, t = null;
|
|
@@ -601,8 +618,8 @@ function Oe(l) {
|
|
|
601
618
|
}
|
|
602
619
|
class Me {
|
|
603
620
|
constructor(e) {
|
|
604
|
-
|
|
605
|
-
|
|
621
|
+
c(this, "modelviewer");
|
|
622
|
+
c(this, "_didWarnAboutMissingUrl", !1);
|
|
606
623
|
this.modelviewer = e;
|
|
607
624
|
}
|
|
608
625
|
onBeforeUpdateLOD(e, t, r, i) {
|
|
@@ -622,18 +639,18 @@ class Me {
|
|
|
622
639
|
const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
|
|
623
640
|
if (i && r && t.material) {
|
|
624
641
|
let n = function(o) {
|
|
625
|
-
var
|
|
642
|
+
var g, f, p;
|
|
626
643
|
if (o[$] == !0)
|
|
627
644
|
return;
|
|
628
645
|
o[$] = !0, o.userData && (o.userData.LOD = -1);
|
|
629
646
|
const a = Object.keys(o);
|
|
630
|
-
for (let
|
|
631
|
-
const
|
|
632
|
-
if ((
|
|
633
|
-
const A = (
|
|
634
|
-
if ((
|
|
635
|
-
const
|
|
636
|
-
|
|
647
|
+
for (let u = 0; u < a.length; u++) {
|
|
648
|
+
const h = a[u], D = o[h];
|
|
649
|
+
if ((D == null ? void 0 : D.isTexture) === !0) {
|
|
650
|
+
const A = (f = (g = D.userData) == null ? void 0 : g.associations) == null ? void 0 : f.textures, G = r.parser.json.textures[A];
|
|
651
|
+
if ((p = G.extensions) != null && p[R]) {
|
|
652
|
+
const x = G.extensions[R];
|
|
653
|
+
x && i && v.registerTexture(i, D, x.lods.length, x);
|
|
637
654
|
}
|
|
638
655
|
}
|
|
639
656
|
}
|
|
@@ -648,32 +665,34 @@ class Me {
|
|
|
648
665
|
}
|
|
649
666
|
tryParseMeshLOD(e, t) {
|
|
650
667
|
var n, s;
|
|
651
|
-
if (t[
|
|
668
|
+
if (t[ie] == !0)
|
|
652
669
|
return;
|
|
653
|
-
t[
|
|
670
|
+
t[ie] = !0;
|
|
654
671
|
const r = this.getUrl();
|
|
655
672
|
if (!r)
|
|
656
673
|
return;
|
|
657
|
-
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[
|
|
674
|
+
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
|
|
658
675
|
if (i && r) {
|
|
659
676
|
const o = t.uuid;
|
|
660
677
|
v.registerMesh(r, o, t, 0, i.lods.length, i);
|
|
661
678
|
}
|
|
662
679
|
}
|
|
663
680
|
}
|
|
664
|
-
function
|
|
665
|
-
|
|
681
|
+
function Ce(l, e, t, r) {
|
|
682
|
+
ne(e), oe(t), t.register((n) => new v(n, l));
|
|
666
683
|
const i = new B(e);
|
|
667
684
|
return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
|
|
668
685
|
}
|
|
669
686
|
document.addEventListener("DOMContentLoaded", () => {
|
|
670
|
-
|
|
687
|
+
we(document.querySelector("model-viewer"));
|
|
671
688
|
});
|
|
672
689
|
export {
|
|
673
|
-
|
|
690
|
+
R as EXTENSION_NAME,
|
|
674
691
|
B as LODsManager,
|
|
675
692
|
v as NEEDLE_progressive,
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
693
|
+
we as patchModelViewer,
|
|
694
|
+
ke as registerPlugin,
|
|
695
|
+
_e as setDracoDecoderLocation,
|
|
696
|
+
Be as setKTX2TranscoderLocation,
|
|
697
|
+
Ce as useNeedleProgressive
|
|
679
698
|
};
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,m),null)),g=!1;if(
|
|
3
|
-
`,v),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+u,y.guid);let _=0;if(x.parser.json.textures){let v=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const w=f?.extensions[P];if(w!=null&&w.guid&&w.guid===y.guid){v=!0;break}}_++}if(v){let f=await S.getDependency("texture",_);return s&&console.log('change "'+r.name+'" \u2192 "'+f.name+'"',u,_,f,d),r instanceof j&&(f=this.copySettings(r,f)),f&&(f.guid=y.guid),p(f)}}if(_=0,x.parser.json.meshes){let v=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const w=f?.extensions[P];if(w!=null&&w.guid&&w.guid===y.guid){v=!0;break}}_++}if(v){const f=await S.getDependency("mesh",_),w=y;if(s&&console.log(`Loaded Mesh "${f.name}"`,u,_,f,d),f.isMesh===!0){const E=f.geometry;return D.assignLODInformation(a.url,E,i,e,void 0,w.density),p(E)}else{const E=new Array;for(let C=0;C<f.children.length;C++){const W=f.children[C];if(W instanceof U){const R=W.geometry;D.assignLODInformation(a.url,R,i,e,C,w.density),E.push(R)}}return p(E)}}}return p(null)});return this.previouslyLoaded.set(d,A),await A}else if(r instanceof j){s&&console.log("Load texture from uri: "+u);const d=await new ie().loadAsync(u);return d?(d.guid=l.guid,d.flipY=!1,d.needsUpdate=!0,d.colorSpace=r.colorSpace,s&&console.log(l,d)):L&&console.warn("failed loading",u),d}}else L&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${r.name}`,r.type);return null}static assignLODInformation(r,e,t,o,n,s){if(!e)return;e.userData||(e.userData={});const a=new ye(r,t,o,n,s);e.userData.LODS=a,e.userData.LOD=o}static getAssignedLODInformation(r){var e;return((e=r?.userData)==null?void 0:e.LODS)||null}static copySettings(r,e){return this._copiedTextures.get(r)||(e=e.clone(),this._copiedTextures.set(r,e),e.offset=r.offset,e.repeat=r.repeat,e.colorSpace=r.colorSpace,e)}};let O=D;c(O,"registerTexture",(r,e,t,o)=>{L&&console.log("> Progressive: register texture",t,e.name,e.uuid,e,o),e.source&&(e.source[X]=o);const n=o.guid;D.assignLODInformation(r,e,n,0,0,void 0),D.lodInfos.set(n,o),D.lowresCache.set(n,e)}),c(O,"registerMesh",(r,e,t,o,n,s)=>{var a;L&&console.log("> Progressive: register mesh",n,t.name,s,t.uuid,t);const i=t.geometry;i.userData||(i.userData={}),D.assignLODInformation(r,i,e,o,n,s.density),D.lodInfos.set(e,s);let l=D.lowresCache.get(e);l?l.push(t.geometry):l=[t.geometry],D.lowresCache.set(e,l);for(const h of V)(a=h.onRegisteredNewMesh)==null||a.call(h,t,s)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"lowresCache",new Map),c(O,"_copiedTextures",new Map);class ye{constructor(e,t,o,n,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=t,this.level=o,n!=null&&(this.index=n),s!=null&&(this.density=s)}}const K=q("debugprogressive"),xe=q("noprogressive"),T=class{constructor(r){c(this,"renderer"),c(this,"projectionScreenMatrix",new Y),c(this,"cameraFrustrum",new ae),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"plugins",[]),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new le),c(this,"_tempBox",new J),c(this,"tempMatrix",new Y),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=r}static getObjectLODState(r){var e;return(e=r.userData)==null?void 0:e.LOD_state}enable(){if(this._originalRender)return;let r=0;this._originalRender=this.renderer.render;const e=this;Q(this.renderer),this.renderer.render=function(t,o){e.renderer.getRenderTarget()==null&&(r=0,e._frame+=1);const n=e._frame,s=r++;e.onBeforeRender(t,o,s,n),e._originalRender.call(this,t,o),e.onAfterRender(t,o,s,n)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(r,e,t,o){}onAfterRender(r,e,t,o){var n,s;if(!this.pause&&t==0){if(xe||this.updateInterval>0&&o%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const a=1e5,i=this.renderer.renderLists.get(r,t),l=i.opaque;for(const u of l){if(u.material&&(((n=u.geometry)==null?void 0:n.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){K&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}const d=u.object;(d instanceof U||d.isMesh)&&this.updateLODs(r,e,d,a)}const h=i.transparent;for(const u of h){const d=u.object;(d instanceof U||d.isMesh)&&this.updateLODs(r,e,d,a)}}}updateLODs(r,e,t,o){var n,s;for(const h of this.plugins)(n=h.onBeforeUpdateLOD)==null||n.call(h,this.renderer,r,e,t);let a=t.userData.LOD_state;a||(a=new ve,t.userData.LOD_state=a);let i=this.calculateLodLevel(e,t,a,o);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(t,i);let l=0;if(t.material){const h=t["DEBUG:LOD"];if(h!=null&&(l=h),Array.isArray(t.material))for(const u of t.material)this.loadProgressiveTextures(u,l);else this.loadProgressiveTextures(t.material,l)}for(const h of this.plugins)(s=h.onAfterUpdatedLOD)==null||s.call(h,this.renderer,r,e,t,i);a.lastLodLevel=i}loadProgressiveTextures(r,e){return r&&r.userData&&r.userData.LOD!==e?(r.userData.LOD=e,O.assignTextureLOD(r,e)):Promise.resolve(null)}loadProgressiveMeshes(r,e){if(!r)return Promise.resolve(null);if(r.userData||(r.userData={}),r.userData.LOD!==e){r.userData.LOD=e;const t=r.geometry;return O.assignMeshLOD(r,e).then(o=>(o&&r.userData.LOD==e&&t!=r.geometry,o))}return Promise.resolve(null)}calculateLodLevel(r,e,t,o){var n;if(!e)return-1;let s=10+1;if(r){if(K&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&r.isPerspectiveCamera){const h=r;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 g=r.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&h.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const v=2,f=1.5,w=(g.x+m.x)*.5,E=(g.y+m.y)*.5;b=(b-w)*v+w,x=(x-E)*v+E,S=(S-w)*v+w,_=(_-E)*v+E;const C=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),R=Math.max(C,W);t.lastCentrality=(f-R)*(f-R)*(f-R)}else t.lastCentrality=1;const u=this._tempBox.getSize(this._tempBoxSize);u.multiplyScalar(.5),screen.availHeight>0&&u.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),u.x*=h.aspect;const d=r.matrixWorldInverse,M=new J;M.copy(l),M.applyMatrix4(e.matrixWorld),M.applyMatrix4(d);const y=M.getSize(this._tempBox2Size),A=Math.max(y.x,y.y);if(Math.max(u.x,u.y)!=0&&A!=0&&(u.z=y.z/Math.max(y.x,y.y)*Math.max(u.x,u.y)),t.lastScreenCoverage=Math.max(u.x,u.y,u.z),t.lastScreenspaceVolume.copy(u),t.lastScreenCoverage*=t.lastCentrality,K&&T.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=T.corner0,b=T.corner1,x=T.corner2,S=T.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),T.debugDrawLine(m,b,255),T.debugDrawLine(m,x,255),T.debugDrawLine(b,S,255),T.debugDrawLine(x,S,255)}let p=999;if(i&&t.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/t.lastScreenCoverage<o){p=g;break}}p<s&&(s=p)}}return s}};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);class ve{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const re=Symbol("NEEDLE_mesh_lod"),z=Symbol("NEEDLE_texture_lod");function te(r){if(!r)return null;let e=null,t=null;for(let o=r;o!=null;o=Object.getPrototypeOf(o)){const n=Object.getOwnPropertySymbols(o),s=n.find(i=>i.toString()=="Symbol(renderer)"),a=n.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=r[s].threeRenderer),!t&&a!=null&&(t=r[a])}if(e){console.log("Adding Needle LODs to modelviewer");const o=new I(e);if(o.plugins.push(new Le(r)),o.enable(),t){const n=t.camera||t.traverse(s=>s.type=="PerspectiveCamera")[0];n&&e.render(t,n)}return()=>{o.disable()}}return null}class Le{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,t,o,n){this.tryParseMeshLOD(t,n),this.tryParseTextureLOD(t,n)}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[z]==!0)return;t[z]=!0;const o=this.tryGetCurrentGLTF(e),n=this.getUrl();if(n&&o&&t.material){let s=function(i){var l,h,u;if(i[z]==!0)return;i[z]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let M=0;M<d.length;M++){const y=d[M],A=i[y];if(A?.isTexture===!0){const p=(h=(l=A.userData)==null?void 0:l.associations)==null?void 0:h.textures,g=o.parser.json.textures[p];if((u=g.extensions)!=null&&u[P]){const m=g.extensions[P];m&&n&&O.registerTexture(n,A,m.lods.length,m)}}}};const a=t.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,t){var o,n;if(t[re]==!0)return;t[re]=!0;const s=this.getUrl();if(!s)return;const a=(n=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:n[P];if(a&&s){const i=t.uuid;O.registerMesh(s,i,t,0,a.lods.length,a)}}}function De(r,e,t,o){Q(e),Z(t),t.register(s=>new O(s,r));const n=new I(e);return o?.enableLODsManager!==!1&&n.enable(),n}document.addEventListener("DOMContentLoaded",()=>{te(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,O as NEEDLE_progressive,te as patchModelViewer,pe as registerPlugin,De as useNeedleProgressive};
|
|
1
|
+
var ne=Object.defineProperty,ie=(r,e,t)=>e in r?ne(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,c=(r,e,t)=>(ie(r,typeof e!="symbol"?e+"":e,t),t);import{Mesh as U,BufferGeometry as $,Material as ae,Texture as C,TextureLoader as le,Matrix4 as Q,Frustum as ue,Sphere as ce,Box3 as Z,Vector3 as B}from"three";import{GLTFLoader as de}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as he}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as fe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ge}from"three/examples/jsm/loaders/KTX2Loader.js";let z="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",q="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(z+"draco_decoder.js",{method:"head"}).catch(r=>{z="./include/draco/",q="./include/ktx2/"});function me(r){z=r}function pe(r){q=r}let R,V,G;function ee(r){R||(R=new fe,R.setDecoderPath(z),R.setDecoderConfig({type:"js"})),G||(G=new ge,G.setTranscoderPath(q)),V||(V=he),r?G.detectSupport(r):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function re(r){r.dracoLoader||r.setDRACOLoader(R),r.ktx2Loader||r.setKTX2Loader(G),r.meshoptDecoder||r.setMeshoptDecoder(V)}function X(r){const e=new URL(window.location.href).searchParams.get(r);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function ye(r,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||r===void 0)return e;const t=r.lastIndexOf("/");if(t>=0){const o=r.substring(0,t+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}const K=new Array;function Le(r){K.push(r)}const P="NEEDLE_progressive",v=X("debugprogressive"),H=Symbol("needle-progressive-texture"),N=new Map,Y=new Set;if(v){let r=function(){e+=1,console.log("Toggle LOD level",e,N),N.forEach((n,s)=>{for(const a of n.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=w.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,d),l&&(t=Math.max(t,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,o=!1;window.addEventListener("keyup",n=>{n.key==="p"&&r(),n.key==="w"&&(o=!o,Y&&Y.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=o)}))})}function te(r,e,t){var o;if(!v)return;N.has(r)||N.set(r,{keys:[],sourceId:t});const n=N.get(r);((o=n?.keys)==null?void 0:o.includes(e))==!1&&n.keys.push(e)}const O=class{constructor(r,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=r,this.url=e}get name(){return P}static getMeshLODInformation(r){const e=this.getAssignedLODInformation(r);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(r,e){var t;if(r.isMaterial===!0){for(const s of Object.keys(r)){const a=r[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(r.isGroup===!0){for(const s of r.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let o,n;if(r.isMesh?o=r.geometry:(r.isBufferGeometry||r.isTexture)&&(o=r),o&&(t=o?.userData)!=null&&t.LODS){const s=o.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(r,e){var t;if(!r)return Promise.resolve(null);if(r instanceof U||r.isMesh===!0){const o=r.geometry,n=this.getAssignedLODInformation(o);if(!n)return Promise.resolve(null);for(const s of K)(t=s.onBeforeGetLODMesh)==null||t.call(s,r,e);return r["LOD:requested level"]=e,O.getOrLoadLOD(o,e).then(s=>{if(r["LOD:requested level"]===e){if(delete r["LOD:requested level"],Array.isArray(s)){const a=n.index||0;s=s[a]}s&&o!=s&&s instanceof $&&(r.geometry=s,v&&te(r,"geometry",n.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",r,s),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",r);return Promise.resolve(null)}static assignTextureLOD(r,e=0){if(!r)return Promise.resolve(null);if(r instanceof ae||r.isMaterial===!0){const t=r,o=[],n=new Array;if(v&&Y.add(t),t.uniforms&&t.isRawShaderMaterial||t.isShaderMaterial===!0){const s=t;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,t,a);o.push(l),n.push(a)}}}else for(const s of Object.keys(t)){const a=t[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,t,s);o.push(i),n.push(s)}}return Promise.all(o).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=n[i];l&&l.isTexture===!0?a.push({material:t,slot:d,texture:l,level:e}):a.push({material:t,slot:d,texture:null,level:e})}return a})}if(r instanceof C||r.isTexture===!0){const t=r;return this.assignTextureLODForSlot(t,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(r,e,t,o){return r?.isTexture!==!0?Promise.resolve(null):O.getOrLoadLOD(r,e).then(n=>{if(Array.isArray(n))return null;if(n?.isTexture===!0){if(n!=r&&(t&&o&&(t[o]=n),v&&o&&t)){const s=this.getAssignedLODInformation(r);s&&te(t,o,s.url)}return n}else v=="verbose"&&console.warn("No LOD found for",r,e);return null}).catch(n=>(console.error("Error loading LOD",r,n),null))}afterRoot(r){var e,t;return v&&console.log("AFTER",this.url,r),(e=this.parser.json.textures)==null||e.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.extensions[P];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===n&&(a=!0,O.registerTexture(this.url,i,n,s));a||this.parser.getDependency("texture",n).then(i=>{i&&O.registerTexture(this.url,i,n,s)})}}}),(t=this.parser.json.meshes)==null||t.forEach((o,n)=>{if(o!=null&&o.extensions){const s=o?.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===n&&O.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(r,e){var t,o,n;const s=v=="verbose",a=r.userData.LODS;if(!a)return null;const i=a?.key;let l;if(r.isTexture===!0){const d=r;d.source&&d.source[H]&&(l=d.source[H])}if(l||(l=O.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=ye(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
|
|
2
|
+
`,m),null)),g=!1;if(y==null||(y instanceof C&&r instanceof C?(t=y.image)!=null&&t.data||(o=y.source)!=null&&o.data?y=this.copySettings(r,y):(g=!0,this.previouslyLoaded.delete(u)):y instanceof $&&r instanceof $&&((n=y.attributes.position)!=null&&n.array||(g=!0,this.previouslyLoaded.delete(u)))),!g)return y}const L=l,A=new Promise(async(y,g)=>{const m=new de;re(m),v&&(await new Promise(D=>setTimeout(D,1e3)),s&&console.warn("Start loading (delayed) "+h,L.guid));let b=h;if(L&&Array.isArray(L.lods)){const D=L.lods[e];D.hash&&(b+="?v="+D.hash)}const x=await m.loadAsync(b).catch(D=>(console.error(`Error loading LOD ${e} from ${h}
|
|
3
|
+
`,D),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,L.guid);let _=0;if(x.parser.json.textures){let D=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){D=!0;break}}_++}if(D){let f=await S.getDependency("texture",_);return s&&console.log('change "'+r.name+'" \u2192 "'+f.name+'"',h,_,f,u),r instanceof C&&(f=this.copySettings(r,f)),f&&(f.guid=L.guid),y(f)}}if(_=0,x.parser.json.meshes){let D=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const M=f?.extensions[P];if(M!=null&&M.guid&&M.guid===L.guid){D=!0;break}}_++}if(D){const f=await S.getDependency("mesh",_),M=L;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,_,f,u),f.isMesh===!0){const T=f.geometry;return O.assignLODInformation(a.url,T,i,e,void 0,M.density),y(T)}else{const T=new Array;for(let k=0;k<f.children.length;k++){const W=f.children[k];if(W instanceof U){const j=W.geometry;O.assignLODInformation(a.url,j,i,e,k,M.density),T.push(j)}}return y(T)}}}return y(null)});return this.previouslyLoaded.set(u,A),await A}else if(r instanceof C){s&&console.log("Load texture from uri: "+h);const u=await new le().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=r.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${r.name}`,r.type);return null}static assignLODInformation(r,e,t,o,n,s){if(!e)return;e.userData||(e.userData={});const a=new xe(r,t,o,n,s);e.userData.LODS=a,e.userData.LOD=o}static getAssignedLODInformation(r){var e;return((e=r?.userData)==null?void 0:e.LODS)||null}static copySettings(r,e){return this._copiedTextures.get(r)||(e=e.clone(),this._copiedTextures.set(r,e),e.offset=r.offset,e.repeat=r.repeat,e.colorSpace=r.colorSpace,e)}};let w=O;c(w,"registerTexture",(r,e,t,o)=>{v&&console.log("> Progressive: register texture",t,e.name,e.uuid,e,o),e.source&&(e.source[H]=o);const n=o.guid;O.assignLODInformation(r,e,n,0,0,void 0),O.lodInfos.set(n,o),O.lowresCache.set(n,e)}),c(w,"registerMesh",(r,e,t,o,n,s)=>{var a;v&&console.log("> Progressive: register mesh",n,t.name,s,t.uuid,t);const i=t.geometry;i.userData||(i.userData={}),O.assignLODInformation(r,i,e,o,n,s.density),O.lodInfos.set(e,s);let l=O.lowresCache.get(e);l?l.push(t.geometry):l=[t.geometry],O.lowresCache.set(e,l);for(const d of K)(a=d.onRegisteredNewMesh)==null||a.call(d,t,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map),c(w,"_copiedTextures",new Map);class xe{constructor(e,t,o,n,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=t,this.level=o,n!=null&&(this.index=n),s!=null&&(this.density=s)}}const J=X("debugprogressive"),De=X("noprogressive"),E=class{constructor(r){c(this,"renderer"),c(this,"projectionScreenMatrix",new Q),c(this,"cameraFrustrum",new ue),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"plugins",[]),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new ce),c(this,"_tempBox",new Z),c(this,"tempMatrix",new Q),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=r}static getObjectLODState(r){var e;return(e=r.userData)==null?void 0:e.LOD_state}enable(){if(this._originalRender)return;let r=0;this._originalRender=this.renderer.render;const e=this;ee(this.renderer),this.renderer.render=function(t,o){e.renderer.getRenderTarget()==null&&(r=0,e._frame+=1);const n=e._frame,s=r++;e.onBeforeRender(t,o,s,n),e._originalRender.call(this,t,o),e.onAfterRender(t,o,s,n)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(r,e,t,o){}onAfterRender(r,e,t,o){var n,s;if(this.pause)return;const a=this.renderer.renderLists.get(r,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(De||this.updateInterval>0&&o%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=1e5;for(const u of i){if(u.material&&(((n=u.geometry)==null?void 0:n.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){J&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(r,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(r,e,p,d)}}}updateLODs(r,e,t,o){var n,s;for(const d of this.plugins)(n=d.onBeforeUpdateLOD)==null||n.call(d,this.renderer,r,e,t);let a=t.userData.LOD_state;a||(a=new ve,t.userData.LOD_state=a);let i=this.calculateLodLevel(e,t,a,o);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(t,i);let l=0;if(t.material){const d=t["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(t.material))for(const h of t.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(t.material,l)}for(const d of this.plugins)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,r,e,t,i);a.lastLodLevel=i}loadProgressiveTextures(r,e){return r&&r.userData&&r.userData.LOD!==e?(r.userData.LOD=e,w.assignTextureLOD(r,e)):Promise.resolve(null)}loadProgressiveMeshes(r,e){if(!r)return Promise.resolve(null);if(r.userData||(r.userData={}),r.userData.LOD!==e){r.userData.LOD=e;const t=r.geometry;return w.assignMeshLOD(r,e).then(o=>(o&&r.userData.LOD==e&&t!=r.geometry,o))}return Promise.resolve(null)}calculateLodLevel(r,e,t,o){var n;if(!e)return-1;let s=10+1;if(r){if(J&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=w.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&r.isPerspectiveCamera){const d=r;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 g=r.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const D=2,f=1.5,M=(g.x+m.x)*.5,T=(g.y+m.y)*.5;b=(b-M)*D+M,x=(x-T)*D+T,S=(S-M)*D+M,_=(_-T)*D+T;const k=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(k,W);t.lastCentrality=(f-j)*(f-j)*(f-j)}else t.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=r.matrixWorldInverse,p=new Z;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const L=p.getSize(this._tempBox2Size),A=Math.max(L.x,L.y);if(Math.max(h.x,h.y)!=0&&A!=0&&(h.z=L.z/Math.max(L.x,L.y)*Math.max(h.x,h.y)),t.lastScreenCoverage=Math.max(h.x,h.y,h.z),t.lastScreenspaceVolume.copy(h),t.lastScreenCoverage*=t.lastCentrality,J&&E.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=E.corner0,b=E.corner1,x=E.corner2,S=E.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),E.debugDrawLine(m,b,255),E.debugDrawLine(m,x,255),E.debugDrawLine(b,S,255),E.debugDrawLine(x,S,255)}let y=999;if(i&&t.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/t.lastScreenCoverage<o){y=g;break}}y<s&&(s=y)}}return s}};let I=E;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B);class ve{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const se=Symbol("NEEDLE_mesh_lod"),F=Symbol("NEEDLE_texture_lod");function oe(r){if(!r)return null;let e=null,t=null;for(let o=r;o!=null;o=Object.getPrototypeOf(o)){const n=Object.getOwnPropertySymbols(o),s=n.find(i=>i.toString()=="Symbol(renderer)"),a=n.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=r[s].threeRenderer),!t&&a!=null&&(t=r[a])}if(e){console.log("Adding Needle LODs to modelviewer");const o=new I(e);if(o.plugins.push(new Oe(r)),o.enable(),t){const n=t.camera||t.traverse(s=>s.type=="PerspectiveCamera")[0];n&&e.render(t,n)}return()=>{o.disable()}}return null}class Oe{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,t,o,n){this.tryParseMeshLOD(t,n),this.tryParseTextureLOD(t,n)}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[F]==!0)return;t[F]=!0;const o=this.tryGetCurrentGLTF(e),n=this.getUrl();if(n&&o&&t.material){let s=function(i){var l,d,h;if(i[F]==!0)return;i[F]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const L=u[p],A=i[L];if(A?.isTexture===!0){const y=(d=(l=A.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=o.parser.json.textures[y];if((h=g.extensions)!=null&&h[P]){const m=g.extensions[P];m&&n&&w.registerTexture(n,A,m.lods.length,m)}}}};const a=t.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,t){var o,n;if(t[se]==!0)return;t[se]=!0;const s=this.getUrl();if(!s)return;const a=(n=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:n[P];if(a&&s){const i=t.uuid;w.registerMesh(s,i,t,0,a.lods.length,a)}}}function we(r,e,t,o){ee(e),re(t),t.register(s=>new w(s,r));const n=new I(e);return o?.enableLODsManager!==!1&&n.enable(),n}document.addEventListener("DOMContentLoaded",()=>{oe(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,w as NEEDLE_progressive,oe as patchModelViewer,Le as registerPlugin,me as setDracoDecoderLocation,pe as setKTX2TranscoderLocation,we as useNeedleProgressive};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`,I),null)),
|
|
3
|
-
`,L),null));if(!y)return null;const b=y.parser;r&&console.log("Loading finished "+c,D.guid);let O=0;if(y.parser.json.textures){let L=!1;for(const d of y.parser.json.textures){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[C];if(v!=null&&v.guid&&v.guid===D.guid){L=!0;break}}O++}if(L){let d=await b.getDependency("texture",O);return r&&console.log('change "'+e.name+'" → "'+d.name+'"',c,O,d,f),e instanceof p.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=D.guid),x(d)}}if(O=0,y.parser.json.meshes){let L=!1;for(const d of y.parser.json.meshes){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[C];if(v!=null&&v.guid&&v.guid===D.guid){L=!0;break}}O++}if(L){const d=await b.getDependency("mesh",O),v=D;if(r&&console.log(`Loaded Mesh "${d.name}"`,c,O,d,f),d.isMesh===!0){const B=d.geometry;return S.assignLODInformation(i.url,B,o,t,void 0,v.density),x(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const k=d.children[E];if(k instanceof p.Mesh){const W=k.geometry;S.assignLODInformation(i.url,W,o,t,E,v.density),B.push(W)}}return x(B)}}}return x(null)});return this.previouslyLoaded.set(f,P),await P}else if(e instanceof p.Texture){r&&console.log("Load texture from uri: "+c);const M=await new p.TextureLoader().loadAsync(c);return M?(M.guid=s.guid,M.flipY=!1,M.needsUpdate=!0,M.colorSpace=e.colorSpace,r&&console.log(s,M)):T&&console.warn("failed loading",c),M}}else T&&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 de(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){const r=this._copiedTextures.get(e);return r||(t=t.clone(),this._copiedTextures.set(e,t),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t)}};let w=S;u(w,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[q]=i);const o=i.guid;S.assignLODInformation(e,t,o,0,0,void 0),S.lodInfos.set(o,i),S.lowresCache.set(o,t)}),u(w,"registerMesh",(e,t,r,i,o,s)=>{var h;T&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;n.userData||(n.userData={}),S.assignLODInformation(e,n,t,i,o,s.density),S.lodInfos.set(t,s);let a=S.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],S.lowresCache.set(t,a);for(const g of K)(h=g.onRegisteredNewMesh)==null||h.call(g,r,s)}),u(w,"lodInfos",new Map),u(w,"previouslyLoaded",new Map),u(w,"lowresCache",new Map),u(w,"_copiedTextures",new Map);class de{constructor(e,t,r,i,o){u(this,"url");u(this,"key");u(this,"level");u(this,"index");u(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const $=H("debugprogressive"),ge=H("noprogressive"),A=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new p.Matrix4);u(this,"cameraFrustrum",new p.Frustum);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"plugins",[]);u(this,"_frame",0);u(this,"_originalRender");u(this,"_sphere",new p.Sphere);u(this,"_tempBox",new p.Box3);u(this,"tempMatrix",new p.Matrix4);u(this,"_tempWorldPosition",new p.Vector3);u(this,"_tempBoxSize",new p.Vector3);u(this,"_tempBox2Size",new p.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;Z(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 o,s;if(!this.pause&&r==0){if(ge||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const n=1e5,a=this.renderer.renderLists.get(e,r),h=a.opaque;for(const c of h){if(c.material&&(((o=c.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=c.geometry)==null?void 0:s.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){$&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}const f=c.object;(f instanceof p.Mesh||f.isMesh)&&this.updateLODs(e,t,f,n)}const g=a.transparent;for(const c of g){const f=c.object;(f instanceof p.Mesh||f.isMesh)&&this.updateLODs(e,t,f,n)}}}updateLODs(e,t,r,i){var a,h;for(const g of this.plugins)(a=g.onBeforeUpdateLOD)==null||a.call(g,this.renderer,e,t,r);let o=r.userData.LOD_state;o||(o=new he,r.userData.LOD_state=o);let s=this.calculateLodLevel(t,r,o,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let n=0;if(r.material){const g=r["DEBUG:LOD"];if(g!=null&&(n=g),Array.isArray(r.material))for(const c of r.material)this.loadProgressiveTextures(c,n);else this.loadProgressiveTextures(r.material,n)}for(const g of this.plugins)(h=g.onAfterUpdatedLOD)==null||h.call(g,this.renderer,e,t,r,s);o.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,w.assignTextureLOD(e,t)):Promise.resolve(null)}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 w.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}calculateLodLevel(e,t,r,i){var n;if(!t)return-1;let s=10+1;if(e){if($&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=w.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods;if(!h||h.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(t)))return 99;const g=t.geometry.boundingBox;if(g&&e.isPerspectiveCamera){const c=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 m=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m))return 0}if(this._tempBox.copy(g),this._tempBox.applyMatrix4(t.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&c.fov>70){const m=this._tempBox.min,y=this._tempBox.max;let b=m.x,O=m.y,L=y.x,d=y.y;const v=2,B=1.5,E=(m.x+y.x)*.5,k=(m.y+y.y)*.5;b=(b-E)*v+E,O=(O-k)*v+k,L=(L-E)*v+E,d=(d-k)*v+k;const W=b<0&&L>0?0:Math.min(Math.abs(m.x),Math.abs(y.x)),te=O<0&&d>0?0:Math.min(Math.abs(m.y),Math.abs(y.y)),V=Math.max(W,te);r.lastCentrality=(B-V)*(B-V)*(B-V)}else r.lastCentrality=1;const f=this._tempBox.getSize(this._tempBoxSize);f.multiplyScalar(.5),screen.availHeight>0&&f.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),f.x*=c.aspect;const M=e.matrixWorldInverse,D=new p.Box3;D.copy(g),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(M);const P=D.getSize(this._tempBox2Size),G=Math.max(P.x,P.y);if(Math.max(f.x,f.y)!=0&&G!=0&&(f.z=P.z/Math.max(P.x,P.y)*Math.max(f.x,f.y)),r.lastScreenCoverage=Math.max(f.x,f.y,f.z),r.lastScreenspaceVolume.copy(f),r.lastScreenCoverage*=r.lastCentrality,$&&A.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const y=A.corner0,b=A.corner1,O=A.corner2,L=A.corner3;y.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=y.x,O.copy(this._tempBox.max),O.y=y.y,L.copy(this._tempBox.max);const d=(y.z+L.z)*.5;y.z=b.z=O.z=L.z=d,y.applyMatrix4(m),b.applyMatrix4(m),O.applyMatrix4(m),L.applyMatrix4(m),A.debugDrawLine(y,b,255),A.debugDrawLine(y,O,255),A.debugDrawLine(b,L,255),A.debugDrawLine(O,L,255)}let R=999;if(h&&r.lastScreenCoverage>0){for(let m=0;m<h.length;m++)if(h[m].density/r.lastScreenCoverage<i){R=m;break}}R<s&&(s=R)}}return s}};let _=A;u(_,"debugDrawLine"),u(_,"corner0",new p.Vector3),u(_,"corner1",new p.Vector3),u(_,"corner2",new p.Vector3),u(_,"corner3",new p.Vector3);class he{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new p.Vector3);u(this,"lastCentrality",0)}}const Q=Symbol("NEEDLE_mesh_lod"),z=Symbol("NEEDLE_texture_lod");function ee(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=new _(e);if(r.plugins.push(new pe(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 pe{constructor(e){u(this,"modelviewer");u(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[z]==!0)return;t[z]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,g,c;if(n[z]==!0)return;n[z]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const M=a[f],D=n[M];if((D==null?void 0:D.isTexture)===!0){const P=(g=(h=D.userData)==null?void 0:h.associations)==null?void 0:g.textures,G=r.parser.json.textures[P];if((c=G.extensions)!=null&&c[C]){const x=G.extensions[C];x&&i&&w.registerTexture(i,D,x.lods.length,x)}}}};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[Q]==!0)return;t[Q]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;w.registerMesh(r,n,t,0,i.lods.length,i)}}}function ye(l,e,t,r){Z(e),j(t),t.register(o=>new w(o,l));const i=new _(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ee(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=_;exports.NEEDLE_progressive=w;exports.patchModelViewer=ee;exports.registerPlugin=fe;exports.useNeedleProgressive=ye;
|
|
1
|
+
"use strict";var ie=Object.defineProperty;var oe=(l,e,t)=>e in l?ie(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(oe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),ne=require("three/examples/jsm/loaders/GLTFLoader.js"),ae=require("three/examples/jsm/libs/meshopt_decoder.module.js"),le=require("three/examples/jsm/loaders/DRACOLoader.js"),ue=require("three/examples/jsm/loaders/KTX2Loader.js");let V="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(V+"draco_decoder.js",{method:"head"}).catch(l=>{V="./include/draco/",J="./include/ktx2/"});function ce(l){V=l}function fe(l){J=l}let F,K,U;function ee(l){F||(F=new le.DRACOLoader,F.setDecoderPath(V),F.setDecoderConfig({type:"js"})),U||(U=new ue.KTX2Loader,U.setTranscoderPath(J)),K||(K=ae.MeshoptDecoder),l?U.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function te(l){l.dracoLoader||l.setDRACOLoader(F),l.ktx2Loader||l.setKTX2Loader(U),l.meshoptDecoder||l.setMeshoptDecoder(K)}function Q(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}const Y=new Array;function ge(l){Y.push(l)}const C="NEEDLE_progressive",T=Q("debugprogressive"),X=Symbol("needle-progressive-texture"),N=new Map,H=new Set;if(T){let l=function(){e+=1,console.log("Toggle LOD level",e,N),N.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=M.getMeshLODInformation(n),g=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,M.assignMeshLOD(o,g),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,M.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,H&&H.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function Z(l,e,t){var i;if(!T)return;N.has(l)||N.set(l,{keys:[],sourceId:t});const r=N.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const S=class{constructor(e,t){c(this,"parser");c(this,"url");T&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static hasLODLevelAvailable(e,t){var o;if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(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 h.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of Y)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,S.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 h.BufferGeometry&&(e.geometry=s,T&&Z(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else T&&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 h.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(T&&H.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 g=this.assignTextureLODForSlot(a,t,r,n);i.push(g),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 g=s[a],f=o[a];g&&g.isTexture===!0?n.push({material:r,slot:f,texture:g,level:t}):n.push({material:r,slot:f,texture:null,level:t})}return n})}if(e instanceof h.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):S.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e&&(r&&i&&(r[i]=o),T&&i&&r)){const s=this.getAssignedLODInformation(e);s&&Z(r,i,s.url)}return o}else T=="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 T&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,S.registerTexture(this.url,a,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&S.registerTexture(this.url,a,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&S.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,g;const r=T=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const f=e;f.source&&f.source[X]&&(s=f.source[X])}if(s||(s=S.lodInfos.get(o)),s){if(t>0){let u=!1;const p=Array.isArray(s.lods);if(p&&t>=s.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(o)}const f=Array.isArray(s.lods)?s.lods[t].path:s.lods;if(!f)return T&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const y=de(i.url,f);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const u=y+"_"+s.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${u}`);let O=await p.catch(I=>(console.error(`Error loading LOD ${t} from ${y}
|
|
2
|
+
`,I),null)),k=!1;if(O==null||(O instanceof h.Texture&&e instanceof h.Texture?(n=O.image)!=null&&n.data||(a=O.source)!=null&&a.data?O=this.copySettings(e,O):(k=!0,this.previouslyLoaded.delete(u)):O instanceof h.BufferGeometry&&e instanceof h.BufferGeometry&&((g=O.attributes.position)!=null&&g.array||(k=!0,this.previouslyLoaded.delete(u)))),!k)return O}const x=s,P=new Promise(async(O,k)=>{const I=new ne.GLTFLoader;te(I),T&&(await new Promise(m=>setTimeout(m,1e3)),r&&console.warn("Start loading (delayed) "+y,x.guid));let D=y;if(x&&Array.isArray(x.lods)){const m=x.lods[t];m.hash&&(D+="?v="+m.hash)}const L=await I.loadAsync(D).catch(m=>(console.error(`Error loading LOD ${t} from ${y}
|
|
3
|
+
`,m),null));if(!L)return null;const b=L.parser;r&&console.log("Loading finished "+y,x.guid);let w=0;if(L.parser.json.textures){let m=!1;for(const d of L.parser.json.textures){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[C];if(v!=null&&v.guid&&v.guid===x.guid){m=!0;break}}w++}if(m){let d=await b.getDependency("texture",w);return r&&console.log('change "'+e.name+'" → "'+d.name+'"',y,w,d,u),e instanceof h.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=x.guid),O(d)}}if(w=0,L.parser.json.meshes){let m=!1;for(const d of L.parser.json.meshes){if(d!=null&&d.extensions){const v=d==null?void 0:d.extensions[C];if(v!=null&&v.guid&&v.guid===x.guid){m=!0;break}}w++}if(m){const d=await b.getDependency("mesh",w),v=x;if(r&&console.log(`Loaded Mesh "${d.name}"`,y,w,d,u),d.isMesh===!0){const B=d.geometry;return S.assignLODInformation(i.url,B,o,t,void 0,v.density),O(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const R=d.children[E];if(R instanceof h.Mesh){const W=R.geometry;S.assignLODInformation(i.url,W,o,t,E,v.density),B.push(W)}}return O(B)}}}return O(null)});return this.previouslyLoaded.set(u,P),await P}else if(e instanceof h.Texture){r&&console.log("Load texture from uri: "+y);const p=await new h.TextureLoader().loadAsync(y);return p?(p.guid=s.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=e.colorSpace,r&&console.log(s,p)):T&&console.warn("failed loading",y),p}}else T&&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 he(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){const r=this._copiedTextures.get(e);return r||(t=t.clone(),this._copiedTextures.set(e,t),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t)}};let M=S;c(M,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[X]=i);const o=i.guid;S.assignLODInformation(e,t,o,0,0,void 0),S.lodInfos.set(o,i),S.lowresCache.set(o,t)}),c(M,"registerMesh",(e,t,r,i,o,s)=>{var g;T&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;n.userData||(n.userData={}),S.assignLODInformation(e,n,t,i,o,s.density),S.lodInfos.set(t,s);let a=S.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],S.lowresCache.set(t,a);for(const f of Y)(g=f.onRegisteredNewMesh)==null||g.call(f,r,s)}),c(M,"lodInfos",new Map),c(M,"previouslyLoaded",new Map),c(M,"lowresCache",new Map),c(M,"_copiedTextures",new Map);class he{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 $=Q("debugprogressive"),pe=Q("noprogressive"),A=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new h.Matrix4);c(this,"cameraFrustrum",new h.Frustum);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"plugins",[]);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new h.Sphere);c(this,"_tempBox",new h.Box3);c(this,"tempMatrix",new h.Matrix4);c(this,"_tempWorldPosition",new h.Vector3);c(this,"_tempBoxSize",new h.Vector3);c(this,"_tempBox2Size",new h.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;ee(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,g;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(n){if(pe||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=1e5;for(const u of s){if(u.material&&(((a=u.geometry)==null?void 0:a.type)==="BoxGeometry"||((g=u.geometry)==null?void 0:g.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){$&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}const p=u.object;(p instanceof h.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}const y=o.transparent;for(const u of y){const p=u.object;(p instanceof h.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}}}updateLODs(e,t,r,i){var a,g;for(const f of this.plugins)(a=f.onBeforeUpdateLOD)==null||a.call(f,this.renderer,e,t,r);let o=r.userData.LOD_state;o||(o=new ye,r.userData.LOD_state=o);let s=this.calculateLodLevel(t,r,o,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let n=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(n=f),Array.isArray(r.material))for(const y of r.material)this.loadProgressiveTextures(y,n);else this.loadProgressiveTextures(r.material,n)}for(const f of this.plugins)(g=f.onAfterUpdatedLOD)==null||g.call(f,this.renderer,e,t,r,s);o.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,M.assignTextureLOD(e,t)):Promise.resolve(null)}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 M.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}calculateLodLevel(e,t,r,i){var n;if(!t)return-1;let s=10+1;if(e){if($&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=M.getMeshLODInformation(t.geometry),g=a==null?void 0:a.lods;if(!g||g.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const y=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 D=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(D))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const D=this._tempBox.min,L=this._tempBox.max;let b=D.x,w=D.y,m=L.x,d=L.y;const v=2,B=1.5,E=(D.x+L.x)*.5,R=(D.y+L.y)*.5;b=(b-E)*v+E,w=(w-R)*v+R,m=(m-E)*v+E,d=(d-R)*v+R;const W=b<0&&m>0?0:Math.min(Math.abs(D.x),Math.abs(L.x)),se=w<0&&d>0?0:Math.min(Math.abs(D.y),Math.abs(L.y)),q=Math.max(W,se);r.lastCentrality=(B-q)*(B-q)*(B-q)}else r.lastCentrality=1;const u=this._tempBox.getSize(this._tempBoxSize);u.multiplyScalar(.5),screen.availHeight>0&&u.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),u.x*=y.aspect;const p=e.matrixWorldInverse,x=new h.Box3;x.copy(f),x.applyMatrix4(t.matrixWorld),x.applyMatrix4(p);const P=x.getSize(this._tempBox2Size),G=Math.max(P.x,P.y);if(Math.max(u.x,u.y)!=0&&G!=0&&(u.z=P.z/Math.max(P.x,P.y)*Math.max(u.x,u.y)),r.lastScreenCoverage=Math.max(u.x,u.y,u.z),r.lastScreenspaceVolume.copy(u),r.lastScreenCoverage*=r.lastCentrality,$&&A.debugDrawLine){const D=this.tempMatrix.copy(this.projectionScreenMatrix);D.invert();const L=A.corner0,b=A.corner1,w=A.corner2,m=A.corner3;L.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=L.x,w.copy(this._tempBox.max),w.y=L.y,m.copy(this._tempBox.max);const d=(L.z+m.z)*.5;L.z=b.z=w.z=m.z=d,L.applyMatrix4(D),b.applyMatrix4(D),w.applyMatrix4(D),m.applyMatrix4(D),A.debugDrawLine(L,b,255),A.debugDrawLine(L,w,255),A.debugDrawLine(b,m,255),A.debugDrawLine(w,m,255)}let k=999;if(g&&r.lastScreenCoverage>0){for(let D=0;D<g.length;D++)if(g[D].density/r.lastScreenCoverage<i){k=D;break}}k<s&&(s=k)}}return s}};let _=A;c(_,"debugDrawLine"),c(_,"corner0",new h.Vector3),c(_,"corner1",new h.Vector3),c(_,"corner2",new h.Vector3),c(_,"corner3",new h.Vector3);class ye{constructor(){c(this,"lastLodLevel",0);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new h.Vector3);c(this,"lastCentrality",0)}}const j=Symbol("NEEDLE_mesh_lod"),z=Symbol("NEEDLE_texture_lod");function re(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=new _(e);if(r.plugins.push(new Le(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 Le{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[z]==!0)return;t[z]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var g,f,y;if(n[z]==!0)return;n[z]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let u=0;u<a.length;u++){const p=a[u],x=n[p];if((x==null?void 0:x.isTexture)===!0){const P=(f=(g=x.userData)==null?void 0:g.associations)==null?void 0:f.textures,G=r.parser.json.textures[P];if((y=G.extensions)!=null&&y[C]){const O=G.extensions[C];O&&i&&M.registerTexture(i,x,O.lods.length,O)}}}};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[j]==!0)return;t[j]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;M.registerMesh(r,n,t,0,i.lods.length,i)}}}function me(l,e,t,r){ee(e),te(t),t.register(o=>new M(o,l));const i=new _(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{re(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=_;exports.NEEDLE_progressive=M;exports.patchModelViewer=re;exports.registerPlugin=ge;exports.setDracoDecoderLocation=ce;exports.setKTX2TranscoderLocation=fe;exports.useNeedleProgressive=me;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./extension.js";
|
|
2
2
|
export * from "./plugins/index.js";
|
|
3
3
|
export { LODsManager } from "./lods_manager.js";
|
|
4
|
+
export { setDracoDecoderLocation, setKTX2TranscoderLocation } from "./loaders.js";
|
|
4
5
|
import { WebGLRenderer } from "three";
|
|
5
6
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
6
7
|
import { LODsManager } from "./lods_manager.js";
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./extension.js";
|
|
2
2
|
export * from "./plugins/index.js";
|
|
3
3
|
export { LODsManager } from "./lods_manager.js";
|
|
4
|
+
export { setDracoDecoderLocation, setKTX2TranscoderLocation } from "./loaders.js";
|
|
4
5
|
import { addDracoAndKTX2Loaders, createLoaders } from "./loaders.js";
|
|
5
6
|
import { NEEDLE_progressive } from "./extension.js";
|
|
6
7
|
import { LODsManager } from "./lods_manager.js";
|
package/lib/loaders.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { WebGLRenderer } from 'three';
|
|
2
2
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
3
|
+
/**
|
|
4
|
+
* Set the location of the Draco decoder.
|
|
5
|
+
* @default 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/'
|
|
6
|
+
*/
|
|
7
|
+
export declare function setDracoDecoderLocation(location: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Set the location of the KTX2 transcoder.
|
|
10
|
+
* @default 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/'
|
|
11
|
+
*/
|
|
12
|
+
export declare function setKTX2TranscoderLocation(location: string): void;
|
|
3
13
|
export declare function createLoaders(renderer: WebGLRenderer): void;
|
|
4
14
|
export declare function addDracoAndKTX2Loaders(loader: GLTFLoader): void;
|
package/lib/loaders.js
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
|
|
2
2
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
3
3
|
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/';
|
|
5
|
+
let DEFAULT_KTX2_TRANSCODER_LOCATION = 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/';
|
|
6
|
+
fetch(DEFAULT_DRACO_DECODER_LOCATION + "draco_decoder.js", { method: "head" })
|
|
7
|
+
.catch(_ => {
|
|
8
|
+
DEFAULT_DRACO_DECODER_LOCATION = "./include/draco/";
|
|
9
|
+
DEFAULT_KTX2_TRANSCODER_LOCATION = "./include/ktx2/";
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Set the location of the Draco decoder.
|
|
13
|
+
* @default 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/'
|
|
14
|
+
*/
|
|
15
|
+
export function setDracoDecoderLocation(location) {
|
|
16
|
+
DEFAULT_DRACO_DECODER_LOCATION = location;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Set the location of the KTX2 transcoder.
|
|
20
|
+
* @default 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/'
|
|
21
|
+
*/
|
|
22
|
+
export function setKTX2TranscoderLocation(location) {
|
|
23
|
+
DEFAULT_KTX2_TRANSCODER_LOCATION = location;
|
|
24
|
+
}
|
|
6
25
|
let dracoLoader;
|
|
7
26
|
let meshoptDecoder;
|
|
8
27
|
let ktx2Loader;
|
package/lib/lods_manager.js
CHANGED
|
@@ -70,11 +70,25 @@ export class LODsManager {
|
|
|
70
70
|
}
|
|
71
71
|
onBeforeRender(_scene, _camera, _stack, _frame) {
|
|
72
72
|
}
|
|
73
|
-
onAfterRender(scene, camera,
|
|
73
|
+
onAfterRender(scene, camera, _stack, frame) {
|
|
74
74
|
if (this.pause)
|
|
75
75
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
const renderList = this.renderer.renderLists.get(scene, 0);
|
|
77
|
+
const opaque = renderList.opaque;
|
|
78
|
+
let updateLODs = true;
|
|
79
|
+
// check if we're rendering a postprocessing pass
|
|
80
|
+
if (opaque.length === 1) {
|
|
81
|
+
const material = opaque[0].material;
|
|
82
|
+
// pmndrs postprocessing
|
|
83
|
+
if (material.name === "EffectMaterial") {
|
|
84
|
+
updateLODs = false;
|
|
85
|
+
}
|
|
86
|
+
// builtin three postprocessing
|
|
87
|
+
else if (material.name === "CopyShader") {
|
|
88
|
+
updateLODs = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (updateLODs) {
|
|
78
92
|
if (suppressProgressiveLoading)
|
|
79
93
|
return;
|
|
80
94
|
if (this.updateInterval > 0 && frame % this.updateInterval != 0)
|
|
@@ -92,8 +106,6 @@ export class LODsManager {
|
|
|
92
106
|
currentAllowedDensity *= 1.25;
|
|
93
107
|
}
|
|
94
108
|
*/
|
|
95
|
-
const renderList = this.renderer.renderLists.get(scene, stack);
|
|
96
|
-
const opaque = renderList.opaque;
|
|
97
109
|
for (const entry of opaque) {
|
|
98
110
|
if (entry.material && (entry.geometry?.type === "BoxGeometry" || entry.geometry?.type === "BufferGeometry")) {
|
|
99
111
|
// Ignore the skybox
|
package/package.json
CHANGED