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