@needle-tools/gltf-progressive 1.0.0-alpha.8 → 1.1.0-alpha
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 +42 -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 +465 -318
- 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 +108 -15
- 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,65 +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 (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
210
|
+
if (w && re.add(r), r.uniforms && r.isRawShaderMaterial || r.isShaderMaterial === !0) {
|
|
211
|
+
const s = r;
|
|
212
|
+
for (const o of Object.keys(s.uniforms)) {
|
|
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);
|
|
166
217
|
}
|
|
167
218
|
}
|
|
168
|
-
else
|
|
219
|
+
} else
|
|
169
220
|
for (const s of Object.keys(r)) {
|
|
170
221
|
const o = r[s];
|
|
171
222
|
if ((o == null ? void 0 : o.isTexture) === !0) {
|
|
172
|
-
const
|
|
173
|
-
i.push(
|
|
223
|
+
const l = this.assignTextureLODForSlot(o, t, r, s);
|
|
224
|
+
i.push(l), n.push(s);
|
|
174
225
|
}
|
|
175
226
|
}
|
|
176
227
|
return Promise.all(i).then((s) => {
|
|
177
228
|
const o = new Array();
|
|
178
|
-
for (let
|
|
179
|
-
const
|
|
180
|
-
|
|
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 });
|
|
181
232
|
}
|
|
182
233
|
return o;
|
|
183
234
|
});
|
|
184
235
|
}
|
|
185
|
-
if (e instanceof
|
|
236
|
+
if (e instanceof N || e.isTexture === !0) {
|
|
186
237
|
const r = e;
|
|
187
238
|
return this.assignTextureLODForSlot(r, t, null, null);
|
|
188
239
|
}
|
|
189
240
|
return Promise.resolve(null);
|
|
190
241
|
}
|
|
191
242
|
static assignTextureLODForSlot(e, t, r, i) {
|
|
192
|
-
|
|
193
|
-
|
|
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))
|
|
194
250
|
return null;
|
|
195
|
-
if ((
|
|
196
|
-
if (
|
|
197
|
-
const
|
|
198
|
-
|
|
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);
|
|
199
255
|
}
|
|
200
|
-
return
|
|
256
|
+
return s;
|
|
201
257
|
} else
|
|
202
|
-
|
|
258
|
+
w == "verbose" && console.warn("No LOD found for", e, t);
|
|
203
259
|
return null;
|
|
204
|
-
}).catch((
|
|
260
|
+
}).catch((s) => (console.error("Error loading LOD", e, s), null));
|
|
205
261
|
}
|
|
206
262
|
afterRoot(e) {
|
|
207
263
|
var t, r;
|
|
208
|
-
return
|
|
264
|
+
return w && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
|
|
209
265
|
if (i != null && i.extensions) {
|
|
210
266
|
const s = i == null ? void 0 : i.extensions[R];
|
|
211
267
|
if (s) {
|
|
212
268
|
let o = !1;
|
|
213
|
-
for (const
|
|
214
|
-
|
|
215
|
-
o || this.parser.getDependency("texture", n).then((
|
|
216
|
-
|
|
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);
|
|
217
273
|
});
|
|
218
274
|
}
|
|
219
275
|
}
|
|
@@ -223,195 +279,205 @@ const M = class {
|
|
|
223
279
|
if (s && s.lods) {
|
|
224
280
|
for (const o of this.parser.associations.keys())
|
|
225
281
|
if (o.isMesh) {
|
|
226
|
-
const
|
|
227
|
-
|
|
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);
|
|
228
284
|
}
|
|
229
285
|
}
|
|
230
286
|
}
|
|
231
287
|
}), null;
|
|
232
288
|
}
|
|
233
289
|
static async getOrLoadLOD(e, t) {
|
|
234
|
-
var o,
|
|
235
|
-
const r =
|
|
290
|
+
var o, l, d, h;
|
|
291
|
+
const r = w == "verbose", i = e.userData.LODS;
|
|
236
292
|
if (!i)
|
|
237
293
|
return null;
|
|
238
294
|
const n = i == null ? void 0 : i.key;
|
|
239
295
|
let s;
|
|
240
296
|
if (e.isTexture === !0) {
|
|
241
|
-
const
|
|
242
|
-
|
|
297
|
+
const m = e;
|
|
298
|
+
m.source && m.source[j] && (s = m.source[j]);
|
|
243
299
|
}
|
|
244
|
-
if (s || (s =
|
|
300
|
+
if (s || (s = v.lodInfos.get(n)), s) {
|
|
245
301
|
if (t > 0) {
|
|
246
|
-
let
|
|
247
|
-
const
|
|
248
|
-
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)
|
|
249
305
|
return this.lowresCache.get(n);
|
|
250
306
|
}
|
|
251
|
-
const
|
|
252
|
-
if (!
|
|
253
|
-
return
|
|
254
|
-
const
|
|
255
|
-
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")) {
|
|
256
312
|
if (!s.guid)
|
|
257
313
|
return console.warn("missing pointer for glb/gltf texture", s), null;
|
|
258
|
-
const
|
|
259
|
-
if (
|
|
260
|
-
r && console.log(`LOD ${t} was already loading/loaded: ${
|
|
261
|
-
let
|
|
262
|
-
`,
|
|
263
|
-
if (
|
|
264
|
-
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;
|
|
265
321
|
}
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
let
|
|
270
|
-
if (
|
|
271
|
-
const
|
|
272
|
-
|
|
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);
|
|
273
329
|
}
|
|
274
|
-
const
|
|
275
|
-
`,
|
|
276
|
-
if (!
|
|
330
|
+
const E = await F.loadAsync(J).catch((g) => (console.error(`Error loading LOD ${t} from ${u}
|
|
331
|
+
`, g), null));
|
|
332
|
+
if (!E)
|
|
277
333
|
return null;
|
|
278
|
-
const
|
|
279
|
-
r && console.log("Loading finished " +
|
|
280
|
-
let
|
|
281
|
-
if (
|
|
282
|
-
let
|
|
283
|
-
for (const
|
|
284
|
-
if (
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
287
|
-
|
|
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;
|
|
288
344
|
break;
|
|
289
345
|
}
|
|
290
346
|
}
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
if (y) {
|
|
294
|
-
let g = await b.getDependency("texture", x);
|
|
295
|
-
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++;
|
|
296
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);
|
|
297
354
|
}
|
|
298
|
-
if (
|
|
299
|
-
let
|
|
300
|
-
for (const
|
|
301
|
-
if (
|
|
302
|
-
const
|
|
303
|
-
if (
|
|
304
|
-
|
|
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;
|
|
305
362
|
break;
|
|
306
363
|
}
|
|
307
364
|
}
|
|
308
|
-
|
|
365
|
+
p++;
|
|
309
366
|
}
|
|
310
|
-
if (
|
|
311
|
-
const
|
|
312
|
-
if (r && console.log(`Loaded Mesh "${
|
|
313
|
-
const
|
|
314
|
-
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(_);
|
|
315
372
|
} else {
|
|
316
|
-
const
|
|
317
|
-
for (let
|
|
318
|
-
const
|
|
319
|
-
if (
|
|
320
|
-
const
|
|
321
|
-
|
|
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);
|
|
322
379
|
}
|
|
323
380
|
}
|
|
324
|
-
return
|
|
381
|
+
return O(_);
|
|
325
382
|
}
|
|
326
383
|
}
|
|
327
384
|
}
|
|
328
|
-
return
|
|
385
|
+
return O(null);
|
|
329
386
|
});
|
|
330
|
-
return this.previouslyLoaded.set(
|
|
331
|
-
} else if (e instanceof
|
|
332
|
-
r && console.log("Load texture from uri: " +
|
|
333
|
-
const
|
|
334
|
-
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;
|
|
335
392
|
}
|
|
336
393
|
} else
|
|
337
|
-
|
|
394
|
+
w && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
|
|
338
395
|
return null;
|
|
339
396
|
}
|
|
340
397
|
static assignLODInformation(e, t, r, i, n, s) {
|
|
341
398
|
if (!t)
|
|
342
399
|
return;
|
|
343
400
|
t.userData || (t.userData = {});
|
|
344
|
-
const o = new
|
|
401
|
+
const o = new Te(e, r, i, n, s);
|
|
345
402
|
t.userData.LODS = o, t.userData.LOD = i;
|
|
346
403
|
}
|
|
347
404
|
static getAssignedLODInformation(e) {
|
|
348
405
|
var t;
|
|
349
406
|
return ((t = e == null ? void 0 : e.userData) == null ? void 0 : t.LODS) || null;
|
|
350
407
|
}
|
|
408
|
+
// private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
|
|
351
409
|
static copySettings(e, t) {
|
|
352
|
-
|
|
353
|
-
|
|
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;
|
|
354
413
|
}
|
|
355
414
|
};
|
|
356
|
-
let
|
|
415
|
+
let S = v;
|
|
357
416
|
/**
|
|
358
417
|
* Register a texture with LOD information
|
|
359
418
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
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);
|
|
362
421
|
const n = i.guid;
|
|
363
|
-
|
|
422
|
+
v.assignLODInformation(e, t, n, 0, 0, void 0), v.lodInfos.set(n, i), v.lowresCache.set(n, t);
|
|
364
423
|
}), /**
|
|
365
424
|
* Register a mesh with LOD information
|
|
366
425
|
*/
|
|
367
|
-
|
|
368
|
-
var
|
|
369
|
-
|
|
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);
|
|
370
429
|
const o = r.geometry;
|
|
371
|
-
o.userData || (o.userData = {}),
|
|
372
|
-
let
|
|
373
|
-
|
|
374
|
-
for (const
|
|
375
|
-
(
|
|
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);
|
|
376
435
|
}), /** A map of key = asset uuid and value = LOD information */
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
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 {
|
|
381
440
|
constructor(e, t, r, i, n) {
|
|
382
|
-
|
|
441
|
+
f(this, "url");
|
|
383
442
|
/** the key to lookup the LOD information */
|
|
384
|
-
|
|
385
|
-
|
|
443
|
+
f(this, "key");
|
|
444
|
+
f(this, "level");
|
|
386
445
|
/** For multi objects (e.g. a group of meshes) this is the index of the object */
|
|
387
|
-
|
|
446
|
+
f(this, "index");
|
|
388
447
|
/** the mesh density */
|
|
389
|
-
|
|
448
|
+
f(this, "density");
|
|
390
449
|
this.url = e, this.key = t, this.level = r, i != null && (this.index = i), n != null && (this.density = n);
|
|
391
450
|
}
|
|
392
451
|
}
|
|
393
|
-
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[] = [];
|
|
394
454
|
constructor(e) {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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);
|
|
398
463
|
/**
|
|
399
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.
|
|
400
465
|
*/
|
|
401
|
-
|
|
466
|
+
f(this, "updateInterval", 0);
|
|
402
467
|
/**
|
|
403
468
|
* If set to true, the LODsManager will not update the LODs.
|
|
404
469
|
*/
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
470
|
+
f(this, "pause", !1);
|
|
471
|
+
f(this, "_frame", 0);
|
|
472
|
+
f(this, "_originalRender");
|
|
408
473
|
// private testIfLODLevelsAreAvailable() {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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());
|
|
415
481
|
this.renderer = e;
|
|
416
482
|
}
|
|
417
483
|
/** @internal */
|
|
@@ -419,6 +485,25 @@ const Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
|
|
|
419
485
|
var t;
|
|
420
486
|
return (t = e.userData) == null ? void 0 : t.LOD_state;
|
|
421
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
|
+
}
|
|
422
507
|
/**
|
|
423
508
|
* Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
|
|
424
509
|
*/
|
|
@@ -428,10 +513,10 @@ const Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
|
|
|
428
513
|
let e = 0;
|
|
429
514
|
this._originalRender = this.renderer.render;
|
|
430
515
|
const t = this;
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const s =
|
|
434
|
-
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);
|
|
435
520
|
};
|
|
436
521
|
}
|
|
437
522
|
disable() {
|
|
@@ -440,46 +525,61 @@ const Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
|
|
|
440
525
|
onBeforeRender(e, t, r, i) {
|
|
441
526
|
}
|
|
442
527
|
onAfterRender(e, t, r, i) {
|
|
443
|
-
var
|
|
444
|
-
if (
|
|
528
|
+
var l, d;
|
|
529
|
+
if (this.pause)
|
|
445
530
|
return;
|
|
446
|
-
this.
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
const f = c.object;
|
|
454
|
-
(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);
|
|
455
536
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
(
|
|
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
|
+
}
|
|
460
564
|
}
|
|
461
565
|
}
|
|
462
566
|
/** Update the LOD levels for the renderer. */
|
|
463
|
-
updateLODs(e, t, r, i) {
|
|
464
|
-
var
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
s = Math.round(
|
|
471
|
-
let o =
|
|
472
|
-
if (r.material) {
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
for (const c of r.material)
|
|
476
|
-
this.loadProgressiveTextures(c, o);
|
|
477
|
-
else
|
|
478
|
-
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);
|
|
479
579
|
}
|
|
480
|
-
for (const
|
|
481
|
-
(
|
|
482
|
-
|
|
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;
|
|
483
583
|
}
|
|
484
584
|
/** Load progressive textures for the given material
|
|
485
585
|
* @param material the material to load the textures for
|
|
@@ -487,7 +587,16 @@ const Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
|
|
|
487
587
|
* @returns Promise with true if the LOD was loaded, false if not
|
|
488
588
|
*/
|
|
489
589
|
loadProgressiveTextures(e, t) {
|
|
490
|
-
|
|
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));
|
|
491
600
|
}
|
|
492
601
|
/** Load progressive meshes for the given mesh
|
|
493
602
|
* @param mesh the mesh to load the LOD for
|
|
@@ -501,91 +610,120 @@ const Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
|
|
|
501
610
|
if (e.userData || (e.userData = {}), e.userData.LOD !== t) {
|
|
502
611
|
e.userData.LOD = t;
|
|
503
612
|
const r = e.geometry;
|
|
504
|
-
return
|
|
613
|
+
return S.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
|
|
505
614
|
}
|
|
506
615
|
return Promise.resolve(null);
|
|
507
616
|
}
|
|
508
|
-
|
|
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
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const m = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
544
|
-
m.invert();
|
|
545
|
-
const p = T.corner0, b = T.corner1, x = T.corner2, y = T.corner3;
|
|
546
|
-
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);
|
|
547
|
-
const g = (p.z + y.z) * 0.5;
|
|
548
|
-
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);
|
|
549
|
-
}
|
|
550
|
-
let C = 999;
|
|
551
|
-
if (h && r.lastScreenCoverage > 0) {
|
|
552
|
-
for (let m = 0; m < h.length; m++)
|
|
553
|
-
if (h[m].density / r.lastScreenCoverage < i) {
|
|
554
|
-
C = m;
|
|
555
|
-
break;
|
|
556
|
-
}
|
|
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;
|
|
557
652
|
}
|
|
558
|
-
C < s && (s = C);
|
|
559
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);
|
|
560
689
|
}
|
|
561
|
-
|
|
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;
|
|
562
695
|
}
|
|
563
696
|
};
|
|
564
|
-
let
|
|
697
|
+
let b = T;
|
|
565
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.
|
|
566
699
|
*/
|
|
567
|
-
|
|
568
|
-
|
|
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 {
|
|
569
705
|
constructor() {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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);
|
|
574
712
|
}
|
|
575
713
|
}
|
|
576
|
-
const
|
|
577
|
-
function
|
|
578
|
-
if (!
|
|
714
|
+
const ce = Symbol("NEEDLE_mesh_lod"), X = Symbol("NEEDLE_texture_lod");
|
|
715
|
+
function Ee(a) {
|
|
716
|
+
if (!a)
|
|
579
717
|
return null;
|
|
580
718
|
let e = null, t = null;
|
|
581
|
-
for (let r =
|
|
719
|
+
for (let r = a; r != null; r = Object.getPrototypeOf(r)) {
|
|
582
720
|
const i = Object.getOwnPropertySymbols(r), n = i.find((o) => o.toString() == "Symbol(renderer)"), s = i.find((o) => o.toString() == "Symbol(scene)");
|
|
583
|
-
!e && n != null && (e =
|
|
721
|
+
!e && n != null && (e = a[n].threeRenderer), !t && s != null && (t = a[s]);
|
|
584
722
|
}
|
|
585
723
|
if (e) {
|
|
586
724
|
console.log("Adding Needle LODs to modelviewer");
|
|
587
|
-
const r =
|
|
588
|
-
if (
|
|
725
|
+
const r = b.get(e);
|
|
726
|
+
if (b.addPlugin(new Ce(a)), r.enable(), t) {
|
|
589
727
|
const i = t.camera || t.traverse((n) => n.type == "PerspectiveCamera")[0];
|
|
590
728
|
i && e.render(t, i);
|
|
591
729
|
}
|
|
@@ -595,10 +733,10 @@ function Me(l) {
|
|
|
595
733
|
}
|
|
596
734
|
return null;
|
|
597
735
|
}
|
|
598
|
-
class
|
|
736
|
+
class Ce {
|
|
599
737
|
constructor(e) {
|
|
600
|
-
|
|
601
|
-
|
|
738
|
+
f(this, "modelviewer");
|
|
739
|
+
f(this, "_didWarnAboutMissingUrl", !1);
|
|
602
740
|
this.modelviewer = e;
|
|
603
741
|
}
|
|
604
742
|
onBeforeUpdateLOD(e, t, r, i) {
|
|
@@ -612,24 +750,28 @@ class ve {
|
|
|
612
750
|
return e._currentGLTF;
|
|
613
751
|
}
|
|
614
752
|
tryParseTextureLOD(e, t) {
|
|
615
|
-
if (t[
|
|
753
|
+
if (t[X] == !0)
|
|
616
754
|
return;
|
|
617
|
-
t[
|
|
755
|
+
t[X] = !0;
|
|
618
756
|
const r = this.tryGetCurrentGLTF(e), i = this.getUrl();
|
|
619
757
|
if (i && r && t.material) {
|
|
620
758
|
let n = function(o) {
|
|
621
|
-
var
|
|
622
|
-
if (o[
|
|
759
|
+
var d, h, m;
|
|
760
|
+
if (o[X] == !0)
|
|
623
761
|
return;
|
|
624
|
-
o[
|
|
625
|
-
const
|
|
626
|
-
for (let
|
|
627
|
-
const
|
|
628
|
-
if ((
|
|
629
|
-
const
|
|
630
|
-
if (
|
|
631
|
-
|
|
632
|
-
|
|
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);
|
|
633
775
|
}
|
|
634
776
|
}
|
|
635
777
|
}
|
|
@@ -644,32 +786,37 @@ class ve {
|
|
|
644
786
|
}
|
|
645
787
|
tryParseMeshLOD(e, t) {
|
|
646
788
|
var n, s;
|
|
647
|
-
if (t[
|
|
789
|
+
if (t[ce] == !0)
|
|
648
790
|
return;
|
|
649
|
-
t[
|
|
791
|
+
t[ce] = !0;
|
|
650
792
|
const r = this.getUrl();
|
|
651
793
|
if (!r)
|
|
652
794
|
return;
|
|
653
795
|
const i = (s = (n = t.userData) == null ? void 0 : n.gltfExtensions) == null ? void 0 : s[R];
|
|
654
796
|
if (i && r) {
|
|
655
797
|
const o = t.uuid;
|
|
656
|
-
|
|
798
|
+
S.registerMesh(r, o, t, 0, i.lods.length, i);
|
|
657
799
|
}
|
|
658
800
|
}
|
|
659
801
|
}
|
|
660
|
-
function
|
|
661
|
-
|
|
662
|
-
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);
|
|
663
805
|
return (r == null ? void 0 : r.enableLODsManager) !== !1 && i.enable(), i;
|
|
664
806
|
}
|
|
665
807
|
document.addEventListener("DOMContentLoaded", () => {
|
|
666
|
-
|
|
808
|
+
Ee(document.querySelector("model-viewer"));
|
|
667
809
|
});
|
|
668
810
|
export {
|
|
669
811
|
R as EXTENSION_NAME,
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
|
675
822
|
};
|