@harpern/edu-modelhub-viewer-core 0.1.0-beta.0 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +3 -0
- package/dist/announce.d.ts +1 -1
- package/dist/coordinates.d.ts +1 -1
- package/dist/index.cjs +12 -12
- package/dist/index.d.ts +3 -2
- package/dist/index.js +826 -360
- package/dist/metadata.d.ts +7 -2
- package/dist/normalize.d.ts +10 -1
- package/dist/regions.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/types.d.ts +147 -0
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -1,29 +1,476 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { SpriteMaterial as V, CanvasTexture as E, Sprite as W, Vector3 as b, Raycaster as q, AmbientLight as Y, SpotLight as H, Color as T, DirectionalLight as X, Box3 as v } from "three";
|
|
2
|
+
const C = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
3
|
+
function _(e, t) {
|
|
4
|
+
const n = /* @__PURE__ */ new WeakSet(), o = [
|
|
5
|
+
{ value: e, path: "" }
|
|
6
|
+
], r = (i, s) => {
|
|
7
|
+
o.push({ value: i, path: s });
|
|
8
|
+
};
|
|
9
|
+
for (; o.length > 0; ) {
|
|
10
|
+
const { value: i, path: s } = o.pop();
|
|
11
|
+
if (!(typeof i != "object" || i === null || n.has(i)))
|
|
12
|
+
if (n.add(i), Array.isArray(i))
|
|
13
|
+
for (let c = 0; c < i.length; c++)
|
|
14
|
+
r(i[c], `${s}[${c}]`);
|
|
15
|
+
else
|
|
16
|
+
t(i, s, r);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function K(e) {
|
|
20
|
+
const t = [];
|
|
21
|
+
return _(e, (n, o, r) => {
|
|
22
|
+
for (const i of Object.keys(n)) {
|
|
23
|
+
const s = o === "" ? i : `${o}.${i}`;
|
|
24
|
+
C.has(i) ? t.push({ path: s, key: i }) : r(n[i], s);
|
|
25
|
+
}
|
|
26
|
+
}), t;
|
|
27
|
+
}
|
|
28
|
+
function Z(e) {
|
|
29
|
+
return _(e, (t, n, o) => {
|
|
30
|
+
for (const r of Object.keys(t))
|
|
31
|
+
C.has(r) ? delete t[r] : o(t[r], n);
|
|
32
|
+
}), e;
|
|
33
|
+
}
|
|
34
|
+
const N = 1179937895, k = 2, Q = 1313821514, J = 21;
|
|
35
|
+
class g extends Error {
|
|
36
|
+
constructor(t) {
|
|
37
|
+
super(t), this.name = "GlbParseError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function ee(e) {
|
|
41
|
+
return e instanceof ArrayBuffer ? new DataView(e) : new DataView(e.buffer, e.byteOffset, e.byteLength);
|
|
42
|
+
}
|
|
43
|
+
function te(e) {
|
|
44
|
+
return e === null ? "null" : Array.isArray(e) ? "an array" : typeof e;
|
|
45
|
+
}
|
|
46
|
+
function ne(e) {
|
|
47
|
+
const t = ee(e);
|
|
48
|
+
if (t.byteLength < J)
|
|
49
|
+
throw new g(
|
|
50
|
+
`Input too short to be a GLB file (${t.byteLength} bytes).`
|
|
51
|
+
);
|
|
52
|
+
const n = t.getUint32(
|
|
53
|
+
0,
|
|
54
|
+
!0
|
|
55
|
+
/* littleEndian */
|
|
56
|
+
);
|
|
57
|
+
if (n !== N)
|
|
58
|
+
throw new g(
|
|
59
|
+
`Invalid GLB magic: expected 0x${N.toString(16)}, got 0x${n.toString(16)}.`
|
|
60
|
+
);
|
|
61
|
+
const o = t.getUint32(4, !0);
|
|
62
|
+
if (o !== k)
|
|
63
|
+
throw new g(
|
|
64
|
+
`Unsupported GLB version: expected ${k}, got ${o}.`
|
|
65
|
+
);
|
|
66
|
+
const r = t.getUint32(8, !0);
|
|
67
|
+
if (r > t.byteLength)
|
|
68
|
+
throw new g(
|
|
69
|
+
`GLB header reports ${r} bytes but only ${t.byteLength} bytes were supplied.`
|
|
70
|
+
);
|
|
71
|
+
if (t.byteLength < 20)
|
|
72
|
+
throw new g("GLB file truncated before first chunk header.");
|
|
73
|
+
const i = t.getUint32(12, !0), s = t.getUint32(16, !0);
|
|
74
|
+
if (s !== Q)
|
|
75
|
+
throw new g(
|
|
76
|
+
`First GLB chunk is not JSON (type 0x${s.toString(16)}).`
|
|
77
|
+
);
|
|
78
|
+
if (20 + i > r)
|
|
79
|
+
throw new g(
|
|
80
|
+
`JSON chunk claims ${i} bytes but the declared GLB length is only ${r} bytes.`
|
|
81
|
+
);
|
|
82
|
+
if (20 + i > t.byteLength)
|
|
83
|
+
throw new g(
|
|
84
|
+
`JSON chunk claims ${i} bytes but only ${t.byteLength - 20} bytes remain in the buffer.`
|
|
85
|
+
);
|
|
86
|
+
const c = new Uint8Array(
|
|
87
|
+
t.buffer,
|
|
88
|
+
t.byteOffset + 20,
|
|
89
|
+
i
|
|
90
|
+
), l = new TextDecoder("utf-8").decode(c);
|
|
91
|
+
let a;
|
|
92
|
+
try {
|
|
93
|
+
a = JSON.parse(l);
|
|
94
|
+
} catch (u) {
|
|
95
|
+
throw new g(
|
|
96
|
+
`Failed to parse GLB JSON chunk: ${u.message}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (a === null || typeof a != "object" || Array.isArray(a))
|
|
100
|
+
throw new g(
|
|
101
|
+
`GLB JSON chunk root must be an object, got ${te(a)}.`
|
|
102
|
+
);
|
|
103
|
+
return a;
|
|
104
|
+
}
|
|
105
|
+
function oe(e) {
|
|
106
|
+
const t = ne(e).extensions;
|
|
107
|
+
if (t === null || typeof t != "object" || Array.isArray(t))
|
|
108
|
+
return null;
|
|
109
|
+
const n = t.EDU_modelhub;
|
|
110
|
+
return n === void 0 ? null : Z(n);
|
|
111
|
+
}
|
|
112
|
+
const re = /^[a-z][a-z0-9_]*$/, ie = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, se = /^[a-z]{2}$/, ae = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
113
|
+
function d(e, t) {
|
|
114
|
+
return { field: e, message: t, severity: "error" };
|
|
115
|
+
}
|
|
116
|
+
function $(e, t) {
|
|
117
|
+
return { field: e, message: t, severity: "warning" };
|
|
118
|
+
}
|
|
119
|
+
function x(e) {
|
|
120
|
+
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
121
|
+
}
|
|
122
|
+
function w(e) {
|
|
123
|
+
return typeof e == "string" && e.trim() !== "";
|
|
124
|
+
}
|
|
125
|
+
function U(e) {
|
|
126
|
+
return typeof e == "number" && Number.isInteger(e) && e >= 0;
|
|
127
|
+
}
|
|
128
|
+
function h(e) {
|
|
129
|
+
if (e === void 0) return "undefined";
|
|
130
|
+
let t;
|
|
131
|
+
if (typeof e == "string")
|
|
132
|
+
t = `"${e}"`;
|
|
133
|
+
else
|
|
134
|
+
try {
|
|
135
|
+
const n = JSON.stringify(e);
|
|
136
|
+
if (n === void 0) return typeof e;
|
|
137
|
+
t = n;
|
|
138
|
+
} catch {
|
|
139
|
+
return Array.isArray(e) ? "an array" : typeof e;
|
|
140
|
+
}
|
|
141
|
+
return t.length > 60 ? `${t.slice(0, 57)}...` : t;
|
|
142
|
+
}
|
|
143
|
+
function F(e) {
|
|
144
|
+
const t = [], n = e;
|
|
145
|
+
if (!x(n))
|
|
146
|
+
return [d("", `Payload must be a JSON object, got ${h(n)}.`)];
|
|
147
|
+
ce(n, t), ue(n.specVersion, t), le(n.coordinateSpace, t), de(n.model, t);
|
|
148
|
+
const o = pe(n.regions, t);
|
|
149
|
+
return ye(n.annotations, o, t), t;
|
|
150
|
+
}
|
|
151
|
+
function ce(e, t) {
|
|
152
|
+
for (const n of K(e))
|
|
153
|
+
t.push(
|
|
154
|
+
d(
|
|
155
|
+
n.path,
|
|
156
|
+
`Disallowed key "${n.key}" at ${n.path} (prototype-pollution vector).`
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
function ue(e, t) {
|
|
161
|
+
(typeof e != "string" || !ae.test(e)) && t.push(
|
|
162
|
+
d(
|
|
163
|
+
"specVersion",
|
|
164
|
+
`specVersion must be a semver string (e.g. "0.1.0"), got ${h(e)}.`
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
function le(e, t) {
|
|
169
|
+
e !== void 0 && e !== "gltf" && e !== "blender" && t.push(
|
|
170
|
+
d(
|
|
171
|
+
"coordinateSpace",
|
|
172
|
+
`coordinateSpace must be "gltf" or "blender" when present, got ${h(e)}.`
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
function de(e, t) {
|
|
177
|
+
if (!x(e)) {
|
|
178
|
+
t.push(
|
|
179
|
+
d(
|
|
180
|
+
"model",
|
|
181
|
+
`model is required and must be an object, got ${h(e)}.`
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const n = e, o = n.title;
|
|
187
|
+
w(o) || t.push(
|
|
188
|
+
d(
|
|
189
|
+
"model.title",
|
|
190
|
+
`model.title is required and must be a non-empty string, got ${h(o)}.`
|
|
191
|
+
)
|
|
192
|
+
);
|
|
193
|
+
const r = n.altText;
|
|
194
|
+
w(r) ? r.length > 300 && t.push(
|
|
195
|
+
d(
|
|
196
|
+
"model.altText",
|
|
197
|
+
`model.altText exceeds 300 characters (${r.length} chars).`
|
|
198
|
+
)
|
|
199
|
+
) : t.push(
|
|
200
|
+
d(
|
|
201
|
+
"model.altText",
|
|
202
|
+
`model.altText is required and must be a non-empty string, got ${h(r)}.`
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
const i = n.language;
|
|
206
|
+
i !== void 0 && (typeof i != "string" || !se.test(i)) && t.push(
|
|
207
|
+
$(
|
|
208
|
+
"model.language",
|
|
209
|
+
`model.language should be an ISO 639-1 two-letter code (e.g. "en"), got ${h(i)}.`
|
|
210
|
+
)
|
|
211
|
+
), fe(n, t), me(n.source, t), he(n, t), w(n.longDescription) || t.push(
|
|
212
|
+
$("model.longDescription", "model.longDescription is recommended.")
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
function fe(e, t) {
|
|
216
|
+
const n = ["CC0", "CC BY", "CC BY-SA", "All Rights Reserved"], o = e.license;
|
|
217
|
+
o !== void 0 && (typeof o != "string" || !n.includes(o)) && t.push(
|
|
218
|
+
d(
|
|
219
|
+
"model.license",
|
|
220
|
+
`model.license must be one of ${n.map((r) => `"${r}"`).join(", ")}, got ${h(o)}.`
|
|
221
|
+
)
|
|
222
|
+
), (o === "CC BY" || o === "CC BY-SA") && !w(e.attribution) && t.push(
|
|
223
|
+
$(
|
|
224
|
+
"model.attribution",
|
|
225
|
+
'model.attribution is recommended when license is "CC BY" or "CC BY-SA".'
|
|
226
|
+
)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
function me(e, t) {
|
|
230
|
+
if (e === void 0) return;
|
|
231
|
+
const n = ["scan", "photogrammetry", "manual", "other"];
|
|
232
|
+
if (typeof e != "string" || !n.includes(e)) {
|
|
233
|
+
const o = n.map((r) => `"${r}"`).join(", ");
|
|
234
|
+
t.push(
|
|
235
|
+
d(
|
|
236
|
+
"model.source",
|
|
237
|
+
`model.source must be one of ${o}, got ${h(e)}.`
|
|
238
|
+
)
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function he(e, t) {
|
|
243
|
+
for (const n of ["created", "modified"]) {
|
|
244
|
+
const o = e[n];
|
|
245
|
+
o !== void 0 && (typeof o != "string" || !ie.test(o)) && t.push(
|
|
246
|
+
$(
|
|
247
|
+
`model.${n}`,
|
|
248
|
+
`model.${n} should be ISO 8601 UTC (YYYY-MM-DDTHH:MM:SSZ), got ${h(o)}.`
|
|
249
|
+
)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function pe(e, t) {
|
|
254
|
+
const n = /* @__PURE__ */ new Set();
|
|
255
|
+
if (!Array.isArray(e) || e.length === 0)
|
|
256
|
+
return t.push(d("regions", "At least one region is required.")), n;
|
|
257
|
+
for (let o = 0; o < e.length; o++) {
|
|
258
|
+
const r = e[o], i = `regions[${o}]`;
|
|
259
|
+
if (!x(r)) {
|
|
260
|
+
t.push(
|
|
261
|
+
d(i, `${i} must be an object, got ${h(r)}.`)
|
|
262
|
+
);
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
ge(r, i, n, t);
|
|
266
|
+
}
|
|
267
|
+
return n;
|
|
268
|
+
}
|
|
269
|
+
function ge(e, t, n, o) {
|
|
270
|
+
const r = e.id;
|
|
271
|
+
typeof r != "string" || !re.test(r) ? o.push(
|
|
272
|
+
d(
|
|
273
|
+
`${t}.id`,
|
|
274
|
+
`${t}.id must be a non-empty snake_case string (lowercase letters, digits, underscores; must start with a letter), got ${h(r)}.`
|
|
275
|
+
)
|
|
276
|
+
) : n.has(r) ? o.push(
|
|
277
|
+
d(`${t}.id`, `Duplicate region id "${r}" at ${t}.`)
|
|
278
|
+
) : n.add(r);
|
|
279
|
+
const i = e.visibilityDefault;
|
|
280
|
+
i !== void 0 && i !== "shown" && i !== "hidden" && o.push(
|
|
281
|
+
d(
|
|
282
|
+
`${t}.visibilityDefault`,
|
|
283
|
+
`${t}.visibilityDefault must be "shown" or "hidden", got ${h(i)}.`
|
|
284
|
+
)
|
|
285
|
+
);
|
|
286
|
+
const s = e.order;
|
|
287
|
+
s !== void 0 && !U(s) && o.push(
|
|
288
|
+
$(
|
|
289
|
+
`${t}.order`,
|
|
290
|
+
`${t}.order should be a non-negative integer, got ${h(s)}.`
|
|
291
|
+
)
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
function ye(e, t, n) {
|
|
295
|
+
if (!Array.isArray(e)) {
|
|
296
|
+
n.push(d("annotations", "annotations must be an array."));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
e.length < 3 && n.push(
|
|
300
|
+
$(
|
|
301
|
+
"annotations",
|
|
302
|
+
`Only ${e.length} annotation(s) defined (3–8 recommended).`
|
|
303
|
+
)
|
|
304
|
+
), e.length > 8 && n.push(
|
|
305
|
+
$(
|
|
306
|
+
"annotations",
|
|
307
|
+
`${e.length} annotations defined (3–8 recommended).`
|
|
308
|
+
)
|
|
309
|
+
);
|
|
310
|
+
const o = {
|
|
311
|
+
seenRegionIds: t,
|
|
312
|
+
seenAnnotationIds: /* @__PURE__ */ new Set(),
|
|
313
|
+
seenReadingOrders: /* @__PURE__ */ new Set()
|
|
314
|
+
};
|
|
315
|
+
for (let r = 0; r < e.length; r++) {
|
|
316
|
+
const i = e[r], s = `annotations[${r}]`;
|
|
317
|
+
if (!x(i)) {
|
|
318
|
+
n.push(
|
|
319
|
+
d(s, `${s} must be an object, got ${h(i)}.`)
|
|
320
|
+
);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
be(i, s, o, n);
|
|
324
|
+
}
|
|
325
|
+
ve(o.seenReadingOrders, n);
|
|
326
|
+
}
|
|
327
|
+
function be(e, t, n, o) {
|
|
328
|
+
const r = e.id;
|
|
329
|
+
w(r) ? n.seenAnnotationIds.has(r) ? o.push(
|
|
330
|
+
d(`${t}.id`, `Duplicate annotation id "${r}" at ${t}.`)
|
|
331
|
+
) : n.seenAnnotationIds.add(r) : o.push(
|
|
332
|
+
d(
|
|
333
|
+
`${t}.id`,
|
|
334
|
+
`${t}.id is required and must be a non-empty string, got ${h(r)}.`
|
|
335
|
+
)
|
|
336
|
+
);
|
|
337
|
+
const i = e.regionId;
|
|
338
|
+
i !== void 0 && i !== "" && (typeof i != "string" || !n.seenRegionIds.has(i)) && o.push(
|
|
339
|
+
d(
|
|
340
|
+
`${t}.regionId`,
|
|
341
|
+
`${t}.regionId ${h(i)} does not match any region id.`
|
|
342
|
+
)
|
|
343
|
+
), $e(e.readingOrder, t, n, o), we(e.anchor, t, o), xe(e.camera, t, o);
|
|
344
|
+
}
|
|
345
|
+
function $e(e, t, n, o) {
|
|
346
|
+
e !== void 0 && (U(e) ? n.seenReadingOrders.has(e) ? o.push(
|
|
347
|
+
d(
|
|
348
|
+
`${t}.readingOrder`,
|
|
349
|
+
`Duplicate readingOrder value ${e} at ${t}.`
|
|
350
|
+
)
|
|
351
|
+
) : n.seenReadingOrders.add(e) : o.push(
|
|
352
|
+
d(
|
|
353
|
+
`${t}.readingOrder`,
|
|
354
|
+
`${t}.readingOrder must be a non-negative integer, got ${h(e)}.`
|
|
355
|
+
)
|
|
356
|
+
));
|
|
357
|
+
}
|
|
358
|
+
function we(e, t, n) {
|
|
359
|
+
if (!x(e)) {
|
|
360
|
+
n.push(
|
|
361
|
+
d(
|
|
362
|
+
`${t}.anchor`,
|
|
363
|
+
`${t}.anchor is required and must be an object, got ${h(e)}.`
|
|
364
|
+
)
|
|
365
|
+
);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const o = e, r = o.type;
|
|
369
|
+
if (r === "marker") {
|
|
370
|
+
const i = o.position;
|
|
371
|
+
(!Array.isArray(i) || i.length !== 3 || !i.every((s) => typeof s == "number")) && n.push(
|
|
372
|
+
d(
|
|
373
|
+
`${t}.anchor.position`,
|
|
374
|
+
`${t}.anchor.position must be an array of exactly 3 numbers for type "marker".`
|
|
375
|
+
)
|
|
376
|
+
);
|
|
377
|
+
} else r === "node" || r === "primitive" || r === "aabb" ? w(o.ref) || n.push(
|
|
378
|
+
d(
|
|
379
|
+
`${t}.anchor.ref`,
|
|
380
|
+
`${t}.anchor.ref is required for anchor type "${r}".`
|
|
381
|
+
)
|
|
382
|
+
) : n.push(
|
|
383
|
+
d(
|
|
384
|
+
`${t}.anchor.type`,
|
|
385
|
+
`${t}.anchor.type must be "marker", "node", "primitive", or "aabb", got ${h(r)}.`
|
|
386
|
+
)
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
function xe(e, t, n) {
|
|
390
|
+
if (e === void 0) return;
|
|
391
|
+
if (!x(e)) {
|
|
392
|
+
n.push(
|
|
393
|
+
d(
|
|
394
|
+
`${t}.camera`,
|
|
395
|
+
`${t}.camera must be an object when present, got ${h(e)}.`
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
for (const r of ["eye", "target"]) {
|
|
401
|
+
const i = e[r];
|
|
402
|
+
(!Array.isArray(i) || i.length !== 3 || !i.every((s) => typeof s == "number" && Number.isFinite(s))) && n.push(
|
|
403
|
+
d(
|
|
404
|
+
`${t}.camera.${r}`,
|
|
405
|
+
`${t}.camera.${r} must be an array of exactly 3 finite numbers.`
|
|
406
|
+
)
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
const o = e.fov;
|
|
410
|
+
o !== void 0 && (typeof o != "number" || !(o > 0)) && n.push(
|
|
411
|
+
d(
|
|
412
|
+
`${t}.camera.fov`,
|
|
413
|
+
`${t}.camera.fov must be a number greater than 0 when present, got ${h(o)}.`
|
|
414
|
+
)
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
function ve(e, t) {
|
|
418
|
+
if (e.size === 0) return;
|
|
419
|
+
const n = [...e].sort((o, r) => o - r);
|
|
420
|
+
for (let o = 0; o < n.length; o++)
|
|
421
|
+
if (n[o] !== o) {
|
|
422
|
+
t.push(
|
|
423
|
+
$(
|
|
424
|
+
"annotations[*].readingOrder",
|
|
425
|
+
`readingOrder values are not sequential from 0. Expected 0–${n.length - 1} but found gaps or wrong start.`
|
|
426
|
+
)
|
|
427
|
+
);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
class B extends Error {
|
|
432
|
+
constructor(t) {
|
|
433
|
+
super(t), this.name = "AdaptError";
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
class Ae {
|
|
437
|
+
adapt(t) {
|
|
438
|
+
var n, o;
|
|
439
|
+
const r = t.model, i = ((n = r == null ? void 0 : r.title) == null ? void 0 : n.trim()) ?? "", s = ((o = r == null ? void 0 : r.altText) == null ? void 0 : o.trim()) ?? "";
|
|
440
|
+
if (!i)
|
|
441
|
+
throw new B("Sidecar is missing required field: model.title");
|
|
442
|
+
if (!s)
|
|
443
|
+
throw new B("Sidecar is missing required field: model.altText");
|
|
444
|
+
return t;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const Se = new Ae();
|
|
448
|
+
function Ie(e) {
|
|
449
|
+
return Se.adapt(e);
|
|
450
|
+
}
|
|
451
|
+
function Me(e) {
|
|
5
452
|
return e.filter((t) => t.severity === "error");
|
|
6
453
|
}
|
|
7
|
-
function
|
|
8
|
-
const [t,
|
|
454
|
+
function Oe(e) {
|
|
455
|
+
const [t, n = ""] = e.split("?", 2);
|
|
9
456
|
if (!/\.glb$/i.test(t)) return null;
|
|
10
|
-
const
|
|
11
|
-
return
|
|
457
|
+
const o = t.replace(/\.glb$/i, ".modelhub.json");
|
|
458
|
+
return n ? `${o}?${n}` : o;
|
|
12
459
|
}
|
|
13
|
-
function
|
|
14
|
-
var
|
|
460
|
+
function Ke(e, t) {
|
|
461
|
+
var i;
|
|
15
462
|
if (!e || e.startsWith("blob:") || e.startsWith("data:")) return "";
|
|
16
|
-
const
|
|
17
|
-
return
|
|
463
|
+
const n = t ?? ((i = globalThis.location) == null ? void 0 : i.href), o = n ? new URL(e, n).href : e, r = o.lastIndexOf("/");
|
|
464
|
+
return r === -1 ? "" : o.slice(0, r + 1);
|
|
18
465
|
}
|
|
19
|
-
async function
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
22
|
-
throw new Error(`Failed to fetch ${e} (HTTP ${
|
|
23
|
-
return
|
|
466
|
+
async function Te(e, t = fetch) {
|
|
467
|
+
const n = await t(e);
|
|
468
|
+
if (!n.ok)
|
|
469
|
+
throw new Error(`Failed to fetch ${e} (HTTP ${n.status}).`);
|
|
470
|
+
return n.arrayBuffer();
|
|
24
471
|
}
|
|
25
|
-
function
|
|
26
|
-
const t =
|
|
472
|
+
function Ne(e) {
|
|
473
|
+
const t = oe(e);
|
|
27
474
|
if (!t)
|
|
28
475
|
return {
|
|
29
476
|
payload: null,
|
|
@@ -31,25 +478,25 @@ function G(e) {
|
|
|
31
478
|
findings: [],
|
|
32
479
|
problem: "This model carries no EDU_modelhub metadata."
|
|
33
480
|
};
|
|
34
|
-
const
|
|
35
|
-
return { payload: t, source: "embedded", findings:
|
|
36
|
-
}
|
|
37
|
-
async function
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
if (t.sidecar === !1) return { ...
|
|
41
|
-
const s = (t.sidecarUrl ??
|
|
42
|
-
if (!s) return { ...
|
|
481
|
+
const n = F(t);
|
|
482
|
+
return { payload: t, source: "embedded", findings: n, problem: null };
|
|
483
|
+
}
|
|
484
|
+
async function Ze(e, t = {}) {
|
|
485
|
+
const n = t.fetchImpl ?? fetch, o = await Te(e, n), r = Ne(o);
|
|
486
|
+
if (r.payload) return { ...r, bytes: o };
|
|
487
|
+
if (t.sidecar === !1) return { ...r, bytes: o };
|
|
488
|
+
const s = (t.sidecarUrl ?? Oe)(e);
|
|
489
|
+
if (!s) return { ...r, bytes: o };
|
|
43
490
|
try {
|
|
44
|
-
const c = await
|
|
491
|
+
const c = await n(s);
|
|
45
492
|
if (c.ok) {
|
|
46
|
-
const
|
|
493
|
+
const l = Ie(await c.json());
|
|
47
494
|
return {
|
|
48
|
-
payload:
|
|
495
|
+
payload: l,
|
|
49
496
|
source: "sidecar",
|
|
50
|
-
findings:
|
|
497
|
+
findings: F(l),
|
|
51
498
|
problem: null,
|
|
52
|
-
bytes:
|
|
499
|
+
bytes: o
|
|
53
500
|
};
|
|
54
501
|
}
|
|
55
502
|
} catch {
|
|
@@ -59,238 +506,255 @@ async function ue(e, t = {}) {
|
|
|
59
506
|
source: "none",
|
|
60
507
|
findings: [],
|
|
61
508
|
problem: "This model has no EDU_modelhub metadata, either embedded in the file or in a sidecar beside it.",
|
|
62
|
-
bytes:
|
|
509
|
+
bytes: o
|
|
63
510
|
};
|
|
64
511
|
}
|
|
65
|
-
function
|
|
512
|
+
function Qe(e, t = "EDU_modelhub", n = console) {
|
|
66
513
|
if (!(e != null && e.length)) return;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
`${t}: ${
|
|
70
|
-
|
|
514
|
+
const o = Me(e), r = e.filter((i) => i.severity !== "error");
|
|
515
|
+
o.length && n.warn(`${t}: ${o.length} validation error(s)`, o), r.length && n.info(
|
|
516
|
+
`${t}: ${r.length} validation warning(s)`,
|
|
517
|
+
r
|
|
71
518
|
);
|
|
72
519
|
}
|
|
73
|
-
function
|
|
520
|
+
function Je(e) {
|
|
521
|
+
return (e == null ? void 0 : e.name) === "GlbParseError";
|
|
522
|
+
}
|
|
523
|
+
function G(e) {
|
|
74
524
|
return Array.isArray(e) && e.length === 3 && e.every((t) => typeof t == "number" && Number.isFinite(t));
|
|
75
525
|
}
|
|
76
|
-
function
|
|
526
|
+
function P(e) {
|
|
77
527
|
return e === "blender";
|
|
78
528
|
}
|
|
79
|
-
function
|
|
80
|
-
if (!
|
|
81
|
-
const [
|
|
82
|
-
return
|
|
529
|
+
function A(e, t) {
|
|
530
|
+
if (!G(e)) return null;
|
|
531
|
+
const [n, o, r] = e;
|
|
532
|
+
return P(t) ? [n, r, -o] : [n, o, r];
|
|
83
533
|
}
|
|
84
|
-
function
|
|
85
|
-
if (!
|
|
86
|
-
const [
|
|
87
|
-
return
|
|
534
|
+
function et(e, t) {
|
|
535
|
+
if (!G(e)) return null;
|
|
536
|
+
const [n, o, r] = e;
|
|
537
|
+
return P(t) ? [n, -r, o] : [n, o, r];
|
|
88
538
|
}
|
|
89
|
-
function
|
|
539
|
+
function ke(e) {
|
|
90
540
|
if (!Array.isArray(e)) return [];
|
|
91
541
|
const t = /* @__PURE__ */ new Set();
|
|
92
|
-
return e.map((
|
|
93
|
-
const
|
|
94
|
-
let s =
|
|
95
|
-
for (; t.has(s); ) s = `${
|
|
96
|
-
return t.add(s), { ...
|
|
542
|
+
return e.map((n, o) => {
|
|
543
|
+
const i = (typeof (n == null ? void 0 : n.id) == "string" ? n.id.trim() : "") || `annotation-${o + 1}`;
|
|
544
|
+
let s = i, c = 2;
|
|
545
|
+
for (; t.has(s); ) s = `${i}-${c++}`;
|
|
546
|
+
return t.add(s), { ...n ?? {}, id: s };
|
|
97
547
|
});
|
|
98
548
|
}
|
|
99
|
-
function
|
|
100
|
-
const t =
|
|
101
|
-
return t.map((
|
|
102
|
-
(
|
|
103
|
-
).map((
|
|
549
|
+
function M(e) {
|
|
550
|
+
const t = ke(e == null ? void 0 : e.annotations), n = (o) => Number.isFinite(o.readingOrder) ? o.readingOrder : Number.MAX_SAFE_INTEGER;
|
|
551
|
+
return t.map((o, r) => ({ annotation: o, index: r })).sort(
|
|
552
|
+
(o, r) => n(o.annotation) - n(r.annotation) || o.index - r.index
|
|
553
|
+
).map((o) => o.annotation);
|
|
554
|
+
}
|
|
555
|
+
function z(e) {
|
|
556
|
+
return (Array.isArray(e == null ? void 0 : e.regions) ? e.regions : []).map((n, o) => ({ region: n, index: o })).sort(
|
|
557
|
+
(n, o) => (n.region.order ?? Number.MAX_SAFE_INTEGER) - (o.region.order ?? Number.MAX_SAFE_INTEGER) || n.index - o.index
|
|
558
|
+
).map((n) => n.region);
|
|
559
|
+
}
|
|
560
|
+
const Be = "Auto-created from object ";
|
|
561
|
+
function Le(e) {
|
|
562
|
+
var n;
|
|
563
|
+
const t = (n = e == null ? void 0 : e.description) == null ? void 0 : n.trim();
|
|
564
|
+
return t ? !t.startsWith(Be) : !1;
|
|
104
565
|
}
|
|
105
|
-
function
|
|
106
|
-
return
|
|
107
|
-
(
|
|
108
|
-
|
|
566
|
+
function tt(e) {
|
|
567
|
+
return Array.isArray(e) ? e.filter(
|
|
568
|
+
(t) => {
|
|
569
|
+
var n;
|
|
570
|
+
return Le(t) || !((n = t.description) != null && n.trim());
|
|
571
|
+
}
|
|
572
|
+
) : [];
|
|
109
573
|
}
|
|
110
|
-
function
|
|
574
|
+
function L(e) {
|
|
111
575
|
var t;
|
|
112
576
|
return e ? ((t = e.label) == null ? void 0 : t.trim()) || e.id || "Unnamed region" : "Unknown region";
|
|
113
577
|
}
|
|
114
|
-
function
|
|
578
|
+
function nt(e) {
|
|
115
579
|
if (!e) return [];
|
|
116
|
-
const t = [],
|
|
117
|
-
let
|
|
118
|
-
for (; (
|
|
119
|
-
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
function
|
|
123
|
-
const t = e == null ? void 0 : e.coordinateSpace,
|
|
124
|
-
|
|
580
|
+
const t = [], n = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
|
|
581
|
+
let o = 0, r;
|
|
582
|
+
for (; (r = n.exec(e)) !== null; )
|
|
583
|
+
r.index > o && t.push({ text: e.slice(o, r.index) }), t.push({ text: r[1], url: r[2] }), o = r.index + r[0].length;
|
|
584
|
+
return o < e.length && t.push({ text: e.slice(o) }), t.filter((i) => i.text.trim() || i.url);
|
|
585
|
+
}
|
|
586
|
+
function ot(e) {
|
|
587
|
+
const t = e == null ? void 0 : e.coordinateSpace, n = z(e), o = M(e), r = new Map(n.map((a) => [a.id, a])), i = new Map(
|
|
588
|
+
o.map((a) => [a.id, a])
|
|
125
589
|
), s = /* @__PURE__ */ new Map();
|
|
126
|
-
for (const a of
|
|
127
|
-
const
|
|
128
|
-
if (!
|
|
129
|
-
const
|
|
130
|
-
|
|
590
|
+
for (const a of o) {
|
|
591
|
+
const u = a.regionId;
|
|
592
|
+
if (!u) continue;
|
|
593
|
+
const f = s.get(u);
|
|
594
|
+
f ? f.push(a) : s.set(u, [a]);
|
|
131
595
|
}
|
|
132
596
|
const c = [];
|
|
133
|
-
for (const a of
|
|
134
|
-
const
|
|
135
|
-
if (!
|
|
136
|
-
const
|
|
137
|
-
if (!
|
|
138
|
-
const
|
|
597
|
+
for (const a of o) {
|
|
598
|
+
const u = a.anchor;
|
|
599
|
+
if (!u || u.type !== "marker") continue;
|
|
600
|
+
const f = A(u.position, t);
|
|
601
|
+
if (!f) continue;
|
|
602
|
+
const m = a.camera, p = m ? A(m.eye, t) : null, y = m ? A(m.target, t) : null;
|
|
139
603
|
c.push({
|
|
140
604
|
annotation: a,
|
|
141
|
-
position:
|
|
142
|
-
...
|
|
605
|
+
position: f,
|
|
606
|
+
...p && y ? {
|
|
143
607
|
camera: {
|
|
144
|
-
eye:
|
|
145
|
-
target:
|
|
146
|
-
...
|
|
608
|
+
eye: p,
|
|
609
|
+
target: y,
|
|
610
|
+
...m != null && m.fov ? { fov: m.fov } : {}
|
|
147
611
|
}
|
|
148
612
|
} : {}
|
|
149
613
|
});
|
|
150
614
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
615
|
+
const l = new Set(
|
|
616
|
+
n.filter((a) => a.visibilityDefault === "hidden").map((a) => a.id)
|
|
153
617
|
);
|
|
154
618
|
return {
|
|
155
619
|
payload: e,
|
|
156
|
-
regions:
|
|
157
|
-
regionsById:
|
|
158
|
-
annotations:
|
|
159
|
-
annotationsById:
|
|
620
|
+
regions: n,
|
|
621
|
+
regionsById: r,
|
|
622
|
+
annotations: o,
|
|
623
|
+
annotationsById: i,
|
|
160
624
|
annotationsByRegion: s,
|
|
161
625
|
markerAnchors: c,
|
|
162
|
-
hiddenRegionIds:
|
|
626
|
+
hiddenRegionIds: l
|
|
163
627
|
};
|
|
164
628
|
}
|
|
165
|
-
function
|
|
629
|
+
function De(e) {
|
|
166
630
|
return e.isMesh === !0;
|
|
167
631
|
}
|
|
168
|
-
function
|
|
169
|
-
var
|
|
170
|
-
const
|
|
171
|
-
for (const [a,
|
|
172
|
-
for (const
|
|
173
|
-
const
|
|
174
|
-
typeof
|
|
632
|
+
function rt(e, t, n = []) {
|
|
633
|
+
var l;
|
|
634
|
+
const o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
|
|
635
|
+
for (const [a, u] of ((t == null ? void 0 : t.meshes) ?? []).entries())
|
|
636
|
+
for (const f of u.primitives ?? []) {
|
|
637
|
+
const m = (l = f.extras) == null ? void 0 : l.modelhubRegionId;
|
|
638
|
+
typeof m == "string" && m && (s.set(a, m), u.name && r.set(u.name, m));
|
|
175
639
|
}
|
|
176
640
|
for (const a of (t == null ? void 0 : t.nodes) ?? []) {
|
|
177
641
|
if (a.mesh === void 0 || !a.name) continue;
|
|
178
|
-
const
|
|
179
|
-
|
|
642
|
+
const u = s.get(a.mesh);
|
|
643
|
+
u && i.set(a.name, u);
|
|
180
644
|
}
|
|
181
|
-
const c = new Set(
|
|
645
|
+
const c = new Set(n.map((a) => a.id));
|
|
182
646
|
return e.traverse((a) => {
|
|
183
|
-
var
|
|
184
|
-
if (!
|
|
185
|
-
const
|
|
186
|
-
if (!
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
}),
|
|
190
|
-
}
|
|
191
|
-
function
|
|
647
|
+
var p, y;
|
|
648
|
+
if (!De(a)) return;
|
|
649
|
+
const u = (y = (p = a.geometry) == null ? void 0 : p.userData) == null ? void 0 : y.modelhubRegionId, f = typeof u == "string" && u || i.get(a.name) || r.get(a.name) || (c.has(a.name) ? a.name : void 0);
|
|
650
|
+
if (!f) return;
|
|
651
|
+
const m = o.get(f);
|
|
652
|
+
m ? m.push(a) : o.set(f, [a]), a.userData.modelhubOriginalMaterial === void 0 && (a.userData.modelhubOriginalMaterial = a.material);
|
|
653
|
+
}), o;
|
|
654
|
+
}
|
|
655
|
+
function it(e) {
|
|
192
656
|
const t = {};
|
|
193
|
-
for (const [
|
|
657
|
+
for (const [n, o] of e) t[n] = o.length;
|
|
194
658
|
return t;
|
|
195
659
|
}
|
|
196
|
-
function
|
|
197
|
-
for (const
|
|
660
|
+
function Re(e, t, n) {
|
|
661
|
+
for (const o of e.get(t) ?? []) o.visible = n;
|
|
198
662
|
}
|
|
199
|
-
function
|
|
200
|
-
for (const
|
|
201
|
-
|
|
663
|
+
function st(e, t) {
|
|
664
|
+
for (const n of e.keys())
|
|
665
|
+
Re(e, n, !t.has(n));
|
|
202
666
|
}
|
|
203
|
-
function
|
|
204
|
-
for (const
|
|
667
|
+
function at(e, t, n) {
|
|
668
|
+
for (const o of e.get(t) ?? []) o.material = n;
|
|
205
669
|
}
|
|
206
|
-
function
|
|
207
|
-
for (const
|
|
208
|
-
const
|
|
209
|
-
|
|
670
|
+
function ct(e, t) {
|
|
671
|
+
for (const n of e.get(t) ?? []) {
|
|
672
|
+
const o = n.userData.modelhubOriginalMaterial;
|
|
673
|
+
o && (n.material = o);
|
|
210
674
|
}
|
|
211
675
|
}
|
|
212
|
-
const
|
|
213
|
-
function
|
|
676
|
+
const Ee = "#2196f3", ut = "#ff5722";
|
|
677
|
+
function j(e, t = {}) {
|
|
214
678
|
const {
|
|
215
|
-
fill:
|
|
216
|
-
text:
|
|
217
|
-
textStroke:
|
|
218
|
-
} = t,
|
|
219
|
-
s.width =
|
|
679
|
+
fill: n = Ee,
|
|
680
|
+
text: o = "#ffffff",
|
|
681
|
+
textStroke: r = "rgba(0, 0, 0, 0.45)"
|
|
682
|
+
} = t, i = 256, s = document.createElement("canvas");
|
|
683
|
+
s.width = i, s.height = i;
|
|
220
684
|
const c = s.getContext("2d");
|
|
221
|
-
return c && (c.beginPath(), c.arc(
|
|
685
|
+
return c && (c.beginPath(), c.arc(i / 2, i / 2, i / 2 - 4, 0, Math.PI * 2), c.fillStyle = n, c.fill(), c.strokeStyle = "#ffffff", c.lineWidth = 8, c.stroke(), c.fillStyle = o, c.strokeStyle = r, c.lineWidth = 10, c.font = "bold 132px Arial, sans-serif", c.textAlign = "center", c.textBaseline = "middle", c.strokeText(String(e), i / 2, i / 2), c.fillText(String(e), i / 2, i / 2)), s;
|
|
222
686
|
}
|
|
223
|
-
function
|
|
224
|
-
const
|
|
225
|
-
map: new
|
|
687
|
+
function Ce(e, t = 0.2, n) {
|
|
688
|
+
const o = new V({
|
|
689
|
+
map: new E(j(e, n)),
|
|
226
690
|
transparent: !0,
|
|
227
691
|
depthTest: !1
|
|
228
|
-
}),
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
function
|
|
232
|
-
var
|
|
233
|
-
const
|
|
234
|
-
(
|
|
235
|
-
}
|
|
236
|
-
function
|
|
237
|
-
return t.map((
|
|
238
|
-
const s =
|
|
239
|
-
return s.position.set(...
|
|
692
|
+
}), r = new W(o);
|
|
693
|
+
return r.scale.set(t, t, 1), r.renderOrder = 999, r;
|
|
694
|
+
}
|
|
695
|
+
function lt(e, t, n) {
|
|
696
|
+
var r;
|
|
697
|
+
const o = e.material;
|
|
698
|
+
(r = o.map) == null || r.dispose(), o.map = new E(j(t, { fill: n })), o.needsUpdate = !0;
|
|
699
|
+
}
|
|
700
|
+
function dt(e, t, n = 0.2, o) {
|
|
701
|
+
return t.map((r, i) => {
|
|
702
|
+
const s = Ce(i + 1, n, o);
|
|
703
|
+
return s.position.set(...r.position), s.name = `modelhub_marker_${r.annotation.id}`, s.userData.annotationId = r.annotation.id, s.userData.displayNumber = i + 1, e.add(s), s;
|
|
240
704
|
});
|
|
241
705
|
}
|
|
242
|
-
function
|
|
243
|
-
const { camera: t, model:
|
|
244
|
-
|
|
245
|
-
for (const
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
a[
|
|
249
|
-
x: (
|
|
250
|
-
y: (-
|
|
706
|
+
function ft(e) {
|
|
707
|
+
const { camera: t, model: n, anchors: o, width: r, height: i, isOccluded: s } = e, c = e.referenceDistance ?? 1, l = new b(), a = {};
|
|
708
|
+
n.updateMatrixWorld();
|
|
709
|
+
for (const u of o) {
|
|
710
|
+
l.set(...u.position).applyMatrix4(n.matrixWorld);
|
|
711
|
+
const f = l.distanceTo(t.position), m = s ? s(l, f) : !1, p = l.clone().project(t);
|
|
712
|
+
a[u.annotation.id] = {
|
|
713
|
+
x: (p.x * 0.5 + 0.5) * r,
|
|
714
|
+
y: (-p.y * 0.5 + 0.5) * i,
|
|
251
715
|
scale: Math.min(
|
|
252
716
|
1.6,
|
|
253
|
-
Math.max(0.55, c / Math.max(
|
|
717
|
+
Math.max(0.55, c / Math.max(f, 1e-3))
|
|
254
718
|
),
|
|
255
|
-
zIndex: Math.max(1, Math.round((1 -
|
|
256
|
-
inView:
|
|
257
|
-
occluded:
|
|
719
|
+
zIndex: Math.max(1, Math.round((1 - p.z) * 1e5)) + (m ? 0 : 2e5),
|
|
720
|
+
inView: p.z < 1 && p.x > -1.05 && p.x < 1.05 && p.y > -1.05 && p.y < 1.05,
|
|
721
|
+
occluded: m
|
|
258
722
|
};
|
|
259
723
|
}
|
|
260
724
|
return a;
|
|
261
725
|
}
|
|
262
|
-
const
|
|
726
|
+
const _e = 0.03, Ue = {
|
|
263
727
|
enabled: !1,
|
|
264
728
|
isOccluded: () => !1,
|
|
265
729
|
dispose: () => {
|
|
266
730
|
}
|
|
267
731
|
};
|
|
268
|
-
async function
|
|
269
|
-
var
|
|
270
|
-
let t = [],
|
|
732
|
+
async function mt(e) {
|
|
733
|
+
var i;
|
|
734
|
+
let t = [], n = [];
|
|
271
735
|
if (e.traverse((s) => {
|
|
272
736
|
if (!s.isMesh) return;
|
|
273
737
|
const c = s.geometry;
|
|
274
|
-
c != null && c.computeBoundsTree && (t.push(c),
|
|
275
|
-
}), !t.length) return
|
|
738
|
+
c != null && c.computeBoundsTree && (t.push(c), n.push(s));
|
|
739
|
+
}), !t.length) return Ue;
|
|
276
740
|
for (const s of t)
|
|
277
|
-
s.boundsTree || (
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
const
|
|
741
|
+
s.boundsTree || (i = s.computeBoundsTree) == null || i.call(s, { maxLeafTris: 8 });
|
|
742
|
+
const o = new q();
|
|
743
|
+
o.firstHitOnly = !0;
|
|
744
|
+
const r = new b();
|
|
281
745
|
return {
|
|
282
746
|
enabled: !0,
|
|
283
|
-
isOccluded(s, c,
|
|
284
|
-
return
|
|
747
|
+
isOccluded(s, c, l) {
|
|
748
|
+
return r.subVectors(c, s.position).normalize(), o.set(s.position, r), o.near = 0, o.far = Math.max(0, l - _e), o.camera = s, o.intersectObjects(n, !1).length > 0;
|
|
285
749
|
},
|
|
286
750
|
dispose() {
|
|
287
751
|
var s;
|
|
288
752
|
for (const c of t) (s = c.disposeBoundsTree) == null || s.call(c);
|
|
289
|
-
t = [],
|
|
753
|
+
t = [], n = [];
|
|
290
754
|
}
|
|
291
755
|
};
|
|
292
756
|
}
|
|
293
|
-
const
|
|
757
|
+
const I = {
|
|
294
758
|
headlight: {
|
|
295
759
|
ambient: 0.7,
|
|
296
760
|
lights: [
|
|
@@ -347,216 +811,216 @@ const y = {
|
|
|
347
811
|
{ color: [0.42, 0.74, 1], intensity: 0.25, position: [7.23, 6.78, 1.29] }
|
|
348
812
|
]
|
|
349
813
|
}
|
|
350
|
-
},
|
|
351
|
-
function
|
|
352
|
-
return Object.keys(
|
|
814
|
+
}, Fe = "headlight";
|
|
815
|
+
function ht() {
|
|
816
|
+
return Object.keys(I);
|
|
353
817
|
}
|
|
354
|
-
function
|
|
818
|
+
function Ge(e) {
|
|
355
819
|
var t;
|
|
356
820
|
(t = e.parent) == null || t.remove(e);
|
|
357
821
|
}
|
|
358
|
-
function
|
|
822
|
+
function pt(e) {
|
|
359
823
|
var c;
|
|
360
|
-
const { scene: t, camera:
|
|
824
|
+
const { scene: t, camera: n, exposure: o = 1 } = e;
|
|
361
825
|
(c = e.previous) == null || c.remove();
|
|
362
|
-
const
|
|
363
|
-
t.add(s),
|
|
364
|
-
for (const
|
|
826
|
+
const r = I[e.preset ?? ""] ?? I[Fe], i = [], s = new Y(16777215, r.ambient * o);
|
|
827
|
+
t.add(s), i.push(s);
|
|
828
|
+
for (const l of r.lights) {
|
|
365
829
|
let a;
|
|
366
|
-
if (
|
|
367
|
-
const
|
|
368
|
-
|
|
830
|
+
if (l.spot) {
|
|
831
|
+
const f = new H(new T(...l.color));
|
|
832
|
+
f.angle = 0.5, f.penumbra = 0.9, f.decay = 0, a = f;
|
|
369
833
|
} else
|
|
370
|
-
a = new
|
|
371
|
-
a.intensity =
|
|
372
|
-
const
|
|
373
|
-
|
|
834
|
+
a = new X(new T(...l.color));
|
|
835
|
+
a.intensity = l.intensity, a.position.set(...l.position);
|
|
836
|
+
const u = a.target;
|
|
837
|
+
l.attach ? (u == null || u.position.set(0, 0, l.spot ? -1 : 0), n.add(a), u && n.add(u)) : (t.add(a), u && t.add(u)), i.push(a), u && i.push(u);
|
|
374
838
|
}
|
|
375
839
|
return {
|
|
376
|
-
lights:
|
|
840
|
+
lights: i,
|
|
377
841
|
remove() {
|
|
378
|
-
for (const
|
|
379
|
-
|
|
842
|
+
for (const l of i) Ge(l);
|
|
843
|
+
i.length = 0;
|
|
380
844
|
}
|
|
381
845
|
};
|
|
382
846
|
}
|
|
383
|
-
const
|
|
847
|
+
const S = [
|
|
384
848
|
{ id: "white", label: "White", hex: "#ffffff", light: !0 },
|
|
385
849
|
{ id: "light-grey", label: "Light grey", hex: "#d4d4d4", light: !0 },
|
|
386
850
|
{ id: "medium-grey", label: "Medium grey", hex: "#808080", light: !1 },
|
|
387
851
|
{ id: "dark-grey", label: "Dark grey", hex: "#252525", light: !1 },
|
|
388
852
|
{ id: "black", label: "Black", hex: "#000000", light: !1 }
|
|
389
|
-
],
|
|
390
|
-
function
|
|
853
|
+
], Pe = "dark-grey";
|
|
854
|
+
function ze(e) {
|
|
391
855
|
if (typeof e != "string") return "";
|
|
392
856
|
const t = e.trim().replace(/^#/, "");
|
|
393
|
-
return /^[0-9a-f]{6}$/i.test(t) ? `#${t.toLowerCase()}` : /^[0-9a-f]{3}$/i.test(t) ? `#${[...t].map((
|
|
857
|
+
return /^[0-9a-f]{6}$/i.test(t) ? `#${t.toLowerCase()}` : /^[0-9a-f]{3}$/i.test(t) ? `#${[...t].map((n) => n + n).join("").toLowerCase()}` : "";
|
|
394
858
|
}
|
|
395
|
-
function
|
|
859
|
+
function je(e) {
|
|
396
860
|
const t = Number.parseInt(e.replace("#", ""), 16);
|
|
397
861
|
return Number.isFinite(t) ? (0.299 * (t >> 16 & 255) + 0.587 * (t >> 8 & 255) + 0.114 * (t & 255)) / 255 : 0;
|
|
398
862
|
}
|
|
399
|
-
function
|
|
400
|
-
const
|
|
401
|
-
return
|
|
863
|
+
function gt(e, t) {
|
|
864
|
+
const n = ze(t);
|
|
865
|
+
return n ? {
|
|
402
866
|
id: "custom",
|
|
403
867
|
label: "Custom",
|
|
404
|
-
hex:
|
|
405
|
-
light:
|
|
406
|
-
} :
|
|
868
|
+
hex: n,
|
|
869
|
+
light: je(n) > 0.5
|
|
870
|
+
} : S.find((o) => o.id === e) ?? S.find((o) => o.id === Pe) ?? S[0];
|
|
407
871
|
}
|
|
408
|
-
const
|
|
409
|
-
function
|
|
872
|
+
const Ve = 2;
|
|
873
|
+
function D(e) {
|
|
410
874
|
e.updateMatrixWorld(!0);
|
|
411
|
-
const t = new
|
|
412
|
-
return e.traverse((
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
}), t.isEmpty() ? new
|
|
416
|
-
}
|
|
417
|
-
function
|
|
418
|
-
const
|
|
419
|
-
e.scale.multiplyScalar(
|
|
420
|
-
const s =
|
|
421
|
-
return e.position.sub(s.getCenter(new
|
|
422
|
-
}
|
|
423
|
-
function
|
|
875
|
+
const t = new v(), n = new v();
|
|
876
|
+
return e.traverse((o) => {
|
|
877
|
+
const r = o, i = o;
|
|
878
|
+
r.isSkinnedMesh ? (r.computeBoundingBox(), r.boundingBox && (n.copy(r.boundingBox).applyMatrix4(r.matrixWorld), t.union(n))) : i.isMesh && i.geometry && (i.geometry.boundingBox || i.geometry.computeBoundingBox(), i.geometry.boundingBox && (n.copy(i.geometry.boundingBox).applyMatrix4(i.matrixWorld), t.union(n)));
|
|
879
|
+
}), t.isEmpty() ? new v().setFromObject(e) : t;
|
|
880
|
+
}
|
|
881
|
+
function yt(e, t = Ve) {
|
|
882
|
+
const o = D(e).getSize(new b()), r = Math.max(o.x, o.y, o.z) || 1, i = t / r;
|
|
883
|
+
e.scale.multiplyScalar(i);
|
|
884
|
+
const s = D(e);
|
|
885
|
+
return e.position.sub(s.getCenter(new b())), i;
|
|
886
|
+
}
|
|
887
|
+
function bt(e, t = 1.3) {
|
|
424
888
|
return t / Math.tan(e * Math.PI / 360);
|
|
425
889
|
}
|
|
426
|
-
const
|
|
427
|
-
function
|
|
890
|
+
const We = 0.5, qe = 1.5;
|
|
891
|
+
function $t(e, t, n = {}) {
|
|
428
892
|
t.updateMatrixWorld();
|
|
429
|
-
const
|
|
893
|
+
const o = new b(...e.position).applyMatrix4(
|
|
430
894
|
t.matrixWorld
|
|
431
895
|
);
|
|
432
896
|
if (e.camera) {
|
|
433
|
-
const
|
|
897
|
+
const l = new b(...e.camera.eye).applyMatrix4(
|
|
434
898
|
t.matrixWorld
|
|
435
|
-
),
|
|
899
|
+
), u = new b(...e.camera.target).applyMatrix4(
|
|
436
900
|
t.matrixWorld
|
|
437
|
-
).clone().sub(
|
|
438
|
-
|
|
439
|
-
const
|
|
901
|
+
).clone().sub(l);
|
|
902
|
+
u.lengthSq() < 1e-10 && u.copy(o).sub(l), u.normalize();
|
|
903
|
+
const f = Math.max(o.distanceTo(l), 0.2);
|
|
440
904
|
return {
|
|
441
|
-
position:
|
|
442
|
-
target:
|
|
905
|
+
position: l,
|
|
906
|
+
target: l.clone().addScaledVector(u, f),
|
|
443
907
|
...e.camera.fov ? { fov: e.camera.fov } : {}
|
|
444
908
|
};
|
|
445
909
|
}
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
const s =
|
|
449
|
-
return c.y =
|
|
910
|
+
const r = n.outward ?? !0, i = new b(o.x, 0, o.z);
|
|
911
|
+
i.lengthSq() < 1e-8 && i.set(0, 0, 1), i.normalize();
|
|
912
|
+
const s = r ? -(n.outwardDistance ?? We) : n.inwardDistance ?? qe, c = o.clone().addScaledVector(i, s);
|
|
913
|
+
return c.y = o.y, { position: c, target: o };
|
|
450
914
|
}
|
|
451
|
-
const
|
|
915
|
+
const Ye = { cancel: () => {
|
|
452
916
|
} };
|
|
453
|
-
function
|
|
454
|
-
const { camera: t, controls:
|
|
455
|
-
|
|
917
|
+
function wt(e) {
|
|
918
|
+
const { camera: t, controls: n, to: o, onFrame: r, onDone: i } = e, s = () => {
|
|
919
|
+
r == null || r(), i == null || i();
|
|
456
920
|
};
|
|
457
921
|
if (e.reducedMotion)
|
|
458
|
-
return t.position.copy(
|
|
459
|
-
const c = e.durationMs ?? 900,
|
|
460
|
-
let
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
t.position.lerpVectors(
|
|
922
|
+
return t.position.copy(o.position), n.target.copy(o.target), n.update(), s(), Ye;
|
|
923
|
+
const c = e.durationMs ?? 900, l = t.position.clone(), a = n.target.clone(), u = performance.now();
|
|
924
|
+
let f = null;
|
|
925
|
+
const m = (p) => {
|
|
926
|
+
const y = Math.min((p - u) / c, 1), O = y * (2 - y);
|
|
927
|
+
t.position.lerpVectors(l, o.position, O), n.target.lerpVectors(a, o.target, O), n.update(), r == null || r(), y < 1 ? f = requestAnimationFrame(m) : (f = null, i == null || i());
|
|
464
928
|
};
|
|
465
|
-
return
|
|
929
|
+
return f = requestAnimationFrame(m), {
|
|
466
930
|
cancel() {
|
|
467
|
-
|
|
931
|
+
f !== null && cancelAnimationFrame(f), f = null;
|
|
468
932
|
}
|
|
469
933
|
};
|
|
470
934
|
}
|
|
471
|
-
function
|
|
472
|
-
const
|
|
473
|
-
e.fov !==
|
|
935
|
+
function xt(e, t, n) {
|
|
936
|
+
const o = t || n;
|
|
937
|
+
e.fov !== o && (e.fov = o, e.updateProjectionMatrix());
|
|
474
938
|
}
|
|
475
|
-
const
|
|
476
|
-
function
|
|
477
|
-
var
|
|
939
|
+
const He = 500;
|
|
940
|
+
function vt(e) {
|
|
941
|
+
var r, i, s;
|
|
478
942
|
if (!e)
|
|
479
943
|
return "Model loaded, but it carries no educational metadata.";
|
|
480
944
|
const t = [];
|
|
481
|
-
(
|
|
482
|
-
const
|
|
483
|
-
return
|
|
484
|
-
`${
|
|
945
|
+
(r = e.model) != null && r.title && t.push(`${e.model.title} loaded`), (i = e.model) != null && i.altText && t.push(e.model.altText);
|
|
946
|
+
const n = ((s = e.regions) == null ? void 0 : s.length) ?? 0, o = M(e).length;
|
|
947
|
+
return n && t.push(`${n} labeled ${n === 1 ? "region" : "regions"}`), o && t.push(
|
|
948
|
+
`${o} ${o === 1 ? "annotation" : "annotations"}`
|
|
485
949
|
), t.map((c) => c.replace(/\.$/, "")).join(". ") + ".";
|
|
486
950
|
}
|
|
487
|
-
function
|
|
488
|
-
return `Annotation ${t + 1} of ${
|
|
951
|
+
function At(e, t, n) {
|
|
952
|
+
return `Annotation ${t + 1} of ${n}: ${e || "Untitled"}.`;
|
|
489
953
|
}
|
|
490
|
-
function
|
|
491
|
-
let
|
|
954
|
+
function St(e, t = He, n = () => Date.now()) {
|
|
955
|
+
let o = -1 / 0, r = null, i = null;
|
|
492
956
|
const s = (a) => {
|
|
493
|
-
|
|
957
|
+
o = n(), r = null, e(a);
|
|
494
958
|
};
|
|
495
959
|
return { announce: (a) => {
|
|
496
|
-
const
|
|
497
|
-
if (
|
|
960
|
+
const u = n() - o;
|
|
961
|
+
if (u >= t) {
|
|
498
962
|
s(a);
|
|
499
963
|
return;
|
|
500
964
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}, t -
|
|
965
|
+
r = a, i || (i = setTimeout(() => {
|
|
966
|
+
i = null, r !== null && s(r);
|
|
967
|
+
}, t - u));
|
|
504
968
|
}, flush: () => {
|
|
505
|
-
|
|
969
|
+
i && (clearTimeout(i), i = null), r !== null && s(r);
|
|
506
970
|
} };
|
|
507
971
|
}
|
|
508
|
-
function
|
|
972
|
+
function R(e, t) {
|
|
509
973
|
return `## ${e}
|
|
510
974
|
${t}
|
|
511
975
|
|
|
512
976
|
`;
|
|
513
977
|
}
|
|
514
|
-
function
|
|
515
|
-
const
|
|
516
|
-
let
|
|
978
|
+
function It(e, t = {}) {
|
|
979
|
+
const n = e.model ?? {}, o = z(e), r = M(e);
|
|
980
|
+
let i = `# ${n.title || "Untitled model"}
|
|
517
981
|
|
|
518
982
|
`;
|
|
519
|
-
if (
|
|
520
|
-
|
|
983
|
+
if (n.altText && (i += R(t.summaryHeading ?? "Summary", n.altText)), n.longDescription && (i += R("Full description", n.longDescription)), o.length) {
|
|
984
|
+
i += `## Regions (${o.length})
|
|
521
985
|
|
|
522
986
|
`;
|
|
523
|
-
for (const s of
|
|
524
|
-
|
|
987
|
+
for (const s of o)
|
|
988
|
+
i += `### ${L(s)}
|
|
525
989
|
${s.description || "No description."}
|
|
526
990
|
|
|
527
991
|
`;
|
|
528
992
|
}
|
|
529
|
-
return
|
|
993
|
+
return r.length && (i += `## Annotations (${r.length})
|
|
530
994
|
|
|
531
|
-
`,
|
|
532
|
-
const
|
|
533
|
-
|
|
995
|
+
`, r.forEach((s, c) => {
|
|
996
|
+
const l = s.regionId ? ` (${L(o.find((u) => u.id === s.regionId))})` : "", a = `${c + 1}. ${s.title || "Untitled"}${l}`;
|
|
997
|
+
i += `### ${a}
|
|
534
998
|
${s.body || "No description."}
|
|
535
999
|
|
|
536
1000
|
`;
|
|
537
|
-
})),
|
|
538
|
-
`,
|
|
539
|
-
`,
|
|
540
|
-
`,
|
|
541
|
-
`,
|
|
542
|
-
`,
|
|
1001
|
+
})), i += `## Licensing
|
|
1002
|
+
`, i += `- **License:** ${n.license || "Not specified"}
|
|
1003
|
+
`, i += `- **Attribution:** ${n.attribution || "Not specified"}
|
|
1004
|
+
`, i += `- **Creator:** ${n.creator || "Not specified"}
|
|
1005
|
+
`, i += `- **Source:** ${n.source || "Not specified"}
|
|
1006
|
+
`, i;
|
|
543
1007
|
}
|
|
544
|
-
function
|
|
545
|
-
var
|
|
546
|
-
return `${(((
|
|
1008
|
+
function Mt(e) {
|
|
1009
|
+
var n;
|
|
1010
|
+
return `${(((n = e.model) == null ? void 0 : n.title) || "model").trim().replace(/[^\w\-. ]+/g, "").replace(/\s+/g, "_") || "model"}_transcript.md`;
|
|
547
1011
|
}
|
|
548
|
-
function
|
|
1012
|
+
function Ot(e) {
|
|
549
1013
|
e && e.traverse((t) => {
|
|
550
|
-
var
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
const
|
|
554
|
-
|
|
1014
|
+
var i, s;
|
|
1015
|
+
const n = t, o = n.geometry;
|
|
1016
|
+
o && (o.boundsTree && o.disposeBoundsTree && o.disposeBoundsTree(), (i = o.dispose) == null || i.call(o));
|
|
1017
|
+
const r = [].concat(
|
|
1018
|
+
n.material ?? []
|
|
555
1019
|
);
|
|
556
|
-
for (const c of
|
|
1020
|
+
for (const c of r)
|
|
557
1021
|
if (c) {
|
|
558
|
-
for (const
|
|
559
|
-
const a =
|
|
1022
|
+
for (const l of Object.values(c)) {
|
|
1023
|
+
const a = l;
|
|
560
1024
|
a && a.isTexture && a.dispose();
|
|
561
1025
|
}
|
|
562
1026
|
(s = c.dispose) == null || s.call(c);
|
|
@@ -564,62 +1028,64 @@ function Ue(e) {
|
|
|
564
1028
|
});
|
|
565
1029
|
}
|
|
566
1030
|
export {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
$ as
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
1031
|
+
S as BACKGROUND_OPTIONS,
|
|
1032
|
+
He as CAMERA_ANNOUNCE_INTERVAL,
|
|
1033
|
+
Pe as DEFAULT_BACKGROUND,
|
|
1034
|
+
Fe as DEFAULT_LIGHTING,
|
|
1035
|
+
I as LIGHTING_PRESETS,
|
|
1036
|
+
Ee as MARKER_FILL,
|
|
1037
|
+
ut as MARKER_FILL_ACTIVE,
|
|
1038
|
+
Ve as NORMALIZED_SIZE,
|
|
1039
|
+
_e as OCCLUSION_BIAS,
|
|
1040
|
+
qe as TOUR_DISTANCE_INWARD,
|
|
1041
|
+
We as TOUR_DISTANCE_OUTWARD,
|
|
1042
|
+
At as annotationSummary,
|
|
1043
|
+
M as annotationsInReadingOrder,
|
|
1044
|
+
xt as applyFov,
|
|
1045
|
+
pt as applyLighting,
|
|
1046
|
+
st as applyVisibilityDefaults,
|
|
1047
|
+
rt as buildRegionMeshMap,
|
|
1048
|
+
It as buildTranscript,
|
|
1049
|
+
ct as clearRegionHighlight,
|
|
1050
|
+
D as computeDisplayBox,
|
|
1051
|
+
$t as computeTourPlacement,
|
|
1052
|
+
St as createAnnouncer,
|
|
1053
|
+
Ce as createMarkerSprite,
|
|
1054
|
+
dt as createMarkerSprites,
|
|
1055
|
+
mt as createOcclusionIndex,
|
|
1056
|
+
Ot as disposeSceneGraph,
|
|
1057
|
+
bt as distanceForFov,
|
|
1058
|
+
j as drawMarkerCanvas,
|
|
1059
|
+
Me as errorsOf,
|
|
1060
|
+
Te as fetchBytes,
|
|
1061
|
+
wt as flyCamera,
|
|
1062
|
+
yt as frameModel,
|
|
1063
|
+
et as fromViewerPosition,
|
|
1064
|
+
at as highlightRegion,
|
|
1065
|
+
Le as isAuthoredRegion,
|
|
1066
|
+
Je as isGlbParseError,
|
|
1067
|
+
G as isVec3,
|
|
1068
|
+
ht as lightingPresetNames,
|
|
1069
|
+
Ze as loadModel,
|
|
1070
|
+
Qe as logFindings,
|
|
1071
|
+
je as luminance,
|
|
1072
|
+
vt as modelSummary,
|
|
1073
|
+
P as needsConversion,
|
|
1074
|
+
ke as normalizeAnnotationIds,
|
|
1075
|
+
ze as normalizeHexColor,
|
|
1076
|
+
ot as normalizeModel,
|
|
1077
|
+
nt as parseBodySegments,
|
|
1078
|
+
ft as projectMarkers,
|
|
1079
|
+
Ne as readEmbedded,
|
|
1080
|
+
tt as readableRegions,
|
|
1081
|
+
it as regionBindingCounts,
|
|
1082
|
+
L as regionLabel,
|
|
1083
|
+
z as regionsInOrder,
|
|
1084
|
+
gt as resolveBackground,
|
|
1085
|
+
Ke as resourcePathFor,
|
|
1086
|
+
lt as setMarkerSpriteColor,
|
|
1087
|
+
Re as setRegionVisible,
|
|
1088
|
+
Oe as sidecarUrlFor,
|
|
1089
|
+
A as toViewerPosition,
|
|
1090
|
+
Mt as transcriptFileName
|
|
625
1091
|
};
|