@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.
@@ -1,74 +1,86 @@
1
- var oe = Object.defineProperty;
2
- var ae = (l, e, t) => e in l ? oe(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var u = (l, e, t) => (ae(l, typeof e != "symbol" ? e + "" : e, t), t);
4
- import { Mesh as q, BufferGeometry as X, Material as le, RawShaderMaterial as ue, Texture as U, TextureLoader as ce, Matrix4 as j, Frustum as fe, Sphere as de, Box3 as ee, Vector3 as k } from "three";
5
- import { GLTFLoader as ge } from "three/examples/jsm/loaders/GLTFLoader.js";
6
- import { MeshoptDecoder as he } from "three/examples/jsm/libs/meshopt_decoder.module.js";
7
- import { DRACOLoader as pe } from "three/examples/jsm/loaders/DRACOLoader.js";
8
- import { KTX2Loader as ye } from "three/examples/jsm/loaders/KTX2Loader.js";
9
- const me = "https://www.gstatic.com/draco/versioned/decoders/1.4.1/", Le = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
10
- let F, H, W;
11
- function se(l) {
12
- F || (F = new pe(), F.setDecoderPath(me), F.setDecoderConfig({ type: "js" })), W || (W = new ye(), W.setTranscoderPath(Le)), H || (H = he), l ? W.detectSupport(l) : console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail");
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
- function ie(l) {
15
- l.dracoLoader || l.setDRACOLoader(F), l.ktx2Loader || l.setKTX2Loader(W), l.meshoptDecoder || l.setMeshoptDecoder(H);
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 Z(l) {
18
- const t = new URL(window.location.href).searchParams.get(l);
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 De(l, e) {
22
- if (e === void 0 || e.startsWith("./") || e.startsWith("http") || l === void 0)
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 = l.lastIndexOf("/");
33
+ const t = a.lastIndexOf("/");
25
34
  if (t >= 0) {
26
- const r = l.substring(0, t + 1);
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
- const J = new Array();
34
- function Be(l) {
35
- J.push(l);
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", S = Z("debugprogressive"), V = Symbol("needle-progressive-texture"), z = /* @__PURE__ */ new Map(), Q = /* @__PURE__ */ new Set();
38
- if (S) {
39
- let l = function() {
40
- e += 1, console.log("Toggle LOD level", e, z), z.forEach((i, n) => {
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 a = v.getMeshLODInformation(o), h = a ? Math.min(e, a.lods.length) : 0;
45
- n["DEBUG:LOD"] = e, v.assignMeshLOD(n, h), a && (t = Math.max(t, a.lods.length - 1));
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, v.assignTextureLOD(n, 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" && l(), i.key === "w" && (r = !r, Q && Q.forEach((n) => {
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 te(l, e, t) {
71
+ function ae(a, e, t) {
60
72
  var i;
61
- if (!S)
73
+ if (!w)
62
74
  return;
63
- z.has(l) || z.set(l, { keys: [], sourceId: t });
64
- const r = z.get(l);
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 M = class {
79
+ const v = class {
68
80
  constructor(e, t) {
69
- u(this, "parser");
70
- u(this, "url");
71
- S && console.log("Progressive extension registered for", t), this.parser = e, this.url = t;
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 q || e.isMesh === !0) {
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 J)
182
+ for (const s of B)
133
183
  (r = s.onBeforeGetLODMesh) == null || r.call(s, e, t);
134
- return e["LOD:requested level"] = t, M.getOrLoadLOD(i, t).then((s) => {
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 X && (e.geometry = s, S && te(e, "geometry", n.url));
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
- S && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", e);
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 le || e.isMaterial === !0) {
208
+ if (e instanceof xe || e.isMaterial === !0) {
159
209
  const r = e, i = [], n = new Array();
160
- if (S && Q.add(r), r instanceof ue)
161
- for (const s of Object.keys(r.uniforms)) {
162
- const o = r.uniforms[s].value;
163
- if ((o == null ? void 0 : o.isTexture) === !0) {
164
- const a = this.assignTextureLODForSlot(o, t, r, s);
165
- i.push(a), n.push(s);
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 a = this.assignTextureLODForSlot(o, t, r, s);
173
- i.push(a), n.push(s);
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 a = 0; a < s.length; a++) {
179
- const h = s[a], d = n[a];
180
- h && h.isTexture === !0 ? o.push({ material: r, slot: d, texture: h, level: t }) : o.push({ material: r, slot: d, texture: null, level: t });
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 U || e.isTexture === !0) {
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
- return (e == null ? void 0 : e.isTexture) !== !0 ? Promise.resolve(null) : M.getOrLoadLOD(e, t).then((n) => {
193
- if (Array.isArray(n))
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 ((n == null ? void 0 : n.isTexture) === !0) {
196
- if (n != e && (r && i && (r[i] = n), S && i && r)) {
197
- const s = this.getAssignedLODInformation(e);
198
- s && te(r, i, s.url);
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 n;
256
+ return s;
201
257
  } else
202
- S == "verbose" && console.warn("No LOD found for", e, t);
258
+ w == "verbose" && console.warn("No LOD found for", e, t);
203
259
  return null;
204
- }).catch((n) => (console.error("Error loading LOD", e, n), null));
260
+ }).catch((s) => (console.error("Error loading LOD", e, s), null));
205
261
  }
206
262
  afterRoot(e) {
207
263
  var t, r;
208
- return S && console.log("AFTER", this.url, e), (t = this.parser.json.textures) == null || t.forEach((i, n) => {
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 a of this.parser.associations.keys())
214
- a.isTexture === !0 && this.parser.associations.get(a).textures === n && (o = !0, M.registerTexture(this.url, a, n, s));
215
- o || this.parser.getDependency("texture", n).then((a) => {
216
- a && M.registerTexture(this.url, a, n, s);
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 a = this.parser.associations.get(o);
227
- a.meshes === n && M.registerMesh(this.url, s.guid, o, s.lods.length, a.primitives, s);
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, a, h;
235
- const r = S == "verbose", i = e.userData.LODS;
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 d = e;
242
- d.source && d.source[V] && (s = d.source[V]);
297
+ const m = e;
298
+ m.source && m.source[j] && (s = m.source[j]);
243
299
  }
244
- if (s || (s = M.lodInfos.get(n)), s) {
300
+ if (s || (s = v.lodInfos.get(n)), s) {
245
301
  if (t > 0) {
246
- let f = !1;
247
- const w = Array.isArray(s.lods);
248
- if (w && t >= s.lods.length ? f = !0 : w || (f = !0), f)
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 d = Array.isArray(s.lods) ? s.lods[t].path : s.lods;
252
- if (!d)
253
- return S && !s["missing:uri"] && (s["missing:uri"] = !0, console.warn("Missing uri for progressive asset for LOD " + t, s)), null;
254
- const c = De(i.url, d);
255
- if (c.endsWith(".glb") || c.endsWith(".gltf")) {
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 f = c + "_" + s.guid, w = this.previouslyLoaded.get(f);
259
- if (w !== void 0) {
260
- r && console.log(`LOD ${t} was already loading/loaded: ${f}`);
261
- let D = await w.catch((I) => (console.error(`Error loading LOD ${t} from ${c}
262
- `, I), null)), C = !1;
263
- if (D == null || (D instanceof U && e instanceof U ? (o = D.image) != null && o.data || (a = D.source) != null && a.data ? D = this.copySettings(e, D) : (C = !0, this.previouslyLoaded.delete(f)) : D instanceof X && e instanceof X && ((h = D.attributes.position) != null && h.array || (C = !0, this.previouslyLoaded.delete(f)))), !C)
264
- return D;
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 L = s, A = new Promise(async (D, C) => {
267
- const I = new ge();
268
- ie(I), S && (await new Promise((y) => setTimeout(y, 1e3)), r && console.warn("Start loading (delayed) " + c, L.guid));
269
- let m = c;
270
- if (L && Array.isArray(L.lods)) {
271
- const y = L.lods[t];
272
- y.hash && (m += "?v=" + y.hash);
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 p = await I.loadAsync(m).catch((y) => (console.error(`Error loading LOD ${t} from ${c}
275
- `, y), null));
276
- if (!p)
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 b = p.parser;
279
- r && console.log("Loading finished " + c, L.guid);
280
- let x = 0;
281
- if (p.parser.json.textures) {
282
- let y = !1;
283
- for (const g of p.parser.json.textures) {
284
- if (g != null && g.extensions) {
285
- const O = g == null ? void 0 : g.extensions[R];
286
- if (O != null && O.guid && O.guid === L.guid) {
287
- y = !0;
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
- x++;
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 (x = 0, p.parser.json.meshes) {
299
- let y = !1;
300
- for (const g of p.parser.json.meshes) {
301
- if (g != null && g.extensions) {
302
- const O = g == null ? void 0 : g.extensions[R];
303
- if (O != null && O.guid && O.guid === L.guid) {
304
- y = !0;
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
- x++;
365
+ p++;
309
366
  }
310
- if (y) {
311
- const g = await b.getDependency("mesh", x), O = L;
312
- if (r && console.log(`Loaded Mesh "${g.name}"`, c, x, g, f), g.isMesh === !0) {
313
- const P = g.geometry;
314
- return M.assignLODInformation(i.url, P, n, t, void 0, O.density), D(P);
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 P = new Array();
317
- for (let _ = 0; _ < g.children.length; _++) {
318
- const E = g.children[_];
319
- if (E instanceof q) {
320
- const N = E.geometry;
321
- M.assignLODInformation(i.url, N, n, t, _, O.density), P.push(N);
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 D(P);
381
+ return O(_);
325
382
  }
326
383
  }
327
384
  }
328
- return D(null);
385
+ return O(null);
329
386
  });
330
- return this.previouslyLoaded.set(f, A), await A;
331
- } else if (e instanceof U) {
332
- r && console.log("Load texture from uri: " + c);
333
- const w = await new ce().loadAsync(c);
334
- return w ? (w.guid = s.guid, w.flipY = !1, w.needsUpdate = !0, w.colorSpace = e.colorSpace, r && console.log(s, w)) : S && console.warn("failed loading", c), w;
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
- S && console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`, e.type);
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 xe(e, r, i, n, s);
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
- const r = this._copiedTextures.get(e);
353
- return r || (t = t.clone(), this._copiedTextures.set(e, t), t.offset = e.offset, t.repeat = e.repeat, t.colorSpace = e.colorSpace, t);
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 v = M;
415
+ let S = v;
357
416
  /**
358
417
  * Register a texture with LOD information
359
418
  */
360
- u(v, "registerTexture", (e, t, r, i) => {
361
- S && console.log("> Progressive: register texture", r, t.name, t.uuid, t, i), t.source && (t.source[V] = i);
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
- M.assignLODInformation(e, t, n, 0, 0, void 0), M.lodInfos.set(n, i), M.lowresCache.set(n, t);
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
- u(v, "registerMesh", (e, t, r, i, n, s) => {
368
- var h;
369
- S && console.log("> Progressive: register mesh", n, r.name, s, r.uuid, r);
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 = {}), M.assignLODInformation(e, o, t, i, n, s.density), M.lodInfos.set(t, s);
372
- let a = M.lowresCache.get(t);
373
- a ? a.push(r.geometry) : a = [r.geometry], M.lowresCache.set(t, a);
374
- for (const d of J)
375
- (h = d.onRegisteredNewMesh) == null || h.call(d, r, s);
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
- u(v, "lodInfos", /* @__PURE__ */ new Map()), /** cache of already loaded mesh lods */
378
- u(v, "previouslyLoaded", /* @__PURE__ */ new Map()), /** this contains the geometry/textures that were originally loaded */
379
- u(v, "lowresCache", /* @__PURE__ */ new Map()), u(v, "_copiedTextures", /* @__PURE__ */ new Map());
380
- class xe {
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
- u(this, "url");
441
+ f(this, "url");
383
442
  /** the key to lookup the LOD information */
384
- u(this, "key");
385
- u(this, "level");
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
- u(this, "index");
446
+ f(this, "index");
388
447
  /** the mesh density */
389
- u(this, "density");
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 Y = Z("debugprogressive"), we = Z("noprogressive"), T = class {
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
- u(this, "renderer");
396
- u(this, "projectionScreenMatrix", new j());
397
- u(this, "cameraFrustrum", new fe());
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
- u(this, "updateInterval", 0);
466
+ f(this, "updateInterval", 0);
402
467
  /**
403
468
  * If set to true, the LODsManager will not update the LODs.
404
469
  */
405
- u(this, "pause", !1);
406
- u(this, "plugins", []);
407
- u(this, "_originalRender");
470
+ f(this, "pause", !1);
471
+ f(this, "_frame", 0);
472
+ f(this, "_originalRender");
408
473
  // private testIfLODLevelsAreAvailable() {
409
- u(this, "_sphere", new de());
410
- u(this, "_tempBox", new ee());
411
- u(this, "tempMatrix", new j());
412
- u(this, "_tempWorldPosition", new k());
413
- u(this, "_tempBoxSize", new k());
414
- u(this, "_tempBox2Size", new k());
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
- let r = 0;
432
- se(this.renderer), this.renderer.render = function(i, n) {
433
- const s = r++, o = e++;
434
- t.onBeforeRender(i, n, o, s), t._originalRender.call(this, i, n), t.onAfterRender(i, n, o, s), e--;
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 h, d;
444
- if (we || this.pause || this.updateInterval > 0 && i % this.updateInterval != 0)
528
+ var l, d;
529
+ if (this.pause)
445
530
  return;
446
- this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix, t.matrixWorldInverse), this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix, this.renderer.coordinateSystem);
447
- const n = 1e5, s = this.renderer.renderLists.get(e, r), o = s.opaque;
448
- for (const c of o) {
449
- if (c.material && (((h = c.geometry) == null ? void 0 : h.type) === "BoxGeometry" || ((d = c.geometry) == null ? void 0 : d.type) === "BufferGeometry") && (c.material.name === "SphericalGaussianBlur" || c.material.name == "BackgroundCubeMaterial" || c.material.name === "CubemapFromEquirect" || c.material.name === "EquirectangularToCubeUV")) {
450
- Y && (c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", c, c.material.name, c.material.type)));
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
- const a = s.transparent;
457
- for (const c of a) {
458
- const f = c.object;
459
- (f instanceof q || f.isMesh) && this.updateLODs(e, t, f, n);
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 a, h;
465
- for (const d of this.plugins)
466
- (a = d.onBeforeUpdateLOD) == null || a.call(d, this.renderer, e, t, r);
467
- let n = r.userData.LOD_state;
468
- n || (n = new Oe(), r.userData.LOD_state = n);
469
- let s = this.calculateLodLevel(t, r, n, i);
470
- s = Math.round(s), s >= 0 && this.loadProgressiveMeshes(r, s);
471
- let o = 0;
472
- if (r.material) {
473
- const d = r["DEBUG:LOD"];
474
- if (d != null && (o = d), Array.isArray(r.material))
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 d of this.plugins)
481
- (h = d.onAfterUpdatedLOD) == null || h.call(d, this.renderer, e, t, r, s);
482
- n.lastLodLevel = s;
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
- return e && e.userData && e.userData.LOD !== t ? (e.userData.LOD = t, v.assignTextureLOD(e, t)) : Promise.resolve(null);
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 v.assignMeshLOD(e, t).then((i) => (i && e.userData.LOD == t && r != e.geometry, i));
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
- calculateLodLevel(e, t, r, i) {
509
- var o;
510
- if (!t)
511
- return -1;
512
- let s = 10 + 1;
513
- if (e) {
514
- if (Y && t["DEBUG:LOD"] != null)
515
- return t["DEBUG:LOD"];
516
- const a = v.getMeshLODInformation(t.geometry), h = a == null ? void 0 : a.lods;
517
- if (!h || h.length <= 0 || !((o = this.cameraFrustrum) != null && o.intersectsObject(t)))
518
- return 99;
519
- const d = t.geometry.boundingBox;
520
- if (d && e.isPerspectiveCamera) {
521
- const c = e;
522
- if (t.geometry.attributes.color && t.geometry.attributes.color.count < 100 && t.geometry.boundingSphere) {
523
- this._sphere.copy(t.geometry.boundingSphere), this._sphere.applyMatrix4(t.matrixWorld);
524
- const m = e.getWorldPosition(this._tempWorldPosition);
525
- if (this._sphere.containsPoint(m))
526
- return 0;
527
- }
528
- if (this._tempBox.copy(d), this._tempBox.applyMatrix4(t.matrixWorld), this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && c.fov > 70) {
529
- const m = this._tempBox.min, p = this._tempBox.max;
530
- let b = m.x, x = m.y, y = p.x, g = p.y;
531
- const O = 2, P = 1.5, _ = (m.x + p.x) * 0.5, E = (m.y + p.y) * 0.5;
532
- b = (b - _) * O + _, x = (x - E) * O + E, y = (y - _) * O + _, g = (g - E) * O + E;
533
- const N = b < 0 && y > 0 ? 0 : Math.min(Math.abs(m.x), Math.abs(p.x)), ne = x < 0 && g > 0 ? 0 : Math.min(Math.abs(m.y), Math.abs(p.y)), K = Math.max(N, ne);
534
- r.lastCentrality = (P - K) * (P - K) * (P - K);
535
- } else
536
- r.lastCentrality = 1;
537
- const f = this._tempBox.getSize(this._tempBoxSize);
538
- f.multiplyScalar(0.5), screen.availHeight > 0 && f.multiplyScalar(this.renderer.domElement.clientHeight / screen.availHeight), f.x *= c.aspect;
539
- const w = e.matrixWorldInverse, L = new ee();
540
- L.copy(d), L.applyMatrix4(t.matrixWorld), L.applyMatrix4(w);
541
- const A = L.getSize(this._tempBox2Size), G = Math.max(A.x, A.y);
542
- if (Math.max(f.x, f.y) != 0 && G != 0 && (f.z = A.z / Math.max(A.x, A.y) * Math.max(f.x, f.y)), r.lastScreenCoverage = Math.max(f.x, f.y, f.z), r.lastScreenspaceVolume.copy(f), r.lastScreenCoverage *= r.lastCentrality, Y && T.debugDrawLine) {
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
- return s;
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 B = T;
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
- u(B, "debugDrawLine"), u(B, "corner0", new k()), u(B, "corner1", new k()), u(B, "corner2", new k()), u(B, "corner3", new k());
568
- class Oe {
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
- u(this, "lastLodLevel", 0);
571
- u(this, "lastScreenCoverage", 0);
572
- u(this, "lastScreenspaceVolume", new k());
573
- u(this, "lastCentrality", 0);
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 re = Symbol("NEEDLE_mesh_lod"), $ = Symbol("NEEDLE_texture_lod");
577
- function Me(l) {
578
- if (!l)
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 = l; r != null; r = Object.getPrototypeOf(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 = l[n].threeRenderer), !t && s != null && (t = l[s]);
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 = new B(e);
588
- if (r.plugins.push(new ve(l)), r.enable(), t) {
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 ve {
736
+ class Ce {
599
737
  constructor(e) {
600
- u(this, "modelviewer");
601
- u(this, "_didWarnAboutMissingUrl", !1);
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[$] == !0)
753
+ if (t[X] == !0)
616
754
  return;
617
- t[$] = !0;
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 h, d, c;
622
- if (o[$] == !0)
759
+ var d, h, m;
760
+ if (o[X] == !0)
623
761
  return;
624
- o[$] = !0, o.userData && (o.userData.LOD = -1);
625
- const a = Object.keys(o);
626
- for (let f = 0; f < a.length; f++) {
627
- const w = a[f], L = o[w];
628
- if ((L == null ? void 0 : L.isTexture) === !0) {
629
- const A = (d = (h = L.userData) == null ? void 0 : h.associations) == null ? void 0 : d.textures, G = r.parser.json.textures[A];
630
- if ((c = G.extensions) != null && c[R]) {
631
- const D = G.extensions[R];
632
- D && i && v.registerTexture(i, L, D.lods.length, D);
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[re] == !0)
789
+ if (t[ce] == !0)
648
790
  return;
649
- t[re] = !0;
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
- v.registerMesh(r, o, t, 0, i.lods.length, i);
798
+ S.registerMesh(r, o, t, 0, i.lods.length, i);
657
799
  }
658
800
  }
659
801
  }
660
- function Ce(l, e, t, r) {
661
- se(e), ie(t), t.register((n) => new v(n, l));
662
- const i = new B(e);
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
- Me(document.querySelector("model-viewer"));
808
+ Ee(document.querySelector("model-viewer"));
667
809
  });
668
810
  export {
669
811
  R as EXTENSION_NAME,
670
- B as LODsManager,
671
- v as NEEDLE_progressive,
672
- Me as patchModelViewer,
673
- Be as registerPlugin,
674
- Ce as useNeedleProgressive
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
  };