@needle-tools/engine 4.7.3-next.65e7878 → 4.7.3-next.b448b7a

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.
Files changed (32) hide show
  1. package/dist/gltf-progressive-BMJtMiwp.js +1204 -0
  2. package/dist/gltf-progressive-DMJSXxbo.umd.cjs +8 -0
  3. package/dist/gltf-progressive-zQ2CaD2H.min.js +8 -0
  4. package/dist/{needle-engine.bundle-B0QYYufM.js → needle-engine.bundle-BQzYQCWt.js} +36 -10
  5. package/dist/{needle-engine.bundle-BCAZfCyl.min.js → needle-engine.bundle-BUgKFz_t.min.js} +7 -7
  6. package/dist/{needle-engine.bundle-C6yScKUU.umd.cjs → needle-engine.bundle-CmHXdQmP.umd.cjs} +8 -8
  7. package/dist/needle-engine.js +3 -3
  8. package/dist/needle-engine.min.js +1 -1
  9. package/dist/needle-engine.umd.cjs +1 -1
  10. package/dist/{postprocessing-TkXiVrjY.min.js → postprocessing-BzY0H7ry.min.js} +8 -8
  11. package/dist/{postprocessing-CNCT892s.umd.cjs → postprocessing-Dw2OCMp4.umd.cjs} +8 -8
  12. package/dist/{postprocessing-qvgDnYKK.js → postprocessing-vKBVFpSz.js} +9 -9
  13. package/lib/engine/engine_lods.js +1 -1
  14. package/lib/engine/engine_lods.js.map +1 -1
  15. package/lib/engine-components/OrbitControls.d.ts +19 -1
  16. package/lib/engine-components/OrbitControls.js +30 -1
  17. package/lib/engine-components/OrbitControls.js.map +1 -1
  18. package/lib/engine-components/postprocessing/PostProcessingHandler.js +1 -1
  19. package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
  20. package/lib/engine-components/postprocessing/Volume.d.ts +3 -1
  21. package/lib/engine-components/postprocessing/Volume.js +2 -0
  22. package/lib/engine-components/postprocessing/Volume.js.map +1 -1
  23. package/package.json +2 -2
  24. package/plugins/vite/logger.client.js +68 -30
  25. package/plugins/vite/logger.js +5 -5
  26. package/src/engine/engine_lods.ts +3 -3
  27. package/src/engine-components/OrbitControls.ts +34 -2
  28. package/src/engine-components/postprocessing/PostProcessingHandler.ts +1 -1
  29. package/src/engine-components/postprocessing/Volume.ts +2 -1
  30. package/dist/gltf-progressive-BCZdu3Gc.min.js +0 -8
  31. package/dist/gltf-progressive-C6QbvrB4.umd.cjs +0 -8
  32. package/dist/gltf-progressive-CCddD-3B.js +0 -1159
@@ -0,0 +1,1204 @@
1
+ var He = Object.defineProperty;
2
+ var Be = (o) => {
3
+ throw TypeError(o);
4
+ };
5
+ var Qe = (o, e, t) => e in o ? He(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
6
+ var u = (o, e, t) => Qe(o, typeof e != "symbol" ? e + "" : e, t), Ge = (o, e, t) => e.has(o) || Be("Cannot " + t);
7
+ var L = (o, e, t) => (Ge(o, e, "read from private field"), t ? t.call(o) : e.get(o)), Y = (o, e, t) => e.has(o) ? Be("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(o) : e.set(o, t), z = (o, e, t, s) => (Ge(o, e, "write to private field"), s ? s.call(o, t) : e.set(o, t), t);
8
+ import { BufferGeometry as ye, Mesh as te, Texture as ne, TextureLoader as je, Matrix4 as $e, Clock as Je, MeshStandardMaterial as Ze, Sphere as et, Box3 as ke, Vector3 as V } from "./three-DrqIzZTH.js";
9
+ import { DRACOLoader as tt, KTX2Loader as st, MeshoptDecoder as rt, GLTFLoader as Ce } from "./three-examples-tvuhV8Ne.js";
10
+ const it = "";
11
+ globalThis.GLTF_PROGRESSIVE_VERSION = it;
12
+ console.debug("[gltf-progressive] version -");
13
+ let q = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", se = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
14
+ const nt = q, ot = se, Fe = new URL(q + "draco_decoder.js");
15
+ Fe.searchParams.append("range", "true");
16
+ fetch(Fe, {
17
+ method: "GET",
18
+ headers: {
19
+ Range: "bytes=0-1"
20
+ }
21
+ }).catch((o) => {
22
+ console.debug(`Failed to fetch remote Draco decoder from ${q} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), q === nt && at("./include/draco/"), se === ot && lt("./include/ktx2/");
23
+ }).finally(() => {
24
+ Ue();
25
+ });
26
+ function at(o) {
27
+ q = o, k && k[Pe] != q ? (console.debug("Updating Draco decoder path to " + o), k[Pe] = q, k.setDecoderPath(q), k.preload()) : console.debug("Setting Draco decoder path to " + o);
28
+ }
29
+ function lt(o) {
30
+ se = o, R && R.transcoderPath != se ? (console.debug("Updating KTX2 transcoder path to " + o), R.setTranscoderPath(se), R.init()) : console.debug("Setting KTX2 transcoder path to " + o);
31
+ }
32
+ const Pe = Symbol("dracoDecoderPath");
33
+ let k, Le, R;
34
+ function Ue() {
35
+ k || (k = new tt(), k[Pe] = q, k.setDecoderPath(q), k.setDecoderConfig({ type: "js" }), k.preload()), R || (R = new st(), R.setTranscoderPath(se), R.init()), Le || (Le = rt);
36
+ }
37
+ function ze(o) {
38
+ return Ue(), o ? R.detectSupport(o) : o !== null && console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"), { dracoLoader: k, ktx2Loader: R, meshoptDecoder: Le };
39
+ }
40
+ function Ne(o) {
41
+ o.dracoLoader || o.setDRACOLoader(k), o.ktx2Loader || o.setKTX2Loader(R), o.meshoptDecoder || o.setMeshoptDecoder(Le);
42
+ }
43
+ const Te = /* @__PURE__ */ new WeakMap();
44
+ function qe(o, e) {
45
+ let t = Te.get(o);
46
+ t ? t = Object.assign(t, e) : t = e, Te.set(o, t);
47
+ }
48
+ const ve = Ce.prototype.load;
49
+ function ut(...o) {
50
+ const e = Te.get(this);
51
+ let t = o[0];
52
+ const s = new URL(t, window.location.href);
53
+ if (s.hostname.endsWith("needle.tools")) {
54
+ const r = (e == null ? void 0 : e.progressive) !== void 0 ? e.progressive : !0, i = e != null && e.usecase ? e.usecase : "default";
55
+ r ? this.requestHeader.Accept = `*/*;progressive=allowed;usecase=${i}` : this.requestHeader.Accept = `*/*;usecase=${i}`, t = s.toString();
56
+ }
57
+ return o[0] = t, ve == null ? void 0 : ve.call(this, ...o);
58
+ }
59
+ Ce.prototype.load = ut;
60
+ ue("debugprogressive");
61
+ function ue(o) {
62
+ if (typeof window > "u") return !1;
63
+ const t = new URL(window.location.href).searchParams.get(o);
64
+ return t == null || t === "0" || t === "false" ? !1 : t === "" ? !0 : t;
65
+ }
66
+ function dt(o, e) {
67
+ if (e === void 0 || e.startsWith("./") || e.startsWith("http") || o === void 0)
68
+ return e;
69
+ const t = o.lastIndexOf("/");
70
+ if (t >= 0) {
71
+ const s = o.substring(0, t + 1);
72
+ for (; s.endsWith("/") && e.startsWith("/"); ) e = e.substring(1);
73
+ return s + e;
74
+ }
75
+ return e;
76
+ }
77
+ let oe;
78
+ function ct() {
79
+ return oe !== void 0 || (oe = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), ue("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", oe)), oe;
80
+ }
81
+ function ft() {
82
+ if (typeof window > "u") return !1;
83
+ const o = new URL(window.location.href), e = o.hostname === "localhost" || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o.hostname);
84
+ return o.hostname === "127.0.0.1" || e;
85
+ }
86
+ class ht {
87
+ constructor(e = 100, t = {}) {
88
+ u(this, "_running", /* @__PURE__ */ new Map());
89
+ u(this, "_queue", []);
90
+ u(this, "debug", !1);
91
+ u(this, "tick", () => {
92
+ this.internalUpdate(), setTimeout(this.tick, 10);
93
+ });
94
+ this.maxConcurrent = e, this.debug = t.debug ?? !1, window.requestAnimationFrame(this.tick);
95
+ }
96
+ /**
97
+ * Request a slot for a promise with a specific key. This function returns a promise with a `use` method that can be called to add the promise to the queue.
98
+ */
99
+ slot(e) {
100
+ return this.debug && console.debug(`[PromiseQueue]: Requesting slot for key ${e}, running: ${this._running.size}, waiting: ${this._queue.length}`), new Promise((t) => {
101
+ this._queue.push({ key: e, resolve: t });
102
+ });
103
+ }
104
+ add(e, t) {
105
+ this._running.has(e) || (this._running.set(e, t), t.finally(() => {
106
+ this._running.delete(e), this.debug && console.debug(`[PromiseQueue]: Promise for key ${e} finished, running: ${this._running.size}, waiting: ${this._queue.length}`);
107
+ }), this.debug && console.debug(`[PromiseQueue]: Adding promise for key ${e}, running: ${this._running.size}, waiting: ${this._queue.length}`));
108
+ }
109
+ internalUpdate() {
110
+ const e = this.maxConcurrent - this._running.size;
111
+ for (let t = 0; t < e && this._queue.length > 0; t++) {
112
+ this.debug && console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);
113
+ const { key: s, resolve: n } = this._queue.shift();
114
+ n({
115
+ use: (r) => this.add(s, r)
116
+ });
117
+ }
118
+ }
119
+ }
120
+ const gt = typeof window > "u" && typeof document > "u", Ae = Symbol("needle:raycast-mesh");
121
+ function de(o) {
122
+ return (o == null ? void 0 : o[Ae]) instanceof ye ? o[Ae] : null;
123
+ }
124
+ function pt(o, e) {
125
+ if ((o.type === "Mesh" || o.type === "SkinnedMesh") && !de(o)) {
126
+ const s = yt(e);
127
+ s.userData = { isRaycastMesh: !0 }, o[Ae] = s;
128
+ }
129
+ }
130
+ function mt(o = !0) {
131
+ if (o) {
132
+ if (ae) return;
133
+ const e = ae = te.prototype.raycast;
134
+ te.prototype.raycast = function(t, s) {
135
+ const n = this, r = de(n);
136
+ let i;
137
+ r && n.isMesh && (i = n.geometry, n.geometry = r), e.call(this, t, s), i && (n.geometry = i);
138
+ };
139
+ } else {
140
+ if (!ae) return;
141
+ te.prototype.raycast = ae, ae = null;
142
+ }
143
+ }
144
+ let ae = null;
145
+ function yt(o) {
146
+ const e = new ye();
147
+ for (const t in o.attributes)
148
+ e.setAttribute(t, o.getAttribute(t));
149
+ return e.setIndex(o.getIndex()), e;
150
+ }
151
+ const Q = new Array(), x = ue("debugprogressive");
152
+ let pe, ee = -1;
153
+ if (x) {
154
+ let o = function() {
155
+ ee += 1, ee >= e && (ee = -1), console.log(`Toggle LOD level [${ee}]`);
156
+ }, e = 6;
157
+ window.addEventListener("keyup", (t) => {
158
+ t.key === "p" && o(), t.key === "w" && (pe = !pe, console.log(`Toggle wireframe [${pe}]`));
159
+ const s = parseInt(t.key);
160
+ !isNaN(s) && s >= 0 && (ee = s, console.log(`Set LOD level to [${ee}]`));
161
+ });
162
+ }
163
+ function Ve(o) {
164
+ if (x)
165
+ if (Array.isArray(o))
166
+ for (const e of o)
167
+ Ve(e);
168
+ else o && "wireframe" in o && (o.wireframe = pe === !0);
169
+ }
170
+ const W = "NEEDLE_progressive", Oe = Symbol("needle-progressive-texture"), _ = class _ {
171
+ constructor(e, t) {
172
+ u(this, "parser");
173
+ u(this, "url");
174
+ u(this, "_isLoadingMesh");
175
+ u(this, "loadMesh", (e) => {
176
+ var s, n;
177
+ if (this._isLoadingMesh) return null;
178
+ const t = (n = (s = this.parser.json.meshes[e]) == null ? void 0 : s.extensions) == null ? void 0 : n[W];
179
+ return t ? (this._isLoadingMesh = !0, this.parser.getDependency("mesh", e).then((r) => {
180
+ var i;
181
+ return this._isLoadingMesh = !1, r && _.registerMesh(this.url, t.guid, r, (i = t.lods) == null ? void 0 : i.length, 0, t), r;
182
+ })) : null;
183
+ });
184
+ x && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
185
+ }
186
+ /** The name of the extension */
187
+ get name() {
188
+ return W;
189
+ }
190
+ static getMeshLODExtension(e) {
191
+ const t = this.getAssignedLODInformation(e);
192
+ return t != null && t.key ? this.lodInfos.get(t.key) : null;
193
+ }
194
+ static getPrimitiveIndex(e) {
195
+ var s;
196
+ const t = (s = this.getAssignedLODInformation(e)) == null ? void 0 : s.index;
197
+ return t ?? -1;
198
+ }
199
+ static getMaterialMinMaxLODsCount(e, t) {
200
+ const s = this, n = "LODS:minmax", r = e[n];
201
+ if (r != null) return r;
202
+ if (t || (t = {
203
+ min_count: 1 / 0,
204
+ max_count: 0,
205
+ lods: []
206
+ }), Array.isArray(e)) {
207
+ for (const a of e)
208
+ this.getMaterialMinMaxLODsCount(a, t);
209
+ return e[n] = t, t;
210
+ }
211
+ if (x === "verbose" && console.log("getMaterialMinMaxLODsCount", e), e.type === "ShaderMaterial" || e.type === "RawShaderMaterial") {
212
+ const a = e;
213
+ for (const l of Object.keys(a.uniforms)) {
214
+ const c = a.uniforms[l].value;
215
+ (c == null ? void 0 : c.isTexture) === !0 && i(c, t);
216
+ }
217
+ } else if (e.isMaterial)
218
+ for (const a of Object.keys(e)) {
219
+ const l = e[a];
220
+ (l == null ? void 0 : l.isTexture) === !0 && i(l, t);
221
+ }
222
+ return e[n] = t, t;
223
+ function i(a, l) {
224
+ const c = s.getAssignedLODInformation(a);
225
+ if (c) {
226
+ const d = s.lodInfos.get(c.key);
227
+ if (d && d.lods) {
228
+ l.min_count = Math.min(l.min_count, d.lods.length), l.max_count = Math.max(l.max_count, d.lods.length);
229
+ for (let p = 0; p < d.lods.length; p++) {
230
+ const f = d.lods[p];
231
+ f.width && (l.lods[p] = l.lods[p] || { min_height: 1 / 0, max_height: 0 }, l.lods[p].min_height = Math.min(l.lods[p].min_height, f.height), l.lods[p].max_height = Math.max(l.lods[p].max_height, f.height));
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ /** Check if a LOD level is available for a mesh or a texture
238
+ * @param obj the mesh or texture to check
239
+ * @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
240
+ * @returns true if the LOD level is available (or if any LOD level is available if level is undefined)
241
+ */
242
+ static hasLODLevelAvailable(e, t) {
243
+ var r;
244
+ if (Array.isArray(e)) {
245
+ for (const i of e)
246
+ if (this.hasLODLevelAvailable(i, t)) return !0;
247
+ return !1;
248
+ }
249
+ if (e.isMaterial === !0) {
250
+ for (const i of Object.keys(e)) {
251
+ const a = e[i];
252
+ if (a && a.isTexture && this.hasLODLevelAvailable(a, t))
253
+ return !0;
254
+ }
255
+ return !1;
256
+ } else if (e.isGroup === !0) {
257
+ for (const i of e.children)
258
+ if (i.isMesh === !0 && this.hasLODLevelAvailable(i, t))
259
+ return !0;
260
+ }
261
+ let s, n;
262
+ if (e.isMesh ? s = e.geometry : (e.isBufferGeometry || e.isTexture) && (s = e), s && (r = s == null ? void 0 : s.userData) != null && r.LODS) {
263
+ const i = s.userData.LODS;
264
+ if (n = this.lodInfos.get(i.key), t === void 0) return n != null;
265
+ if (n)
266
+ return Array.isArray(n.lods) ? t < n.lods.length : t === 0;
267
+ }
268
+ return !1;
269
+ }
270
+ /** Load a different resolution of a mesh (if available)
271
+ * @param context the context
272
+ * @param source the sourceid of the file from which the mesh is loaded (this is usually the component's sourceId)
273
+ * @param mesh the mesh to load the LOD for
274
+ * @param level the level of detail to load (0 is the highest resolution)
275
+ * @returns a promise that resolves to the mesh with the requested LOD level
276
+ * @example
277
+ * ```javascript
278
+ * const mesh = this.gameObject as Mesh;
279
+ * NEEDLE_progressive.assignMeshLOD(context, sourceId, mesh, 1).then(mesh => {
280
+ * console.log("Mesh with LOD level 1 loaded", mesh);
281
+ * });
282
+ * ```
283
+ */
284
+ static assignMeshLOD(e, t) {
285
+ var s;
286
+ if (!e) return Promise.resolve(null);
287
+ if (e instanceof te || e.isMesh === !0) {
288
+ const n = e.geometry, r = this.getAssignedLODInformation(n);
289
+ if (!r)
290
+ return Promise.resolve(null);
291
+ for (const i of Q)
292
+ (s = i.onBeforeGetLODMesh) == null || s.call(i, e, t);
293
+ return e["LOD:requested level"] = t, _.getOrLoadLOD(n, t).then((i) => {
294
+ if (Array.isArray(i)) {
295
+ const a = r.index || 0;
296
+ i = i[a];
297
+ }
298
+ return e["LOD:requested level"] === t && (delete e["LOD:requested level"], i && n != i && ((i == null ? void 0 : i.isBufferGeometry) ? e.geometry = i : x && console.error("Invalid LOD geometry", i))), i;
299
+ }).catch((i) => (console.error("Error loading mesh LOD", e, i), null));
300
+ } else x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
301
+ return Promise.resolve(null);
302
+ }
303
+ static assignTextureLOD(e, t = 0) {
304
+ if (!e) return Promise.resolve(null);
305
+ if (e.isMesh === !0) {
306
+ const s = e;
307
+ if (Array.isArray(s.material)) {
308
+ const n = new Array();
309
+ for (const r of s.material) {
310
+ const i = this.assignTextureLOD(r, t);
311
+ n.push(i);
312
+ }
313
+ return Promise.all(n).then((r) => {
314
+ const i = new Array();
315
+ for (const a of r)
316
+ Array.isArray(a) && i.push(...a);
317
+ return i;
318
+ });
319
+ } else
320
+ return this.assignTextureLOD(s.material, t);
321
+ }
322
+ if (e.isMaterial === !0) {
323
+ const s = e, n = [], r = new Array();
324
+ if (s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
325
+ const i = s;
326
+ for (const a of Object.keys(i.uniforms)) {
327
+ const l = i.uniforms[a].value;
328
+ if ((l == null ? void 0 : l.isTexture) === !0) {
329
+ const c = this.assignTextureLODForSlot(l, t, s, a).then((d) => (d && i.uniforms[a].value != d && (i.uniforms[a].value = d, i.uniformsNeedUpdate = !0), d));
330
+ n.push(c), r.push(a);
331
+ }
332
+ }
333
+ } else
334
+ for (const i of Object.keys(s)) {
335
+ const a = s[i];
336
+ if ((a == null ? void 0 : a.isTexture) === !0) {
337
+ const l = this.assignTextureLODForSlot(a, t, s, i);
338
+ n.push(l), r.push(i);
339
+ }
340
+ }
341
+ return Promise.all(n).then((i) => {
342
+ const a = new Array();
343
+ for (let l = 0; l < i.length; l++) {
344
+ const c = i[l], d = r[l];
345
+ c && c.isTexture === !0 ? a.push({ material: s, slot: d, texture: c, level: t }) : a.push({ material: s, slot: d, texture: null, level: t });
346
+ }
347
+ return a;
348
+ });
349
+ }
350
+ if (e instanceof ne || e.isTexture === !0) {
351
+ const s = e;
352
+ return this.assignTextureLODForSlot(s, t, null, null);
353
+ }
354
+ return Promise.resolve(null);
355
+ }
356
+ static assignTextureLODForSlot(e, t, s, n) {
357
+ return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) : n === "glyphMap" ? Promise.resolve(e) : _.getOrLoadLOD(e, t).then((r) => {
358
+ if (Array.isArray(r)) return null;
359
+ if ((r == null ? void 0 : r.isTexture) === !0) {
360
+ if (r != e && s && n) {
361
+ const i = s[n];
362
+ if (i && !x) {
363
+ const a = this.getAssignedLODInformation(i);
364
+ if (a && (a == null ? void 0 : a.level) < t)
365
+ return x === "verbose" && console.warn("Assigned texture level is already higher: ", a.level, t, s, i, r), null;
366
+ }
367
+ s[n] = r;
368
+ }
369
+ return r;
370
+ } else x == "verbose" && console.warn("No LOD found for", e, t);
371
+ return null;
372
+ }).catch((r) => (console.error("Error loading LOD", e, r), null));
373
+ }
374
+ afterRoot(e) {
375
+ var t, s;
376
+ return x && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((n, r) => {
377
+ var i;
378
+ if (n != null && n.extensions) {
379
+ const a = n == null ? void 0 : n.extensions[W];
380
+ if (a) {
381
+ if (!a.lods) {
382
+ x && console.warn("Texture has no LODs", a);
383
+ return;
384
+ }
385
+ let l = !1;
386
+ for (const c of this.parser.associations.keys())
387
+ if (c.isTexture === !0) {
388
+ const d = this.parser.associations.get(c);
389
+ (d == null ? void 0 : d.textures) === r && (l = !0, _.registerTexture(this.url, c, (i = a.lods) == null ? void 0 : i.length, r, a));
390
+ }
391
+ l || this.parser.getDependency("texture", r).then((c) => {
392
+ var d;
393
+ c && _.registerTexture(this.url, c, (d = a.lods) == null ? void 0 : d.length, r, a);
394
+ });
395
+ }
396
+ }
397
+ }), (s = this.parser.json.meshes) == null || s.forEach((n, r) => {
398
+ if (n != null && n.extensions) {
399
+ const i = n == null ? void 0 : n.extensions[W];
400
+ if (i && i.lods) {
401
+ for (const a of this.parser.associations.keys())
402
+ if (a.isMesh) {
403
+ const l = this.parser.associations.get(a);
404
+ (l == null ? void 0 : l.meshes) === r && _.registerMesh(this.url, i.guid, a, i.lods.length, l.primitives, i);
405
+ }
406
+ }
407
+ }
408
+ }), null;
409
+ }
410
+ static async getOrLoadLOD(e, t) {
411
+ var a, l, c, d;
412
+ const s = x == "verbose", n = e.userData.LODS;
413
+ if (!n)
414
+ return null;
415
+ const r = n == null ? void 0 : n.key;
416
+ let i;
417
+ if (e.isTexture === !0) {
418
+ const p = e;
419
+ p.source && p.source[Oe] && (i = p.source[Oe]);
420
+ }
421
+ if (i || (i = _.lodInfos.get(r)), i) {
422
+ if (t > 0) {
423
+ let D = !1;
424
+ const O = Array.isArray(i.lods);
425
+ if (O && t >= i.lods.length ? D = !0 : O || (D = !0), D)
426
+ return this.lowresCache.get(r);
427
+ }
428
+ const p = Array.isArray(i.lods) ? (a = i.lods[t]) == null ? void 0 : a.path : i.lods;
429
+ if (!p)
430
+ return x && !i["missing:uri"] && (i["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, i)), null;
431
+ const f = dt(n.url, p);
432
+ if (f.endsWith(".glb") || f.endsWith(".gltf")) {
433
+ if (!i.guid)
434
+ return console.warn("missing pointer for glb/gltf texture", i), null;
435
+ const D = f + "_" + i.guid, O = this.previouslyLoaded.get(D);
436
+ if (O !== void 0) {
437
+ s && console.log(`LOD ${t} was already loading/loaded: ${D}`);
438
+ let h = await O.catch((T) => (console.error(`Error loading LOD ${t} from ${f}
439
+ `, T), null)), w = !1;
440
+ if (h == null || (h instanceof ne && e instanceof ne ? (l = h.image) != null && l.data || (c = h.source) != null && c.data ? h = this.copySettings(e, h) : (w = !0, this.previouslyLoaded.delete(D)) : h instanceof ye && e instanceof ye && ((d = h.attributes.position) != null && d.array || (w = !0, this.previouslyLoaded.delete(D)))), !w)
441
+ return h;
442
+ }
443
+ const P = await this.queue.slot(f);
444
+ if (!P.use)
445
+ return x && console.log(`LOD ${t} was aborted: ${f}`), null;
446
+ const b = i, E = new Promise(async (h, w) => {
447
+ const T = new Ce();
448
+ Ne(T), x && (await new Promise((v) => setTimeout(v, 1e3)), s && console.warn("Start loading (delayed) " + f, b.guid));
449
+ let F = f;
450
+ if (b && Array.isArray(b.lods)) {
451
+ const v = b.lods[t];
452
+ v.hash && (F += "?v=" + v.hash);
453
+ }
454
+ const S = await T.loadAsync(F).catch((v) => (console.error(`Error loading LOD ${t} from ${f}
455
+ `, v), h(null)));
456
+ if (!S)
457
+ return h(null);
458
+ const Z = S.parser;
459
+ s && console.log("Loading finished " + f, b.guid);
460
+ let A = 0;
461
+ if (S.parser.json.textures) {
462
+ let v = !1;
463
+ for (const m of S.parser.json.textures) {
464
+ if (m != null && m.extensions) {
465
+ const g = m == null ? void 0 : m.extensions[W];
466
+ if (g != null && g.guid && g.guid === b.guid) {
467
+ v = !0;
468
+ break;
469
+ }
470
+ }
471
+ A++;
472
+ }
473
+ if (v) {
474
+ let m = await Z.getDependency("texture", A);
475
+ return m && _.assignLODInformation(n.url, m, r, t, void 0), s && console.log('change "' + e.name + '" → "' + m.name + '"', f, A, m, D), e instanceof ne && (m = this.copySettings(e, m)), m && (m.guid = b.guid), h(m);
476
+ } else x && console.warn("Could not find texture with guid", b.guid, S.parser.json);
477
+ }
478
+ if (A = 0, S.parser.json.meshes) {
479
+ let v = !1;
480
+ for (const m of S.parser.json.meshes) {
481
+ if (m != null && m.extensions) {
482
+ const g = m == null ? void 0 : m.extensions[W];
483
+ if (g != null && g.guid && g.guid === b.guid) {
484
+ v = !0;
485
+ break;
486
+ }
487
+ }
488
+ A++;
489
+ }
490
+ if (v) {
491
+ const m = await Z.getDependency("mesh", A);
492
+ if (s && console.log(`Loaded Mesh "${m.name}"`, f, A, m, D), m.isMesh === !0) {
493
+ const g = m.geometry;
494
+ return _.assignLODInformation(n.url, g, r, t, 0), h(g);
495
+ } else {
496
+ const g = new Array();
497
+ for (let M = 0; M < m.children.length; M++) {
498
+ const C = m.children[M];
499
+ if (C.isMesh === !0) {
500
+ const B = C.geometry;
501
+ _.assignLODInformation(n.url, B, r, t, M), g.push(B);
502
+ }
503
+ }
504
+ return h(g);
505
+ }
506
+ } else x && console.warn("Could not find mesh with guid", b.guid, S.parser.json);
507
+ }
508
+ return h(null);
509
+ });
510
+ return this.previouslyLoaded.set(D, E), P.use(E), await E;
511
+ } else if (e instanceof ne) {
512
+ s && console.log("Load texture from uri: " + f);
513
+ const O = await new je().loadAsync(f);
514
+ return O ? (O.guid = i.guid, O.flipY = !1, O.needsUpdate = !0, O.colorSpace = e.colorSpace, s && console.log(i, O)) : x && console.warn("failed loading", f), O;
515
+ }
516
+ } else
517
+ x && console.warn(`Can not load LOD ${t}: no LOD info found for "${r}" ${e.name}`, e.type);
518
+ return null;
519
+ }
520
+ static assignLODInformation(e, t, s, n, r) {
521
+ if (!t) return;
522
+ t.userData || (t.userData = {});
523
+ const i = new Lt(e, s, n, r);
524
+ t.userData.LODS = i;
525
+ }
526
+ static getAssignedLODInformation(e) {
527
+ var t;
528
+ return ((t = e == null ? void 0 : e.userData) == null ? void 0 : t.LODS) || null;
529
+ }
530
+ // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
531
+ static copySettings(e, t) {
532
+ return t ? (x && console.warn(`Copy texture settings
533
+ `, e.uuid, `
534
+ `, t.uuid), t = t.clone(), 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) : e;
535
+ }
536
+ };
537
+ /**
538
+ * Register a texture with LOD information
539
+ */
540
+ u(_, "registerTexture", (e, t, s, n, r) => {
541
+ if (x && console.log("> Progressive: register texture", n, t.name, t.uuid, t, r), !t) {
542
+ x && console.error("gltf-progressive: Register texture without texture");
543
+ return;
544
+ }
545
+ t.source && (t.source[Oe] = r);
546
+ const i = r.guid;
547
+ _.assignLODInformation(e, t, i, s, n), _.lodInfos.set(i, r), _.lowresCache.set(i, t);
548
+ }), /**
549
+ * Register a mesh with LOD information
550
+ */
551
+ u(_, "registerMesh", (e, t, s, n, r, i) => {
552
+ var c;
553
+ const a = s.geometry;
554
+ if (!a) {
555
+ x && console.warn("gltf-progressive: Register mesh without geometry");
556
+ return;
557
+ }
558
+ a.userData || (a.userData = {}), x && console.log("> Progressive: register mesh " + s.name, { index: r, uuid: s.uuid }, i, s), _.assignLODInformation(e, a, t, n, r), _.lodInfos.set(t, i);
559
+ let l = _.lowresCache.get(t);
560
+ l ? l.push(s.geometry) : l = [s.geometry], _.lowresCache.set(t, l), n > 0 && !de(s) && pt(s, a);
561
+ for (const d of Q)
562
+ (c = d.onRegisteredNewMesh) == null || c.call(d, s, i);
563
+ }), /** A map of key = asset uuid and value = LOD information */
564
+ u(_, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
565
+ u(_, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
566
+ u(_, "lowresCache", /* @__PURE__ */ new Map()), u(_, "queue", new ht(100, { debug: x != !1 }));
567
+ let N = _;
568
+ class Lt {
569
+ constructor(e, t, s, n) {
570
+ u(this, "url");
571
+ /** the key to lookup the LOD information */
572
+ u(this, "key");
573
+ u(this, "level");
574
+ /** For multi objects (e.g. a group of meshes) this is the index of the object */
575
+ u(this, "index");
576
+ this.url = e, this.key = t, this.level = s, n != null && (this.index = n);
577
+ }
578
+ }
579
+ class me {
580
+ constructor(e, t) {
581
+ u(this, "frame_start");
582
+ u(this, "frame_capture_end");
583
+ u(this, "ready");
584
+ u(this, "_resolve");
585
+ u(this, "_signal");
586
+ u(this, "_resolved", !1);
587
+ u(this, "_addedCount", 0);
588
+ u(this, "_resolvedCount", 0);
589
+ /** These promises are currently being awaited */
590
+ u(this, "_awaiting", []);
591
+ u(this, "_maxPromisesPerObject", 1);
592
+ u(this, "_currentFrame", 0);
593
+ u(this, "_seen", /* @__PURE__ */ new WeakMap());
594
+ var r;
595
+ const n = Math.max(t.frames ?? 2, 2);
596
+ this.frame_start = e, this.frame_capture_end = e + n, this.ready = new Promise((i) => {
597
+ this._resolve = i;
598
+ }), this.ready.finally(() => {
599
+ this._resolved = !0, this._awaiting.length = 0;
600
+ }), this._signal = t.signal, (r = this._signal) == null || r.addEventListener("abort", () => {
601
+ this.resolveNow();
602
+ }), this._maxPromisesPerObject = Math.max(1, t.maxPromisesPerObject ?? 1);
603
+ }
604
+ /**
605
+ * The number of promises that have been added to this group so far.
606
+ */
607
+ get awaitedCount() {
608
+ return this._addedCount;
609
+ }
610
+ get resolvedCount() {
611
+ return this._resolvedCount;
612
+ }
613
+ get currentlyAwaiting() {
614
+ return this._awaiting.length;
615
+ }
616
+ update(e) {
617
+ var t;
618
+ this._currentFrame = e, ((t = this._signal) != null && t.aborted || this._currentFrame > this.frame_capture_end && this._awaiting.length === 0) && this.resolveNow();
619
+ }
620
+ add(e, t, s) {
621
+ if (this._resolved) {
622
+ x && console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
623
+ return;
624
+ }
625
+ if (!(this._currentFrame > this.frame_capture_end)) {
626
+ if (this._maxPromisesPerObject >= 1)
627
+ if (this._seen.has(t)) {
628
+ let n = this._seen.get(t);
629
+ if (n >= this._maxPromisesPerObject) {
630
+ x && console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");
631
+ return;
632
+ }
633
+ this._seen.set(t, n + 1);
634
+ } else
635
+ this._seen.set(t, 1);
636
+ this._awaiting.push(s), this._addedCount++, s.finally(() => {
637
+ this._resolvedCount++, this._awaiting.splice(this._awaiting.indexOf(s), 1);
638
+ });
639
+ }
640
+ }
641
+ resolveNow() {
642
+ var e, t;
643
+ this._resolved || (t = this._resolve) == null || t.call(this, {
644
+ awaited_count: this._addedCount,
645
+ resolved_count: this._resolvedCount,
646
+ cancelled: ((e = this._signal) == null ? void 0 : e.aborted) ?? !1
647
+ });
648
+ }
649
+ }
650
+ u(me, "addPromise", (e, t, s, n) => {
651
+ n.forEach((r) => {
652
+ r.add(e, t, s);
653
+ });
654
+ });
655
+ const I = ue("debugprogressive"), xt = ue("noprogressive"), be = Symbol("Needle:LODSManager"), Se = Symbol("Needle:LODState"), H = Symbol("Needle:CurrentLOD"), G = { mesh_lod: -1, texture_lod: -1 };
656
+ var y, $, X, we, j, re, _e, K;
657
+ let xe = (y = class {
658
+ // readonly plugins: NEEDLE_progressive_plugin[] = [];
659
+ constructor(e, t) {
660
+ u(this, "renderer");
661
+ u(this, "context");
662
+ u(this, "projectionScreenMatrix", new $e());
663
+ /**
664
+ * The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
665
+ * @default 200_000
666
+ */
667
+ u(this, "targetTriangleDensity", 2e5);
668
+ /**
669
+ * The interval in frames to automatically update the bounds of skinned meshes.
670
+ * Set to 0 or a negative value to disable automatic bounds updates.
671
+ * @default 30
672
+ */
673
+ u(this, "skinnedMeshAutoUpdateBoundsInterval", 30);
674
+ /**
675
+ * The update interval in frames. If set to 0, the LODs will be updated every frame. If set to 2, the LODs will be updated every second frame, etc.
676
+ * @default "auto"
677
+ */
678
+ u(this, "updateInterval", "auto");
679
+ Y(this, $, 1);
680
+ /**
681
+ * If set to true, the LODsManager will not update the LODs.
682
+ * @default false
683
+ */
684
+ u(this, "pause", !1);
685
+ /**
686
+ * When set to true the LODsManager will not update the LODs. This can be used to manually update the LODs using the `update` method.
687
+ * Otherwise the LODs will be updated automatically when the renderer renders the scene.
688
+ * @default false
689
+ */
690
+ u(this, "manual", !1);
691
+ u(this, "_newPromiseGroups", []);
692
+ u(this, "_promiseGroupIds", 0);
693
+ u(this, "_lodchangedlisteners", []);
694
+ Y(this, X);
695
+ Y(this, we, new Je());
696
+ Y(this, j, 0);
697
+ Y(this, re, 0);
698
+ Y(this, _e, 0);
699
+ Y(this, K, 0);
700
+ u(this, "_fpsBuffer", [60, 60, 60, 60, 60]);
701
+ // private testIfLODLevelsAreAvailable() {
702
+ u(this, "_sphere", new et());
703
+ u(this, "_tempBox", new ke());
704
+ u(this, "_tempBox2", new ke());
705
+ u(this, "tempMatrix", new $e());
706
+ u(this, "_tempWorldPosition", new V());
707
+ u(this, "_tempBoxSize", new V());
708
+ u(this, "_tempBox2Size", new V());
709
+ this.renderer = e, this.context = { ...t };
710
+ }
711
+ /** @internal */
712
+ static getObjectLODState(e) {
713
+ return e[Se];
714
+ }
715
+ static addPlugin(e) {
716
+ Q.push(e);
717
+ }
718
+ static removePlugin(e) {
719
+ const t = Q.indexOf(e);
720
+ t >= 0 && Q.splice(t, 1);
721
+ }
722
+ /**
723
+ * Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
724
+ * @param renderer The renderer to get the LODsManager for.
725
+ * @returns The LODsManager instance.
726
+ */
727
+ static get(e, t) {
728
+ if (e[be])
729
+ return console.debug("[gltf-progressive] LODsManager already exists for this renderer"), e[be];
730
+ const s = new y(e, {
731
+ engine: "unknown",
732
+ ...t
733
+ });
734
+ return e[be] = s, s;
735
+ }
736
+ /** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
737
+ get plugins() {
738
+ return Q;
739
+ }
740
+ /**
741
+ * Call to await LODs loading during the next render cycle.
742
+ */
743
+ awaitLoading(e) {
744
+ const t = this._promiseGroupIds++, s = new me(L(this, j), { ...e });
745
+ this._newPromiseGroups.push(s);
746
+ const n = performance.now();
747
+ return s.ready.finally(() => {
748
+ const r = this._newPromiseGroups.indexOf(s);
749
+ r >= 0 && (this._newPromiseGroups.splice(r, 1), ft() && performance.measure("LODsManager:awaitLoading", {
750
+ start: n,
751
+ detail: { id: t, name: e == null ? void 0 : e.name, awaited: s.awaitedCount, resolved: s.resolvedCount }
752
+ }));
753
+ }), s.ready;
754
+ }
755
+ _postprocessPromiseGroups() {
756
+ if (this._newPromiseGroups.length !== 0)
757
+ for (let e = this._newPromiseGroups.length - 1; e >= 0; e--)
758
+ this._newPromiseGroups[e].update(L(this, j));
759
+ }
760
+ addEventListener(e, t) {
761
+ e === "changed" && this._lodchangedlisteners.push(t);
762
+ }
763
+ removeEventListener(e, t) {
764
+ if (e === "changed") {
765
+ const s = this._lodchangedlisteners.indexOf(t);
766
+ s >= 0 && this._lodchangedlisteners.splice(s, 1);
767
+ }
768
+ }
769
+ /**
770
+ * Enable the LODsManager. This will replace the render method of the renderer with a method that updates the LODs.
771
+ */
772
+ enable() {
773
+ if (L(this, X)) return;
774
+ console.debug("[gltf-progressive] Enabling LODsManager for renderer");
775
+ let e = 0;
776
+ z(this, X, this.renderer.render);
777
+ const t = this;
778
+ ze(this.renderer), this.renderer.render = function(s, n) {
779
+ const r = t.renderer.getRenderTarget();
780
+ (r == null || "isXRRenderTarget" in r && r.isXRRenderTarget) && (e = 0, z(t, j, L(t, j) + 1), z(t, re, L(t, we).getDelta()), z(t, _e, L(t, _e) + L(t, re)), t._fpsBuffer.shift(), t._fpsBuffer.push(1 / L(t, re)), z(t, K, t._fpsBuffer.reduce((a, l) => a + l) / t._fpsBuffer.length), I && L(t, j) % 200 === 0 && console.log("FPS", Math.round(L(t, K)), "Interval:", L(t, $)));
781
+ const i = e++;
782
+ L(t, X).call(this, s, n), t.onAfterRender(s, n, i);
783
+ };
784
+ }
785
+ disable() {
786
+ L(this, X) && (console.debug("[gltf-progressive] Disabling LODsManager for renderer"), this.renderer.render = L(this, X), z(this, X, void 0));
787
+ }
788
+ update(e, t) {
789
+ this.internalUpdate(e, t);
790
+ }
791
+ onAfterRender(e, t, s) {
792
+ if (this.pause) return;
793
+ const r = this.renderer.renderLists.get(e, 0).opaque;
794
+ let i = !0;
795
+ if (r.length === 1) {
796
+ const a = r[0].material;
797
+ (a.name === "EffectMaterial" || a.name === "CopyShader") && (i = !1);
798
+ }
799
+ if ((t.parent && t.parent.type === "CubeCamera" || s >= 1 && t.type === "OrthographicCamera") && (i = !1), i) {
800
+ if (xt || (this.updateInterval === "auto" ? L(this, K) < 40 && L(this, $) < 10 ? (z(this, $, L(this, $) + 1), I && console.warn("↓ Reducing LOD updates", L(this, $), L(this, K).toFixed(0))) : L(this, K) >= 60 && L(this, $) > 1 && (z(this, $, L(this, $) - 1), I && console.warn("↑ Increasing LOD updates", L(this, $), L(this, K).toFixed(0))) : z(this, $, this.updateInterval), L(this, $) > 0 && L(this, j) % L(this, $) != 0))
801
+ return;
802
+ this.internalUpdate(e, t), this._postprocessPromiseGroups();
803
+ }
804
+ }
805
+ /**
806
+ * Update LODs in a scene
807
+ */
808
+ internalUpdate(e, t) {
809
+ var l, c;
810
+ const s = this.renderer.renderLists.get(e, 0), n = s.opaque;
811
+ this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse);
812
+ const r = this.targetTriangleDensity;
813
+ for (const d of n) {
814
+ if (d.material && (((l = d.geometry) == null ? void 0 : l.type) === "BoxGeometry" || ((c = d.geometry) == null ? void 0 : c.type) === "BufferGeometry") && (d.material.name === "SphericalGaussianBlur" || d.material.name == "BackgroundCubeMaterial" || d.material.name === "CubemapFromEquirect" || d.material.name === "EquirectangularToCubeUV")) {
815
+ I && (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)));
816
+ continue;
817
+ }
818
+ switch (d.material.type) {
819
+ case "LineBasicMaterial":
820
+ case "LineDashedMaterial":
821
+ case "PointsMaterial":
822
+ case "ShadowMaterial":
823
+ case "MeshDistanceMaterial":
824
+ case "MeshDepthMaterial":
825
+ continue;
826
+ }
827
+ if (I === "color" && d.material && !d.object.progressive_debug_color) {
828
+ d.object.progressive_debug_color = !0;
829
+ const f = Math.random() * 16777215, D = new Ze({ color: f });
830
+ d.object.material = D;
831
+ }
832
+ const p = d.object;
833
+ (p instanceof te || p.isMesh) && this.updateLODs(e, t, p, r);
834
+ }
835
+ const i = s.transparent;
836
+ for (const d of i) {
837
+ const p = d.object;
838
+ (p instanceof te || p.isMesh) && this.updateLODs(e, t, p, r);
839
+ }
840
+ const a = s.transmissive;
841
+ for (const d of a) {
842
+ const p = d.object;
843
+ (p instanceof te || p.isMesh) && this.updateLODs(e, t, p, r);
844
+ }
845
+ }
846
+ /** Update the LOD levels for the renderer. */
847
+ updateLODs(e, t, s, n) {
848
+ var a, l;
849
+ s.userData || (s.userData = {});
850
+ let r = s[Se];
851
+ if (r || (r = new wt(), s[Se] = r), r.frames++ < 2)
852
+ return;
853
+ for (const c of Q)
854
+ (a = c.onBeforeUpdateLOD) == null || a.call(c, this.renderer, e, t, s);
855
+ const i = y.overrideGlobalLodLevel !== void 0 ? y.overrideGlobalLodLevel : ee;
856
+ i >= 0 ? (G.mesh_lod = i, G.texture_lod = i) : (this.calculateLodLevel(t, s, r, n, G), G.mesh_lod = Math.round(G.mesh_lod), G.texture_lod = Math.round(G.texture_lod)), G.mesh_lod >= 0 && this.loadProgressiveMeshes(s, G.mesh_lod), s.material && G.texture_lod >= 0 && this.loadProgressiveTextures(s.material, G.texture_lod), x && s.material && !s.isGizmo && Ve(s.material);
857
+ for (const c of Q)
858
+ (l = c.onAfterUpdatedLOD) == null || l.call(c, this.renderer, e, t, s, G);
859
+ r.lastLodLevel_Mesh = G.mesh_lod, r.lastLodLevel_Texture = G.texture_lod;
860
+ }
861
+ /** Load progressive textures for the given material
862
+ * @param material the material to load the textures for
863
+ * @param level the LOD level to load. Level 0 is the best quality, higher levels are lower quality
864
+ * @returns Promise with true if the LOD was loaded, false if not
865
+ */
866
+ loadProgressiveTextures(e, t) {
867
+ if (!e) return;
868
+ if (Array.isArray(e)) {
869
+ for (const r of e)
870
+ this.loadProgressiveTextures(r, t);
871
+ return;
872
+ }
873
+ let s = !1;
874
+ (e[H] === void 0 || t < e[H]) && (s = !0);
875
+ const n = e["DEBUG:LOD"];
876
+ if (n != null && (s = e[H] != n, t = n), s) {
877
+ e[H] = t;
878
+ const r = N.assignTextureLOD(e, t).then((i) => {
879
+ this._lodchangedlisteners.forEach((a) => a({ type: "texture", level: t, object: e }));
880
+ });
881
+ me.addPromise("texture", e, r, this._newPromiseGroups);
882
+ }
883
+ }
884
+ /** Load progressive meshes for the given mesh
885
+ * @param mesh the mesh to load the LOD for
886
+ * @param index the index of the mesh if it's part of a group
887
+ * @param level the LOD level to load. Level 0 is the best quality, higher levels are lower quality
888
+ * @returns Promise with true if the LOD was loaded, false if not
889
+ */
890
+ loadProgressiveMeshes(e, t) {
891
+ if (!e) return Promise.resolve(null);
892
+ let s = e[H] !== t;
893
+ const n = e["DEBUG:LOD"];
894
+ if (n != null && (s = e[H] != n, t = n), s) {
895
+ e[H] = t;
896
+ const r = e.geometry, i = N.assignMeshLOD(e, t).then((a) => (a && e[H] == t && r != e.geometry && this._lodchangedlisteners.forEach((l) => l({ type: "mesh", level: t, object: e })), a));
897
+ return me.addPromise("mesh", e, i, this._newPromiseGroups), i;
898
+ }
899
+ return Promise.resolve(null);
900
+ }
901
+ static isInside(e, t) {
902
+ const s = e.min, n = e.max, r = (s.x + n.x) * 0.5, i = (s.y + n.y) * 0.5;
903
+ return this._tempPtInside.set(r, i, s.z).applyMatrix4(t).z < 0;
904
+ }
905
+ calculateLodLevel(e, t, s, n, r) {
906
+ var b, E, J;
907
+ if (!t) {
908
+ r.mesh_lod = -1, r.texture_lod = -1;
909
+ return;
910
+ }
911
+ if (!e) {
912
+ r.mesh_lod = -1, r.texture_lod = -1;
913
+ return;
914
+ }
915
+ let a = 10 + 1, l = !1;
916
+ if (I && t["DEBUG:LOD"] != null)
917
+ return t["DEBUG:LOD"];
918
+ const c = (b = N.getMeshLODExtension(t.geometry)) == null ? void 0 : b.lods, d = N.getPrimitiveIndex(t.geometry), p = c && c.length > 0, f = N.getMaterialMinMaxLODsCount(t.material), D = (f == null ? void 0 : f.min_count) != 1 / 0 && f.min_count > 0 && f.max_count > 0;
919
+ if (!p && !D) {
920
+ r.mesh_lod = 0, r.texture_lod = 0;
921
+ return;
922
+ }
923
+ p || (l = !0, a = 0);
924
+ const O = this.renderer.domElement.clientHeight || this.renderer.domElement.height;
925
+ let P = t.geometry.boundingBox;
926
+ if (t.type === "SkinnedMesh") {
927
+ const h = t;
928
+ if (!h.boundingBox)
929
+ h.computeBoundingBox();
930
+ else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
931
+ if (!h[y.$skinnedMeshBoundsOffset]) {
932
+ const T = y.skinnedMeshBoundsFrameOffsetCounter++;
933
+ h[y.$skinnedMeshBoundsOffset] = T;
934
+ }
935
+ const w = h[y.$skinnedMeshBoundsOffset];
936
+ if ((s.frames + w) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
937
+ const T = de(h), F = h.geometry;
938
+ T && (h.geometry = T), h.computeBoundingBox(), h.geometry = F;
939
+ }
940
+ }
941
+ P = h.boundingBox;
942
+ }
943
+ if (P) {
944
+ const h = e;
945
+ if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
946
+ this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
947
+ const g = e.getWorldPosition(this._tempWorldPosition);
948
+ if (this._sphere.containsPoint(g)) {
949
+ r.mesh_lod = 0, r.texture_lod = 0;
950
+ return;
951
+ }
952
+ }
953
+ if (this._tempBox.copy(P), this._tempBox.applyMatrix4(t.matrixWorld), h.isPerspectiveCamera && y.isInside(this._tempBox, this.projectionScreenMatrix)) {
954
+ r.mesh_lod = 0, r.texture_lod = 0;
955
+ return;
956
+ }
957
+ if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && h.isPerspectiveCamera && h.fov > 70) {
958
+ const g = this._tempBox.min, M = this._tempBox.max;
959
+ let C = g.x, B = g.y, U = M.x, ie = M.y;
960
+ const ce = 2, Me = 1.5, fe = (g.x + M.x) * 0.5, he = (g.y + M.y) * 0.5;
961
+ C = (C - fe) * ce + fe, B = (B - he) * ce + he, U = (U - fe) * ce + fe, ie = (ie - he) * ce + he;
962
+ const Ke = C < 0 && U > 0 ? 0 : Math.min(Math.abs(g.x), Math.abs(M.x)), Ye = B < 0 && ie > 0 ? 0 : Math.min(Math.abs(g.y), Math.abs(M.y)), De = Math.max(Ke, Ye);
963
+ s.lastCentrality = (Me - De) * (Me - De) * (Me - De);
964
+ } else
965
+ s.lastCentrality = 1;
966
+ const w = this._tempBox.getSize(this._tempBoxSize);
967
+ w.multiplyScalar(0.5), screen.availHeight > 0 && O > 0 && w.multiplyScalar(O / screen.availHeight), e.isPerspectiveCamera ? w.x *= e.aspect : e.isOrthographicCamera;
968
+ const T = e.matrixWorldInverse, F = this._tempBox2;
969
+ F.copy(P), F.applyMatrix4(t.matrixWorld), F.applyMatrix4(T);
970
+ const S = F.getSize(this._tempBox2Size), Z = Math.max(S.x, S.y);
971
+ if (Math.max(w.x, w.y) != 0 && Z != 0 && (w.z = S.z / Math.max(S.x, S.y) * Math.max(w.x, w.y)), s.lastScreenCoverage = Math.max(w.x, w.y, w.z), s.lastScreenspaceVolume.copy(w), s.lastScreenCoverage *= s.lastCentrality, I && y.debugDrawLine) {
972
+ const g = this.tempMatrix.copy(this.projectionScreenMatrix);
973
+ g.invert();
974
+ const M = y.corner0, C = y.corner1, B = y.corner2, U = y.corner3;
975
+ M.copy(this._tempBox.min), C.copy(this._tempBox.max), C.x = M.x, B.copy(this._tempBox.max), B.y = M.y, U.copy(this._tempBox.max);
976
+ const ie = (M.z + U.z) * 0.5;
977
+ M.z = C.z = B.z = U.z = ie, M.applyMatrix4(g), C.applyMatrix4(g), B.applyMatrix4(g), U.applyMatrix4(g), y.debugDrawLine(M, C, 255), y.debugDrawLine(M, B, 255), y.debugDrawLine(C, U, 255), y.debugDrawLine(B, U, 255);
978
+ }
979
+ let v = 999;
980
+ if (c && s.lastScreenCoverage > 0)
981
+ for (let g = 0; g < c.length; g++) {
982
+ const M = c[g];
983
+ if ((((E = M.densities) == null ? void 0 : E[d]) || M.density || 1e-5) / s.lastScreenCoverage < n) {
984
+ v = g;
985
+ break;
986
+ }
987
+ }
988
+ v < a && (a = v, l = !0);
989
+ }
990
+ if (l ? r.mesh_lod = a : r.mesh_lod = s.lastLodLevel_Mesh, I && r.mesh_lod != s.lastLodLevel_Mesh) {
991
+ const w = c == null ? void 0 : c[r.mesh_lod];
992
+ w && console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${w.density.toFixed(0)}) - ${t.name}`);
993
+ }
994
+ if (D) {
995
+ const h = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
996
+ if (s.lastLodLevel_Texture < 0) {
997
+ if (r.texture_lod = f.max_count - 1, I) {
998
+ const w = f.lods[f.max_count - 1];
999
+ I && console.log(`First Texture LOD ${r.texture_lod} (${w.max_height}px) - ${t.name}`);
1000
+ }
1001
+ } else {
1002
+ const w = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
1003
+ let T = s.lastScreenCoverage * 4;
1004
+ ((J = this.context) == null ? void 0 : J.engine) === "model-viewer" && (T *= 1.5);
1005
+ const S = O / window.devicePixelRatio * T;
1006
+ let Z = !1;
1007
+ for (let A = f.lods.length - 1; A >= 0; A--) {
1008
+ const v = f.lods[A];
1009
+ if (!(h && v.max_height >= 2048) && !(ct() && v.max_height > 4096) && (v.max_height > S || !Z && A === 0)) {
1010
+ if (Z = !0, r.texture_lod = A, r.texture_lod < s.lastLodLevel_Texture) {
1011
+ const m = v.max_height;
1012
+ I && console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${m}px
1013
+ Screensize: ${S.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
1014
+ ${t.name}`);
1015
+ }
1016
+ break;
1017
+ }
1018
+ }
1019
+ }
1020
+ } else
1021
+ r.texture_lod = 0;
1022
+ }
1023
+ }, $ = new WeakMap(), X = new WeakMap(), we = new WeakMap(), j = new WeakMap(), re = new WeakMap(), _e = new WeakMap(), K = new WeakMap(), /**
1024
+ * 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.
1025
+ */
1026
+ u(y, "debugDrawLine"), /**
1027
+ * Force override the LOD level for all objects in the scene
1028
+ */
1029
+ u(y, "overrideGlobalLodLevel"), u(y, "corner0", new V()), u(y, "corner1", new V()), u(y, "corner2", new V()), u(y, "corner3", new V()), u(y, "_tempPtInside", new V()), u(y, "skinnedMeshBoundsFrameOffsetCounter", 0), u(y, "$skinnedMeshBoundsOffset", Symbol("gltf-progressive-skinnedMeshBoundsOffset")), y);
1030
+ class wt {
1031
+ constructor() {
1032
+ u(this, "frames", 0);
1033
+ u(this, "lastLodLevel_Mesh", -1);
1034
+ u(this, "lastLodLevel_Texture", -1);
1035
+ u(this, "lastScreenCoverage", 0);
1036
+ u(this, "lastScreenspaceVolume", new V());
1037
+ u(this, "lastCentrality", 0);
1038
+ }
1039
+ }
1040
+ const Ee = Symbol("NEEDLE_mesh_lod"), ge = Symbol("NEEDLE_texture_lod");
1041
+ let le = null;
1042
+ function We() {
1043
+ const o = _t();
1044
+ o && (o.mapURLs(function(e) {
1045
+ return Ie(), e;
1046
+ }), Ie(), le == null || le.disconnect(), le = new MutationObserver((e) => {
1047
+ e.forEach((t) => {
1048
+ t.addedNodes.forEach((s) => {
1049
+ s instanceof HTMLElement && s.tagName.toLowerCase() === "model-viewer" && Xe(s);
1050
+ });
1051
+ });
1052
+ }), le.observe(document, { childList: !0, subtree: !0 }));
1053
+ }
1054
+ function _t() {
1055
+ if (typeof customElements > "u") return null;
1056
+ const o = customElements.get("model-viewer");
1057
+ return o || (customElements.whenDefined("model-viewer").then(() => {
1058
+ console.debug("[gltf-progressive] model-viewer defined"), We();
1059
+ }), null);
1060
+ }
1061
+ function Ie() {
1062
+ if (typeof document > "u") return;
1063
+ document.querySelectorAll("model-viewer").forEach((e) => {
1064
+ Xe(e);
1065
+ });
1066
+ }
1067
+ const Re = /* @__PURE__ */ new WeakSet();
1068
+ let Mt = 0;
1069
+ function Xe(o) {
1070
+ if (!o || Re.has(o))
1071
+ return null;
1072
+ Re.add(o), console.debug("[gltf-progressive] found new model-viewer..." + ++Mt + `
1073
+ `, o.getAttribute("src"));
1074
+ let e = null, t = null, s = null;
1075
+ for (let n = o; n != null; n = Object.getPrototypeOf(n)) {
1076
+ const r = Object.getOwnPropertySymbols(n), i = r.find((c) => c.toString() == "Symbol(renderer)"), a = r.find((c) => c.toString() == "Symbol(scene)"), l = r.find((c) => c.toString() == "Symbol(needsRender)");
1077
+ !e && i != null && (e = o[i].threeRenderer), !t && a != null && (t = o[a]), !s && l != null && (s = o[l]);
1078
+ }
1079
+ if (e && t) {
1080
+ let n = function() {
1081
+ if (s) {
1082
+ let i = 0, a = setInterval(() => {
1083
+ if (i++ > 5) {
1084
+ clearInterval(a);
1085
+ return;
1086
+ }
1087
+ s == null || s.call(o);
1088
+ }, 300);
1089
+ }
1090
+ };
1091
+ console.debug("[gltf-progressive] setup model-viewer");
1092
+ const r = xe.get(e, { engine: "model-viewer" });
1093
+ return xe.addPlugin(new Dt()), r.enable(), r.addEventListener("changed", () => {
1094
+ s == null || s.call(o);
1095
+ }), o.addEventListener("model-visibility", (i) => {
1096
+ i.detail.visible && (s == null || s.call(o));
1097
+ }), o.addEventListener("load", () => {
1098
+ n();
1099
+ }), () => {
1100
+ r.disable();
1101
+ };
1102
+ }
1103
+ return null;
1104
+ }
1105
+ class Dt {
1106
+ constructor() {
1107
+ u(this, "_didWarnAboutMissingUrl", !1);
1108
+ }
1109
+ onBeforeUpdateLOD(e, t, s, n) {
1110
+ this.tryParseMeshLOD(t, n), this.tryParseTextureLOD(t, n);
1111
+ }
1112
+ getUrl(e) {
1113
+ if (!e)
1114
+ return null;
1115
+ let t = e.getAttribute("src");
1116
+ return t || (t = e.src), t || (this._didWarnAboutMissingUrl || console.warn("No url found in modelviewer", e), this._didWarnAboutMissingUrl = !0), t;
1117
+ }
1118
+ tryGetCurrentGLTF(e) {
1119
+ return e._currentGLTF;
1120
+ }
1121
+ tryGetCurrentModelViewer(e) {
1122
+ return e.element;
1123
+ }
1124
+ tryParseTextureLOD(e, t) {
1125
+ if (t[ge] == !0) return;
1126
+ t[ge] = !0;
1127
+ const s = this.tryGetCurrentGLTF(e), n = this.tryGetCurrentModelViewer(e), r = this.getUrl(n);
1128
+ if (r && s && t.material) {
1129
+ let i = function(l) {
1130
+ var d, p, f;
1131
+ if (l[ge] == !0) return;
1132
+ l[ge] = !0, l.userData && (l.userData.LOD = -1);
1133
+ const c = Object.keys(l);
1134
+ for (let D = 0; D < c.length; D++) {
1135
+ const O = c[D], P = l[O];
1136
+ if ((P == null ? void 0 : P.isTexture) === !0) {
1137
+ const b = (p = (d = P.userData) == null ? void 0 : d.associations) == null ? void 0 : p.textures;
1138
+ if (b == null) continue;
1139
+ const E = s.parser.json.textures[b];
1140
+ if (!E) {
1141
+ console.warn("Texture data not found for texture index " + b);
1142
+ continue;
1143
+ }
1144
+ if ((f = E == null ? void 0 : E.extensions) != null && f[W]) {
1145
+ const J = E.extensions[W];
1146
+ J && r && N.registerTexture(r, P, J.lods.length, b, J);
1147
+ }
1148
+ }
1149
+ }
1150
+ };
1151
+ const a = t.material;
1152
+ if (Array.isArray(a)) for (const l of a) i(l);
1153
+ else i(a);
1154
+ }
1155
+ }
1156
+ tryParseMeshLOD(e, t) {
1157
+ var i, a;
1158
+ if (t[Ee] == !0) return;
1159
+ t[Ee] = !0;
1160
+ const s = this.tryGetCurrentModelViewer(e), n = this.getUrl(s);
1161
+ if (!n)
1162
+ return;
1163
+ const r = (a = (i = t.userData) == null ? void 0 : i.gltfExtensions) == null ? void 0 : a[W];
1164
+ if (r && n) {
1165
+ const l = t.uuid;
1166
+ N.registerMesh(n, l, t, 0, r.lods.length, r);
1167
+ }
1168
+ }
1169
+ }
1170
+ function vt(o, e, t, s) {
1171
+ ze(e), Ne(t), qe(t, {
1172
+ progressive: !0,
1173
+ ...s == null ? void 0 : s.hints
1174
+ }), t.register((r) => new N(r, o));
1175
+ const n = xe.get(e);
1176
+ return (s == null ? void 0 : s.enableLODsManager) !== !1 && n.enable(), n;
1177
+ }
1178
+ We();
1179
+ if (!gt) {
1180
+ const o = {
1181
+ gltfProgressive: {
1182
+ useNeedleProgressive: vt,
1183
+ LODsManager: xe,
1184
+ configureLoader: qe,
1185
+ getRaycastMesh: de,
1186
+ useRaycastMeshes: mt
1187
+ }
1188
+ };
1189
+ if (!globalThis.Needle)
1190
+ globalThis.Needle = o;
1191
+ else
1192
+ for (const e in o)
1193
+ globalThis.Needle[e] = o[e];
1194
+ }
1195
+ export {
1196
+ xe as LODsManager,
1197
+ N as NEEDLE_progressive,
1198
+ Ne as addDracoAndKTX2Loaders,
1199
+ qe as configureLoader,
1200
+ ze as createLoaders,
1201
+ de as getRaycastMesh,
1202
+ at as setDracoDecoderLocation,
1203
+ lt as setKTX2TranscoderLocation
1204
+ };