@needle-tools/gltf-progressive 1.0.0-alpha.9 → 1.1.0-alpha.1
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 +39 -0
- package/README.md +92 -0
- package/examples/modelviewer.html +27 -0
- package/examples/react-three-fiber/.prettierrc +10 -0
- package/examples/react-three-fiber/favicon.png +0 -0
- package/examples/react-three-fiber/index.html +24 -0
- package/examples/react-three-fiber/package-lock.json +4023 -0
- package/examples/react-three-fiber/package.json +34 -0
- package/examples/react-three-fiber/tsconfig.json +22 -0
- package/examples/react-three-fiber/vite.config.js +39 -0
- package/examples/threejs/index.html +51 -0
- package/examples/threejs/main.js +76 -0
- package/gltf-progressive.js +462 -316
- package/gltf-progressive.min.js +5 -3
- package/gltf-progressive.umd.cjs +5 -3
- package/lib/extension.d.ts +8 -2
- package/lib/extension.js +102 -11
- package/lib/index.d.ts +5 -4
- package/lib/index.js +6 -4
- package/lib/loaders.d.ts +10 -0
- package/lib/loaders.js +21 -2
- package/lib/lods_manager.d.ts +50 -3
- package/lib/lods_manager.js +354 -219
- package/lib/plugins/index.d.ts +1 -1
- package/lib/plugins/index.js +0 -1
- package/lib/plugins/modelviewer.js +7 -3
- package/lib/plugins/plugin.d.ts +4 -5
- package/lib/plugins/plugin.js +0 -6
- package/lib/utils.d.ts +13 -0
- package/lib/utils.js +24 -0
- package/package.json +1 -1
package/gltf-progressive.js
CHANGED
|
@@ -1,74 +1,86 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
var ge = Object.defineProperty;
|
|
2
|
+
var pe = (a, e, t) => e in a ? ge(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
|
|
3
|
+
var f = (a, e, t) => (pe(a, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import { MeshoptDecoder as ye } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
5
|
+
import { DRACOLoader as me } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
6
|
+
import { KTX2Loader as Le } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
7
|
+
import { BufferGeometry as Y, Mesh as V, Material as xe, Texture as N, TextureLoader as De, Matrix4 as ne, Frustum as Me, Sphere as Oe, Box3 as oe, Vector3 as k } from "three";
|
|
8
|
+
import { GLTFLoader as we } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
9
|
+
let H = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", se = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
|
|
10
|
+
fetch(H + "draco_decoder.js", { method: "head" }).catch((a) => {
|
|
11
|
+
H = "./include/draco/", se = "./include/ktx2/";
|
|
12
|
+
});
|
|
13
|
+
function Ue(a) {
|
|
14
|
+
H = a;
|
|
15
|
+
}
|
|
16
|
+
function Ne(a) {
|
|
17
|
+
se = a;
|
|
13
18
|
}
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
let z, te, W;
|
|
20
|
+
function fe(a) {
|
|
21
|
+
z || (z = new me(), z.setDecoderPath(H), z.setDecoderConfig({ type: "js" })), W || (W = new Le(), W.setTranscoderPath(se)), te || (te = ye), a ? W.detectSupport(a) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
|
|
16
22
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
23
|
+
function ue(a) {
|
|
24
|
+
a.dracoLoader || a.setDRACOLoader(z), a.ktx2Loader || a.setKTX2Loader(W), a.meshoptDecoder || a.setMeshoptDecoder(te);
|
|
25
|
+
}
|
|
26
|
+
function ie(a) {
|
|
27
|
+
const t = new URL(window.location.href).searchParams.get(a);
|
|
19
28
|
return t == null || t === "0" || t === "false" ? !1 : t === "" ? !0 : t;
|
|
20
29
|
}
|
|
21
|
-
function
|
|
22
|
-
if (e === void 0 || e.startsWith("./") || e.startsWith("http") ||
|
|
30
|
+
function ve(a, e) {
|
|
31
|
+
if (e === void 0 || e.startsWith("./") || e.startsWith("http") || a === void 0)
|
|
23
32
|
return e;
|
|
24
|
-
const t =
|
|
33
|
+
const t = a.lastIndexOf("/");
|
|
25
34
|
if (t >= 0) {
|
|
26
|
-
const r =
|
|
35
|
+
const r = a.substring(0, t + 1);
|
|
27
36
|
for (; r.endsWith("/") && e.startsWith("/"); )
|
|
28
37
|
e = e.substring(1);
|
|
29
38
|
return r + e;
|
|
30
39
|
}
|
|
31
40
|
return e;
|
|
32
41
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
function Se(a) {
|
|
43
|
+
var e;
|
|
44
|
+
return ((e = a.userData) == null ? void 0 : e["needle:raycast-mesh"]) instanceof Y ? a.userData["needle:raycast-mesh"] : null;
|
|
45
|
+
}
|
|
46
|
+
function _e(a, e) {
|
|
47
|
+
(a.type === "Mesh" || a.type === "SkinnedMesh") && (a.userData || (a.userData = {}), a.userData["needle:raycast-mesh"] = e);
|
|
36
48
|
}
|
|
37
|
-
const R = "NEEDLE_progressive",
|
|
38
|
-
if (
|
|
39
|
-
let
|
|
40
|
-
e += 1, console.log("Toggle LOD level", e,
|
|
49
|
+
const B = new Array(), R = "NEEDLE_progressive", w = ie("debugprogressive"), j = Symbol("needle-progressive-texture"), $ = /* @__PURE__ */ new Map(), re = /* @__PURE__ */ new Set();
|
|
50
|
+
if (w) {
|
|
51
|
+
let a = function() {
|
|
52
|
+
e += 1, console.log("Toggle LOD level", e, $), $.forEach((i, n) => {
|
|
41
53
|
for (const s of i.keys) {
|
|
42
54
|
const o = n[s];
|
|
43
55
|
if (o.isBufferGeometry === !0) {
|
|
44
|
-
const
|
|
45
|
-
n["DEBUG:LOD"] = e,
|
|
56
|
+
const l = S.getMeshLODInformation(o), d = l ? Math.min(e, l.lods.length) : 0;
|
|
57
|
+
n["DEBUG:LOD"] = e, S.assignMeshLOD(n, d), l && (t = Math.max(t, l.lods.length - 1));
|
|
46
58
|
} else if (n.isMaterial === !0) {
|
|
47
|
-
n["DEBUG:LOD"] = e,
|
|
59
|
+
n["DEBUG:LOD"] = e, S.assignTextureLOD(n, e);
|
|
48
60
|
break;
|
|
49
61
|
}
|
|
50
62
|
}
|
|
51
63
|
}), e >= t && (e = -1);
|
|
52
64
|
}, e = -1, t = 2, r = !1;
|
|
53
65
|
window.addEventListener("keyup", (i) => {
|
|
54
|
-
i.key === "p" &&
|
|
66
|
+
i.key === "p" && a(), i.key === "w" && (r = !r, re && re.forEach((n) => {
|
|
55
67
|
n.name != "BackgroundCubeMaterial" && "wireframe" in n && (n.wireframe = r);
|
|
56
68
|
}));
|
|
57
69
|
});
|
|
58
70
|
}
|
|
59
|
-
function
|
|
71
|
+
function ae(a, e, t) {
|
|
60
72
|
var i;
|
|
61
|
-
if (!
|
|
73
|
+
if (!w)
|
|
62
74
|
return;
|
|
63
|
-
|
|
64
|
-
const r =
|
|
75
|
+
$.has(a) || $.set(a, { keys: [], sourceId: t });
|
|
76
|
+
const r = $.get(a);
|
|
65
77
|
((i = r == null ? void 0 : r.keys) == null ? void 0 : i.includes(e)) == !1 && r.keys.push(e);
|
|
66
78
|
}
|
|
67
|
-
const
|
|
79
|
+
const v = class {
|
|
68
80
|
constructor(e, t) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
f(this, "parser");
|
|
82
|
+
f(this, "url");
|
|
83
|
+
w && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
|
|
72
84
|
}
|
|
73
85
|
/** The name of the extension */
|
|
74
86
|
get name() {
|
|
@@ -78,6 +90,38 @@ const M = class {
|
|
|
78
90
|
const t = this.getAssignedLODInformation(e);
|
|
79
91
|
return t != null && t.key ? this.lodInfos.get(t.key) : null;
|
|
80
92
|
}
|
|
93
|
+
static getMaterialMinMaxLODsCount(e, t = { min: 1 / 0, max: -1 }) {
|
|
94
|
+
if (Array.isArray(e)) {
|
|
95
|
+
for (const n of e)
|
|
96
|
+
this.getMaterialMinMaxLODsCount(n, t);
|
|
97
|
+
return t;
|
|
98
|
+
}
|
|
99
|
+
let r = t.min, i = t.max;
|
|
100
|
+
if (e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
|
|
101
|
+
const n = e;
|
|
102
|
+
for (const s of Object.keys(n.uniforms)) {
|
|
103
|
+
const o = n.uniforms[s].value;
|
|
104
|
+
if ((o == null ? void 0 : o.isTexture) === !0) {
|
|
105
|
+
const l = this.getAssignedLODInformation(o);
|
|
106
|
+
if (l) {
|
|
107
|
+
const d = this.lodInfos.get(l.key);
|
|
108
|
+
d && d.lods && (r = Math.min(r, d.lods.length), i = Math.max(i, d.lods.length));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} else if (e.isMaterial)
|
|
113
|
+
for (const n of Object.keys(e)) {
|
|
114
|
+
const s = e[n];
|
|
115
|
+
if ((s == null ? void 0 : s.isTexture) === !0) {
|
|
116
|
+
const o = this.getAssignedLODInformation(s);
|
|
117
|
+
if (o) {
|
|
118
|
+
const l = this.lodInfos.get(o.key);
|
|
119
|
+
l && l.lods && (r = Math.min(r, l.lods.length), i = Math.max(i, l.lods.length));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return t.min = r, t.max = i, t;
|
|
124
|
+
}
|
|
81
125
|
/** Check if a LOD level is available for a mesh or a texture
|
|
82
126
|
* @param obj the mesh or texture to check
|
|
83
127
|
* @param level the level of detail to check for (0 is the highest resolution). If undefined, the function checks if any LOD level is available
|
|
@@ -85,10 +129,16 @@ const M = class {
|
|
|
85
129
|
*/
|
|
86
130
|
static hasLODLevelAvailable(e, t) {
|
|
87
131
|
var n;
|
|
132
|
+
if (Array.isArray(e)) {
|
|
133
|
+
for (const s of e)
|
|
134
|
+
if (this.hasLODLevelAvailable(s, t))
|
|
135
|
+
return !0;
|
|
136
|
+
return !1;
|
|
137
|
+
}
|
|
88
138
|
if (e.isMaterial === !0) {
|
|
89
139
|
for (const s of Object.keys(e)) {
|
|
90
140
|
const o = e[s];
|
|
91
|
-
if (o.isTexture && this.hasLODLevelAvailable(o, t))
|
|
141
|
+
if (o && o.isTexture && this.hasLODLevelAvailable(o, t))
|
|
92
142
|
return !0;
|
|
93
143
|
}
|
|
94
144
|
return !1;
|
|
@@ -125,24 +175,24 @@ const M = class {
|
|
|
125
175
|
var r;
|
|
126
176
|
if (!e)
|
|
127
177
|
return Promise.resolve(null);
|
|
128
|
-
if (e instanceof
|
|
178
|
+
if (e instanceof V || e.isMesh === !0) {
|
|
129
179
|
const i = e.geometry, n = this.getAssignedLODInformation(i);
|
|
130
180
|
if (!n)
|
|
131
181
|
return Promise.resolve(null);
|
|
132
|
-
for (const s of
|
|
182
|
+
for (const s of B)
|
|
133
183
|
(r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
|
|
134
|
-
return e["LOD:requested level"] = t,
|
|
184
|
+
return e["LOD:requested level"] = t, v.getOrLoadLOD(i, t).then((s) => {
|
|
135
185
|
if (e["LOD:requested level"] === t) {
|
|
136
186
|
if (delete e["LOD:requested level"], Array.isArray(s)) {
|
|
137
187
|
const o = n.index || 0;
|
|
138
188
|
s = s[o];
|
|
139
189
|
}
|
|
140
|
-
s && i != s && s instanceof
|
|
190
|
+
s && i != s && s instanceof Y && (e.geometry = s, w && ae(e, "geometry", n.url));
|
|
141
191
|
}
|
|
142
192
|
return s;
|
|
143
193
|
}).catch((s) => (console.error("Error loading mesh LOD", e, s), null));
|
|
144
194
|
} else
|
|
145
|
-
|
|
195
|
+
w && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
|
|
146
196
|
return Promise.resolve(null);
|
|
147
197
|
}
|
|
148
198
|
/** Load a different resolution of a texture (if available)
|
|
@@ -155,66 +205,71 @@ const M = class {
|
|
|
155
205
|
static assignTextureLOD(e, t = 0) {
|
|
156
206
|
if (!e)
|
|
157
207
|
return Promise.resolve(null);
|
|
158
|
-
if (e instanceof
|
|
208
|
+
if (e instanceof xe || e.isMaterial === !0) {
|
|
159
209
|
const r = e, i = [], n = new Array();
|
|
160
|
-
if (
|
|
210
|
+
if (w && re.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
|
|
161
211
|
const s = r;
|
|
162
212
|
for (const o of Object.keys(s.uniforms)) {
|
|
163
|
-
const
|
|
164
|
-
if ((
|
|
165
|
-
const
|
|
166
|
-
i.push(
|
|
213
|
+
const l = s.uniforms[o].value;
|
|
214
|
+
if ((l == null ? void 0 : l.isTexture) === !0) {
|
|
215
|
+
const d = this.assignTextureLODForSlot(l, t, r, o);
|
|
216
|
+
i.push(d), n.push(o);
|
|
167
217
|
}
|
|
168
218
|
}
|
|
169
219
|
} else
|
|
170
220
|
for (const s of Object.keys(r)) {
|
|
171
221
|
const o = r[s];
|
|
172
222
|
if ((o == null ? void 0 : o.isTexture) === !0) {
|
|
173
|
-
const
|
|
174
|
-
i.push(
|
|
223
|
+
const l = this.assignTextureLODForSlot(o, t, r, s);
|
|
224
|
+
i.push(l), n.push(s);
|
|
175
225
|
}
|
|
176
226
|
}
|
|
177
227
|
return Promise.all(i).then((s) => {
|
|
178
228
|
const o = new Array();
|
|
179
|
-
for (let
|
|
180
|
-
const
|
|
181
|
-
|
|
229
|
+
for (let l = 0; l < s.length; l++) {
|
|
230
|
+
const d = s[l], h = n[l];
|
|
231
|
+
d && d.isTexture === !0 ? o.push({ material: r, slot: h, texture: d, level: t }) : o.push({ material: r, slot: h, texture: null, level: t });
|
|
182
232
|
}
|
|
183
233
|
return o;
|
|
184
234
|
});
|
|
185
235
|
}
|
|
186
|
-
if (e instanceof
|
|
236
|
+
if (e instanceof N || e.isTexture === !0) {
|
|
187
237
|
const r = e;
|
|
188
238
|
return this.assignTextureLODForSlot(r, t, null, null);
|
|
189
239
|
}
|
|
190
240
|
return Promise.resolve(null);
|
|
191
241
|
}
|
|
192
242
|
static assignTextureLODForSlot(e, t, r, i) {
|
|
193
|
-
|
|
194
|
-
|
|
243
|
+
if ((e == null ? void 0 : e.isTexture) !== !0)
|
|
244
|
+
return Promise.resolve(null);
|
|
245
|
+
if (i === "glyphMap")
|
|
246
|
+
return Promise.resolve(e);
|
|
247
|
+
const n = "LOD:requested level:" + i;
|
|
248
|
+
return r && (r[n] = t), v.getOrLoadLOD(e, t).then((s) => {
|
|
249
|
+
if (r && r[n] != t || Array.isArray(s))
|
|
195
250
|
return null;
|
|
196
|
-
if ((
|
|
197
|
-
if (
|
|
198
|
-
const
|
|
199
|
-
|
|
251
|
+
if ((s == null ? void 0 : s.isTexture) === !0) {
|
|
252
|
+
if (s != e && (r && i && (r[i] = s), w && i && r)) {
|
|
253
|
+
const o = this.getAssignedLODInformation(e);
|
|
254
|
+
o && ae(r, i, o.url);
|
|
200
255
|
}
|
|
201
|
-
return
|
|
256
|
+
return s;
|
|
202
257
|
} else
|
|
203
|
-
|
|
258
|
+
w == "verbose" && console.warn("No LOD found for", e, t);
|
|
204
259
|
return null;
|
|
205
|
-
}).catch((
|
|
260
|
+
}).catch((s) => (console.error("Error loading LOD", e, s), null));
|
|
206
261
|
}
|
|
207
262
|
afterRoot(e) {
|
|
208
263
|
var t, r;
|
|
209
|
-
return
|
|
264
|
+
return w && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
|
|
210
265
|
if (i != null && i.extensions) {
|
|
211
266
|
const s = i == null ? void 0 : i.extensions[R];
|
|
212
267
|
if (s) {
|
|
213
268
|
let o = !1;
|
|
214
|
-
for (const
|
|
215
|
-
|
|
216
|
-
o || this.parser.getDependency("texture", n).then((
|
|
217
|
-
|
|
269
|
+
for (const l of this.parser.associations.keys())
|
|
270
|
+
l.isTexture === !0 && this.parser.associations.get(l).textures === n && (o = !0, v.registerTexture(this.url, l, n, s));
|
|
271
|
+
o || this.parser.getDependency("texture", n).then((l) => {
|
|
272
|
+
l && v.registerTexture(this.url, l, n, s);
|
|
218
273
|
});
|
|
219
274
|
}
|
|
220
275
|
}
|
|
@@ -224,195 +279,205 @@ const M = class {
|
|
|
224
279
|
if (s && s.lods) {
|
|
225
280
|
for (const o of this.parser.associations.keys())
|
|
226
281
|
if (o.isMesh) {
|
|
227
|
-
const
|
|
228
|
-
|
|
282
|
+
const l = this.parser.associations.get(o);
|
|
283
|
+
l.meshes === n && v.registerMesh(this.url, s.guid, o, s.lods.length, l.primitives, s);
|
|
229
284
|
}
|
|
230
285
|
}
|
|
231
286
|
}
|
|
232
287
|
}), null;
|
|
233
288
|
}
|
|
234
289
|
static async getOrLoadLOD(e, t) {
|
|
235
|
-
var o,
|
|
236
|
-
const r =
|
|
290
|
+
var o, l, d, h;
|
|
291
|
+
const r = w == "verbose", i = e.userData.LODS;
|
|
237
292
|
if (!i)
|
|
238
293
|
return null;
|
|
239
294
|
const n = i == null ? void 0 : i.key;
|
|
240
295
|
let s;
|
|
241
296
|
if (e.isTexture === !0) {
|
|
242
|
-
const
|
|
243
|
-
|
|
297
|
+
const m = e;
|
|
298
|
+
m.source && m.source[j] && (s = m.source[j]);
|
|
244
299
|
}
|
|
245
|
-
if (s || (s =
|
|
300
|
+
if (s || (s = v.lodInfos.get(n)), s) {
|
|
246
301
|
if (t > 0) {
|
|
247
|
-
let
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
302
|
+
let y = !1;
|
|
303
|
+
const x = Array.isArray(s.lods);
|
|
304
|
+
if (x && t >= s.lods.length ? y = !0 : x || (y = !0), y)
|
|
250
305
|
return this.lowresCache.get(n);
|
|
251
306
|
}
|
|
252
|
-
const
|
|
253
|
-
if (!
|
|
254
|
-
return
|
|
255
|
-
const
|
|
256
|
-
if (
|
|
307
|
+
const m = Array.isArray(s.lods) ? (o = s.lods[t]) == null ? void 0 : o.path : s.lods;
|
|
308
|
+
if (!m)
|
|
309
|
+
return w && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
|
|
310
|
+
const u = ve(i.url, m);
|
|
311
|
+
if (u.endsWith(".glb") || u.endsWith(".gltf")) {
|
|
257
312
|
if (!s.guid)
|
|
258
313
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
r && console.log(`LOD ${t} was already loading/loaded: ${
|
|
262
|
-
let
|
|
263
|
-
`,
|
|
264
|
-
if (
|
|
265
|
-
return
|
|
314
|
+
const y = u + "_" + s.guid, x = this.previouslyLoaded.get(y);
|
|
315
|
+
if (x !== void 0) {
|
|
316
|
+
r && console.log(`LOD ${t} was already loading/loaded: ${y}`);
|
|
317
|
+
let O = await x.catch((F) => (console.error(`Error loading LOD ${t} from ${u}
|
|
318
|
+
`, F), null)), P = !1;
|
|
319
|
+
if (O == null || (O instanceof N && e instanceof N ? (l = O.image) != null && l.data || (d = O.source) != null && d.data ? O = this.copySettings(e, O) : (P = !0, this.previouslyLoaded.delete(y)) : O instanceof Y && e instanceof Y && ((h = O.attributes.position) != null && h.array || (P = !0, this.previouslyLoaded.delete(y)))), !P)
|
|
320
|
+
return O;
|
|
266
321
|
}
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
let
|
|
271
|
-
if (
|
|
272
|
-
const
|
|
273
|
-
|
|
322
|
+
const M = s, D = new Promise(async (O, P) => {
|
|
323
|
+
const F = new we();
|
|
324
|
+
ue(F), w && (await new Promise((g) => setTimeout(g, 1e3)), r && console.warn("Start loading (delayed) " + u, M.guid));
|
|
325
|
+
let J = u;
|
|
326
|
+
if (M && Array.isArray(M.lods)) {
|
|
327
|
+
const g = M.lods[t];
|
|
328
|
+
g.hash && (J += "?v=" + g.hash);
|
|
274
329
|
}
|
|
275
|
-
const
|
|
276
|
-
`,
|
|
277
|
-
if (!
|
|
330
|
+
const E = await F.loadAsync(J).catch((g) => (console.error(`Error loading LOD ${t} from ${u}
|
|
331
|
+
`, g), null));
|
|
332
|
+
if (!E)
|
|
278
333
|
return null;
|
|
279
|
-
const
|
|
280
|
-
r && console.log("Loading finished " +
|
|
281
|
-
let
|
|
282
|
-
if (
|
|
283
|
-
let
|
|
284
|
-
for (const
|
|
285
|
-
if (
|
|
286
|
-
const
|
|
287
|
-
if (
|
|
288
|
-
|
|
334
|
+
const Q = E.parser;
|
|
335
|
+
r && console.log("Loading finished " + u, M.guid);
|
|
336
|
+
let p = 0;
|
|
337
|
+
if (E.parser.json.textures) {
|
|
338
|
+
let g = !1;
|
|
339
|
+
for (const c of E.parser.json.textures) {
|
|
340
|
+
if (c != null && c.extensions) {
|
|
341
|
+
const L = c == null ? void 0 : c.extensions[R];
|
|
342
|
+
if (L != null && L.guid && L.guid === M.guid) {
|
|
343
|
+
g = !0;
|
|
289
344
|
break;
|
|
290
345
|
}
|
|
291
346
|
}
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
if (y) {
|
|
295
|
-
let g = await b.getDependency("texture", x);
|
|
296
|
-
return r && console.log('change "' + e.name + '" → "' + g.name + '"', c, x, g, f), e instanceof U && (g = this.copySettings(e, g)), g && (g.guid = L.guid), D(g);
|
|
347
|
+
p++;
|
|
297
348
|
}
|
|
349
|
+
if (g) {
|
|
350
|
+
let c = await Q.getDependency("texture", p);
|
|
351
|
+
return c && v.assignLODInformation(i.url, c, n, t, void 0, void 0), r && console.log('change "' + e.name + '" → "' + c.name + '"', u, p, c, y), e instanceof N && (c = this.copySettings(e, c)), c && (c.guid = M.guid), O(c);
|
|
352
|
+
} else
|
|
353
|
+
w && console.warn("Could not find texture with guid", M.guid);
|
|
298
354
|
}
|
|
299
|
-
if (
|
|
300
|
-
let
|
|
301
|
-
for (const
|
|
302
|
-
if (
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
|
|
355
|
+
if (p = 0, E.parser.json.meshes) {
|
|
356
|
+
let g = !1;
|
|
357
|
+
for (const c of E.parser.json.meshes) {
|
|
358
|
+
if (c != null && c.extensions) {
|
|
359
|
+
const L = c == null ? void 0 : c.extensions[R];
|
|
360
|
+
if (L != null && L.guid && L.guid === M.guid) {
|
|
361
|
+
g = !0;
|
|
306
362
|
break;
|
|
307
363
|
}
|
|
308
364
|
}
|
|
309
|
-
|
|
365
|
+
p++;
|
|
310
366
|
}
|
|
311
|
-
if (
|
|
312
|
-
const
|
|
313
|
-
if (r && console.log(`Loaded Mesh "${
|
|
314
|
-
const
|
|
315
|
-
return
|
|
367
|
+
if (g) {
|
|
368
|
+
const c = await Q.getDependency("mesh", p), L = M;
|
|
369
|
+
if (r && console.log(`Loaded Mesh "${c.name}"`, u, p, c, y), c.isMesh === !0) {
|
|
370
|
+
const _ = c.geometry;
|
|
371
|
+
return v.assignLODInformation(i.url, _, n, t, void 0, L.density), O(_);
|
|
316
372
|
} else {
|
|
317
|
-
const
|
|
318
|
-
for (let
|
|
319
|
-
const
|
|
320
|
-
if (
|
|
321
|
-
const
|
|
322
|
-
|
|
373
|
+
const _ = new Array();
|
|
374
|
+
for (let C = 0; C < c.children.length; C++) {
|
|
375
|
+
const I = c.children[C];
|
|
376
|
+
if (I instanceof V) {
|
|
377
|
+
const U = I.geometry;
|
|
378
|
+
v.assignLODInformation(i.url, U, n, t, C, L.density), _.push(U);
|
|
323
379
|
}
|
|
324
380
|
}
|
|
325
|
-
return
|
|
381
|
+
return O(_);
|
|
326
382
|
}
|
|
327
383
|
}
|
|
328
384
|
}
|
|
329
|
-
return
|
|
385
|
+
return O(null);
|
|
330
386
|
});
|
|
331
|
-
return this.previouslyLoaded.set(
|
|
332
|
-
} else if (e instanceof
|
|
333
|
-
r && console.log("Load texture from uri: " +
|
|
334
|
-
const
|
|
335
|
-
return
|
|
387
|
+
return this.previouslyLoaded.set(y, D), await D;
|
|
388
|
+
} else if (e instanceof N) {
|
|
389
|
+
r && console.log("Load texture from uri: " + u);
|
|
390
|
+
const x = await new De().loadAsync(u);
|
|
391
|
+
return x ? (x.guid = s.guid, x.flipY = !1, x.needsUpdate = !0, x.colorSpace = e.colorSpace, r && console.log(s, x)) : w && console.warn("failed loading", u), x;
|
|
336
392
|
}
|
|
337
393
|
} else
|
|
338
|
-
|
|
394
|
+
w && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
339
395
|
return null;
|
|
340
396
|
}
|
|
341
397
|
static assignLODInformation(e, t, r, i, n, s) {
|
|
342
398
|
if (!t)
|
|
343
399
|
return;
|
|
344
400
|
t.userData || (t.userData = {});
|
|
345
|
-
const o = new
|
|
401
|
+
const o = new Te(e, r, i, n, s);
|
|
346
402
|
t.userData.LODS = o, t.userData.LOD = i;
|
|
347
403
|
}
|
|
348
404
|
static getAssignedLODInformation(e) {
|
|
349
405
|
var t;
|
|
350
406
|
return ((t = e == null ? void 0 : e.userData) == null ? void 0 : t.LODS) || null;
|
|
351
407
|
}
|
|
408
|
+
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
352
409
|
static copySettings(e, t) {
|
|
353
|
-
|
|
354
|
-
|
|
410
|
+
return t = t.clone(), w && console.warn(`Copying texture settings
|
|
411
|
+
`, e.uuid, `
|
|
412
|
+
`, 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;
|
|
355
413
|
}
|
|
356
414
|
};
|
|
357
|
-
let
|
|
415
|
+
let S = v;
|
|
358
416
|
/**
|
|
359
417
|
* Register a texture with LOD information
|
|
360
418
|
*/
|
|
361
|
-
|
|
362
|
-
|
|
419
|
+
f(S, "registerTexture", (e, t, r, i) => {
|
|
420
|
+
w && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[j] = i);
|
|
363
421
|
const n = i.guid;
|
|
364
|
-
|
|
422
|
+
v.assignLODInformation(e, t, n, 0, 0, void 0), v.lodInfos.set(n, i), v.lowresCache.set(n, t);
|
|
365
423
|
}), /**
|
|
366
424
|
* Register a mesh with LOD information
|
|
367
425
|
*/
|
|
368
|
-
|
|
369
|
-
var
|
|
370
|
-
|
|
426
|
+
f(S, "registerMesh", (e, t, r, i, n, s) => {
|
|
427
|
+
var d;
|
|
428
|
+
w && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
|
|
371
429
|
const o = r.geometry;
|
|
372
|
-
o.userData || (o.userData = {}),
|
|
373
|
-
let
|
|
374
|
-
|
|
375
|
-
for (const
|
|
376
|
-
(
|
|
430
|
+
o.userData || (o.userData = {}), v.assignLODInformation(e, o, t, i, n, s.density), v.lodInfos.set(t, s);
|
|
431
|
+
let l = v.lowresCache.get(t);
|
|
432
|
+
l ? l.push(r.geometry) : l = [r.geometry], v.lowresCache.set(t, l), i > 0 && !Se(r) && _e(r, o);
|
|
433
|
+
for (const h of B)
|
|
434
|
+
(d = h.onRegisteredNewMesh) == null || d.call(h, r, s);
|
|
377
435
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
class
|
|
436
|
+
f(S, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
|
|
437
|
+
f(S, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
|
|
438
|
+
f(S, "lowresCache", /* @__PURE__ */ new Map());
|
|
439
|
+
class Te {
|
|
382
440
|
constructor(e, t, r, i, n) {
|
|
383
|
-
|
|
441
|
+
f(this, "url");
|
|
384
442
|
/** the key to lookup the LOD information */
|
|
385
|
-
|
|
386
|
-
|
|
443
|
+
f(this, "key");
|
|
444
|
+
f(this, "level");
|
|
387
445
|
/** For multi objects (e.g. a group of meshes) this is the index of the object */
|
|
388
|
-
|
|
446
|
+
f(this, "index");
|
|
389
447
|
/** the mesh density */
|
|
390
|
-
|
|
448
|
+
f(this, "density");
|
|
391
449
|
this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
|
|
392
450
|
}
|
|
393
451
|
}
|
|
394
|
-
const
|
|
452
|
+
const ee = ie("debugprogressive"), Ae = ie("noprogressive"), le = Symbol("Needle:LODSManager"), A = { mesh_lod: -1, texture_lod: -1 }, T = class {
|
|
453
|
+
// readonly plugins: NEEDLE_progressive_plugin[] = [];
|
|
395
454
|
constructor(e) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
455
|
+
f(this, "renderer");
|
|
456
|
+
f(this, "projectionScreenMatrix", new ne());
|
|
457
|
+
f(this, "cameraFrustrum", new Me());
|
|
458
|
+
/**
|
|
459
|
+
* The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
|
|
460
|
+
* @default 200_000
|
|
461
|
+
*/
|
|
462
|
+
f(this, "targetTriangleDensity", 2e5);
|
|
399
463
|
/**
|
|
400
464
|
* The update interval in frames. If set to 0, the LODs will be updated every frame. If set to 1, the LODs will be updated every second frame, etc.
|
|
401
465
|
*/
|
|
402
|
-
|
|
466
|
+
f(this, "updateInterval", 0);
|
|
403
467
|
/**
|
|
404
468
|
* If set to true, the LODsManager will not update the LODs.
|
|
405
469
|
*/
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
470
|
+
f(this, "pause", !1);
|
|
471
|
+
f(this, "_frame", 0);
|
|
472
|
+
f(this, "_originalRender");
|
|
409
473
|
// private testIfLODLevelsAreAvailable() {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
474
|
+
f(this, "_sphere", new Oe());
|
|
475
|
+
f(this, "_tempBox", new oe());
|
|
476
|
+
f(this, "_tempBox2", new oe());
|
|
477
|
+
f(this, "tempMatrix", new ne());
|
|
478
|
+
f(this, "_tempWorldPosition", new k());
|
|
479
|
+
f(this, "_tempBoxSize", new k());
|
|
480
|
+
f(this, "_tempBox2Size", new k());
|
|
416
481
|
this.renderer = e;
|
|
417
482
|
}
|
|
418
483
|
/** @internal */
|
|
@@ -420,6 +485,25 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
420
485
|
var t;
|
|
421
486
|
return (t = e.userData) == null ? void 0 : t.LOD_state;
|
|
422
487
|
}
|
|
488
|
+
static addPlugin(e) {
|
|
489
|
+
B.push(e);
|
|
490
|
+
}
|
|
491
|
+
static removePlugin(e) {
|
|
492
|
+
const t = B.indexOf(e);
|
|
493
|
+
t >= 0 && B.splice(t, 1);
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
|
|
497
|
+
* @param renderer The renderer to get the LODsManager for.
|
|
498
|
+
* @returns The LODsManager instance.
|
|
499
|
+
*/
|
|
500
|
+
static get(e) {
|
|
501
|
+
return e[le] ? e[le] : new T(e);
|
|
502
|
+
}
|
|
503
|
+
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
504
|
+
get plugins() {
|
|
505
|
+
return B;
|
|
506
|
+
}
|
|
423
507
|
/**
|
|
424
508
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
425
509
|
*/
|
|
@@ -429,10 +513,10 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
429
513
|
let e = 0;
|
|
430
514
|
this._originalRender = this.renderer.render;
|
|
431
515
|
const t = this;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const s =
|
|
435
|
-
t.onBeforeRender(
|
|
516
|
+
fe(this.renderer), this.renderer.render = function(r, i) {
|
|
517
|
+
t.renderer.getRenderTarget() == null && (e = 0, t._frame += 1);
|
|
518
|
+
const s = t._frame, o = e++;
|
|
519
|
+
t.onBeforeRender(r, i, o, s), t._originalRender.call(this, r, i), t.onAfterRender(r, i, o, s);
|
|
436
520
|
};
|
|
437
521
|
}
|
|
438
522
|
disable() {
|
|
@@ -441,46 +525,61 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
441
525
|
onBeforeRender(e, t, r, i) {
|
|
442
526
|
}
|
|
443
527
|
onAfterRender(e, t, r, i) {
|
|
444
|
-
var
|
|
445
|
-
if (
|
|
528
|
+
var l, d;
|
|
529
|
+
if (this.pause)
|
|
446
530
|
return;
|
|
447
|
-
this.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
continue;
|
|
453
|
-
}
|
|
454
|
-
const f = c.object;
|
|
455
|
-
(f instanceof q || f.isMesh) && this.updateLODs(e, t, f, n);
|
|
531
|
+
const n = this.renderer.renderLists.get(e, 0), s = n.opaque;
|
|
532
|
+
let o = !0;
|
|
533
|
+
if (s.length === 1) {
|
|
534
|
+
const h = s[0].material;
|
|
535
|
+
(h.name === "EffectMaterial" || h.name === "CopyShader") && (o = !1);
|
|
456
536
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
(
|
|
537
|
+
if (t.parent && t.parent.type === "CubeCamera" && (o = !1), o) {
|
|
538
|
+
if (Ae || this.updateInterval > 0 && i % this.updateInterval != 0)
|
|
539
|
+
return;
|
|
540
|
+
this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
|
|
541
|
+
const h = this.targetTriangleDensity;
|
|
542
|
+
for (const u of s) {
|
|
543
|
+
if (u.material && (((l = u.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((d = u.geometry) == null ? void 0 : d.type) === "BufferGeometry") && (u.material.name === "SphericalGaussianBlur" || u.material.name == "BackgroundCubeMaterial" || u.material.name === "CubemapFromEquirect" || u.material.name === "EquirectangularToCubeUV")) {
|
|
544
|
+
ee && (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", u, u.material.name, u.material.type)));
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
switch (u.material.type) {
|
|
548
|
+
case "LineBasicMaterial":
|
|
549
|
+
case "LineDashedMaterial":
|
|
550
|
+
case "PointsMaterial":
|
|
551
|
+
case "ShadowMaterial":
|
|
552
|
+
case "MeshDistanceMaterial":
|
|
553
|
+
case "MeshDepthMaterial":
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
const y = u.object;
|
|
557
|
+
(y instanceof V || y.isMesh) && this.updateLODs(e, t, y, h, i);
|
|
558
|
+
}
|
|
559
|
+
const m = n.transparent;
|
|
560
|
+
for (const u of m) {
|
|
561
|
+
const y = u.object;
|
|
562
|
+
(y instanceof V || y.isMesh) && this.updateLODs(e, t, y, h, i);
|
|
563
|
+
}
|
|
461
564
|
}
|
|
462
565
|
}
|
|
463
566
|
/** Update the LOD levels for the renderer. */
|
|
464
|
-
updateLODs(e, t, r, i) {
|
|
465
|
-
var
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
s = Math.round(
|
|
472
|
-
let o =
|
|
473
|
-
if (r.material) {
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
for (const c of r.material)
|
|
477
|
-
this.loadProgressiveTextures(c, o);
|
|
478
|
-
else
|
|
479
|
-
this.loadProgressiveTextures(r.material, o);
|
|
567
|
+
updateLODs(e, t, r, i, n) {
|
|
568
|
+
var l, d;
|
|
569
|
+
let s = r.userData.LOD_state;
|
|
570
|
+
if (s || (s = new Pe(), r.userData.LOD_state = s), s.frames++ < 2)
|
|
571
|
+
return;
|
|
572
|
+
for (const h of B)
|
|
573
|
+
(l = h.onBeforeUpdateLOD) == null || l.call(h, this.renderer, e, t, r);
|
|
574
|
+
this.calculateLodLevel(t, r, s, i, A), A.mesh_lod = Math.round(A.mesh_lod), A.texture_lod = Math.round(A.texture_lod), A.mesh_lod >= 0 && this.loadProgressiveMeshes(r, A.mesh_lod);
|
|
575
|
+
let o = A.texture_lod;
|
|
576
|
+
if (r.material && o >= 0) {
|
|
577
|
+
const h = r["DEBUG:LOD"];
|
|
578
|
+
h != null && (o = h), this.loadProgressiveTextures(r.material, o);
|
|
480
579
|
}
|
|
481
|
-
for (const
|
|
482
|
-
(
|
|
483
|
-
|
|
580
|
+
for (const h of B)
|
|
581
|
+
(d = h.onAfterUpdatedLOD) == null || d.call(h, this.renderer, e, t, r, A);
|
|
582
|
+
s.lastLodLevel_Mesh = A.mesh_lod, s.lasLodLevel_Texture = A.texture_lod;
|
|
484
583
|
}
|
|
485
584
|
/** Load progressive textures for the given material
|
|
486
585
|
* @param material the material to load the textures for
|
|
@@ -488,7 +587,16 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
488
587
|
* @returns Promise with true if the LOD was loaded, false if not
|
|
489
588
|
*/
|
|
490
589
|
loadProgressiveTextures(e, t) {
|
|
491
|
-
|
|
590
|
+
if (!e)
|
|
591
|
+
return;
|
|
592
|
+
if (Array.isArray(e)) {
|
|
593
|
+
for (const n of e)
|
|
594
|
+
this.loadProgressiveTextures(n, t);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const r = e;
|
|
598
|
+
let i = !1;
|
|
599
|
+
(r.NEEDLE_LOD == null || t < r.NEEDLE_LOD) && (i = !0), i && (r.NEEDLE_LOD = t, S.assignTextureLOD(e, t));
|
|
492
600
|
}
|
|
493
601
|
/** Load progressive meshes for the given mesh
|
|
494
602
|
* @param mesh the mesh to load the LOD for
|
|
@@ -502,91 +610,120 @@ const Y = Z("debugprogressive"), xe = Z("noprogressive"), T = class {
|
|
|
502
610
|
if (e.userData || (e.userData = {}), e.userData.LOD !== t) {
|
|
503
611
|
e.userData.LOD = t;
|
|
504
612
|
const r = e.geometry;
|
|
505
|
-
return
|
|
613
|
+
return S.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
|
|
506
614
|
}
|
|
507
615
|
return Promise.resolve(null);
|
|
508
616
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
const m = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
545
|
-
m.invert();
|
|
546
|
-
const p = T.corner0, b = T.corner1, x = T.corner2, y = T.corner3;
|
|
547
|
-
p.copy(this._tempBox.min), b.copy(this._tempBox.max), b.x = p.x, x.copy(this._tempBox.max), x.y = p.y, y.copy(this._tempBox.max);
|
|
548
|
-
const g = (p.z + y.z) * 0.5;
|
|
549
|
-
p.z = b.z = x.z = y.z = g, p.applyMatrix4(m), b.applyMatrix4(m), x.applyMatrix4(m), y.applyMatrix4(m), T.debugDrawLine(p, b, 255), T.debugDrawLine(p, x, 255), T.debugDrawLine(b, y, 255), T.debugDrawLine(x, y, 255);
|
|
550
|
-
}
|
|
551
|
-
let C = 999;
|
|
552
|
-
if (h && r.lastScreenCoverage > 0) {
|
|
553
|
-
for (let m = 0; m < h.length; m++)
|
|
554
|
-
if (h[m].density / r.lastScreenCoverage < i) {
|
|
555
|
-
C = m;
|
|
556
|
-
break;
|
|
557
|
-
}
|
|
617
|
+
static isInside(e, t) {
|
|
618
|
+
const r = e.min, i = e.max, n = (r.x + i.x) * 0.5, s = (r.y + i.y) * 0.5;
|
|
619
|
+
return this._tempPtInside.set(n, s, r.z).applyMatrix4(t).z < 0;
|
|
620
|
+
}
|
|
621
|
+
calculateLodLevel(e, t, r, i, n) {
|
|
622
|
+
var x;
|
|
623
|
+
if (!t) {
|
|
624
|
+
n.mesh_lod = -1, n.texture_lod = -1;
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (!e) {
|
|
628
|
+
n.mesh_lod = -1, n.texture_lod = -1;
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
let o = 10 + 1;
|
|
632
|
+
if (ee && t["DEBUG:LOD"] != null)
|
|
633
|
+
return t["DEBUG:LOD"];
|
|
634
|
+
const l = S.getMeshLODInformation(t.geometry), d = l == null ? void 0 : l.lods, h = d && d.length > 0, m = S.getMaterialMinMaxLODsCount(t.material), u = (m == null ? void 0 : m.min) != 1 / 0 && m.min > 0 && m.max > 0;
|
|
635
|
+
if (!h && !u) {
|
|
636
|
+
n.mesh_lod = 0, n.texture_lod = 0;
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (h || (o = 0), !((x = this.cameraFrustrum) != null && x.intersectsObject(t))) {
|
|
640
|
+
n.mesh_lod = 99, n.texture_lod = 99;
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const y = t.geometry.boundingBox;
|
|
644
|
+
if (y && e.isPerspectiveCamera) {
|
|
645
|
+
const M = e;
|
|
646
|
+
if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
|
|
647
|
+
this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
|
|
648
|
+
const p = e.getWorldPosition(this._tempWorldPosition);
|
|
649
|
+
if (this._sphere.containsPoint(p)) {
|
|
650
|
+
n.mesh_lod = 0, n.texture_lod = 0;
|
|
651
|
+
return;
|
|
558
652
|
}
|
|
559
|
-
C < s && (s = C);
|
|
560
653
|
}
|
|
654
|
+
if (this._tempBox.copy(y), this._tempBox.applyMatrix4(t.matrixWorld), T.isInside(this._tempBox, this.projectionScreenMatrix)) {
|
|
655
|
+
n.mesh_lod = 0, n.texture_lod = 0;
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && M.fov > 70) {
|
|
659
|
+
const p = this._tempBox.min, g = this._tempBox.max;
|
|
660
|
+
let c = p.x, L = p.y, _ = g.x, C = g.y;
|
|
661
|
+
const I = 2, U = 1.5, q = (p.x + g.x) * 0.5, K = (p.y + g.y) * 0.5;
|
|
662
|
+
c = (c - q) * I + q, L = (L - K) * I + K, _ = (_ - q) * I + q, C = (C - K) * I + K;
|
|
663
|
+
const de = c < 0 && _ > 0 ? 0 : Math.min(Math.abs(p.x), Math.abs(g.x)), he = L < 0 && C > 0 ? 0 : Math.min(Math.abs(p.y), Math.abs(g.y)), Z = Math.max(de, he);
|
|
664
|
+
r.lastCentrality = (U - Z) * (U - Z) * (U - Z);
|
|
665
|
+
} else
|
|
666
|
+
r.lastCentrality = 1;
|
|
667
|
+
const D = this._tempBox.getSize(this._tempBoxSize);
|
|
668
|
+
D.multiplyScalar(0.5), screen.availHeight > 0 && D.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), D.x *= M.aspect;
|
|
669
|
+
const G = e.matrixWorldInverse, O = this._tempBox2;
|
|
670
|
+
O.copy(y), O.applyMatrix4(t.matrixWorld), O.applyMatrix4(G);
|
|
671
|
+
const P = O.getSize(this._tempBox2Size), F = Math.max(P.x, P.y);
|
|
672
|
+
if (Math.max(D.x, D.y) != 0 && F != 0 && (D.z = P.z / Math.max(P.x, P.y) * Math.max(D.x, D.y)), r.lastScreenCoverage = Math.max(D.x, D.y, D.z), r.lastScreenspaceVolume.copy(D), r.lastScreenCoverage *= r.lastCentrality, ee && T.debugDrawLine) {
|
|
673
|
+
const p = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
674
|
+
p.invert();
|
|
675
|
+
const g = T.corner0, c = T.corner1, L = T.corner2, _ = T.corner3;
|
|
676
|
+
g.copy(this._tempBox.min), c.copy(this._tempBox.max), c.x = g.x, L.copy(this._tempBox.max), L.y = g.y, _.copy(this._tempBox.max);
|
|
677
|
+
const C = (g.z + _.z) * 0.5;
|
|
678
|
+
g.z = c.z = L.z = _.z = C, g.applyMatrix4(p), c.applyMatrix4(p), L.applyMatrix4(p), _.applyMatrix4(p), T.debugDrawLine(g, c, 255), T.debugDrawLine(g, L, 255), T.debugDrawLine(c, _, 255), T.debugDrawLine(L, _, 255);
|
|
679
|
+
}
|
|
680
|
+
let E = 999;
|
|
681
|
+
if (d && r.lastScreenCoverage > 0) {
|
|
682
|
+
for (let p = 0; p < d.length; p++)
|
|
683
|
+
if (d[p].density / r.lastScreenCoverage < i) {
|
|
684
|
+
E = p;
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
E < o && (o = E);
|
|
561
689
|
}
|
|
562
|
-
|
|
690
|
+
if (n.mesh_lod = o, m != null && m.min && m.min > 0 && m.max > 0) {
|
|
691
|
+
const M = Math.min(1, Math.max(0, r.lastScreenCoverage * 3));
|
|
692
|
+
n.texture_lod = be(m.max, 0, M);
|
|
693
|
+
} else
|
|
694
|
+
n.texture_lod = 0;
|
|
563
695
|
}
|
|
564
696
|
};
|
|
565
|
-
let
|
|
697
|
+
let b = T;
|
|
566
698
|
/** Assign a function to draw debug lines for the LODs. This function will be called with the start and end position of the line and the color of the line when the `debugprogressive` query parameter is set.
|
|
567
699
|
*/
|
|
568
|
-
|
|
569
|
-
|
|
700
|
+
f(b, "debugDrawLine"), f(b, "corner0", new k()), f(b, "corner1", new k()), f(b, "corner2", new k()), f(b, "corner3", new k()), f(b, "_tempPtInside", new k());
|
|
701
|
+
function be(a, e, t) {
|
|
702
|
+
return a + (e - a) * t;
|
|
703
|
+
}
|
|
704
|
+
class Pe {
|
|
570
705
|
constructor() {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
706
|
+
f(this, "frames", 0);
|
|
707
|
+
f(this, "lastLodLevel_Mesh", 0);
|
|
708
|
+
f(this, "lasLodLevel_Texture", 0);
|
|
709
|
+
f(this, "lastScreenCoverage", 0);
|
|
710
|
+
f(this, "lastScreenspaceVolume", new k());
|
|
711
|
+
f(this, "lastCentrality", 0);
|
|
575
712
|
}
|
|
576
713
|
}
|
|
577
|
-
const
|
|
578
|
-
function
|
|
579
|
-
if (!
|
|
714
|
+
const ce = Symbol("NEEDLE_mesh_lod"), X = Symbol("NEEDLE_texture_lod");
|
|
715
|
+
function Ee(a) {
|
|
716
|
+
if (!a)
|
|
580
717
|
return null;
|
|
581
718
|
let e = null, t = null;
|
|
582
|
-
for (let r =
|
|
719
|
+
for (let r = a; r != null; r = Object.getPrototypeOf(r)) {
|
|
583
720
|
const i = Object.getOwnPropertySymbols(r), n = i.find((o) => o.toString() == "Symbol(renderer)"), s = i.find((o) => o.toString() == "Symbol(scene)");
|
|
584
|
-
!e && n != null && (e =
|
|
721
|
+
!e && n != null && (e = a[n].threeRenderer), !t && s != null && (t = a[s]);
|
|
585
722
|
}
|
|
586
723
|
if (e) {
|
|
587
724
|
console.log("Adding Needle LODs to modelviewer");
|
|
588
|
-
const r =
|
|
589
|
-
if (
|
|
725
|
+
const r = b.get(e);
|
|
726
|
+
if (b.addPlugin(new Ce(a)), r.enable(), t) {
|
|
590
727
|
const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
|
|
591
728
|
i && e.render(t, i);
|
|
592
729
|
}
|
|
@@ -596,10 +733,10 @@ function Oe(l) {
|
|
|
596
733
|
}
|
|
597
734
|
return null;
|
|
598
735
|
}
|
|
599
|
-
class
|
|
736
|
+
class Ce {
|
|
600
737
|
constructor(e) {
|
|
601
|
-
|
|
602
|
-
|
|
738
|
+
f(this, "modelviewer");
|
|
739
|
+
f(this, "_didWarnAboutMissingUrl", !1);
|
|
603
740
|
this.modelviewer = e;
|
|
604
741
|
}
|
|
605
742
|
onBeforeUpdateLOD(e, t, r, i) {
|
|
@@ -613,24 +750,28 @@ class Me {
|
|
|
613
750
|
return e._currentGLTF;
|
|
614
751
|
}
|
|
615
752
|
tryParseTextureLOD(e, t) {
|
|
616
|
-
if (t[
|
|
753
|
+
if (t[X] == !0)
|
|
617
754
|
return;
|
|
618
|
-
t[
|
|
755
|
+
t[X] = !0;
|
|
619
756
|
const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
|
|
620
757
|
if (i && r && t.material) {
|
|
621
758
|
let n = function(o) {
|
|
622
|
-
var
|
|
623
|
-
if (o[
|
|
759
|
+
var d, h, m;
|
|
760
|
+
if (o[X] == !0)
|
|
624
761
|
return;
|
|
625
|
-
o[
|
|
626
|
-
const
|
|
627
|
-
for (let
|
|
628
|
-
const
|
|
629
|
-
if ((
|
|
630
|
-
const
|
|
631
|
-
if (
|
|
632
|
-
|
|
633
|
-
|
|
762
|
+
o[X] = !0, o.userData && (o.userData.LOD = -1);
|
|
763
|
+
const l = Object.keys(o);
|
|
764
|
+
for (let u = 0; u < l.length; u++) {
|
|
765
|
+
const y = l[u], x = o[y];
|
|
766
|
+
if ((x == null ? void 0 : x.isTexture) === !0) {
|
|
767
|
+
const M = (h = (d = x.userData) == null ? void 0 : d.associations) == null ? void 0 : h.textures, D = r.parser.json.textures[M];
|
|
768
|
+
if (!D) {
|
|
769
|
+
console.warn("Texture data not found for texture index " + M);
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
if ((m = D == null ? void 0 : D.extensions) != null && m[R]) {
|
|
773
|
+
const G = D.extensions[R];
|
|
774
|
+
G && i && S.registerTexture(i, x, G.lods.length, G);
|
|
634
775
|
}
|
|
635
776
|
}
|
|
636
777
|
}
|
|
@@ -645,32 +786,37 @@ class Me {
|
|
|
645
786
|
}
|
|
646
787
|
tryParseMeshLOD(e, t) {
|
|
647
788
|
var n, s;
|
|
648
|
-
if (t[
|
|
789
|
+
if (t[ce] == !0)
|
|
649
790
|
return;
|
|
650
|
-
t[
|
|
791
|
+
t[ce] = !0;
|
|
651
792
|
const r = this.getUrl();
|
|
652
793
|
if (!r)
|
|
653
794
|
return;
|
|
654
795
|
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
|
|
655
796
|
if (i && r) {
|
|
656
797
|
const o = t.uuid;
|
|
657
|
-
|
|
798
|
+
S.registerMesh(r, o, t, 0, i.lods.length, i);
|
|
658
799
|
}
|
|
659
800
|
}
|
|
660
801
|
}
|
|
661
|
-
function
|
|
662
|
-
|
|
663
|
-
const i =
|
|
802
|
+
function ze(a, e, t, r) {
|
|
803
|
+
fe(e), ue(t), t.register((n) => new S(n, a));
|
|
804
|
+
const i = b.get(e);
|
|
664
805
|
return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
|
|
665
806
|
}
|
|
666
807
|
document.addEventListener("DOMContentLoaded", () => {
|
|
667
|
-
|
|
808
|
+
Ee(document.querySelector("model-viewer"));
|
|
668
809
|
});
|
|
669
810
|
export {
|
|
670
811
|
R as EXTENSION_NAME,
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
812
|
+
b as LODsManager,
|
|
813
|
+
S as NEEDLE_progressive,
|
|
814
|
+
ue as addDracoAndKTX2Loaders,
|
|
815
|
+
fe as createLoaders,
|
|
816
|
+
Se as getRaycastMesh,
|
|
817
|
+
Ee as patchModelViewer,
|
|
818
|
+
Ue as setDracoDecoderLocation,
|
|
819
|
+
Ne as setKTX2TranscoderLocation,
|
|
820
|
+
_e as setRaycastMesh,
|
|
821
|
+
ze as useNeedleProgressive
|
|
676
822
|
};
|