@needle-tools/gltf-progressive 1.2.0-alpha.5 → 1.2.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/README.md +5 -0
- package/gltf-progressive.js +194 -190
- package/gltf-progressive.min.js +4 -4
- package/gltf-progressive.umd.cjs +4 -4
- package/lib/extension.js +5 -0
- package/lib/lods_manager.js +0 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,9 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.2.0-alpha.6] - 2023-06-12
|
|
8
|
+
- fix: minor bug where opened glTF has `NEEDLE_progressive` extension but no lods array because the glTF is a LOD variant
|
|
9
|
+
|
|
7
10
|
## [1.2.0-alpha.5] - 2023-06-10
|
|
8
11
|
- fix: safeguard when `registerMesh` or `registerTexture` are being called with invalid data
|
|
9
12
|
- examples: update vanilla threejs example
|
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Examples are in the `/examples` directory. Live versions can be found in the lin
|
|
|
15
15
|
- [Vanilla three.js](https://engine.needle.tools/demos/gltf-progressive/threejs/) - multiple models and animations
|
|
16
16
|
- [\<model-viewer\>](https://engine.needle.tools/demos/gltf-progressive/modelviewer)
|
|
17
17
|
- [React Three Fiber](https://engine.needle.tools/demos/gltf-progressive/r3f/)
|
|
18
|
+
- [Needle Engine](https://stackblitz.com/edit/needle-engine-gltf-progressive?file=src%2Fmain.ts) - Interactive Example on StackBlitz
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
<br/>
|
|
@@ -105,6 +106,10 @@ The example can be found in `examples/modelviewer.html`
|
|
|
105
106
|
</body>
|
|
106
107
|
```
|
|
107
108
|
|
|
109
|
+
### Needle Engine
|
|
110
|
+
|
|
111
|
+
[Needle Engine](https://needle.tools) natively supports progressive loading of these glTF files! See [docs.needle.tools](https://docs.needle.tools) for more information.
|
|
112
|
+
|
|
108
113
|
|
|
109
114
|
# Contact ✒️
|
|
110
115
|
<b>[🌵 needle — tools for creators](https://needle.tools)</b> •
|
package/gltf-progressive.js
CHANGED
|
@@ -59,9 +59,9 @@ function Ke(l = !0) {
|
|
|
59
59
|
return;
|
|
60
60
|
const e = K = F.prototype.raycast;
|
|
61
61
|
F.prototype.raycast = function(t, r) {
|
|
62
|
-
const
|
|
63
|
-
let
|
|
64
|
-
n &&
|
|
62
|
+
const i = this, n = ae(i);
|
|
63
|
+
let s;
|
|
64
|
+
n && i.isMesh && (s = i.geometry, i.geometry = n), e.call(this, t, r), s && (i.geometry = s);
|
|
65
65
|
};
|
|
66
66
|
} else {
|
|
67
67
|
if (!K)
|
|
@@ -76,12 +76,12 @@ function Pe(l) {
|
|
|
76
76
|
e.setAttribute(t, l.getAttribute(t));
|
|
77
77
|
return e.setIndex(l.getIndex()), e;
|
|
78
78
|
}
|
|
79
|
-
const I = new Array(), B = "NEEDLE_progressive",
|
|
80
|
-
if (
|
|
79
|
+
const I = new Array(), B = "NEEDLE_progressive", D = j("debugprogressive"), se = Symbol("needle-progressive-texture"), V = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Set();
|
|
80
|
+
if (D) {
|
|
81
81
|
let l = function() {
|
|
82
|
-
e += 1, console.log("Toggle LOD level", e, V), V.forEach((
|
|
83
|
-
for (const
|
|
84
|
-
const o = n[
|
|
82
|
+
e += 1, console.log("Toggle LOD level", e, V), V.forEach((i, n) => {
|
|
83
|
+
for (const s of i.keys) {
|
|
84
|
+
const o = n[s];
|
|
85
85
|
if (o.isBufferGeometry === !0) {
|
|
86
86
|
const a = v.getMeshLODInformation(o), h = a ? Math.min(e, a.lods.length) : 0;
|
|
87
87
|
n["DEBUG:LOD"] = e, v.assignMeshLOD(n, h), a && (t = Math.max(t, a.lods.length - 1));
|
|
@@ -92,19 +92,19 @@ if (O) {
|
|
|
92
92
|
}
|
|
93
93
|
}), e >= t && (e = -1);
|
|
94
94
|
}, e = -1, t = 2, r = !1;
|
|
95
|
-
window.addEventListener("keyup", (
|
|
96
|
-
|
|
95
|
+
window.addEventListener("keyup", (i) => {
|
|
96
|
+
i.key === "p" && l(), i.key === "w" && (r = !r, ne && ne.forEach((n) => {
|
|
97
97
|
n.name != "BackgroundCubeMaterial" && "wireframe" in n && (n.wireframe = r);
|
|
98
98
|
}));
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
function ue(l, e, t) {
|
|
102
|
-
var
|
|
103
|
-
if (!
|
|
102
|
+
var i;
|
|
103
|
+
if (!D)
|
|
104
104
|
return;
|
|
105
105
|
V.has(l) || V.set(l, { keys: [], sourceId: t });
|
|
106
106
|
const r = V.get(l);
|
|
107
|
-
((
|
|
107
|
+
((i = r == null ? void 0 : r.keys) == null ? void 0 : i.includes(e)) == !1 && r.keys.push(e);
|
|
108
108
|
}
|
|
109
109
|
const _ = class {
|
|
110
110
|
constructor(e, t) {
|
|
@@ -112,13 +112,13 @@ const _ = class {
|
|
|
112
112
|
c(this, "url");
|
|
113
113
|
c(this, "_isLoadingMesh");
|
|
114
114
|
c(this, "loadMesh", (e) => {
|
|
115
|
-
var r,
|
|
115
|
+
var r, i;
|
|
116
116
|
if (this._isLoadingMesh)
|
|
117
117
|
return null;
|
|
118
|
-
const t = (
|
|
118
|
+
const t = (i = (r = this.parser.json.meshes[e]) == null ? void 0 : r.extensions) == null ? void 0 : i[B];
|
|
119
119
|
return t ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", e).then((n) => (this._isLoadingMesh = !1, n && _.registerMesh(this.url, t.guid, n, t.lods.length, void 0, t), n))) : null;
|
|
120
120
|
});
|
|
121
|
-
|
|
121
|
+
D && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
|
|
122
122
|
}
|
|
123
123
|
/** The name of the extension */
|
|
124
124
|
get name() {
|
|
@@ -129,7 +129,7 @@ const _ = class {
|
|
|
129
129
|
return t != null && t.key ? this.lodInfos.get(t.key) : null;
|
|
130
130
|
}
|
|
131
131
|
static getMaterialMinMaxLODsCount(e, t) {
|
|
132
|
-
const r = this,
|
|
132
|
+
const r = this, i = "LODS:minmax", n = e[i];
|
|
133
133
|
if (n != null)
|
|
134
134
|
return n;
|
|
135
135
|
if (t || (t = {
|
|
@@ -139,21 +139,21 @@ const _ = class {
|
|
|
139
139
|
}), Array.isArray(e)) {
|
|
140
140
|
for (const o of e)
|
|
141
141
|
this.getMaterialMinMaxLODsCount(o, t);
|
|
142
|
-
return e[
|
|
142
|
+
return e[i] = t, t;
|
|
143
143
|
}
|
|
144
|
-
if (
|
|
144
|
+
if (D === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
|
|
145
145
|
const o = e;
|
|
146
146
|
for (const a of Object.keys(o.uniforms)) {
|
|
147
147
|
const h = o.uniforms[a].value;
|
|
148
|
-
(h == null ? void 0 : h.isTexture) === !0 &&
|
|
148
|
+
(h == null ? void 0 : h.isTexture) === !0 && s(h, t);
|
|
149
149
|
}
|
|
150
150
|
} else if (e.isMaterial)
|
|
151
151
|
for (const o of Object.keys(e)) {
|
|
152
152
|
const a = e[o];
|
|
153
|
-
(a == null ? void 0 : a.isTexture) === !0 &&
|
|
153
|
+
(a == null ? void 0 : a.isTexture) === !0 && s(a, t);
|
|
154
154
|
}
|
|
155
|
-
return e[
|
|
156
|
-
function
|
|
155
|
+
return e[i] = t, t;
|
|
156
|
+
function s(o, a) {
|
|
157
157
|
const h = r.getAssignedLODInformation(o);
|
|
158
158
|
if (h) {
|
|
159
159
|
const d = r.lodInfos.get(h.key);
|
|
@@ -175,30 +175,30 @@ const _ = class {
|
|
|
175
175
|
static hasLODLevelAvailable(e, t) {
|
|
176
176
|
var n;
|
|
177
177
|
if (Array.isArray(e)) {
|
|
178
|
-
for (const
|
|
179
|
-
if (this.hasLODLevelAvailable(
|
|
178
|
+
for (const s of e)
|
|
179
|
+
if (this.hasLODLevelAvailable(s, t))
|
|
180
180
|
return !0;
|
|
181
181
|
return !1;
|
|
182
182
|
}
|
|
183
183
|
if (e.isMaterial === !0) {
|
|
184
|
-
for (const
|
|
185
|
-
const o = e[
|
|
184
|
+
for (const s of Object.keys(e)) {
|
|
185
|
+
const o = e[s];
|
|
186
186
|
if (o && o.isTexture && this.hasLODLevelAvailable(o, t))
|
|
187
187
|
return !0;
|
|
188
188
|
}
|
|
189
189
|
return !1;
|
|
190
190
|
} else if (e.isGroup === !0) {
|
|
191
|
-
for (const
|
|
192
|
-
if (
|
|
191
|
+
for (const s of e.children)
|
|
192
|
+
if (s.isMesh === !0 && this.hasLODLevelAvailable(s, t))
|
|
193
193
|
return !0;
|
|
194
194
|
}
|
|
195
|
-
let r,
|
|
195
|
+
let r, i;
|
|
196
196
|
if (e.isMesh ? r = e.geometry : (e.isBufferGeometry || e.isTexture) && (r = e), r && (n = r == null ? void 0 : r.userData) != null && n.LODS) {
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
return
|
|
200
|
-
if (
|
|
201
|
-
return Array.isArray(
|
|
197
|
+
const s = r.userData.LODS;
|
|
198
|
+
if (i = this.lodInfos.get(s.key), t === void 0)
|
|
199
|
+
return i != null;
|
|
200
|
+
if (i)
|
|
201
|
+
return Array.isArray(i.lods) ? t < i.lods.length : t === 0;
|
|
202
202
|
}
|
|
203
203
|
return !1;
|
|
204
204
|
}
|
|
@@ -221,23 +221,23 @@ const _ = class {
|
|
|
221
221
|
if (!e)
|
|
222
222
|
return Promise.resolve(null);
|
|
223
223
|
if (e instanceof F || e.isMesh === !0) {
|
|
224
|
-
const
|
|
224
|
+
const i = e.geometry, n = this.getAssignedLODInformation(i);
|
|
225
225
|
if (!n)
|
|
226
226
|
return Promise.resolve(null);
|
|
227
|
-
for (const
|
|
228
|
-
(r =
|
|
229
|
-
return e["LOD:requested level"] = t, _.getOrLoadLOD(
|
|
227
|
+
for (const s of I)
|
|
228
|
+
(r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
|
|
229
|
+
return e["LOD:requested level"] = t, _.getOrLoadLOD(i, t).then((s) => {
|
|
230
230
|
if (e["LOD:requested level"] === t) {
|
|
231
|
-
if (delete e["LOD:requested level"], Array.isArray(
|
|
231
|
+
if (delete e["LOD:requested level"], Array.isArray(s)) {
|
|
232
232
|
const o = n.index || 0;
|
|
233
|
-
|
|
233
|
+
s = s[o];
|
|
234
234
|
}
|
|
235
|
-
|
|
235
|
+
s && i != s && s instanceof Y && (e.geometry = s, D && ue(e, "geometry", n.url));
|
|
236
236
|
}
|
|
237
|
-
return
|
|
238
|
-
}).catch((
|
|
237
|
+
return s;
|
|
238
|
+
}).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
|
|
239
239
|
} else
|
|
240
|
-
|
|
240
|
+
D && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
|
|
241
241
|
return Promise.resolve(null);
|
|
242
242
|
}
|
|
243
243
|
/** Load a different resolution of a texture (if available)
|
|
@@ -251,28 +251,28 @@ const _ = class {
|
|
|
251
251
|
if (!e)
|
|
252
252
|
return Promise.resolve(null);
|
|
253
253
|
if (e instanceof we || e.isMaterial === !0) {
|
|
254
|
-
const r = e,
|
|
255
|
-
if (
|
|
256
|
-
const
|
|
257
|
-
for (const o of Object.keys(
|
|
258
|
-
const a =
|
|
254
|
+
const r = e, i = [], n = new Array();
|
|
255
|
+
if (D && ne.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
|
|
256
|
+
const s = r;
|
|
257
|
+
for (const o of Object.keys(s.uniforms)) {
|
|
258
|
+
const a = s.uniforms[o].value;
|
|
259
259
|
if ((a == null ? void 0 : a.isTexture) === !0) {
|
|
260
260
|
const h = this.assignTextureLODForSlot(a, t, r, o);
|
|
261
|
-
|
|
261
|
+
i.push(h), n.push(o);
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
} else
|
|
265
|
-
for (const
|
|
266
|
-
const o = r[
|
|
265
|
+
for (const s of Object.keys(r)) {
|
|
266
|
+
const o = r[s];
|
|
267
267
|
if ((o == null ? void 0 : o.isTexture) === !0) {
|
|
268
|
-
const a = this.assignTextureLODForSlot(o, t, r,
|
|
269
|
-
|
|
268
|
+
const a = this.assignTextureLODForSlot(o, t, r, s);
|
|
269
|
+
i.push(a), n.push(s);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
-
return Promise.all(
|
|
272
|
+
return Promise.all(i).then((s) => {
|
|
273
273
|
const o = new Array();
|
|
274
|
-
for (let a = 0; a <
|
|
275
|
-
const h =
|
|
274
|
+
for (let a = 0; a < s.length; a++) {
|
|
275
|
+
const h = s[a], d = n[a];
|
|
276
276
|
h && h.isTexture === !0 ? o.push({ material: r, slot: d, texture: h, level: t }) : o.push({ material: r, slot: d, texture: null, level: t });
|
|
277
277
|
}
|
|
278
278
|
return o;
|
|
@@ -284,54 +284,58 @@ const _ = class {
|
|
|
284
284
|
}
|
|
285
285
|
return Promise.resolve(null);
|
|
286
286
|
}
|
|
287
|
-
static assignTextureLODForSlot(e, t, r,
|
|
288
|
-
return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) :
|
|
287
|
+
static assignTextureLODForSlot(e, t, r, i) {
|
|
288
|
+
return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) : i === "glyphMap" ? Promise.resolve(e) : _.getOrLoadLOD(e, t).then((n) => {
|
|
289
289
|
if (Array.isArray(n))
|
|
290
290
|
return null;
|
|
291
291
|
if ((n == null ? void 0 : n.isTexture) === !0) {
|
|
292
292
|
if (n != e) {
|
|
293
|
-
if (r &&
|
|
294
|
-
const
|
|
295
|
-
if (
|
|
296
|
-
const o = this.getAssignedLODInformation(
|
|
293
|
+
if (r && i) {
|
|
294
|
+
const s = r[i];
|
|
295
|
+
if (s) {
|
|
296
|
+
const o = this.getAssignedLODInformation(s);
|
|
297
297
|
if (o && (o == null ? void 0 : o.level) < t)
|
|
298
|
-
return
|
|
298
|
+
return D === "verbose" && console.warn("Assigned texture level is already higher: ", o.level, t, r, s, n), null;
|
|
299
299
|
}
|
|
300
|
-
r[
|
|
300
|
+
r[i] = n;
|
|
301
301
|
}
|
|
302
|
-
if (
|
|
303
|
-
const
|
|
304
|
-
|
|
302
|
+
if (D && i && r) {
|
|
303
|
+
const s = this.getAssignedLODInformation(e);
|
|
304
|
+
s && ue(r, i, s.url);
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
return n;
|
|
308
308
|
} else
|
|
309
|
-
|
|
309
|
+
D == "verbose" && console.warn("No LOD found for", e, t);
|
|
310
310
|
return null;
|
|
311
311
|
}).catch((n) => (console.error("Error loading LOD", e, n), null));
|
|
312
312
|
}
|
|
313
313
|
afterRoot(e) {
|
|
314
314
|
var t, r;
|
|
315
|
-
return
|
|
316
|
-
if (
|
|
317
|
-
const
|
|
318
|
-
if (
|
|
315
|
+
return D && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
|
|
316
|
+
if (i != null && i.extensions) {
|
|
317
|
+
const s = i == null ? void 0 : i.extensions[B];
|
|
318
|
+
if (s) {
|
|
319
|
+
if (!s.lods) {
|
|
320
|
+
D && console.warn("Texture has no LODs", s);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
319
323
|
let o = !1;
|
|
320
324
|
for (const a of this.parser.associations.keys())
|
|
321
|
-
a.isTexture === !0 && this.parser.associations.get(a).textures === n && (o = !0, _.registerTexture(this.url, a,
|
|
325
|
+
a.isTexture === !0 && this.parser.associations.get(a).textures === n && (o = !0, _.registerTexture(this.url, a, s.lods.length, n, s));
|
|
322
326
|
o || this.parser.getDependency("texture", n).then((a) => {
|
|
323
|
-
a && _.registerTexture(this.url, a,
|
|
327
|
+
a && _.registerTexture(this.url, a, s.lods.length, n, s);
|
|
324
328
|
});
|
|
325
329
|
}
|
|
326
330
|
}
|
|
327
|
-
}), (r = this.parser.json.meshes) == null || r.forEach((
|
|
328
|
-
if (
|
|
329
|
-
const
|
|
330
|
-
if (
|
|
331
|
+
}), (r = this.parser.json.meshes) == null || r.forEach((i, n) => {
|
|
332
|
+
if (i != null && i.extensions) {
|
|
333
|
+
const s = i == null ? void 0 : i.extensions[B];
|
|
334
|
+
if (s && s.lods) {
|
|
331
335
|
for (const o of this.parser.associations.keys())
|
|
332
336
|
if (o.isMesh) {
|
|
333
337
|
const a = this.parser.associations.get(o);
|
|
334
|
-
a.meshes === n && _.registerMesh(this.url,
|
|
338
|
+
a.meshes === n && _.registerMesh(this.url, s.guid, o, s.lods.length, a.primitives, s);
|
|
335
339
|
}
|
|
336
340
|
}
|
|
337
341
|
}
|
|
@@ -339,43 +343,43 @@ const _ = class {
|
|
|
339
343
|
}
|
|
340
344
|
static async getOrLoadLOD(e, t) {
|
|
341
345
|
var o, a, h, d;
|
|
342
|
-
const r =
|
|
343
|
-
if (!
|
|
346
|
+
const r = D == "verbose", i = e.userData.LODS;
|
|
347
|
+
if (!i)
|
|
344
348
|
return null;
|
|
345
|
-
const n =
|
|
346
|
-
let
|
|
349
|
+
const n = i == null ? void 0 : i.key;
|
|
350
|
+
let s;
|
|
347
351
|
if (e.isTexture === !0) {
|
|
348
352
|
const g = e;
|
|
349
|
-
g.source && g.source[se] && (
|
|
353
|
+
g.source && g.source[se] && (s = g.source[se]);
|
|
350
354
|
}
|
|
351
|
-
if (
|
|
355
|
+
if (s || (s = _.lodInfos.get(n)), s) {
|
|
352
356
|
if (t > 0) {
|
|
353
357
|
let m = !1;
|
|
354
|
-
const
|
|
355
|
-
if (
|
|
358
|
+
const M = Array.isArray(s.lods);
|
|
359
|
+
if (M && t >= s.lods.length ? m = !0 : M || (m = !0), m)
|
|
356
360
|
return this.lowresCache.get(n);
|
|
357
361
|
}
|
|
358
|
-
const g = Array.isArray(
|
|
362
|
+
const g = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
|
|
359
363
|
if (!g)
|
|
360
|
-
return
|
|
361
|
-
const f = Te(
|
|
364
|
+
return D && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
|
|
365
|
+
const f = Te(i.url, g);
|
|
362
366
|
if (f.endsWith(".glb") || f.endsWith(".gltf")) {
|
|
363
|
-
if (!
|
|
364
|
-
return console.warn("missing pointer for glb/gltf texture",
|
|
365
|
-
const m = f + "_" +
|
|
366
|
-
if (
|
|
367
|
+
if (!s.guid)
|
|
368
|
+
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
369
|
+
const m = f + "_" + s.guid, M = this.previouslyLoaded.get(m);
|
|
370
|
+
if (M !== void 0) {
|
|
367
371
|
r && console.log(`LOD ${t} was already loading/loaded: ${m}`);
|
|
368
|
-
let x = await
|
|
372
|
+
let x = await M.catch((z) => (console.error(`Error loading LOD ${t} from ${f}
|
|
369
373
|
`, z), null)), T = !1;
|
|
370
374
|
if (x == null || (x instanceof N && e instanceof N ? (a = x.image) != null && a.data || (h = x.source) != null && h.data ? x = this.copySettings(e, x) : (T = !0, this.previouslyLoaded.delete(m)) : x instanceof Y && e instanceof Y && ((d = x.attributes.position) != null && d.array || (T = !0, this.previouslyLoaded.delete(m)))), !T)
|
|
371
375
|
return x;
|
|
372
376
|
}
|
|
373
|
-
const
|
|
377
|
+
const w = s, O = new Promise(async (x, T) => {
|
|
374
378
|
const z = new Se();
|
|
375
|
-
ge(z),
|
|
379
|
+
ge(z), D && (await new Promise((p) => setTimeout(p, 1e3)), r && console.warn("Start loading (delayed) " + f, w.guid));
|
|
376
380
|
let ee = f;
|
|
377
|
-
if (
|
|
378
|
-
const p =
|
|
381
|
+
if (w && Array.isArray(w.lods)) {
|
|
382
|
+
const p = w.lods[t];
|
|
379
383
|
p.hash && (ee += "?v=" + p.hash);
|
|
380
384
|
}
|
|
381
385
|
const E = await z.loadAsync(ee).catch((p) => (console.error(`Error loading LOD ${t} from ${f}
|
|
@@ -383,14 +387,14 @@ const _ = class {
|
|
|
383
387
|
if (!E)
|
|
384
388
|
return null;
|
|
385
389
|
const te = E.parser;
|
|
386
|
-
r && console.log("Loading finished " + f,
|
|
390
|
+
r && console.log("Loading finished " + f, w.guid);
|
|
387
391
|
let y = 0;
|
|
388
392
|
if (E.parser.json.textures) {
|
|
389
393
|
let p = !1;
|
|
390
394
|
for (const u of E.parser.json.textures) {
|
|
391
395
|
if (u != null && u.extensions) {
|
|
392
396
|
const L = u == null ? void 0 : u.extensions[B];
|
|
393
|
-
if (L != null && L.guid && L.guid ===
|
|
397
|
+
if (L != null && L.guid && L.guid === w.guid) {
|
|
394
398
|
p = !0;
|
|
395
399
|
break;
|
|
396
400
|
}
|
|
@@ -399,16 +403,16 @@ const _ = class {
|
|
|
399
403
|
}
|
|
400
404
|
if (p) {
|
|
401
405
|
let u = await te.getDependency("texture", y);
|
|
402
|
-
return u && _.assignLODInformation(
|
|
406
|
+
return u && _.assignLODInformation(i.url, u, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + u.name + '"', f, y, u, m), e instanceof N && (u = this.copySettings(e, u)), u && (u.guid = w.guid), x(u);
|
|
403
407
|
} else
|
|
404
|
-
|
|
408
|
+
D && console.warn("Could not find texture with guid", w.guid);
|
|
405
409
|
}
|
|
406
410
|
if (y = 0, E.parser.json.meshes) {
|
|
407
411
|
let p = !1;
|
|
408
412
|
for (const u of E.parser.json.meshes) {
|
|
409
413
|
if (u != null && u.extensions) {
|
|
410
414
|
const L = u == null ? void 0 : u.extensions[B];
|
|
411
|
-
if (L != null && L.guid && L.guid ===
|
|
415
|
+
if (L != null && L.guid && L.guid === w.guid) {
|
|
412
416
|
p = !0;
|
|
413
417
|
break;
|
|
414
418
|
}
|
|
@@ -416,17 +420,17 @@ const _ = class {
|
|
|
416
420
|
y++;
|
|
417
421
|
}
|
|
418
422
|
if (p) {
|
|
419
|
-
const u = await te.getDependency("mesh", y), L =
|
|
423
|
+
const u = await te.getDependency("mesh", y), L = w;
|
|
420
424
|
if (r && console.log(`Loaded Mesh "${u.name}"`, f, y, u, m), u.isMesh === !0) {
|
|
421
425
|
const S = u.geometry;
|
|
422
|
-
return _.assignLODInformation(
|
|
426
|
+
return _.assignLODInformation(i.url, S, n, t, void 0, L.density), x(S);
|
|
423
427
|
} else {
|
|
424
428
|
const S = new Array();
|
|
425
429
|
for (let C = 0; C < u.children.length; C++) {
|
|
426
430
|
const G = u.children[C];
|
|
427
431
|
if (G instanceof F) {
|
|
428
432
|
const $ = G.geometry;
|
|
429
|
-
_.assignLODInformation(
|
|
433
|
+
_.assignLODInformation(i.url, $, n, t, C, L.density), S.push($);
|
|
430
434
|
}
|
|
431
435
|
}
|
|
432
436
|
return x(S);
|
|
@@ -435,22 +439,22 @@ const _ = class {
|
|
|
435
439
|
}
|
|
436
440
|
return x(null);
|
|
437
441
|
});
|
|
438
|
-
return this.previouslyLoaded.set(m,
|
|
442
|
+
return this.previouslyLoaded.set(m, O), await O;
|
|
439
443
|
} else if (e instanceof N) {
|
|
440
444
|
r && console.log("Load texture from uri: " + f);
|
|
441
|
-
const
|
|
442
|
-
return
|
|
445
|
+
const M = await new Oe().loadAsync(f);
|
|
446
|
+
return M ? (M.guid = s.guid, M.flipY = !1, M.needsUpdate = !0, M.colorSpace = e.colorSpace, r && console.log(s, M)) : D && console.warn("failed loading", f), M;
|
|
443
447
|
}
|
|
444
448
|
} else
|
|
445
|
-
|
|
449
|
+
D && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
446
450
|
return null;
|
|
447
451
|
}
|
|
448
|
-
static assignLODInformation(e, t, r,
|
|
452
|
+
static assignLODInformation(e, t, r, i, n, s) {
|
|
449
453
|
if (!t)
|
|
450
454
|
return;
|
|
451
455
|
t.userData || (t.userData = {});
|
|
452
|
-
const o = new Ee(e, r,
|
|
453
|
-
t.userData.LODS = o, t.userData.LOD =
|
|
456
|
+
const o = new Ee(e, r, i, n, s);
|
|
457
|
+
t.userData.LODS = o, t.userData.LOD = i;
|
|
454
458
|
}
|
|
455
459
|
static getAssignedLODInformation(e) {
|
|
456
460
|
var t;
|
|
@@ -458,7 +462,7 @@ const _ = class {
|
|
|
458
462
|
}
|
|
459
463
|
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
460
464
|
static copySettings(e, t) {
|
|
461
|
-
return t = t.clone(),
|
|
465
|
+
return t = t.clone(), D && console.warn(`Copying texture settings
|
|
462
466
|
`, e.uuid, `
|
|
463
467
|
`, t.uuid), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t.magFilter = e.magFilter, t.minFilter = e.minFilter, t.wrapS = e.wrapS, t.wrapT = e.wrapT, t.flipY = e.flipY, t.anisotropy = e.anisotropy, t.mipmaps || (t.generateMipmaps = e.generateMipmaps), t;
|
|
464
468
|
}
|
|
@@ -467,36 +471,36 @@ let v = _;
|
|
|
467
471
|
/**
|
|
468
472
|
* Register a texture with LOD information
|
|
469
473
|
*/
|
|
470
|
-
c(v, "registerTexture", (e, t, r,
|
|
471
|
-
if (
|
|
472
|
-
|
|
474
|
+
c(v, "registerTexture", (e, t, r, i, n) => {
|
|
475
|
+
if (D && console.log("> Progressive: register texture", i, t.name, t.uuid, t, n), !t) {
|
|
476
|
+
D && console.error("gltf-progressive: Register texture without texture");
|
|
473
477
|
return;
|
|
474
478
|
}
|
|
475
479
|
t.source && (t.source[se] = n);
|
|
476
|
-
const
|
|
477
|
-
_.assignLODInformation(e, t,
|
|
480
|
+
const s = n.guid;
|
|
481
|
+
_.assignLODInformation(e, t, s, r, i, void 0), _.lodInfos.set(s, n), _.lowresCache.set(s, t);
|
|
478
482
|
}), /**
|
|
479
483
|
* Register a mesh with LOD information
|
|
480
484
|
*/
|
|
481
|
-
c(v, "registerMesh", (e, t, r,
|
|
485
|
+
c(v, "registerMesh", (e, t, r, i, n, s) => {
|
|
482
486
|
var h;
|
|
483
|
-
|
|
487
|
+
D && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
|
|
484
488
|
const o = r.geometry;
|
|
485
489
|
if (!o) {
|
|
486
|
-
|
|
490
|
+
D && console.warn("gltf-progressive: Register mesh without geometry");
|
|
487
491
|
return;
|
|
488
492
|
}
|
|
489
|
-
o.userData || (o.userData = {}), _.assignLODInformation(e, o, t,
|
|
493
|
+
o.userData || (o.userData = {}), _.assignLODInformation(e, o, t, i, n, s.density), _.lodInfos.set(t, s);
|
|
490
494
|
let a = _.lowresCache.get(t);
|
|
491
|
-
a ? a.push(r.geometry) : a = [r.geometry], _.lowresCache.set(t, a),
|
|
495
|
+
a ? a.push(r.geometry) : a = [r.geometry], _.lowresCache.set(t, a), i > 0 && !ae(r) && be(r, o);
|
|
492
496
|
for (const d of I)
|
|
493
|
-
(h = d.onRegisteredNewMesh) == null || h.call(d, r,
|
|
497
|
+
(h = d.onRegisteredNewMesh) == null || h.call(d, r, s);
|
|
494
498
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
495
499
|
c(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
496
500
|
c(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
497
501
|
c(v, "lowresCache", /* @__PURE__ */ new Map());
|
|
498
502
|
class Ee {
|
|
499
|
-
constructor(e, t, r,
|
|
503
|
+
constructor(e, t, r, i, n) {
|
|
500
504
|
c(this, "url");
|
|
501
505
|
/** the key to lookup the LOD information */
|
|
502
506
|
c(this, "key");
|
|
@@ -505,7 +509,7 @@ class Ee {
|
|
|
505
509
|
c(this, "index");
|
|
506
510
|
/** the mesh density */
|
|
507
511
|
c(this, "density");
|
|
508
|
-
this.url = e, this.key = t, this.level = r,
|
|
512
|
+
this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
|
|
509
513
|
}
|
|
510
514
|
}
|
|
511
515
|
const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LODSManager"), b = { mesh_lod: -1, texture_lod: -1 }, A = class {
|
|
@@ -572,33 +576,33 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
572
576
|
let e = 0;
|
|
573
577
|
this._originalRender = this.renderer.render;
|
|
574
578
|
const t = this;
|
|
575
|
-
he(this.renderer), this.renderer.render = function(r,
|
|
579
|
+
he(this.renderer), this.renderer.render = function(r, i) {
|
|
576
580
|
t.renderer.getRenderTarget() == null && (e = 0, t._frame += 1);
|
|
577
|
-
const
|
|
578
|
-
t.onBeforeRender(r,
|
|
581
|
+
const s = t._frame, o = e++;
|
|
582
|
+
t.onBeforeRender(r, i, o, s), t._originalRender.call(this, r, i), t.onAfterRender(r, i, o, s);
|
|
579
583
|
};
|
|
580
584
|
}
|
|
581
585
|
disable() {
|
|
582
586
|
this._originalRender && (this.renderer.render = this._originalRender, this._originalRender = void 0);
|
|
583
587
|
}
|
|
584
|
-
onBeforeRender(e, t, r,
|
|
588
|
+
onBeforeRender(e, t, r, i) {
|
|
585
589
|
}
|
|
586
|
-
onAfterRender(e, t, r,
|
|
590
|
+
onAfterRender(e, t, r, i) {
|
|
587
591
|
var a, h;
|
|
588
592
|
if (this.pause)
|
|
589
593
|
return;
|
|
590
|
-
const n = this.renderer.renderLists.get(e, 0),
|
|
594
|
+
const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
|
|
591
595
|
let o = !0;
|
|
592
|
-
if (
|
|
593
|
-
const d =
|
|
596
|
+
if (s.length === 1) {
|
|
597
|
+
const d = s[0].material;
|
|
594
598
|
(d.name === "EffectMaterial" || d.name === "CopyShader") && (o = !1);
|
|
595
599
|
}
|
|
596
600
|
if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
|
|
597
|
-
if (Ce || this.updateInterval > 0 &&
|
|
601
|
+
if (Ce || this.updateInterval > 0 && i % this.updateInterval != 0)
|
|
598
602
|
return;
|
|
599
603
|
this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
600
604
|
const d = this.targetTriangleDensity;
|
|
601
|
-
for (const f of
|
|
605
|
+
for (const f of s) {
|
|
602
606
|
if (f.material && (((a = f.geometry) == null ? void 0 : a.type) === "BoxGeometry" || ((h = f.geometry) == null ? void 0 : h.type) === "BufferGeometry") && (f.material.name === "SphericalGaussianBlur" || f.material.name == "BackgroundCubeMaterial" || f.material.name === "CubemapFromEquirect" || f.material.name === "EquirectangularToCubeUV")) {
|
|
603
607
|
U && (f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", f, f.material.name, f.material.type)));
|
|
604
608
|
continue;
|
|
@@ -613,25 +617,25 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
613
617
|
continue;
|
|
614
618
|
}
|
|
615
619
|
const m = f.object;
|
|
616
|
-
(m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d,
|
|
620
|
+
(m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d, i);
|
|
617
621
|
}
|
|
618
622
|
const g = n.transparent;
|
|
619
623
|
for (const f of g) {
|
|
620
624
|
const m = f.object;
|
|
621
|
-
(m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d,
|
|
625
|
+
(m instanceof F || m.isMesh) && this.updateLODs(e, t, m, d, i);
|
|
622
626
|
}
|
|
623
627
|
}
|
|
624
628
|
}
|
|
625
629
|
/** Update the LOD levels for the renderer. */
|
|
626
|
-
updateLODs(e, t, r,
|
|
630
|
+
updateLODs(e, t, r, i, n) {
|
|
627
631
|
var a, h;
|
|
628
632
|
r.userData || (r.userData = {});
|
|
629
|
-
let
|
|
630
|
-
if (
|
|
633
|
+
let s = r.userData.LOD_state;
|
|
634
|
+
if (s || (s = new Re(), r.userData.LOD_state = s), s.frames++ < 2)
|
|
631
635
|
return;
|
|
632
636
|
for (const d of I)
|
|
633
637
|
(a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
|
|
634
|
-
this.calculateLodLevel(t, r,
|
|
638
|
+
this.calculateLodLevel(t, r, s, i, b), b.mesh_lod = Math.round(b.mesh_lod), b.texture_lod = Math.round(b.texture_lod), b.mesh_lod >= 0 && this.loadProgressiveMeshes(r, b.mesh_lod);
|
|
635
639
|
let o = b.texture_lod;
|
|
636
640
|
if (r.material && o >= 0) {
|
|
637
641
|
const d = r["DEBUG:LOD"];
|
|
@@ -639,7 +643,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
639
643
|
}
|
|
640
644
|
for (const d of I)
|
|
641
645
|
(h = d.onAfterUpdatedLOD) == null || h.call(d, this.renderer, e, t, r, b);
|
|
642
|
-
|
|
646
|
+
s.lastLodLevel_Mesh = b.mesh_lod, s.lastLodLevel_Texture = b.texture_lod;
|
|
643
647
|
}
|
|
644
648
|
/** Load progressive textures for the given material
|
|
645
649
|
* @param material the material to load the textures for
|
|
@@ -655,8 +659,8 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
655
659
|
return;
|
|
656
660
|
}
|
|
657
661
|
const r = e;
|
|
658
|
-
let
|
|
659
|
-
(r.NEEDLE_LOD == null || t < r.NEEDLE_LOD) && (
|
|
662
|
+
let i = !1;
|
|
663
|
+
(r.NEEDLE_LOD == null || t < r.NEEDLE_LOD) && (i = !0), i && (r.NEEDLE_LOD = t, v.assignTextureLOD(e, t));
|
|
660
664
|
}
|
|
661
665
|
/** Load progressive meshes for the given mesh
|
|
662
666
|
* @param mesh the mesh to load the LOD for
|
|
@@ -670,16 +674,16 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
670
674
|
if (e.userData || (e.userData = {}), e.userData.LOD !== t) {
|
|
671
675
|
e.userData.LOD = t;
|
|
672
676
|
const r = e.geometry;
|
|
673
|
-
return v.assignMeshLOD(e, t).then((
|
|
677
|
+
return v.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
|
|
674
678
|
}
|
|
675
679
|
return Promise.resolve(null);
|
|
676
680
|
}
|
|
677
681
|
static isInside(e, t) {
|
|
678
|
-
const r = e.min,
|
|
679
|
-
return this._tempPtInside.set(n,
|
|
682
|
+
const r = e.min, i = e.max, n = (r.x + i.x) * 0.5, s = (r.y + i.y) * 0.5;
|
|
683
|
+
return this._tempPtInside.set(n, s, r.z).applyMatrix4(t).z < 0;
|
|
680
684
|
}
|
|
681
|
-
calculateLodLevel(e, t, r,
|
|
682
|
-
var
|
|
685
|
+
calculateLodLevel(e, t, r, i, n) {
|
|
686
|
+
var M;
|
|
683
687
|
if (!t) {
|
|
684
688
|
n.mesh_lod = -1, n.texture_lod = -1;
|
|
685
689
|
return;
|
|
@@ -696,13 +700,13 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
696
700
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
697
701
|
return;
|
|
698
702
|
}
|
|
699
|
-
if (d || (o = 0), !((
|
|
703
|
+
if (d || (o = 0), !((M = this.cameraFrustrum) != null && M.intersectsObject(t))) {
|
|
700
704
|
n.mesh_lod = 99, n.texture_lod = 99;
|
|
701
705
|
return;
|
|
702
706
|
}
|
|
703
707
|
const m = t.geometry.boundingBox;
|
|
704
708
|
if (m && e.isPerspectiveCamera) {
|
|
705
|
-
const
|
|
709
|
+
const w = e;
|
|
706
710
|
if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
|
|
707
711
|
this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
|
|
708
712
|
const y = e.getWorldPosition(this._tempWorldPosition);
|
|
@@ -715,7 +719,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
715
719
|
n.mesh_lod = 0, n.texture_lod = 0;
|
|
716
720
|
return;
|
|
717
721
|
}
|
|
718
|
-
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled &&
|
|
722
|
+
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && w.fov > 70) {
|
|
719
723
|
const y = this._tempBox.min, p = this._tempBox.max;
|
|
720
724
|
let u = y.x, L = y.y, S = p.x, C = p.y;
|
|
721
725
|
const G = 2, $ = 1.5, H = (y.x + p.x) * 0.5, J = (y.y + p.y) * 0.5;
|
|
@@ -724,12 +728,12 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
724
728
|
r.lastCentrality = ($ - re) * ($ - re) * ($ - re);
|
|
725
729
|
} else
|
|
726
730
|
r.lastCentrality = 1;
|
|
727
|
-
const
|
|
728
|
-
|
|
731
|
+
const O = this._tempBox.getSize(this._tempBoxSize);
|
|
732
|
+
O.multiplyScalar(0.5), screen.availHeight > 0 && O.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), O.x *= w.aspect;
|
|
729
733
|
const R = e.matrixWorldInverse, x = this._tempBox2;
|
|
730
734
|
x.copy(m), x.applyMatrix4(t.matrixWorld), x.applyMatrix4(R);
|
|
731
735
|
const T = x.getSize(this._tempBox2Size), z = Math.max(T.x, T.y);
|
|
732
|
-
if (Math.max(
|
|
736
|
+
if (Math.max(O.x, O.y) != 0 && z != 0 && (O.z = T.z / Math.max(T.x, T.y) * Math.max(O.x, O.y)), r.lastScreenCoverage = Math.max(O.x, O.y, O.z), r.lastScreenspaceVolume.copy(O), r.lastScreenCoverage *= r.lastCentrality, U && A.debugDrawLine) {
|
|
733
737
|
const y = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
734
738
|
y.invert();
|
|
735
739
|
const p = A.corner0, u = A.corner1, L = A.corner2, S = A.corner3;
|
|
@@ -740,7 +744,7 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
740
744
|
let E = 999;
|
|
741
745
|
if (h && r.lastScreenCoverage > 0) {
|
|
742
746
|
for (let y = 0; y < h.length; y++)
|
|
743
|
-
if (h[y].density / r.lastScreenCoverage <
|
|
747
|
+
if (h[y].density / r.lastScreenCoverage < i) {
|
|
744
748
|
E = y;
|
|
745
749
|
break;
|
|
746
750
|
}
|
|
@@ -750,11 +754,11 @@ const U = j("debugprogressive"), Ce = j("noprogressive"), fe = Symbol("Needle:LO
|
|
|
750
754
|
if (n.mesh_lod = o, f)
|
|
751
755
|
if (r.lastLodLevel_Texture < 0) {
|
|
752
756
|
if (n.texture_lod = g.max_count - 1, U) {
|
|
753
|
-
const
|
|
754
|
-
U && console.log(`First Texture LOD ${n.texture_lod} (${
|
|
757
|
+
const w = g.lods[g.max_count - 1];
|
|
758
|
+
U && console.log(`First Texture LOD ${n.texture_lod} (${w.max_height}px) - ${t.name}`);
|
|
755
759
|
}
|
|
756
760
|
} else {
|
|
757
|
-
const
|
|
761
|
+
const w = r.lastScreenCoverage * 1.5, R = this.renderer.domElement.clientHeight / window.devicePixelRatio * w;
|
|
758
762
|
for (let x = g.lods.length - 1; x >= 0; x--) {
|
|
759
763
|
const T = g.lods[x];
|
|
760
764
|
if (!(Ae() && T.max_height > 4096) && T.max_height > R) {
|
|
@@ -787,15 +791,15 @@ function ke(l) {
|
|
|
787
791
|
return null;
|
|
788
792
|
let e = null, t = null;
|
|
789
793
|
for (let r = l; r != null; r = Object.getPrototypeOf(r)) {
|
|
790
|
-
const
|
|
791
|
-
!e && n != null && (e = l[n].threeRenderer), !t &&
|
|
794
|
+
const i = Object.getOwnPropertySymbols(r), n = i.find((o) => o.toString() == "Symbol(renderer)"), s = i.find((o) => o.toString() == "Symbol(scene)");
|
|
795
|
+
!e && n != null && (e = l[n].threeRenderer), !t && s != null && (t = l[s]);
|
|
792
796
|
}
|
|
793
797
|
if (e) {
|
|
794
798
|
console.log("Adding Needle LODs to modelviewer");
|
|
795
799
|
const r = P.get(e);
|
|
796
800
|
if (P.addPlugin(new Be(l)), r.enable(), t) {
|
|
797
|
-
const
|
|
798
|
-
|
|
801
|
+
const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
|
|
802
|
+
i && e.render(t, i);
|
|
799
803
|
}
|
|
800
804
|
return () => {
|
|
801
805
|
r.disable();
|
|
@@ -809,8 +813,8 @@ class Be {
|
|
|
809
813
|
c(this, "_didWarnAboutMissingUrl", !1);
|
|
810
814
|
this.modelviewer = e;
|
|
811
815
|
}
|
|
812
|
-
onBeforeUpdateLOD(e, t, r,
|
|
813
|
-
this.tryParseMeshLOD(t,
|
|
816
|
+
onBeforeUpdateLOD(e, t, r, i) {
|
|
817
|
+
this.tryParseMeshLOD(t, i), this.tryParseTextureLOD(t, i);
|
|
814
818
|
}
|
|
815
819
|
getUrl() {
|
|
816
820
|
let e = this.modelviewer.getAttribute("src");
|
|
@@ -823,8 +827,8 @@ class Be {
|
|
|
823
827
|
if (t[Q] == !0)
|
|
824
828
|
return;
|
|
825
829
|
t[Q] = !0;
|
|
826
|
-
const r = this.tryGetCurrentGLTF(e),
|
|
827
|
-
if (
|
|
830
|
+
const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
|
|
831
|
+
if (i && r && t.material) {
|
|
828
832
|
let n = function(o) {
|
|
829
833
|
var h, d, g;
|
|
830
834
|
if (o[Q] == !0)
|
|
@@ -832,47 +836,47 @@ class Be {
|
|
|
832
836
|
o[Q] = !0, o.userData && (o.userData.LOD = -1);
|
|
833
837
|
const a = Object.keys(o);
|
|
834
838
|
for (let f = 0; f < a.length; f++) {
|
|
835
|
-
const m = a[f],
|
|
836
|
-
if ((
|
|
837
|
-
const
|
|
838
|
-
if (!
|
|
839
|
-
console.warn("Texture data not found for texture index " +
|
|
839
|
+
const m = a[f], M = o[m];
|
|
840
|
+
if ((M == null ? void 0 : M.isTexture) === !0) {
|
|
841
|
+
const w = (d = (h = M.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, O = r.parser.json.textures[w];
|
|
842
|
+
if (!O) {
|
|
843
|
+
console.warn("Texture data not found for texture index " + w);
|
|
840
844
|
continue;
|
|
841
845
|
}
|
|
842
|
-
if ((g =
|
|
843
|
-
const R =
|
|
844
|
-
R &&
|
|
846
|
+
if ((g = O == null ? void 0 : O.extensions) != null && g[B]) {
|
|
847
|
+
const R = O.extensions[B];
|
|
848
|
+
R && i && v.registerTexture(i, M, R.lods.length, w, R);
|
|
845
849
|
}
|
|
846
850
|
}
|
|
847
851
|
}
|
|
848
852
|
};
|
|
849
|
-
const
|
|
850
|
-
if (Array.isArray(
|
|
851
|
-
for (const o of
|
|
853
|
+
const s = t.material;
|
|
854
|
+
if (Array.isArray(s))
|
|
855
|
+
for (const o of s)
|
|
852
856
|
n(o);
|
|
853
857
|
else
|
|
854
|
-
n(
|
|
858
|
+
n(s);
|
|
855
859
|
}
|
|
856
860
|
}
|
|
857
861
|
tryParseMeshLOD(e, t) {
|
|
858
|
-
var n,
|
|
862
|
+
var n, s;
|
|
859
863
|
if (t[de] == !0)
|
|
860
864
|
return;
|
|
861
865
|
t[de] = !0;
|
|
862
866
|
const r = this.getUrl();
|
|
863
867
|
if (!r)
|
|
864
868
|
return;
|
|
865
|
-
const
|
|
866
|
-
if (
|
|
869
|
+
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[B];
|
|
870
|
+
if (i && r) {
|
|
867
871
|
const o = t.uuid;
|
|
868
|
-
v.registerMesh(r, o, t, 0,
|
|
872
|
+
v.registerMesh(r, o, t, 0, i.lods.length, i);
|
|
869
873
|
}
|
|
870
874
|
}
|
|
871
875
|
}
|
|
872
876
|
function qe(l, e, t, r) {
|
|
873
877
|
he(e), ge(t), t.register((n) => new v(n, l));
|
|
874
|
-
const
|
|
875
|
-
return (r == null ? void 0 : r.enableLODsManager) !== !1 &&
|
|
878
|
+
const i = P.get(e);
|
|
879
|
+
return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
|
|
876
880
|
}
|
|
877
881
|
document.addEventListener("DOMContentLoaded", () => {
|
|
878
882
|
ke(document.querySelector("model-viewer"));
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as
|
|
2
|
-
`,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new
|
|
3
|
-
`,y),null));if(!x)return null;const
|
|
1
|
+
var me=Object.defineProperty,pe=(t,e,r)=>e in t?me(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(pe(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as ye}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Le}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as $,Mesh as G,Material as ve,Texture as z,TextureLoader as De,Matrix4 as ie,Frustum as Me,Sphere as Oe,Box3 as ae,Vector3 as B}from"three";import{GLTFLoader as _e}from"three/examples/jsm/loaders/GLTFLoader.js";let X="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(X+"draco_decoder.js",{method:"head"}).catch(t=>{X="./include/draco/",ee="./include/ktx2/"});function we(t){X=t}function be(t){ee=t}let U,te,q;function re(t){U||(U=new ye,U.setDecoderPath(X),U.setDecoderConfig({type:"js"})),q||(q=new Le,q.setTranscoderPath(ee)),te||(te=xe),t?q.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function se(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(q),t.meshoptDecoder||t.setMeshoptDecoder(te)}function H(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Se(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let Y;function Te(){return Y!==void 0||(Y=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),H("debugprogressive")&&console.log("isMobileDevice",Y)),Y}function J(t){var e;return((e=t?.userData)==null?void 0:e["needle:raycast-mesh"])instanceof $?t.userData["needle:raycast-mesh"]:null}function le(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!J(t)){const r=Ae(e);r.userData={isRaycastMesh:!0},t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=r}}function Ee(t=!0){if(t){if(V)return;const e=V=G.prototype.raycast;G.prototype.raycast=function(r,n){const o=this,s=J(o);let a;s&&o.isMesh&&(a=o.geometry,o.geometry=s),e.call(this,r,n),a&&(o.geometry=a)}}else{if(!V)return;G.prototype.raycast=V,V=null}}let V=null;function Ae(t){const e=new $;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const R=new Array,P="NEEDLE_progressive",L=H("debugprogressive"),oe=Symbol("needle-progressive-texture"),K=new Map,ne=new Set;if(L){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const u=_.getMeshLODInformation(i),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,_.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,_.assignTextureLOD(s,e);break}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",o=>{o.key==="p"&&t(),o.key==="w"&&(n=!n,ne&&ne.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ue(t,e,r){var n;if(!L)return;K.has(t)||K.set(t,{keys:[],sourceId:r});const o=K.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const M=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,o;if(this._isLoadingMesh)return null;const s=(o=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:o[P];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(a=>(this._isLoadingMesh=!1,a&&M.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),L&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return P}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",o=t[n];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(L==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const i of Object.keys(a.uniforms)){const u=a.uniforms[i].value;u?.isTexture===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const i=t[a];i?.isTexture===!0&&s(i,e)}return t[n]=e,e;function s(a,i){const u=r.getAssignedLODInformation(a);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){i.min_count=Math.min(i.min_count,l.lods.length),i.max_count=Math.max(i.max_count,l.lods.length);for(let g=0;g<l.lods.length;g++){const d=l.lods[g];d.width&&(i.lods[g]=i.lods[g]||{min_height:1/0,max_height:0},i.lods[g].min_height=Math.min(i.lods[g].min_height,d.height),i.lods[g].max_height=Math.max(i.lods[g].max_height,d.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let n,o;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const s=n.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof G||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of R)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const a=o.index||0;s=s[a]}s&&n!=s&&s instanceof $&&(t.geometry=s,L&&ue(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else L&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof ve||t.isMaterial===!0){const r=t,n=[],o=new Array;if(L&&ne.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const u=this.assignTextureLODForSlot(i,e,r,a);n.push(u),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,r,s);n.push(i),o.push(s)}}return Promise.all(n).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const u=s[i],l=o[i];u&&u.isTexture===!0?a.push({material:r,slot:l,texture:u,level:e}):a.push({material:r,slot:l,texture:null,level:e})}return a})}if(t instanceof z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t){if(r&&n){const s=r[n];if(s){const a=this.getAssignedLODInformation(s);if(a&&a?.level<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(L&&n&&r){const s=this.getAssignedLODInformation(t);s&&ue(r,n,s.url)}}return o}else L=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return L&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[P];if(s){if(!s.lods){L&&console.warn("Texture has no LODs",s);return}let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,M.registerTexture(this.url,i,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&M.registerTexture(this.url,i,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[P];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===o&&M.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const a=L=="verbose",i=t.userData.LODS;if(!i)return null;const u=i?.key;let l;if(t.isTexture===!0){const g=t;g.source&&g.source[oe]&&(l=g.source[oe])}if(l||(l=M.lodInfos.get(u)),l){if(e>0){let f=!1;const w=Array.isArray(l.lods);if(w&&e>=l.lods.length?f=!0:w||(f=!0),f)return this.lowresCache.get(u)}const g=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!g)return L&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const d=Se(i.url,g);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=d+"_"+l.guid,w=this.previouslyLoaded.get(f);if(w!==void 0){a&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let p=await w.catch(N=>(console.error(`Error loading LOD ${e} from ${d}
|
|
2
|
+
`,N),null)),b=!1;if(p==null||(p instanceof z&&t instanceof z?(n=p.image)!=null&&n.data||(o=p.source)!=null&&o.data?p=this.copySettings(t,p):(b=!0,this.previouslyLoaded.delete(f)):p instanceof $&&t instanceof $&&((s=p.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return p}const m=l,S=new Promise(async(p,b)=>{const N=new _e;se(N),L&&(await new Promise(y=>setTimeout(y,1e3)),a&&console.warn("Start loading (delayed) "+d,m.guid));let F=d;if(m&&Array.isArray(m.lods)){const y=m.lods[e];y.hash&&(F+="?v="+y.hash)}const x=await N.loadAsync(F).catch(y=>(console.error(`Error loading LOD ${e} from ${d}
|
|
3
|
+
`,y),null));if(!x)return null;const v=x.parser;a&&console.log("Loading finished "+d,m.guid);let D=0;if(x.parser.json.textures){let y=!1;for(const h of x.parser.json.textures){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){let h=await v.getDependency("texture",D);return h&&M.assignLODInformation(i.url,h,u,e,void 0,void 0),a&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',d,D,h,f),t instanceof z&&(h=this.copySettings(t,h)),h&&(h.guid=m.guid),p(h)}else L&&console.warn("Could not find texture with guid",m.guid)}if(D=0,x.parser.json.meshes){let y=!1;for(const h of x.parser.json.meshes){if(h!=null&&h.extensions){const O=h?.extensions[P];if(O!=null&&O.guid&&O.guid===m.guid){y=!0;break}}D++}if(y){const h=await v.getDependency("mesh",D),O=m;if(a&&console.log(`Loaded Mesh "${h.name}"`,d,D,h,f),h.isMesh===!0){const A=h.geometry;return M.assignLODInformation(i.url,A,u,e,void 0,O.density),p(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const k=h.children[C];if(k instanceof G){const j=k.geometry;M.assignLODInformation(i.url,j,u,e,C,O.density),A.push(j)}}return p(A)}}}return p(null)});return this.previouslyLoaded.set(f,S),await S}else if(t instanceof z){a&&console.log("Load texture from uri: "+d);const f=await new De().loadAsync(d);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,a&&console.log(l,f)):L&&console.warn("failed loading",d),f}}else L&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new Pe(t,r,n,o,s);e.userData.LODS=a,e.userData.LOD=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),L&&console.warn(`Copying texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let O=M;c(O,"registerTexture",(t,e,r,n,o)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;M.assignLODInformation(t,e,s,r,n,void 0),M.lodInfos.set(s,o),M.lowresCache.set(s,e)}),c(O,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){v&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"lowresCache",new Map);class Pe{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const W=H("debugprogressive"),Ie=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),c(this,"cameraFrustrum",new Me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new _e),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Ie||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Be,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,O.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=O.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=O.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const f=e.geometry.boundingBox;if(f&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const x=this._tempBox.min,L=this._tempBox.max;let D=x.x,y=x.y,h=L.x,_=L.y;const A=2,C=1.5,k=(x.x+L.x)*.5,j=(x.y+L.y)*.5;D=(D-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,_=(_-j)*A+j;const fe=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(L.x)),ge=y<0&&_>0?0:Math.min(Math.abs(x.y),Math.abs(L.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=w.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const L=T.corner0,D=T.corner1,y=T.corner2,h=T.corner3;L.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=L.x,y.copy(this._tempBox.max),y.y=L.y,h.copy(this._tempBox.max);const _=(L.z+h.z)*.5;L.z=D.z=y.z=h.z=_,L.applyMatrix4(x),D.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(L,D,255),T.debugDrawLine(L,y,255),T.debugDrawLine(D,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const w=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let I=T;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B),c(I,"_tempPtInside",new B);class Be{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=I.get(e);if(I.addPlugin(new Ce(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class Ce{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[Q]==!0)return;r[Q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const w=d[f],m=i[w];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&O.registerTexture(o,m,b.lods.length,S,b)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;O.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new O(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,O as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
|
|
5
|
+
`,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let _=M;c(_,"registerTexture",(t,e,r,n,o)=>{if(L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[oe]=o);const s=o.guid;M.assignLODInformation(t,e,s,r,n,void 0),M.lodInfos.set(s,o),M.lowresCache.set(s,e)}),c(_,"registerMesh",(t,e,r,n,o,s)=>{var a;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){L&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!J(r)&&le(r,i);for(const l of R)(a=l.onRegisteredNewMesh)==null||a.call(l,r,s)}),c(_,"lodInfos",new Map),c(_,"previouslyLoaded",new Map),c(_,"lowresCache",new Map);class Pe{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const W=H("debugprogressive"),Ie=H("noprogressive"),ce=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ie),c(this,"cameraFrustrum",new Me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new Oe),c(this,"_tempBox",new ae),c(this,"_tempBox2",new ae),c(this,"tempMatrix",new ie),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[ce]?t[ce]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;re(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let u=!0;if(i.length===1){const l=i[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(u=!1),u){if(Ie||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const l=this.targetTriangleDensity;for(const d of i){if(d.material&&(((o=d.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=d.geometry)==null?void 0:s.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){W&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const g=a.transparent;for(const d of g){const f=d.object;(f instanceof G||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Be,r.userData.LOD_state=i),i.frames++<2)return;for(const l of R)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let u=E.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of R)(a=l.onAfterUpdatedLOD)==null||a.call(l,this.renderer,t,e,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}const r=t;let n=!1;(r.NEEDLE_LOD==null||e<r.NEEDLE_LOD)&&(n=!0),n&&(r.NEEDLE_LOD=e,_.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return _.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,o){var s;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=_.getMeshLODInformation(e.geometry),u=i?.lods,l=u&&u.length>0,g=_.getMaterialMinMaxLODsCount(e.material),d=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!l&&!d){o.mesh_lod=0,o.texture_lod=0;return}if(l||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const f=e.geometry.boundingBox;if(f&&t.isPerspectiveCamera){const w=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&w.fov>70){const x=this._tempBox.min,v=this._tempBox.max;let D=x.x,y=x.y,h=v.x,O=v.y;const A=2,C=1.5,k=(x.x+v.x)*.5,j=(x.y+v.y)*.5;D=(D-k)*A+k,y=(y-j)*A+j,h=(h-k)*A+k,O=(O-j)*A+j;const fe=D<0&&h>0?0:Math.min(Math.abs(x.x),Math.abs(v.x)),ge=y<0&&O>0?0:Math.min(Math.abs(x.y),Math.abs(v.y)),Z=Math.max(fe,ge);r.lastCentrality=(C-Z)*(C-Z)*(C-Z)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&m.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),m.x*=w.aspect;const S=t.matrixWorldInverse,p=this._tempBox2;p.copy(f),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(S);const b=p.getSize(this._tempBox2Size),N=Math.max(b.x,b.y);if(Math.max(m.x,m.y)!=0&&N!=0&&(m.z=b.z/Math.max(b.x,b.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,W&&T.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const v=T.corner0,D=T.corner1,y=T.corner2,h=T.corner3;v.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=v.x,y.copy(this._tempBox.max),y.y=v.y,h.copy(this._tempBox.max);const O=(v.z+h.z)*.5;v.z=D.z=y.z=h.z=O,v.applyMatrix4(x),D.applyMatrix4(x),y.applyMatrix4(x),h.applyMatrix4(x),T.debugDrawLine(v,D,255),T.debugDrawLine(v,y,255),T.debugDrawLine(D,h,255),T.debugDrawLine(y,h,255)}let F=999;if(u&&r.lastScreenCoverage>0){for(let x=0;x<u.length;x++)if(u[x].density/r.lastScreenCoverage<n){F=x;break}}F<a&&(a=F)}if(o.mesh_lod=a,d)if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,W){const w=g.lods[g.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenCoverage*1.5,m=this.renderer.domElement.clientHeight/window.devicePixelRatio*w;for(let S=g.lods.length-1;S>=0;S--){const p=g.lods[S];if(!(Te()&&p.max_height>4096)&&p.max_height>m){o.texture_lod=S,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${m.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let I=T;c(I,"debugDrawLine"),c(I,"corner0",new B),c(I,"corner1",new B),c(I,"corner2",new B),c(I,"corner3",new B),c(I,"_tempPtInside",new B);class Be{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function he(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=I.get(e);if(I.addPlugin(new Ce(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class Ce{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[Q]==!0)return;r[Q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var u,l,g;if(i[Q]==!0)return;i[Q]=!0,i.userData&&(i.userData.LOD=-1);const d=Object.keys(i);for(let f=0;f<d.length;f++){const w=d[f],m=i[w];if(m?.isTexture===!0){const S=(l=(u=m.userData)==null?void 0:u.associations)==null?void 0:l.textures,p=n.parser.json.textures[S];if(!p){console.warn("Texture data not found for texture index "+S);continue}if((g=p?.extensions)!=null&&g[P]){const b=p.extensions[P];b&&o&&_.registerTexture(o,m,b.lods.length,S,b)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[de]==!0)return;r[de]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[P];if(a&&s){const i=r.uuid;_.registerMesh(s,i,r,0,a.lods.length,a)}}}function Re(t,e,r,n){re(e),se(r),r.register(s=>new _(s,t));const o=I.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{he(document.querySelector("model-viewer"))});export{P as EXTENSION_NAME,I as LODsManager,_ as NEEDLE_progressive,se as addDracoAndKTX2Loaders,re as createLoaders,J as getRaycastMesh,he as patchModelViewer,we as setDracoDecoderLocation,be as setKTX2TranscoderLocation,le as setRaycastMesh,Re as useNeedleProgressive,Ee as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Le=require("three/examples/jsm/loaders/DRACOLoader.js"),xe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),me=require("three/examples/jsm/loaders/GLTFLoader.js");let H="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ie="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(H+"draco_decoder.js",{method:"head"}).catch(l=>{H="./include/draco/",ie="./include/ktx2/"});function De(l){H=l}function Me(l){ie=l}let W,re,V;function oe(l){W||(W=new Le.DRACOLoader,W.setDecoderPath(H),W.setDecoderConfig({type:"js"})),V||(V=new xe.KTX2Loader,V.setTranscoderPath(ie)),re||(re=ye.MeshoptDecoder),l?V.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ne(l){l.dracoLoader||l.setDRACOLoader(W),l.ktx2Loader||l.setKTX2Loader(V),l.meshoptDecoder||l.setMeshoptDecoder(re)}function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function _e(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let $;function Oe(){return $!==void 0||($=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",$)),$}function Q(l){var e;return((e=l==null?void 0:l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function ue(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!Q(l)){const r=ve(e);r.userData={isRaycastMesh:!0},l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=r}}function we(l=!0){if(l){if(U)return;const e=U=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const
|
|
2
|
-
`,F),null)),A=!1;if(m==null||(m instanceof g.Texture&&e instanceof g.Texture?(a=m.image)!=null&&a.data||(h=m.source)!=null&&h.data?m=this.copySettings(e,m):(A=!0,this.previouslyLoaded.delete(x)):m instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((d=m.attributes.position)!=null&&d.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return m}const
|
|
3
|
-
`,y),null));if(!R)return null;const j=R.parser;r&&console.log("Loading finished "+f,
|
|
1
|
+
"use strict";var ge=Object.defineProperty;var pe=(l,e,t)=>e in l?ge(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(pe(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Le=require("three/examples/jsm/loaders/DRACOLoader.js"),xe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),me=require("three/examples/jsm/loaders/GLTFLoader.js");let H="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ie="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(H+"draco_decoder.js",{method:"head"}).catch(l=>{H="./include/draco/",ie="./include/ktx2/"});function De(l){H=l}function Me(l){ie=l}let W,re,V;function oe(l){W||(W=new Le.DRACOLoader,W.setDecoderPath(H),W.setDecoderConfig({type:"js"})),V||(V=new xe.KTX2Loader,V.setTranscoderPath(ie)),re||(re=ye.MeshoptDecoder),l?V.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ne(l){l.dracoLoader||l.setDRACOLoader(W),l.ktx2Loader||l.setKTX2Loader(V),l.meshoptDecoder||l.setMeshoptDecoder(re)}function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function _e(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let $;function Oe(){return $!==void 0||($=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",$)),$}function Q(l){var e;return((e=l==null?void 0:l.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?l.userData["needle:raycast-mesh"]:null}function ue(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!Q(l)){const r=ve(e);r.userData={isRaycastMesh:!0},l.userData||(l.userData={}),l.userData["needle:raycast-mesh"]=r}}function we(l=!0){if(l){if(U)return;const e=U=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=Q(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!U)return;g.Mesh.prototype.raycast=U,U=null}}let U=null;function ve(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const I=new Array,C="NEEDLE_progressive",M=J("debugprogressive"),te=Symbol("needle-progressive-texture"),q=new Map,se=new Set;if(M){let l=function(){e+=1,console.log("Toggle LOD level",e,q),q.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),h=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,h),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,se&&se.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function ae(l,e,t){var i;if(!M)return;q.has(l)||q.set(l,{keys:[],sourceId:t});const r=q.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const v=class{constructor(e,t){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[C];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>(this._isLoadingMesh=!1,o&&v.registerMesh(this.url,t.guid,o,t.lods.length,void 0,t),o))):null});M&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(M==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const h=n.uniforms[a].value;(h==null?void 0:h.isTexture)===!0&&s(h,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const h=r.getAssignedLODInformation(n);if(h){const d=r.lodInfos.get(h.key);if(d&&d.lods){a.min_count=Math.min(a.min_count,d.lods.length),a.max_count=Math.max(a.max_count,d.lods.length);for(let p=0;p<d.lods.length;p++){const f=d.lods[p];f.width&&(a.lods[p]=a.lods[p]||{min_height:1/0,max_height:0},a.lods[p].min_height=Math.min(a.lods[p].min_height,f.height),a.lods[p].max_height=Math.max(a.lods[p].max_height,f.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof g.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of I)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,v.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,M&&ae(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else M&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof g.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(M&&se.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const h=this.assignTextureLODForSlot(a,t,r,n);i.push(h),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const h=s[a],d=o[a];h&&h.isTexture===!0?n.push({material:r,slot:d,texture:h,level:t}):n.push({material:r,slot:d,texture:null,level:t})}return n})}if(e instanceof g.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(e):v.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return M==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(M&&i&&r){const s=this.getAssignedLODInformation(e);s&&ae(r,i,s.url)}}return o}else M=="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 M&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){if(!s.lods){M&&console.warn("Texture has no LODs",s);return}let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,v.registerTexture(this.url,a,s.lods.length,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&v.registerTexture(this.url,a,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&v.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,h,d;const r=M=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const p=e;p.source&&p.source[te]&&(s=p.source[te])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let x=!1;const _=Array.isArray(s.lods);if(_&&t>=s.lods.length?x=!0:_||(x=!0),x)return this.lowresCache.get(o)}const p=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!p)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const f=_e(i.url,p);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=f+"_"+s.guid,_=this.previouslyLoaded.get(x);if(_!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let m=await _.catch(F=>(console.error(`Error loading LOD ${t} from ${f}
|
|
2
|
+
`,F),null)),A=!1;if(m==null||(m instanceof g.Texture&&e instanceof g.Texture?(a=m.image)!=null&&a.data||(h=m.source)!=null&&h.data?m=this.copySettings(e,m):(A=!0,this.previouslyLoaded.delete(x)):m instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((d=m.attributes.position)!=null&&d.array||(A=!0,this.previouslyLoaded.delete(x)))),!A)return m}const O=s,w=new Promise(async(m,A)=>{const F=new me.GLTFLoader;ne(F),M&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+f,O.guid));let Z=f;if(O&&Array.isArray(O.lods)){const y=O.lods[t];y.hash&&(Z+="?v="+y.hash)}const R=await F.loadAsync(Z).catch(y=>(console.error(`Error loading LOD ${t} from ${f}
|
|
3
|
+
`,y),null));if(!R)return null;const j=R.parser;r&&console.log("Loading finished "+f,O.guid);let L=0;if(R.parser.json.textures){let y=!1;for(const u of R.parser.json.textures){if(u!=null&&u.extensions){const D=u==null?void 0:u.extensions[C];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){let u=await j.getDependency("texture",L);return u&&v.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,L,u,x),e instanceof g.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=O.guid),m(u)}else M&&console.warn("Could not find texture with guid",O.guid)}if(L=0,R.parser.json.meshes){let y=!1;for(const u of R.parser.json.meshes){if(u!=null&&u.extensions){const D=u==null?void 0:u.extensions[C];if(D!=null&&D.guid&&D.guid===O.guid){y=!0;break}}L++}if(y){const u=await j.getDependency("mesh",L),D=O;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,L,u,x),u.isMesh===!0){const T=u.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,D.density),m(T)}else{const T=new Array;for(let B=0;B<u.children.length;B++){const G=u.children[B];if(G instanceof g.Mesh){const N=G.geometry;v.assignLODInformation(i.url,N,o,t,B,D.density),T.push(N)}}return m(T)}}}return m(null)});return this.previouslyLoaded.set(x,w),await w}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+f);const _=await new g.TextureLoader().loadAsync(f);return _?(_.guid=s.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=e.colorSpace,r&&console.log(s,_)):M&&console.warn("failed loading",f),_}}else M&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new Se(e,r,i,o,s);t.userData.LODS=n,t.userData.LOD=i}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){return t=t.clone(),M&&console.warn(`Copying texture settings
|
|
4
4
|
`,e.uuid,`
|
|
5
|
-
`,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,s,o)=>{if(w&&console.log("> Progressive: register texture",s,t.name,t.uuid,t,o),!t){w&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const i=o.guid;v.assignLODInformation(e,t,i,r,s,void 0),v.lodInfos.set(i,o),v.lowresCache.set(i,t)}),c(S,"registerMesh",(e,t,r,s,o,i)=>{var h;w&&console.log("> Progressive: register mesh",o,r.name,i,r.uuid,r);const n=r.geometry;if(!n){w&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,s,o,i.density),v.lodInfos.set(t,i);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),s>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,i)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,s,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,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,s){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const i=t._frame,n=e++;t.onBeforeRender(r,s,n,i),t._originalRender.call(this,r,s),t.onAfterRender(r,s,n,i)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,s){}onAfterRender(e,t,r,s){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),i=o.opaque;let n=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&s%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of i){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,s)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,s)}}}updateLODs(e,t,r,s,o){var a,h;r.userData||(r.userData={});let i=r.userData.LOD_state;if(i||(i=new Ae,r.userData.LOD_state=i),i.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,i,s,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);i.lastLodLevel_Mesh=E.mesh_lod,i.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let s=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(s=!0),s&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(s=>(s&&e.userData.LOD==t&&r!=e.geometry,s))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,s=e.max,o=(r.x+s.x)*.5,i=(r.y+s.y)*.5;return this._tempPtInside.set(o,i,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,s,o){var M;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((M=this.cameraFrustrum)!=null&&M.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const x=t.geometry.boundingBox;if(x&&e.isPerspectiveCamera){const _=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&_.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,D=L.y,T=y.x,B=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,D=(D-X)*G+X,T=(T-K)*G+K,B=(B-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=D<0&&B>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const O=this._tempBox.getSize(this._tempBoxSize);O.multiplyScalar(.5),screen.availHeight>0&&O.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),O.x*=_.aspect;const k=e.matrixWorldInverse,m=this._tempBox2;m.copy(x),m.applyMatrix4(t.matrixWorld),m.applyMatrix4(k);const A=m.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(O.x,O.y)!=0&&F!=0&&(O.z=A.z/Math.max(A.x,A.y)*Math.max(O.x,O.y)),r.lastScreenCoverage=Math.max(O.x,O.y,O.z),r.lastScreenspaceVolume.copy(O),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,D=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,D.copy(this._tempBox.max),D.y=y.y,T.copy(this._tempBox.max);const B=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=B,y.applyMatrix4(L),u.applyMatrix4(L),D.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,D,255),b.debugDrawLine(u,T,255),b.debugDrawLine(D,T,255)}let R=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<s){R=L;break}}R<n&&(n=R)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const _=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${_.max_height}px) - ${t.name}`)}}else{const _=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*_;for(let m=p.lods.length-1;m>=0;m--){const A=p.lods[m];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=m,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const s=Object.getOwnPropertySymbols(r),o=s.find(n=>n.toString()=="Symbol(renderer)"),i=s.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&i!=null&&(t=l[i])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const s=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];s&&e.render(t,s)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,s){this.tryParseMeshLOD(t,s),this.tryParseTextureLOD(t,s)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),s=this.getUrl();if(s&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],M=n[x];if((M==null?void 0:M.isTexture)===!0){const _=(d=(h=M.userData)==null?void 0:h.associations)==null?void 0:d.textures,O=r.parser.json.textures[_];if(!O){console.warn("Texture data not found for texture index "+_);continue}if((p=O==null?void 0:O.extensions)!=null&&p[C]){const k=O.extensions[C];k&&s&&S.registerTexture(s,M,k.lods.length,_,k)}}}};const i=t.material;if(Array.isArray(i))for(const n of i)o(n);else o(i)}}tryParseMeshLOD(e,t){var o,i;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const s=(i=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:i[C];if(s&&r){const n=t.uuid;S.registerMesh(r,n,t,0,s.lods.length,s)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const s=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&s.enable(),s}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
|
|
5
|
+
`,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=v;c(S,"registerTexture",(e,t,r,i,o)=>{if(M&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){M&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[te]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),c(S,"registerMesh",(e,t,r,i,o,s)=>{var h;M&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){M&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!Q(r)&&ue(r,n);for(const d of I)(h=d.onRegisteredNewMesh)==null||h.call(d,r,s)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class Se{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Te=J("noprogressive"),le=Symbol("Needle:LODSManager"),E={mesh_lod:-1,texture_lod:-1},b=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new g.Matrix4);c(this,"cameraFrustrum",new g.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new g.Sphere);c(this,"_tempBox",new g.Box3);c(this,"_tempBox2",new g.Box3);c(this,"tempMatrix",new g.Matrix4);c(this,"_tempWorldPosition",new g.Vector3);c(this,"_tempBoxSize",new g.Vector3);c(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[le]?e[le]:new b(e)}get plugins(){return I}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;oe(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,h;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const d=s[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Te||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((h=f.geometry)==null?void 0:h.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){z&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}const p=o.transparent;for(const f of p){const x=f.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,d,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r.userData.LOD_state;if(s||(s=new Ae,r.userData.LOD_state=s),s.frames++<2)return;for(const d of I)(a=d.onBeforeUpdateLOD)==null||a.call(d,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const d=r["DEBUG:LOD"];d!=null&&(n=d),this.loadProgressiveTextures(r.material,n)}for(const d of I)(h=d.onAfterUpdatedLOD)==null||h.call(d,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const o of e)this.loadProgressiveTextures(o,t);return}const r=e;let i=!1;(r.NEEDLE_LOD==null||t<r.NEEDLE_LOD)&&(i=!0),i&&(r.NEEDLE_LOD=t,S.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var _;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=S.getMeshLODInformation(t.geometry),h=a==null?void 0:a.lods,d=h&&h.length>0,p=S.getMaterialMinMaxLODsCount(t.material),f=(p==null?void 0:p.min_count)!=1/0&&p.min_count>0&&p.max_count>0;if(!d&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(d||(n=0),!((_=this.cameraFrustrum)!=null&&_.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const x=t.geometry.boundingBox;if(x&&e.isPerspectiveCamera){const O=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(x),this._tempBox.applyMatrix4(t.matrixWorld),b.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&O.fov>70){const L=this._tempBox.min,y=this._tempBox.max;let u=L.x,D=L.y,T=y.x,B=y.y;const G=2,N=1.5,K=(L.x+y.x)*.5,X=(L.y+y.y)*.5;u=(u-K)*G+K,D=(D-X)*G+X,T=(T-K)*G+K,B=(B-X)*G+X;const de=u<0&&T>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),he=D<0&&B>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),ee=Math.max(de,he);r.lastCentrality=(N-ee)*(N-ee)*(N-ee)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&w.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),w.x*=O.aspect;const k=e.matrixWorldInverse,m=this._tempBox2;m.copy(x),m.applyMatrix4(t.matrixWorld),m.applyMatrix4(k);const A=m.getSize(this._tempBox2Size),F=Math.max(A.x,A.y);if(Math.max(w.x,w.y)!=0&&F!=0&&(w.z=A.z/Math.max(A.x,A.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,z&&b.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const y=b.corner0,u=b.corner1,D=b.corner2,T=b.corner3;y.copy(this._tempBox.min),u.copy(this._tempBox.max),u.x=y.x,D.copy(this._tempBox.max),D.y=y.y,T.copy(this._tempBox.max);const B=(y.z+T.z)*.5;y.z=u.z=D.z=T.z=B,y.applyMatrix4(L),u.applyMatrix4(L),D.applyMatrix4(L),T.applyMatrix4(L),b.debugDrawLine(y,u,255),b.debugDrawLine(y,D,255),b.debugDrawLine(u,T,255),b.debugDrawLine(D,T,255)}let R=999;if(h&&r.lastScreenCoverage>0){for(let L=0;L<h.length;L++)if(h[L].density/r.lastScreenCoverage<i){R=L;break}}R<n&&(n=R)}if(o.mesh_lod=n,f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=p.max_count-1,z){const O=p.lods[p.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${O.max_height}px) - ${t.name}`)}}else{const O=r.lastScreenCoverage*1.5,k=this.renderer.domElement.clientHeight/window.devicePixelRatio*O;for(let m=p.lods.length-1;m>=0;m--){const A=p.lods[m];if(!(Oe()&&A.max_height>4096)&&A.max_height>k){o.texture_lod=m,o.texture_lod<r.lastLodLevel_Texture&&z&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${A.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${k.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let P=b;c(P,"debugDrawLine"),c(P,"corner0",new g.Vector3),c(P,"corner1",new g.Vector3),c(P,"corner2",new g.Vector3),c(P,"corner3",new g.Vector3),c(P,"_tempPtInside",new g.Vector3);class Ae{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new g.Vector3);c(this,"lastCentrality",0)}}const ce=Symbol("NEEDLE_mesh_lod"),Y=Symbol("NEEDLE_texture_lod");function fe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=P.get(e);if(P.addPlugin(new be(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class be{constructor(e){c(this,"modelviewer");c(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[Y]==!0)return;t[Y]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,d,p;if(n[Y]==!0)return;n[Y]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let f=0;f<a.length;f++){const x=a[f],_=n[x];if((_==null?void 0:_.isTexture)===!0){const O=(d=(h=_.userData)==null?void 0:h.associations)==null?void 0:d.textures,w=r.parser.json.textures[O];if(!w){console.warn("Texture data not found for texture index "+O);continue}if((p=w==null?void 0:w.extensions)!=null&&p[C]){const k=w.extensions[C];k&&i&&S.registerTexture(i,_,k.lods.length,O,k)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[ce]==!0)return;t[ce]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}function Pe(l,e,t,r){oe(e),ne(t),t.register(o=>new S(o,l));const i=P.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{fe(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=C;exports.LODsManager=P;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ne;exports.createLoaders=oe;exports.getRaycastMesh=Q;exports.patchModelViewer=fe;exports.setDracoDecoderLocation=De;exports.setKTX2TranscoderLocation=Me;exports.setRaycastMesh=ue;exports.useNeedleProgressive=Pe;exports.useRaycastMeshes=we;
|
package/lib/extension.js
CHANGED
|
@@ -418,6 +418,11 @@ export class NEEDLE_progressive {
|
|
|
418
418
|
if (textureInfo?.extensions) {
|
|
419
419
|
const ext = textureInfo?.extensions[EXTENSION_NAME];
|
|
420
420
|
if (ext) {
|
|
421
|
+
if (!ext.lods) {
|
|
422
|
+
if (debug)
|
|
423
|
+
console.warn("Texture has no LODs", ext);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
421
426
|
let found = false;
|
|
422
427
|
for (const key of this.parser.associations.keys()) {
|
|
423
428
|
if (key.isTexture === true) {
|
package/lib/lods_manager.js
CHANGED
|
@@ -352,13 +352,6 @@ export class LODsManager {
|
|
|
352
352
|
mesh_level = 0;
|
|
353
353
|
}
|
|
354
354
|
if (!this.cameraFrustrum?.intersectsObject(mesh)) {
|
|
355
|
-
// console.log("Mesh not visible");
|
|
356
|
-
// if (debugProgressiveLoading && mesh.geometry.boundingSphere) {
|
|
357
|
-
// const bounds = mesh.geometry.boundingSphere;
|
|
358
|
-
// this._sphere.copy(bounds);
|
|
359
|
-
// this._sphere.applyMatrix4(mesh.matrixWorld);
|
|
360
|
-
// Gizmos.DrawWireSphere(this._sphere.center, this._sphere.radius * 1.01, 0xff5555, .5);
|
|
361
|
-
// }
|
|
362
355
|
// the object is not visible by the camera
|
|
363
356
|
result.mesh_lod = 99;
|
|
364
357
|
result.texture_lod = 99;
|
package/package.json
CHANGED