@needle-tools/engine 4.8.0-next.4eaf70a → 4.8.0-next.58ab763
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/{generateMeshBVH.worker-BaNp_Xtp.js → generateMeshBVH.worker-2qGLkQjg.js} +1 -1
- package/dist/{gltf-progressive-CeuEsYpY.min.js → gltf-progressive-C0OrHmZf.min.js} +4 -4
- package/dist/{gltf-progressive-DY5t1MFv.js → gltf-progressive-CqwFE7bV.js} +78 -63
- package/dist/{gltf-progressive--2HtE1d8.umd.cjs → gltf-progressive-VK6wRj74.umd.cjs} +3 -3
- package/dist/loader.worker-CrU5fNbR.js +27 -0
- package/dist/{needle-engine.bundle-1687n4dK.js → needle-engine.bundle-C-obl9GH.js} +1799 -1781
- package/dist/{needle-engine.bundle-CooE_ge1.umd.cjs → needle-engine.bundle-D2j8atLK.umd.cjs} +87 -87
- package/dist/{needle-engine.bundle-BayRUkg4.min.js → needle-engine.bundle-DYYKGkWL.min.js} +101 -101
- package/dist/needle-engine.js +21 -21
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-DtxaELce.umd.cjs → postprocessing-BgC7XZwK.umd.cjs} +1 -1
- package/dist/{postprocessing-DElbMQgB.js → postprocessing-DddlM3CK.js} +1 -1
- package/dist/rapier--oeYP_h7.umd.cjs +1 -0
- package/dist/{rapier-CU5cp-KB.js → rapier-B3xpyPtq.js} +88 -88
- package/dist/{three-examples-CM6Iip03.js → three-examples-BIuXQPSf.js} +6 -6
- package/dist/{three-examples-BhQvv1B9.umd.cjs → three-examples-CNRuT27G.umd.cjs} +2 -2
- package/dist/{vendor-ClB-U1Hn.js → vendor-CGONwIc0.js} +73 -73
- package/dist/vendor-Cty8Dnri.umd.cjs +1121 -0
- package/lib/engine/engine_gizmos.d.ts +3 -2
- package/lib/engine/engine_gizmos.js +6 -1
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_lightdata.js +2 -0
- package/lib/engine/engine_lightdata.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +12 -3
- package/lib/engine/engine_physics_rapier.js +28 -7
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_types.d.ts +12 -5
- package/lib/engine/engine_types.js +1 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_utils_format.js +8 -2
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine/extensions/extensions.js +1 -1
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/package.json +2 -2
- package/plugins/vite/asap.js +1 -1
- package/plugins/vite/dependencies.js +28 -19
- package/plugins/vite/dependency-watcher.js +6 -1
- package/src/engine/engine_gizmos.ts +4 -1
- package/src/engine/engine_lightdata.ts +2 -0
- package/src/engine/engine_physics_rapier.ts +31 -10
- package/src/engine/engine_serialization_builtin_serializer.ts +1 -1
- package/src/engine/engine_types.ts +14 -5
- package/src/engine/engine_utils_format.ts +9 -2
- package/src/engine/extensions/extensions.ts +1 -1
- package/dist/loader.worker-8olmVOL4.js +0 -1
- package/dist/rapier-CUe6_xwE.umd.cjs +0 -1
- package/dist/vendor-bOWOWClg.umd.cjs +0 -1121
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { BufferGeometry as Q, Mesh as q, Box3 as ge, Vector3 as A, Sphere as
|
|
2
|
-
import { DRACOLoader as Xe, KTX2Loader as Ke, MeshoptDecoder as je, GLTFLoader as xe } from "./three-examples-
|
|
3
|
-
const Se = "3.
|
|
1
|
+
import { BufferGeometry as Q, Mesh as q, Box3 as ge, Vector3 as A, Sphere as Oe, CompressedTexture as Fe, Texture as E, Matrix3 as Ue, InterleavedBuffer as We, InterleavedBufferAttribute as ze, BufferAttribute as Ee, TextureLoader as Ne, Matrix4 as _e, Clock as qe, MeshStandardMaterial as Ve } from "./three-DrqIzZTH.js";
|
|
2
|
+
import { DRACOLoader as Xe, KTX2Loader as Ke, MeshoptDecoder as je, GLTFLoader as xe } from "./three-examples-BIuXQPSf.js";
|
|
3
|
+
const Se = "3.2.0";
|
|
4
4
|
globalThis.GLTF_PROGRESSIVE_VERSION = Se;
|
|
5
5
|
console.debug(`[gltf-progressive] version ${Se}`);
|
|
6
|
-
let
|
|
7
|
-
const Ye =
|
|
6
|
+
let C = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/", V = "https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";
|
|
7
|
+
const Ye = C, He = V, Pe = new URL(C + "draco_decoder.js");
|
|
8
8
|
Pe.searchParams.append("range", "true");
|
|
9
9
|
fetch(Pe, {
|
|
10
10
|
method: "GET",
|
|
@@ -12,16 +12,16 @@ fetch(Pe, {
|
|
|
12
12
|
Range: "bytes=0-1"
|
|
13
13
|
}
|
|
14
14
|
}).catch((o) => {
|
|
15
|
-
console.debug(`Failed to fetch remote Draco decoder from ${
|
|
15
|
+
console.debug(`Failed to fetch remote Draco decoder from ${C} (offline: ${typeof navigator < "u" ? navigator.onLine : "unknown"})`), C === Ye && Je("./include/draco/"), V === He && Ze("./include/ktx2/");
|
|
16
16
|
}).finally(() => {
|
|
17
17
|
Ae();
|
|
18
18
|
});
|
|
19
19
|
const Qe = () => ({
|
|
20
|
-
dracoDecoderPath:
|
|
20
|
+
dracoDecoderPath: C,
|
|
21
21
|
ktx2TranscoderPath: V
|
|
22
22
|
});
|
|
23
23
|
function Je(o) {
|
|
24
|
-
|
|
24
|
+
C = o, T && T[pe] != C ? (console.debug("Updating Draco decoder path to " + o), T[pe] = C, T.setDecoderPath(C), T.preload()) : console.debug("Setting Draco decoder path to " + o);
|
|
25
25
|
}
|
|
26
26
|
function Ze(o) {
|
|
27
27
|
V = o, R && R.transcoderPath != V ? (console.debug("Updating KTX2 transcoder path to " + o), R.setTranscoderPath(V), R.init()) : console.debug("Setting KTX2 transcoder path to " + o);
|
|
@@ -35,7 +35,7 @@ function Te(o) {
|
|
|
35
35
|
const pe = Symbol("dracoDecoderPath");
|
|
36
36
|
let T, re, R;
|
|
37
37
|
function Ae() {
|
|
38
|
-
T || (T = new Xe(), T[pe] =
|
|
38
|
+
T || (T = new Xe(), T[pe] = C, T.setDecoderPath(C), T.setDecoderConfig({ type: "js" }), T.preload()), R || (R = new Ke(), R.setTranscoderPath(V), R.init()), re || (re = je);
|
|
39
39
|
}
|
|
40
40
|
const me = /* @__PURE__ */ new WeakMap();
|
|
41
41
|
function Ie(o, t) {
|
|
@@ -74,7 +74,7 @@ function st(o, t) {
|
|
|
74
74
|
return t;
|
|
75
75
|
}
|
|
76
76
|
let j;
|
|
77
|
-
function
|
|
77
|
+
function ke() {
|
|
78
78
|
return j !== void 0 || (j = /iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent), X("debugprogressive") && console.log("[glTF Progressive]: isMobileDevice", j)), j;
|
|
79
79
|
}
|
|
80
80
|
function Me() {
|
|
@@ -163,16 +163,16 @@ if (g) {
|
|
|
163
163
|
!isNaN(s) && s >= 0 && (N = s, console.log(`Set LOD level to [${N}]`));
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
|
-
function
|
|
166
|
+
function Ce(o) {
|
|
167
167
|
if (g)
|
|
168
168
|
if (Array.isArray(o))
|
|
169
169
|
for (const t of o)
|
|
170
|
-
|
|
170
|
+
Ce(t);
|
|
171
171
|
else o && "wireframe" in o && (o.wireframe = ne === !0);
|
|
172
172
|
}
|
|
173
173
|
const H = new Array();
|
|
174
174
|
let lt = 0;
|
|
175
|
-
const ut =
|
|
175
|
+
const ut = ke() ? 2 : 10;
|
|
176
176
|
function dt(o) {
|
|
177
177
|
if (H.length < ut) {
|
|
178
178
|
const s = H.length;
|
|
@@ -188,7 +188,7 @@ class Le {
|
|
|
188
188
|
static async createWorker(t) {
|
|
189
189
|
const e = new Worker(new URL(
|
|
190
190
|
/* @vite-ignore */
|
|
191
|
-
"/loader.worker-
|
|
191
|
+
"/loader.worker-CrU5fNbR.js",
|
|
192
192
|
import.meta.url
|
|
193
193
|
), {
|
|
194
194
|
type: "module"
|
|
@@ -256,7 +256,7 @@ function ct(o) {
|
|
|
256
256
|
const i = e.morphAttributes[r].map((l) => le(l));
|
|
257
257
|
s.morphAttributes[r] = i;
|
|
258
258
|
}
|
|
259
|
-
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new A(e.boundingBox?.min.x, e.boundingBox?.min.y, e.boundingBox?.min.z), s.boundingBox.max = new A(e.boundingBox?.max.x, e.boundingBox?.max.y, e.boundingBox?.max.z), s.boundingSphere = new
|
|
259
|
+
if (s.morphTargetsRelative = e.morphTargetsRelative ?? !1, s.boundingBox = new ge(), s.boundingBox.min = new A(e.boundingBox?.min.x, e.boundingBox?.min.y, e.boundingBox?.min.z), s.boundingBox.max = new A(e.boundingBox?.max.x, e.boundingBox?.max.y, e.boundingBox?.max.z), s.boundingSphere = new Oe(new A(e.boundingSphere?.center.x, e.boundingSphere?.center.y, e.boundingSphere?.center.z), e.boundingSphere?.radius), e.groups)
|
|
260
260
|
for (const r of e.groups)
|
|
261
261
|
s.addGroup(r.start, r.count, r.materialIndex);
|
|
262
262
|
e.userData && (s.userData = e.userData), t.geometry = s;
|
|
@@ -486,7 +486,8 @@ class y {
|
|
|
486
486
|
}
|
|
487
487
|
parser;
|
|
488
488
|
url;
|
|
489
|
-
constructor(t
|
|
489
|
+
constructor(t) {
|
|
490
|
+
const e = t.options.path;
|
|
490
491
|
g && console.log("Progressive extension registered for", e), this.parser = t, this.url = e;
|
|
491
492
|
}
|
|
492
493
|
_isLoadingMesh;
|
|
@@ -606,8 +607,8 @@ class y {
|
|
|
606
607
|
const d = u + "_" + i.guid, p = await this.queue.slot(u), L = this.previouslyLoaded.get(d);
|
|
607
608
|
if (L !== void 0) {
|
|
608
609
|
s && console.log(`LOD ${e} was already loading/loaded: ${d}`);
|
|
609
|
-
let c = await L.catch((
|
|
610
|
-
`,
|
|
610
|
+
let c = await L.catch((O) => (console.error(`Error loading LOD ${e} from ${u}
|
|
611
|
+
`, O), null)), x = !1;
|
|
611
612
|
if (c == null || (c instanceof E && t instanceof E ? c.image?.data || c.source?.data ? c = this.copySettings(t, c) : (x = !0, this.previouslyLoaded.delete(d)) : c instanceof Q && t instanceof Q && (c.attributes.position?.array || (x = !0, this.previouslyLoaded.delete(d)))), !x)
|
|
612
613
|
return c;
|
|
613
614
|
}
|
|
@@ -631,14 +632,14 @@ class y {
|
|
|
631
632
|
}
|
|
632
633
|
return c(null);
|
|
633
634
|
}
|
|
634
|
-
const
|
|
635
|
-
Te(
|
|
635
|
+
const O = new xe();
|
|
636
|
+
Te(O), g && (await new Promise((w) => setTimeout(w, 1e3)), s && console.warn("Start loading (delayed) " + u, _.guid));
|
|
636
637
|
let B = u;
|
|
637
638
|
if (_ && Array.isArray(_.lods)) {
|
|
638
639
|
const w = _.lods[e];
|
|
639
640
|
w.hash && (B += "?v=" + w.hash);
|
|
640
641
|
}
|
|
641
|
-
const D = await
|
|
642
|
+
const D = await O.loadAsync(B).catch((w) => (console.error(`Error loading LOD ${e} from ${u}
|
|
642
643
|
`, w), c(null)));
|
|
643
644
|
if (!D)
|
|
644
645
|
return c(null);
|
|
@@ -684,8 +685,8 @@ class y {
|
|
|
684
685
|
for (let h = 0; h < m.children.length; h++) {
|
|
685
686
|
const b = m.children[h];
|
|
686
687
|
if (b.isMesh === !0) {
|
|
687
|
-
const
|
|
688
|
-
y.assignLODInformation(r.url,
|
|
688
|
+
const v = b.geometry;
|
|
689
|
+
y.assignLODInformation(r.url, v, n, e, h), f.push(v);
|
|
689
690
|
}
|
|
690
691
|
}
|
|
691
692
|
return c(f);
|
|
@@ -807,7 +808,7 @@ class de {
|
|
|
807
808
|
});
|
|
808
809
|
}
|
|
809
810
|
}
|
|
810
|
-
const
|
|
811
|
+
const k = X("debugprogressive"), pt = X("noprogressive"), ce = Symbol("Needle:LODSManager"), fe = Symbol("Needle:LODState"), U = Symbol("Needle:CurrentLOD"), P = { mesh_lod: -1, texture_lod: -1 };
|
|
811
812
|
let ie = class M {
|
|
812
813
|
/**
|
|
813
814
|
* 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.
|
|
@@ -932,7 +933,7 @@ let ie = class M {
|
|
|
932
933
|
const e = this;
|
|
933
934
|
we(this.renderer), this.renderer.render = function(s, r) {
|
|
934
935
|
const n = e.renderer.getRenderTarget();
|
|
935
|
-
(n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#n += 1, e.#r = e.#i.getDelta(), e.#o += e.#r, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#r), e.#s = e._fpsBuffer.reduce((l, a) => l + a) / e._fpsBuffer.length,
|
|
936
|
+
(n == null || "isXRRenderTarget" in n && n.isXRRenderTarget) && (t = 0, e.#n += 1, e.#r = e.#i.getDelta(), e.#o += e.#r, e._fpsBuffer.shift(), e._fpsBuffer.push(1 / e.#r), e.#s = e._fpsBuffer.reduce((l, a) => l + a) / e._fpsBuffer.length, k && e.#n % 200 === 0 && console.log("FPS", Math.round(e.#s), "Interval:", e.#e));
|
|
936
937
|
const i = t++;
|
|
937
938
|
e.#t.call(this, s, r), e.onAfterRender(s, r, i);
|
|
938
939
|
};
|
|
@@ -953,7 +954,7 @@ let ie = class M {
|
|
|
953
954
|
(l.name === "EffectMaterial" || l.name === "CopyShader") && (i = !1);
|
|
954
955
|
}
|
|
955
956
|
if ((e.parent && e.parent.type === "CubeCamera" || s >= 1 && e.type === "OrthographicCamera") && (i = !1), i) {
|
|
956
|
-
if (pt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1,
|
|
957
|
+
if (pt || (this.updateInterval === "auto" ? this.#s < 40 && this.#e < 10 ? (this.#e += 1, k && console.warn("↓ Reducing LOD updates", this.#e, this.#s.toFixed(0))) : this.#s >= 60 && this.#e > 1 && (this.#e -= 1, k && console.warn("↑ Increasing LOD updates", this.#e, this.#s.toFixed(0))) : this.#e = this.updateInterval, this.#e > 0 && this.#n % this.#e != 0))
|
|
957
958
|
return;
|
|
958
959
|
this.internalUpdate(t, e), this._postprocessPromiseGroups();
|
|
959
960
|
}
|
|
@@ -967,7 +968,7 @@ let ie = class M {
|
|
|
967
968
|
const n = this.targetTriangleDensity;
|
|
968
969
|
for (const a of r) {
|
|
969
970
|
if (a.material && (a.geometry?.type === "BoxGeometry" || a.geometry?.type === "BufferGeometry") && (a.material.name === "SphericalGaussianBlur" || a.material.name == "BackgroundCubeMaterial" || a.material.name === "CubemapFromEquirect" || a.material.name === "EquirectangularToCubeUV")) {
|
|
970
|
-
|
|
971
|
+
k && (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] || (a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"] = !0, console.warn("Ignoring skybox or BLIT object", a, a.material.name, a.material.type)));
|
|
971
972
|
continue;
|
|
972
973
|
}
|
|
973
974
|
switch (a.material.type) {
|
|
@@ -979,7 +980,7 @@ let ie = class M {
|
|
|
979
980
|
case "MeshDepthMaterial":
|
|
980
981
|
continue;
|
|
981
982
|
}
|
|
982
|
-
if (
|
|
983
|
+
if (k === "color" && a.material && !a.object.progressive_debug_color) {
|
|
983
984
|
a.object.progressive_debug_color = !0;
|
|
984
985
|
const d = Math.random() * 16777215, p = new Ve({ color: d });
|
|
985
986
|
a.object.material = p;
|
|
@@ -1007,7 +1008,7 @@ let ie = class M {
|
|
|
1007
1008
|
for (const l of W)
|
|
1008
1009
|
l.onBeforeUpdateLOD?.(this.renderer, t, e, s);
|
|
1009
1010
|
const i = M.overrideGlobalLodLevel !== void 0 ? M.overrideGlobalLodLevel : N;
|
|
1010
|
-
i >= 0 ? (P.mesh_lod = i, P.texture_lod = i) : (this.calculateLodLevel(e, s, n, r, P), P.mesh_lod = Math.round(P.mesh_lod), P.texture_lod = Math.round(P.texture_lod)), P.mesh_lod >= 0 && this.loadProgressiveMeshes(s, P.mesh_lod), s.material && P.texture_lod >= 0 && this.loadProgressiveTextures(s.material, P.texture_lod, i), g && s.material && !s.isGizmo &&
|
|
1011
|
+
i >= 0 ? (P.mesh_lod = i, P.texture_lod = i) : (this.calculateLodLevel(e, s, n, r, P), P.mesh_lod = Math.round(P.mesh_lod), P.texture_lod = Math.round(P.texture_lod)), P.mesh_lod >= 0 && this.loadProgressiveMeshes(s, P.mesh_lod), s.material && P.texture_lod >= 0 && this.loadProgressiveTextures(s.material, P.texture_lod, i), g && s.material && !s.isGizmo && Ce(s.material);
|
|
1011
1012
|
for (const l of W)
|
|
1012
1013
|
l.onAfterUpdatedLOD?.(this.renderer, t, e, s, P);
|
|
1013
1014
|
n.lastLodLevel_Mesh = P.mesh_lod, n.lastLodLevel_Texture = P.texture_lod;
|
|
@@ -1053,7 +1054,7 @@ let ie = class M {
|
|
|
1053
1054
|
return Promise.resolve(null);
|
|
1054
1055
|
}
|
|
1055
1056
|
// private testIfLODLevelsAreAvailable() {
|
|
1056
|
-
_sphere = new
|
|
1057
|
+
_sphere = new Oe();
|
|
1057
1058
|
_tempBox = new ge();
|
|
1058
1059
|
_tempBox2 = new ge();
|
|
1059
1060
|
tempMatrix = new _e();
|
|
@@ -1082,7 +1083,7 @@ let ie = class M {
|
|
|
1082
1083
|
return;
|
|
1083
1084
|
}
|
|
1084
1085
|
let l = 10 + 1, a = !1;
|
|
1085
|
-
if (
|
|
1086
|
+
if (k && e["DEBUG:LOD"] != null)
|
|
1086
1087
|
return e["DEBUG:LOD"];
|
|
1087
1088
|
const u = y.getMeshLODExtension(e.geometry)?.lods, d = y.getPrimitiveIndex(e.geometry), p = u && u.length > 0, L = y.getMaterialMinMaxLODsCount(e.material), _ = L.min_count !== 1 / 0 && L.min_count >= 0 && L.max_count >= 0;
|
|
1088
1089
|
if (!p && !_) {
|
|
@@ -1098,13 +1099,13 @@ let ie = class M {
|
|
|
1098
1099
|
c.computeBoundingBox();
|
|
1099
1100
|
else if (this.skinnedMeshAutoUpdateBoundsInterval > 0) {
|
|
1100
1101
|
if (!c[M.$skinnedMeshBoundsOffset]) {
|
|
1101
|
-
const
|
|
1102
|
-
c[M.$skinnedMeshBoundsOffset] =
|
|
1102
|
+
const O = M.skinnedMeshBoundsFrameOffsetCounter++;
|
|
1103
|
+
c[M.$skinnedMeshBoundsOffset] = O;
|
|
1103
1104
|
}
|
|
1104
1105
|
const x = c[M.$skinnedMeshBoundsOffset];
|
|
1105
1106
|
if ((s.frames + x) % this.skinnedMeshAutoUpdateBoundsInterval === 0) {
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1107
|
+
const O = J(c), B = c.geometry;
|
|
1108
|
+
O && (c.geometry = O), c.computeBoundingBox(), c.geometry = B;
|
|
1108
1109
|
}
|
|
1109
1110
|
}
|
|
1110
1111
|
G = c.boundingBox;
|
|
@@ -1125,58 +1126,58 @@ let ie = class M {
|
|
|
1125
1126
|
}
|
|
1126
1127
|
if (this._tempBox.applyMatrix4(this.projectionScreenMatrix), this.renderer.xr.enabled && c.isPerspectiveCamera && c.fov > 70) {
|
|
1127
1128
|
const f = this._tempBox.min, h = this._tempBox.max;
|
|
1128
|
-
let b = f.x,
|
|
1129
|
+
let b = f.x, v = f.y, $ = h.x, K = h.y;
|
|
1129
1130
|
const Z = 2, oe = 1.5, ee = (f.x + h.x) * 0.5, te = (f.y + h.y) * 0.5;
|
|
1130
|
-
b = (b - ee) * Z + ee,
|
|
1131
|
-
const $e = b < 0 && $ > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(h.x)), Ge =
|
|
1131
|
+
b = (b - ee) * Z + ee, v = (v - te) * Z + te, $ = ($ - ee) * Z + ee, K = (K - te) * Z + te;
|
|
1132
|
+
const $e = b < 0 && $ > 0 ? 0 : Math.min(Math.abs(f.x), Math.abs(h.x)), Ge = v < 0 && K > 0 ? 0 : Math.min(Math.abs(f.y), Math.abs(h.y)), ae = Math.max($e, Ge);
|
|
1132
1133
|
s.lastCentrality = (oe - ae) * (oe - ae) * (oe - ae);
|
|
1133
1134
|
} else
|
|
1134
1135
|
s.lastCentrality = 1;
|
|
1135
1136
|
const x = this._tempBox.getSize(this._tempBoxSize);
|
|
1136
1137
|
x.multiplyScalar(0.5), screen.availHeight > 0 && I > 0 && x.multiplyScalar(I / screen.availHeight), t.isPerspectiveCamera ? x.x *= t.aspect : t.isOrthographicCamera;
|
|
1137
|
-
const
|
|
1138
|
-
B.copy(G), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(
|
|
1138
|
+
const O = t.matrixWorldInverse, B = this._tempBox2;
|
|
1139
|
+
B.copy(G), B.applyMatrix4(e.matrixWorld), B.applyMatrix4(O);
|
|
1139
1140
|
const D = B.getSize(this._tempBox2Size), z = Math.max(D.x, D.y);
|
|
1140
|
-
if (Math.max(x.x, x.y) != 0 && z != 0 && (x.z = D.z / Math.max(D.x, D.y) * Math.max(x.x, x.y)), s.lastScreenCoverage = Math.max(x.x, x.y, x.z), s.lastScreenspaceVolume.copy(x), s.lastScreenCoverage *= s.lastCentrality,
|
|
1141
|
+
if (Math.max(x.x, x.y) != 0 && z != 0 && (x.z = D.z / Math.max(D.x, D.y) * Math.max(x.x, x.y)), s.lastScreenCoverage = Math.max(x.x, x.y, x.z), s.lastScreenspaceVolume.copy(x), s.lastScreenCoverage *= s.lastCentrality, k && M.debugDrawLine) {
|
|
1141
1142
|
const f = this.tempMatrix.copy(this.projectionScreenMatrix);
|
|
1142
1143
|
f.invert();
|
|
1143
|
-
const h = M.corner0, b = M.corner1,
|
|
1144
|
-
h.copy(this._tempBox.min), b.copy(this._tempBox.max), b.x = h.x,
|
|
1144
|
+
const h = M.corner0, b = M.corner1, v = M.corner2, $ = M.corner3;
|
|
1145
|
+
h.copy(this._tempBox.min), b.copy(this._tempBox.max), b.x = h.x, v.copy(this._tempBox.max), v.y = h.y, $.copy(this._tempBox.max);
|
|
1145
1146
|
const K = (h.z + $.z) * 0.5;
|
|
1146
|
-
h.z = b.z =
|
|
1147
|
+
h.z = b.z = v.z = $.z = K, h.applyMatrix4(f), b.applyMatrix4(f), v.applyMatrix4(f), $.applyMatrix4(f), M.debugDrawLine(h, b, 255), M.debugDrawLine(h, v, 255), M.debugDrawLine(b, $, 255), M.debugDrawLine(v, $, 255);
|
|
1147
1148
|
}
|
|
1148
1149
|
let w = 999;
|
|
1149
1150
|
if (u && s.lastScreenCoverage > 0)
|
|
1150
1151
|
for (let f = 0; f < u.length; f++) {
|
|
1151
|
-
const h = u[f],
|
|
1152
|
-
if (d > 0 && Me() && !h.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),
|
|
1152
|
+
const h = u[f], v = (h.densities?.[d] || h.density || 1e-5) / s.lastScreenCoverage;
|
|
1153
|
+
if (d > 0 && Me() && !h.densities && !globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] && (window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"] = !0, console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")), v < r) {
|
|
1153
1154
|
w = f;
|
|
1154
1155
|
break;
|
|
1155
1156
|
}
|
|
1156
1157
|
}
|
|
1157
1158
|
w < l && (l = w, a = !0);
|
|
1158
1159
|
}
|
|
1159
|
-
if (a ? n.mesh_lod = l : n.mesh_lod = s.lastLodLevel_Mesh,
|
|
1160
|
+
if (a ? n.mesh_lod = l : n.mesh_lod = s.lastLodLevel_Mesh, k && n.mesh_lod != s.lastLodLevel_Mesh) {
|
|
1160
1161
|
const x = u?.[n.mesh_lod];
|
|
1161
1162
|
x && console.debug(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${x.densities?.[d].toFixed(0)}) | ${e.name}`);
|
|
1162
1163
|
}
|
|
1163
1164
|
if (_) {
|
|
1164
1165
|
const c = "saveData" in globalThis.navigator && globalThis.navigator.saveData === !0;
|
|
1165
1166
|
if (s.lastLodLevel_Texture < 0) {
|
|
1166
|
-
if (n.texture_lod = L.max_count - 1,
|
|
1167
|
+
if (n.texture_lod = L.max_count - 1, k) {
|
|
1167
1168
|
const x = L.lods[L.max_count - 1];
|
|
1168
|
-
|
|
1169
|
+
k && console.log(`First Texture LOD ${n.texture_lod} (${x.max_height}px) - ${e.name}`);
|
|
1169
1170
|
}
|
|
1170
1171
|
} else {
|
|
1171
1172
|
const x = s.lastScreenspaceVolume.x + s.lastScreenspaceVolume.y + s.lastScreenspaceVolume.z;
|
|
1172
|
-
let
|
|
1173
|
-
this.context?.engine === "model-viewer" && (
|
|
1174
|
-
const D = I / window.devicePixelRatio *
|
|
1173
|
+
let O = s.lastScreenCoverage * 4;
|
|
1174
|
+
this.context?.engine === "model-viewer" && (O *= 1.5);
|
|
1175
|
+
const D = I / window.devicePixelRatio * O;
|
|
1175
1176
|
let z = !1;
|
|
1176
1177
|
for (let S = L.lods.length - 1; S >= 0; S--) {
|
|
1177
1178
|
const w = L.lods[S];
|
|
1178
|
-
if (!(c && w.max_height >= 2048) && !(
|
|
1179
|
-
if (z = !0, n.texture_lod = S,
|
|
1179
|
+
if (!(c && w.max_height >= 2048) && !(ke() && w.max_height > 4096) && (w.max_height > D || !z && S === 0)) {
|
|
1180
|
+
if (z = !0, n.texture_lod = S, k && n.texture_lod < s.lastLodLevel_Texture) {
|
|
1180
1181
|
const m = w.max_height;
|
|
1181
1182
|
console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${m}px
|
|
1182
1183
|
Screensize: ${D.toFixed(0)}px, Coverage: ${(100 * s.lastScreenCoverage).toFixed(2)}%, Volume ${x.toFixed(1)}
|
|
@@ -1227,12 +1228,12 @@ function be() {
|
|
|
1227
1228
|
Be(t);
|
|
1228
1229
|
});
|
|
1229
1230
|
}
|
|
1230
|
-
const
|
|
1231
|
+
const ve = /* @__PURE__ */ new WeakSet();
|
|
1231
1232
|
let xt = 0;
|
|
1232
1233
|
function Be(o) {
|
|
1233
|
-
if (!o ||
|
|
1234
|
+
if (!o || ve.has(o))
|
|
1234
1235
|
return null;
|
|
1235
|
-
|
|
1236
|
+
ve.add(o), console.debug("[gltf-progressive] found new model-viewer..." + ++xt + `
|
|
1236
1237
|
`, o.getAttribute("src"));
|
|
1237
1238
|
let t = null, e = null, s = null;
|
|
1238
1239
|
for (let r = o; r != null; r = Object.getPrototypeOf(r)) {
|
|
@@ -1333,13 +1334,27 @@ class wt {
|
|
|
1333
1334
|
}
|
|
1334
1335
|
}
|
|
1335
1336
|
}
|
|
1336
|
-
function Lt(o
|
|
1337
|
-
|
|
1337
|
+
function Lt(...o) {
|
|
1338
|
+
let t, e, s, r;
|
|
1339
|
+
switch (o.length) {
|
|
1340
|
+
case 2:
|
|
1341
|
+
[s, e] = o, r = {};
|
|
1342
|
+
break;
|
|
1343
|
+
case 3:
|
|
1344
|
+
[s, e, r] = o;
|
|
1345
|
+
break;
|
|
1346
|
+
case 4:
|
|
1347
|
+
[t, e, s, r] = o;
|
|
1348
|
+
break;
|
|
1349
|
+
default:
|
|
1350
|
+
throw new Error("Invalid arguments");
|
|
1351
|
+
}
|
|
1352
|
+
we(e), Te(s), Ie(s, {
|
|
1338
1353
|
progressive: !0,
|
|
1339
|
-
...
|
|
1340
|
-
}),
|
|
1341
|
-
const
|
|
1342
|
-
return
|
|
1354
|
+
...r?.hints
|
|
1355
|
+
}), s.register((i) => new y(i));
|
|
1356
|
+
const n = ie.get(e);
|
|
1357
|
+
return r?.enableLODsManager !== !1 && n.enable(), n;
|
|
1343
1358
|
}
|
|
1344
1359
|
Re();
|
|
1345
1360
|
if (!rt) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";const d=require("./three-B_hneGZr.umd.cjs"),q=require("./three-examples-BhQvv1B9.umd.cjs");var ae=typeof document<"u"?document.currentScript:null;const be="3.1.1";globalThis.GLTF_PROGRESSIVE_VERSION=be;console.debug(`[gltf-progressive] version ${be}`);let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",V="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Be=k,$e=V,ve=new URL(k+"draco_decoder.js");ve.searchParams.append("range","true");fetch(ve,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Be&&Oe("./include/draco/"),V===$e&&Se("./include/ktx2/")}).finally(()=>{Te()});const Ge=()=>({dracoDecoderPath:k,ktx2TranscoderPath:V});function Oe(i){k=i,A&&A[ge]!=k?(console.debug("Updating Draco decoder path to "+i),A[ge]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+i)}function Se(i){V=i,R&&R.transcoderPath!=V?(console.debug("Updating KTX2 transcoder path to "+i),R.setTranscoderPath(V),R.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ne(i){return Te(),i?R.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:se}}function ye(i){i.dracoLoader||i.setDRACOLoader(A),i.ktx2Loader||i.setKTX2Loader(R),i.meshoptDecoder||i.setMeshoptDecoder(se)}const ge=Symbol("dracoDecoderPath");let A,se,R;function Te(){A||(A=new q.DRACOLoader,A[ge]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new q.KTX2Loader,R.setTranscoderPath(V),R.init()),se||(se=q.MeshoptDecoder)}const pe=new WeakMap;function xe(i,t){let e=pe.get(i);e?e=Object.assign(e,t):e=t,pe.set(i,e)}const Fe=q.GLTFLoader.prototype.load;function Ue(...i){const t=pe.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,o=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=r.toString()}return i[0]=e,Fe?.call(this,...i)}q.GLTFLoader.prototype.load=Ue;N("debugprogressive");function N(i){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(i);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Ee(i,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||i===void 0)return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let j;function Pe(){return j!==void 0||(j=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),N("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",j)),j}function Le(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class We{maxConcurrent;_running=new Map;_queue=[];debug=!1;constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const ze=typeof window>"u"&&typeof document>"u",me=Symbol("needle:raycast-mesh");function X(i){return i?.[me]instanceof d.BufferGeometry?i[me]:null}function Ve(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!X(i)){const r=qe(t);r.userData={isRaycastMesh:!0},i[me]=r}}function Ne(i=!0){if(i){if(Y)return;const t=Y=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=X(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!Y)return;d.Mesh.prototype.raycast=Y,Y=null}}let Y=null;function qe(i){const t=new d.BufferGeometry;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const E=new Array,p=N("debugprogressive");let re,z=-1;if(p){let t=function(){z+=1,z>=i&&(z=-1),console.log(`Toggle LOD level [${z}]`)},i=6;window.addEventListener("keyup",e=>{e.key==="p"&&t(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(z=r,console.log(`Set LOD level to [${z}]`))})}function Ae(i){if(p)if(Array.isArray(i))for(const t of i)Ae(t);else i&&"wireframe"in i&&(i.wireframe=re===!0)}const H=new Array;let Xe=0;const Ke=Pe()?2:10;function je(i){if(H.length<Ke){const r=H.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=we.createWorker(i||{});return H.push(n),n}const t=Xe++%H.length;return H[t]}class we{worker;static async createWorker(t){const e=new Worker(new URL("/loader.worker-8olmVOL4.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ae&&ae.tagName.toUpperCase()==="SCRIPT"&&ae.src||new URL("gltf-progressive--2HtE1d8.umd.cjs",document.baseURI).href),{type:"module"});return new we(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ge();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-B_hneGZr.umd.cjs")).then(c=>c.THREE);return new u})(),n=await this._webglRenderer);const l=ne(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1;constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){Ye(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}}function Ye(i){for(const t of i.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(le(n))}for(const n in e.attributes){const s=e.attributes[n],o=le(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const o=e.morphAttributes[n].map(l=>le(l));r.morphAttributes[n]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new d.Matrix3(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function le(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new d.BufferAttribute(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const He=N("gltf-progressive-worker"),Qe=N("gltf-progressive-reduce-mipmaps"),ue=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class x{get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let m=0;m<c.lods.length;m++){const _=c.lods[m];_.width&&(a.lods[m]=a.lods[m]||{min_height:1/0,max_height:0},a.lods[m].min_height=Math.min(a.lods[m].min_height,_.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,_.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of E)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,x.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(c=>(c&&o.uniforms[l].value!=c&&(o.uniforms[l].value=c,o.uniformsNeedUpdate=!0),c));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],c=s[a];u&&u.isTexture===!0?l.push({material:r,slot:c,texture:u,level:e}):l.push({material:r,slot:c,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):x.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!p){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(Qe&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t,e){p&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[F];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&x.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,x.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&x.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&x.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ue]=s);const o=s.guid;x.assignLODInformation(t,e,o,r,n),x.lodInfos.set(o,s),x.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),x.assignLODInformation(t,l,e,n,s),x.lodInfos.set(e,o);let a=x.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],x.lowresCache.set(e,a),n>0&&!X(r)&&Ve(r,l);for(const u of E)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const a=t;a.source&&a.source[ue]&&(o=a.source[ue])}if(o||(o=x.lodInfos.get(s)),o){if(e>0){let c=!1;const m=Array.isArray(o.lods);if(m&&e>=o.lods.length?c=!0:m||(c=!0),c)return this.lowresCache.get(s)}const a=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!a)return p&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const u=Ee(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const c=u+"_"+o.guid,m=await this.queue.slot(u),_=this.previouslyLoaded.get(c);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${c}`);let f=await _.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
|
|
1
|
+
"use strict";const d=require("./three-B_hneGZr.umd.cjs"),q=require("./three-examples-CNRuT27G.umd.cjs");var ae=typeof document<"u"?document.currentScript:null;const be="3.2.0";globalThis.GLTF_PROGRESSIVE_VERSION=be;console.debug(`[gltf-progressive] version ${be}`);let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",N="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Be=k,$e=N,ve=new URL(k+"draco_decoder.js");ve.searchParams.append("range","true");fetch(ve,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Be&&Oe("./include/draco/"),N===$e&&Se("./include/ktx2/")}).finally(()=>{Te()});const Ge=()=>({dracoDecoderPath:k,ktx2TranscoderPath:N});function Oe(i){k=i,A&&A[ge]!=k?(console.debug("Updating Draco decoder path to "+i),A[ge]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+i)}function Se(i){N=i,R&&R.transcoderPath!=N?(console.debug("Updating KTX2 transcoder path to "+i),R.setTranscoderPath(N),R.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ne(i){return Te(),i?R.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:se}}function ye(i){i.dracoLoader||i.setDRACOLoader(A),i.ktx2Loader||i.setKTX2Loader(R),i.meshoptDecoder||i.setMeshoptDecoder(se)}const ge=Symbol("dracoDecoderPath");let A,se,R;function Te(){A||(A=new q.DRACOLoader,A[ge]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new q.KTX2Loader,R.setTranscoderPath(N),R.init()),se||(se=q.MeshoptDecoder)}const pe=new WeakMap;function xe(i,t){let e=pe.get(i);e?e=Object.assign(e,t):e=t,pe.set(i,e)}const Fe=q.GLTFLoader.prototype.load;function Ue(...i){const t=pe.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,o=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=r.toString()}return i[0]=e,Fe?.call(this,...i)}q.GLTFLoader.prototype.load=Ue;V("debugprogressive");function V(i){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(i);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Ee(i,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||i===void 0)return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let j;function Pe(){return j!==void 0||(j=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),V("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",j)),j}function Le(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class We{maxConcurrent;_running=new Map;_queue=[];debug=!1;constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const ze=typeof window>"u"&&typeof document>"u",me=Symbol("needle:raycast-mesh");function X(i){return i?.[me]instanceof d.BufferGeometry?i[me]:null}function Ne(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!X(i)){const r=qe(t);r.userData={isRaycastMesh:!0},i[me]=r}}function Ve(i=!0){if(i){if(Y)return;const t=Y=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=X(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!Y)return;d.Mesh.prototype.raycast=Y,Y=null}}let Y=null;function qe(i){const t=new d.BufferGeometry;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const E=new Array,p=V("debugprogressive");let re,z=-1;if(p){let t=function(){z+=1,z>=i&&(z=-1),console.log(`Toggle LOD level [${z}]`)},i=6;window.addEventListener("keyup",e=>{e.key==="p"&&t(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(z=r,console.log(`Set LOD level to [${z}]`))})}function Ae(i){if(p)if(Array.isArray(i))for(const t of i)Ae(t);else i&&"wireframe"in i&&(i.wireframe=re===!0)}const H=new Array;let Xe=0;const Ke=Pe()?2:10;function je(i){if(H.length<Ke){const r=H.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=we.createWorker(i||{});return H.push(n),n}const t=Xe++%H.length;return H[t]}class we{worker;static async createWorker(t){const e=new Worker(new URL("/loader.worker-CrU5fNbR.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ae&&ae.tagName.toUpperCase()==="SCRIPT"&&ae.src||new URL("gltf-progressive-VK6wRj74.umd.cjs",document.baseURI).href),{type:"module"});return new we(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ge();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-B_hneGZr.umd.cjs")).then(c=>c.THREE);return new u})(),n=await this._webglRenderer);const l=ne(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1;constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){Ye(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}}function Ye(i){for(const t of i.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(le(n))}for(const n in e.attributes){const s=e.attributes[n],o=le(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const o=e.morphAttributes[n].map(l=>le(l));r.morphAttributes[n]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new d.Matrix3(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function le(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new d.BufferAttribute(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const He=V("gltf-progressive-worker"),Qe=V("gltf-progressive-reduce-mipmaps"),ue=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class x{get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let m=0;m<c.lods.length;m++){const _=c.lods[m];_.width&&(a.lods[m]=a.lods[m]||{min_height:1/0,max_height:0},a.lods[m].min_height=Math.min(a.lods[m].min_height,_.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,_.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of E)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,x.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(c=>(c&&o.uniforms[l].value!=c&&(o.uniforms[l].value=c,o.uniformsNeedUpdate=!0),c));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],c=s[a];u&&u.isTexture===!0?l.push({material:r,slot:c,texture:u,level:e}):l.push({material:r,slot:c,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):x.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!p){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(Qe&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;p&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[F];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&x.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,x.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&x.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&x.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ue]=s);const o=s.guid;x.assignLODInformation(t,e,o,r,n),x.lodInfos.set(o,s),x.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),x.assignLODInformation(t,l,e,n,s),x.lodInfos.set(e,o);let a=x.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],x.lowresCache.set(e,a),n>0&&!X(r)&&Ne(r,l);for(const u of E)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const a=t;a.source&&a.source[ue]&&(o=a.source[ue])}if(o||(o=x.lodInfos.get(s)),o){if(e>0){let c=!1;const m=Array.isArray(o.lods);if(m&&e>=o.lods.length?c=!0:m||(c=!0),c)return this.lowresCache.get(s)}const a=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!a)return p&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const u=Ee(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const c=u+"_"+o.guid,m=await this.queue.slot(u),_=this.previouslyLoaded.get(c);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${c}`);let f=await _.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
|
|
2
2
|
`,S),null)),w=!1;if(f==null||(f instanceof d.Texture&&t instanceof d.Texture?f.image?.data||f.source?.data?f=this.copySettings(t,f):(w=!0,this.previouslyLoaded.delete(c)):f instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&(f.attributes.position?.array||(w=!0,this.previouslyLoaded.delete(c)))),!w)return f}if(!m.use)return p&&console.log(`LOD ${e} was aborted: ${u}`),null;const M=o,I=new Promise(async(f,w)=>{if(He){const y=await(await je({})).load(u);if(y.textures.length>0)for(const h of y.textures){let g=h.texture;return x.assignLODInformation(n.url,g,s,e,void 0),t instanceof d.Texture&&(g=this.copySettings(t,g)),g&&(g.guid=M.guid),f(g)}if(y.geometries.length>0){const h=new Array;for(const g of y.geometries){const v=g.geometry;x.assignLODInformation(n.url,v,s,e,g.primitiveIndex),h.push(v)}return f(h)}return f(null)}const S=new q.GLTFLoader;ye(S),p&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let B=u;if(M&&Array.isArray(M.lods)){const L=M.lods[e];L.hash&&(B+="?v="+L.hash)}const b=await S.loadAsync(B).catch(L=>(console.error(`Error loading LOD ${e} from ${u}
|
|
3
3
|
`,L),f(null)));if(!b)return f(null);const W=b.parser;r&&console.log("Loading finished "+u,M.guid);let T=0;if(b.parser.json.textures){let L=!1;for(const y of b.parser.json.textures){if(y?.extensions){const h=y?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){let y=await W.getDependency("texture",T);return y&&x.assignLODInformation(n.url,y,s,e,void 0),r&&console.log('change "'+t.name+'" → "'+y.name+'"',u,T,y,c),t instanceof d.Texture&&(y=this.copySettings(t,y)),y&&(y.guid=M.guid),f(y)}else p&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(T=0,b.parser.json.meshes){let L=!1;for(const y of b.parser.json.meshes){if(y?.extensions){const h=y?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){const y=await W.getDependency("mesh",T);if(r&&console.log(`Loaded Mesh "${y.name}"`,u,T,y,c),y.isMesh===!0){const h=y.geometry;return x.assignLODInformation(n.url,h,s,e,0),f(h)}else{const h=new Array;for(let g=0;g<y.children.length;g++){const v=y.children[g];if(v.isMesh===!0){const O=v.geometry;x.assignLODInformation(n.url,O,s,e,g),h.push(O)}}return f(h)}}else p&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return f(null)});return this.previouslyLoaded.set(c,I),m.use(I),await I}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+u);const m=await new d.TextureLoader().loadAsync(u);return m?(m.guid=o.guid,m.flipY=!1,m.needsUpdate=!0,m.colorSpace=t.colorSpace,r&&console.log(o,m)):p&&console.warn("failed loading",u),m}}else p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static maxConcurrent=50;static queue=new We(x.maxConcurrent,{debug:p!=!1});static assignLODInformation(t,e,r,n,s){if(!e)return;e.userData||(e.userData={});const o=new Je(t,r,n,s);e.userData.LODS=o,"source"in e&&typeof e.source=="object"&&(e.source.LODS=o)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(p==="verbose"&&console.debug(`Copy texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class Je{url;key;level;index;constructor(t,e,r,n){this.url=t,this.key=e,this.level=r,n!=null&&(this.index=n)}}class de{static addPromise=(t,e,r,n)=>{n.forEach(s=>{s.add(t,e,r)})};frame_start;frame_capture_end;ready;_resolve;_signal;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const n=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+n,this.ready=new Promise(s=>{this._resolve=s}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,(this._signal?.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){p&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){p&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+1)}else this._seen.set(e,1);this._awaiting.push(r),this._addedCount++,r.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(r),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const C=N("debugprogressive"),Ze=N("noprogressive"),ce=Symbol("Needle:LODSManager"),fe=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1};let Q=class D{static debugDrawLine;static overrideGlobalLodLevel;static getObjectLODState(t){return t[fe]}static addPlugin(t){E.push(t)}static removePlugin(t){const e=E.indexOf(t);e>=0&&E.splice(e,1)}static get(t,e){if(t[ce])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ce];const r=new D(t,{engine:"unknown",...e});return t[ce]=r,r}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return E}targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new de(this.#s,{...t});this._newPromiseGroups.push(r);const n=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),Le()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#s)}_lodchangedlisteners=[];addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#o=new d.Clock;#s=0;#n=0;#i=0;#r=0;_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;ne(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n=e.#o.getDelta(),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,C&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const o=t++;e.#t.call(this,r,n),e.onAfterRender(r,n,o)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let o=!0;if(s.length===1){const l=s[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(o=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(o=!1),o){if(Ze||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,C&&console.warn("↓ Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,C&&console.warn("↑ Increasing LOD updates",this.#e,this.#r.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#s%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const r=this.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of n){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){C&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(C==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const c=Math.random()*16777215,m=new d.MeshStandardMaterial({color:c});a.object.material=m}const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const o=r.transparent;for(const a of o){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,n){r.userData||(r.userData={});let s=r[fe];if(s||(s=new et,r[fe]=s),s.frames++<2)return;for(const l of E)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const o=D.overrideGlobalLodLevel!==void 0?D.overrideGlobalLodLevel:z;o>=0?(P.mesh_lod=o,P.texture_lod=o):(this.calculateLodLevel(e,r,s,n,P),P.mesh_lod=Math.round(P.mesh_lod),P.texture_lod=Math.round(P.texture_lod)),P.mesh_lod>=0&&this.loadProgressiveMeshes(r,P.mesh_lod),r.material&&P.texture_lod>=0&&this.loadProgressiveTextures(r.material,P.texture_lod,o),p&&r.material&&!r.isGizmo&&Ae(r.material);for(const l of E)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,P);s.lastLodLevel_Mesh=P.mesh_lod,s.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let n=!1;if((t[U]===void 0||e<t[U])&&(n=!0),r!==void 0&&r>=0&&(n=t[U]!=r,e=r),n){t[U]=e;const s=x.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});de.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[U]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[U]!=n,e=n),r){t[U]=e;const s=t.geometry,o=x.assignMeshLOD(t,e).then(l=>(l&&t[U]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return de.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}_sphere=new d.Sphere;_tempBox=new d.Box3;_tempBox2=new d.Box3;tempMatrix=new d.Matrix4;_tempWorldPosition=new d.Vector3;_tempBoxSize=new d.Vector3;_tempBox2Size=new d.Vector3;static corner0=new d.Vector3;static corner1=new d.Vector3;static corner2=new d.Vector3;static corner3=new d.Vector3;static _tempPtInside=new d.Vector3;static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,n,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,a=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=x.getMeshLODExtension(e.geometry)?.lods,c=x.getPrimitiveIndex(e.geometry),m=u&&u.length>0,_=x.getMaterialMinMaxLODsCount(e.material),M=_.min_count!==1/0&&_.min_count>=0&&_.max_count>=0;if(!m&&!M){s.mesh_lod=0,s.texture_lod=0;return}m||(a=!0,l=0);const I=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let G=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const f=e;if(!f.boundingBox)f.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!f[D.$skinnedMeshBoundsOffset]){const S=D.skinnedMeshBoundsFrameOffsetCounter++;f[D.$skinnedMeshBoundsOffset]=S}const w=f[D.$skinnedMeshBoundsOffset];if((r.frames+w)%this.skinnedMeshAutoUpdateBoundsInterval===0){const S=X(f),B=f.geometry;S&&(f.geometry=S),f.computeBoundingBox(),f.geometry=B}}G=f.boundingBox}if(G){const f=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const h=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(G),this._tempBox.applyMatrix4(e.matrixWorld),f.isPerspectiveCamera&&D.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&f.isPerspectiveCamera&&f.fov>70){const h=this._tempBox.min,g=this._tempBox.max;let v=h.x,O=h.y,$=g.x,K=g.y;const J=2,oe=1.5,Z=(h.x+g.x)*.5,ee=(h.y+g.y)*.5;v=(v-Z)*J+Z,O=(O-ee)*J+ee,$=($-Z)*J+Z,K=(K-ee)*J+ee;const ke=v<0&&$>0?0:Math.min(Math.abs(h.x),Math.abs(g.x)),Re=O<0&&K>0?0:Math.min(Math.abs(h.y),Math.abs(g.y)),ie=Math.max(ke,Re);r.lastCentrality=(oe-ie)*(oe-ie)*(oe-ie)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&I>0&&w.multiplyScalar(I/screen.availHeight),t.isPerspectiveCamera?w.x*=t.aspect:t.isOrthographicCamera;const S=t.matrixWorldInverse,B=this._tempBox2;B.copy(G),B.applyMatrix4(e.matrixWorld),B.applyMatrix4(S);const b=B.getSize(this._tempBox2Size),W=Math.max(b.x,b.y);if(Math.max(w.x,w.y)!=0&&W!=0&&(w.z=b.z/Math.max(b.x,b.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,C&&D.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const g=D.corner0,v=D.corner1,O=D.corner2,$=D.corner3;g.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=g.x,O.copy(this._tempBox.max),O.y=g.y,$.copy(this._tempBox.max);const K=(g.z+$.z)*.5;g.z=v.z=O.z=$.z=K,g.applyMatrix4(h),v.applyMatrix4(h),O.applyMatrix4(h),$.applyMatrix4(h),D.debugDrawLine(g,v,255),D.debugDrawLine(g,O,255),D.debugDrawLine(v,$,255),D.debugDrawLine(O,$,255)}let L=999;if(u&&r.lastScreenCoverage>0)for(let h=0;h<u.length;h++){const g=u[h],O=(g.densities?.[c]||g.density||1e-5)/r.lastScreenCoverage;if(c>0&&Le()&&!g.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),O<n){L=h;break}}L<l&&(l=L,a=!0)}if(a?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,C&&s.mesh_lod!=r.lastLodLevel_Mesh){const w=u?.[s.mesh_lod];w&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (density: ${w.densities?.[c].toFixed(0)}) | ${e.name}`)}if(M){const f="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=_.max_count-1,C){const w=_.lods[_.max_count-1];C&&console.log(`First Texture LOD ${s.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let S=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(S*=1.5);const b=I/window.devicePixelRatio*S;let W=!1;for(let T=_.lods.length-1;T>=0;T--){const L=_.lods[T];if(!(f&&L.max_height>=2048)&&!(Pe()&&L.max_height>4096)&&(L.max_height>b||!W&&T===0)){if(W=!0,s.texture_lod=T,C&&s.texture_lod<r.lastLodLevel_Texture){const y=L.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${y}px
|
|
5
|
+
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class Je{url;key;level;index;constructor(t,e,r,n){this.url=t,this.key=e,this.level=r,n!=null&&(this.index=n)}}class de{static addPromise=(t,e,r,n)=>{n.forEach(s=>{s.add(t,e,r)})};frame_start;frame_capture_end;ready;_resolve;_signal;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const n=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+n,this.ready=new Promise(s=>{this._resolve=s}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,(this._signal?.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){p&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){p&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+1)}else this._seen.set(e,1);this._awaiting.push(r),this._addedCount++,r.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(r),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const C=V("debugprogressive"),Ze=V("noprogressive"),ce=Symbol("Needle:LODSManager"),fe=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1};let Q=class D{static debugDrawLine;static overrideGlobalLodLevel;static getObjectLODState(t){return t[fe]}static addPlugin(t){E.push(t)}static removePlugin(t){const e=E.indexOf(t);e>=0&&E.splice(e,1)}static get(t,e){if(t[ce])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ce];const r=new D(t,{engine:"unknown",...e});return t[ce]=r,r}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return E}targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new de(this.#s,{...t});this._newPromiseGroups.push(r);const n=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),Le()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#s)}_lodchangedlisteners=[];addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#o=new d.Clock;#s=0;#n=0;#i=0;#r=0;_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;ne(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n=e.#o.getDelta(),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,C&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const o=t++;e.#t.call(this,r,n),e.onAfterRender(r,n,o)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.renderer.renderLists.get(t,0).opaque;let o=!0;if(s.length===1){const l=s[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(o=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(o=!1),o){if(Ze||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,C&&console.warn("↓ Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,C&&console.warn("↑ Increasing LOD updates",this.#e,this.#r.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#s%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const r=this.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of n){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){C&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(C==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const c=Math.random()*16777215,m=new d.MeshStandardMaterial({color:c});a.object.material=m}const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const o=r.transparent;for(const a of o){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,n){r.userData||(r.userData={});let s=r[fe];if(s||(s=new et,r[fe]=s),s.frames++<2)return;for(const l of E)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const o=D.overrideGlobalLodLevel!==void 0?D.overrideGlobalLodLevel:z;o>=0?(P.mesh_lod=o,P.texture_lod=o):(this.calculateLodLevel(e,r,s,n,P),P.mesh_lod=Math.round(P.mesh_lod),P.texture_lod=Math.round(P.texture_lod)),P.mesh_lod>=0&&this.loadProgressiveMeshes(r,P.mesh_lod),r.material&&P.texture_lod>=0&&this.loadProgressiveTextures(r.material,P.texture_lod,o),p&&r.material&&!r.isGizmo&&Ae(r.material);for(const l of E)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,P);s.lastLodLevel_Mesh=P.mesh_lod,s.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let n=!1;if((t[U]===void 0||e<t[U])&&(n=!0),r!==void 0&&r>=0&&(n=t[U]!=r,e=r),n){t[U]=e;const s=x.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});de.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[U]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[U]!=n,e=n),r){t[U]=e;const s=t.geometry,o=x.assignMeshLOD(t,e).then(l=>(l&&t[U]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return de.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}_sphere=new d.Sphere;_tempBox=new d.Box3;_tempBox2=new d.Box3;tempMatrix=new d.Matrix4;_tempWorldPosition=new d.Vector3;_tempBoxSize=new d.Vector3;_tempBox2Size=new d.Vector3;static corner0=new d.Vector3;static corner1=new d.Vector3;static corner2=new d.Vector3;static corner3=new d.Vector3;static _tempPtInside=new d.Vector3;static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,n,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,a=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=x.getMeshLODExtension(e.geometry)?.lods,c=x.getPrimitiveIndex(e.geometry),m=u&&u.length>0,_=x.getMaterialMinMaxLODsCount(e.material),M=_.min_count!==1/0&&_.min_count>=0&&_.max_count>=0;if(!m&&!M){s.mesh_lod=0,s.texture_lod=0;return}m||(a=!0,l=0);const I=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let G=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const f=e;if(!f.boundingBox)f.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!f[D.$skinnedMeshBoundsOffset]){const S=D.skinnedMeshBoundsFrameOffsetCounter++;f[D.$skinnedMeshBoundsOffset]=S}const w=f[D.$skinnedMeshBoundsOffset];if((r.frames+w)%this.skinnedMeshAutoUpdateBoundsInterval===0){const S=X(f),B=f.geometry;S&&(f.geometry=S),f.computeBoundingBox(),f.geometry=B}}G=f.boundingBox}if(G){const f=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const h=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(G),this._tempBox.applyMatrix4(e.matrixWorld),f.isPerspectiveCamera&&D.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&f.isPerspectiveCamera&&f.fov>70){const h=this._tempBox.min,g=this._tempBox.max;let v=h.x,O=h.y,$=g.x,K=g.y;const J=2,oe=1.5,Z=(h.x+g.x)*.5,ee=(h.y+g.y)*.5;v=(v-Z)*J+Z,O=(O-ee)*J+ee,$=($-Z)*J+Z,K=(K-ee)*J+ee;const ke=v<0&&$>0?0:Math.min(Math.abs(h.x),Math.abs(g.x)),Re=O<0&&K>0?0:Math.min(Math.abs(h.y),Math.abs(g.y)),ie=Math.max(ke,Re);r.lastCentrality=(oe-ie)*(oe-ie)*(oe-ie)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&I>0&&w.multiplyScalar(I/screen.availHeight),t.isPerspectiveCamera?w.x*=t.aspect:t.isOrthographicCamera;const S=t.matrixWorldInverse,B=this._tempBox2;B.copy(G),B.applyMatrix4(e.matrixWorld),B.applyMatrix4(S);const b=B.getSize(this._tempBox2Size),W=Math.max(b.x,b.y);if(Math.max(w.x,w.y)!=0&&W!=0&&(w.z=b.z/Math.max(b.x,b.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,C&&D.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const g=D.corner0,v=D.corner1,O=D.corner2,$=D.corner3;g.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=g.x,O.copy(this._tempBox.max),O.y=g.y,$.copy(this._tempBox.max);const K=(g.z+$.z)*.5;g.z=v.z=O.z=$.z=K,g.applyMatrix4(h),v.applyMatrix4(h),O.applyMatrix4(h),$.applyMatrix4(h),D.debugDrawLine(g,v,255),D.debugDrawLine(g,O,255),D.debugDrawLine(v,$,255),D.debugDrawLine(O,$,255)}let L=999;if(u&&r.lastScreenCoverage>0)for(let h=0;h<u.length;h++){const g=u[h],O=(g.densities?.[c]||g.density||1e-5)/r.lastScreenCoverage;if(c>0&&Le()&&!g.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),O<n){L=h;break}}L<l&&(l=L,a=!0)}if(a?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,C&&s.mesh_lod!=r.lastLodLevel_Mesh){const w=u?.[s.mesh_lod];w&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (density: ${w.densities?.[c].toFixed(0)}) | ${e.name}`)}if(M){const f="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=_.max_count-1,C){const w=_.lods[_.max_count-1];C&&console.log(`First Texture LOD ${s.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let S=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(S*=1.5);const b=I/window.devicePixelRatio*S;let W=!1;for(let T=_.lods.length-1;T>=0;T--){const L=_.lods[T];if(!(f&&L.max_height>=2048)&&!(Pe()&&L.max_height>4096)&&(L.max_height>b||!W&&T===0)){if(W=!0,s.texture_lod=T,C&&s.texture_lod<r.lastLodLevel_Texture){const y=L.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${y}px
|
|
6
6
|
Screensize: ${b.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
|
|
7
7
|
${e.name}`)}break}}}}else s.texture_lod=0}};class et{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new d.Vector3;lastCentrality=0}const _e=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");let he=null;function Ie(){const i=tt();i&&(i.mapURLs(function(t){return Me(),t}),Me(),he?.disconnect(),he=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ce(r)})})}),he.observe(document,{childList:!0,subtree:!0}))}function tt(){if(typeof customElements>"u")return null;const i=customElements.get("model-viewer");return i||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ie()}),null)}function Me(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ce(t)})}const De=new WeakSet;let rt=0;function Ce(i){if(!i||De.has(i))return null;De.add(i),console.debug("[gltf-progressive] found new model-viewer..."+ ++rt+`
|
|
8
|
-
`,i.getAttribute("src"));let t=null,e=null,r=null;for(let n=i;n!=null;n=Object.getPrototypeOf(n)){const s=Object.getOwnPropertySymbols(n),o=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&o!=null&&(t=i[o].threeRenderer),!e&&l!=null&&(e=i[l]),!r&&a!=null&&(r=i[a])}if(t&&e){let s=function(){if(r){let o=0,l=setInterval(()=>{if(o++>5){clearInterval(l);return}r?.call(i)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=Q.get(t,{engine:"model-viewer"});return Q.addPlugin(new st),n.enable(),n.addEventListener("changed",()=>{r?.call(i)}),i.addEventListener("model-visibility",o=>{o.detail.visible&&r?.call(i)}),i.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class st{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[te]==!0)return;e[te]=!0;const r=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),s=this.getUrl(n);if(s&&r&&e.material){let l=function(a){if(a[te]==!0)return;a[te]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let c=0;c<u.length;c++){const m=u[c],_=a[m];if(_?.isTexture===!0){const M=_.userData?.associations?.textures;if(M==null)continue;const I=r.parser.json.textures[M];if(!I){console.warn("Texture data not found for texture index "+M);continue}if(I?.extensions?.[F]){const G=I.extensions[F];G&&s&&x.registerTexture(s,_,G.lods.length,M,G)}}}};const o=e.material;if(Array.isArray(o))for(const a of o)l(a);else l(o)}}tryParseMeshLOD(t,e){if(e[_e]==!0)return;e[_e]=!0;const r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(!n)return;const s=e.userData?.gltfExtensions?.[F];if(s&&n){const o=e.uuid;x.registerMesh(n,o,e,0,s.lods.length,s)}}}function nt(i,t,e,r)
|
|
8
|
+
`,i.getAttribute("src"));let t=null,e=null,r=null;for(let n=i;n!=null;n=Object.getPrototypeOf(n)){const s=Object.getOwnPropertySymbols(n),o=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&o!=null&&(t=i[o].threeRenderer),!e&&l!=null&&(e=i[l]),!r&&a!=null&&(r=i[a])}if(t&&e){let s=function(){if(r){let o=0,l=setInterval(()=>{if(o++>5){clearInterval(l);return}r?.call(i)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=Q.get(t,{engine:"model-viewer"});return Q.addPlugin(new st),n.enable(),n.addEventListener("changed",()=>{r?.call(i)}),i.addEventListener("model-visibility",o=>{o.detail.visible&&r?.call(i)}),i.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class st{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[te]==!0)return;e[te]=!0;const r=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),s=this.getUrl(n);if(s&&r&&e.material){let l=function(a){if(a[te]==!0)return;a[te]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let c=0;c<u.length;c++){const m=u[c],_=a[m];if(_?.isTexture===!0){const M=_.userData?.associations?.textures;if(M==null)continue;const I=r.parser.json.textures[M];if(!I){console.warn("Texture data not found for texture index "+M);continue}if(I?.extensions?.[F]){const G=I.extensions[F];G&&s&&x.registerTexture(s,_,G.lods.length,M,G)}}}};const o=e.material;if(Array.isArray(o))for(const a of o)l(a);else l(o)}}tryParseMeshLOD(t,e){if(e[_e]==!0)return;e[_e]=!0;const r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(!n)return;const s=e.userData?.gltfExtensions?.[F];if(s&&n){const o=e.uuid;x.registerMesh(n,o,e,0,s.lods.length,s)}}}function nt(...i){let t,e,r,n;switch(i.length){case 2:[r,e]=i,n={};break;case 3:[r,e,n]=i;break;case 4:[t,e,r,n]=i;break;default:throw new Error("Invalid arguments")}ne(e),ye(r),xe(r,{progressive:!0,...n?.hints}),r.register(o=>new x(o));const s=Q.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}Ie();if(!ze){const i={gltfProgressive:{useNeedleProgressive:nt,LODsManager:Q,configureLoader:xe,getRaycastMesh:X,useRaycastMeshes:Ve}};if(!globalThis.Needle)globalThis.Needle=i;else for(const t in i)globalThis.Needle[t]=i[t]}exports.LODsManager=Q;exports.NEEDLE_progressive=x;exports.addDracoAndKTX2Loaders=ye;exports.configureLoader=xe;exports.createLoaders=ne;exports.getRaycastMesh=X;exports.setDracoDecoderLocation=Oe;exports.setKTX2TranscoderLocation=Se;
|