three-slicer 0.1.3 → 0.1.5
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/README.md +67 -8
- package/components/README.md +1 -1
- package/components/dist/SettingsPanel.js +12 -12
- package/data/README.md +39 -2
- package/data/config-schema.json +164 -0
- package/data/filaments.js +2 -0
- package/data/processes.js +1 -1
- package/data/ui-tree.json +21 -2
- package/engine/README.md +56 -4
- package/engine/src/data.js +2 -0
- package/engine/src/settings.js +214 -6
- package/engine/src/slicer.worker.js +154 -5
- package/engine/src/slicer_core.js +0 -0
- package/engine/src/slicer_core.mt.js +0 -0
- package/package.json +15 -2
- package/types/data/filaments.js.d.ts +27 -0
- package/types/data.d.ts +7 -0
- package/types/settings-keys.d.ts +35 -1
- package/types/settings.d.ts +42 -0
- package/types/viewer-gcode.d.ts +29 -0
- package/types/viewer-toolpath.d.ts +9 -1
- package/types/viewer.d.ts +53 -0
- package/viewer/README.md +48 -2
- package/viewer/dist/Viewport.js +2706 -1525
- package/viewer/dist/gcode_parse.js +190 -0
- package/viewer/dist/make_worker.js +7 -0
- package/viewer/dist/model_loaders.js +139 -211
- package/viewer/dist/parse_3mf-8oCnCJNK.js +216 -0
- package/viewer/dist/parse_3mf.worker.js +10 -0
- package/viewer/dist/toolpath_gpu.js +162 -137
- package/viewer/styles.css +56 -2
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const it = {
|
|
2
|
+
// OrcaSlicer / PrusaSlicer ;TYPE: names
|
|
3
|
+
"outer wall": 1,
|
|
4
|
+
"external perimeter": 1,
|
|
5
|
+
"inner wall": 1,
|
|
6
|
+
perimeter: 1,
|
|
7
|
+
"internal perimeter": 1,
|
|
8
|
+
"overhang wall": 1,
|
|
9
|
+
"overhang perimeter": 1,
|
|
10
|
+
"sparse infill": 2,
|
|
11
|
+
"internal infill": 2,
|
|
12
|
+
"solid infill": 3,
|
|
13
|
+
"internal solid infill": 3,
|
|
14
|
+
"top solid infill": 3,
|
|
15
|
+
"top surface": 3,
|
|
16
|
+
"bottom surface": 3,
|
|
17
|
+
skirt: 4,
|
|
18
|
+
brim: 4,
|
|
19
|
+
"skirt/brim": 4,
|
|
20
|
+
support: 5,
|
|
21
|
+
"support material": 5,
|
|
22
|
+
"support material interface": 5,
|
|
23
|
+
"support interface": 5,
|
|
24
|
+
"support transition": 5,
|
|
25
|
+
raft: 6,
|
|
26
|
+
"gap fill": 7,
|
|
27
|
+
"gap infill": 7,
|
|
28
|
+
"thin wall": 8,
|
|
29
|
+
bridge: 9,
|
|
30
|
+
"bridge infill": 9,
|
|
31
|
+
"internal bridge": 9,
|
|
32
|
+
"internal bridge infill": 9,
|
|
33
|
+
ironing: 10,
|
|
34
|
+
"prime tower": 11,
|
|
35
|
+
"wipe tower": 11,
|
|
36
|
+
custom: 1,
|
|
37
|
+
// Cura ;TYPE: names
|
|
38
|
+
"wall-outer": 1,
|
|
39
|
+
"wall-inner": 1,
|
|
40
|
+
fill: 2,
|
|
41
|
+
skin: 3,
|
|
42
|
+
"support-interface": 5,
|
|
43
|
+
"prime-tower": 11
|
|
44
|
+
}, nt = [
|
|
45
|
+
["skirt/brim", 4],
|
|
46
|
+
["skirt", 4],
|
|
47
|
+
["walls", 1],
|
|
48
|
+
["thin-wall", 8],
|
|
49
|
+
["gap-fill", 7],
|
|
50
|
+
["bridge", 9],
|
|
51
|
+
["ironing", 10],
|
|
52
|
+
["support", 5],
|
|
53
|
+
["prime tower", 11],
|
|
54
|
+
["wipe_tower_real", 11]
|
|
55
|
+
], st = (w, c) => w === c || c.length < w.length && " (:/".includes(w[c.length]) && w.startsWith(c), at = {
|
|
56
|
+
1: 1,
|
|
57
|
+
2: 1,
|
|
58
|
+
3: 1,
|
|
59
|
+
4: 2,
|
|
60
|
+
5: 3,
|
|
61
|
+
6: 3,
|
|
62
|
+
7: 3,
|
|
63
|
+
8: 10,
|
|
64
|
+
9: 9,
|
|
65
|
+
10: 9,
|
|
66
|
+
11: 7,
|
|
67
|
+
12: 4,
|
|
68
|
+
13: 4,
|
|
69
|
+
14: 5,
|
|
70
|
+
15: 5,
|
|
71
|
+
16: 5,
|
|
72
|
+
17: 11
|
|
73
|
+
};
|
|
74
|
+
function rt(w, c = {}) {
|
|
75
|
+
const V = Math.PI / 4 * (c.filamentDiameter > 0 ? c.filamentDiameter : 1.75) ** 2, tt = c.defaultLayerHeight > 0 ? c.defaultLayerHeight : 0.2;
|
|
76
|
+
let f = 0, u = 0, m = 0, L = 0, x = !0, v = !0, E = 0, P = 1, S = 0, p = null;
|
|
77
|
+
const g = [];
|
|
78
|
+
let z = !1, I = !0, R = NaN, q = 0, H = 0, O = 0;
|
|
79
|
+
const j = /* @__PURE__ */ new Set([0]), W = (s) => {
|
|
80
|
+
p = { z: s, p: [], w: [] }, g.push(p), I = !1, R = NaN, P = 1, S = 0;
|
|
81
|
+
}, et = () => g.length > 1 ? g[g.length - 2].z : 0, C = (s, o, d, b, N, e, t) => {
|
|
82
|
+
const a = Math.hypot(b - s, N - o, e - d);
|
|
83
|
+
if (!(a < 1e-6))
|
|
84
|
+
if (t > 1e-6) {
|
|
85
|
+
O += t, I ? W(Number.isNaN(R) ? e : R) : !z && e > p.z + 1e-3 && W(e);
|
|
86
|
+
const r = P + E * 16;
|
|
87
|
+
p.p.push(s, o, d, r, b, N, e, r);
|
|
88
|
+
const i = Math.max(0.02, p.z - et() || tt), F = S > 0 ? S : t * V / (a * i) + i * (1 - Math.PI / 4);
|
|
89
|
+
p.w.push(Math.min(3, Math.max(0.05, F))), q++;
|
|
90
|
+
} else p && (p.p.push(s, o, d, E * 16, b, N, e, E * 16), p.w.push(0), H++);
|
|
91
|
+
};
|
|
92
|
+
for (const s of w.split(`
|
|
93
|
+
`)) {
|
|
94
|
+
const o = s.indexOf(";"), d = (o < 0 ? s : s.slice(0, o)).trim(), b = o < 0 ? "" : s.slice(o + 1).trim();
|
|
95
|
+
if (b && !d) {
|
|
96
|
+
const t = b.toLowerCase();
|
|
97
|
+
if (t.startsWith("type:")) {
|
|
98
|
+
P = it[t.slice(5).trim()] ?? 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (t.startsWith("_extrusion_role:")) {
|
|
102
|
+
P = at[parseInt(t.slice(16), 10)] ?? 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (t.startsWith("width:")) {
|
|
106
|
+
const i = parseFloat(t.slice(6));
|
|
107
|
+
S = i > 0 ? i : 0;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (t.startsWith("layer_change") || t.startsWith("layer:")) {
|
|
111
|
+
z = !0, I = !0;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (t.startsWith("z:")) {
|
|
115
|
+
const i = parseFloat(t.slice(2));
|
|
116
|
+
I && i > 0 && (z = !0, W(i));
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const a = /^layer \d+ z([-\d.]+)/.exec(t);
|
|
120
|
+
if (a) {
|
|
121
|
+
z = !0, W(parseFloat(a[1]));
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const r = nt.find(([i]) => st(t, i));
|
|
125
|
+
r && (P = r[1]);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (!d) continue;
|
|
129
|
+
const N = d.split(/\s+/), e = N[0].toUpperCase();
|
|
130
|
+
if (e === "G90") {
|
|
131
|
+
x = !0;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (e === "G91") {
|
|
135
|
+
x = !1;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (e === "M82") {
|
|
139
|
+
v = !0;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (e === "M83") {
|
|
143
|
+
v = !1;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (/^T\d+$/.test(e)) {
|
|
147
|
+
E = parseInt(e.slice(1), 10), j.add(E);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (e === "G92" || e === "G0" || e === "G1" || e === "G2" || e === "G3") {
|
|
151
|
+
let t = NaN, a = NaN, r = NaN, i = NaN, F = 0, D = 0;
|
|
152
|
+
for (let h = 1; h < N.length; h++) {
|
|
153
|
+
const n = N[h][0], l = parseFloat(N[h].slice(1));
|
|
154
|
+
Number.isNaN(l) || (n === "X" || n === "x" ? t = l : n === "Y" || n === "y" ? a = l : n === "Z" || n === "z" ? r = l : n === "E" || n === "e" ? i = l : n === "I" || n === "i" ? F = l : (n === "J" || n === "j") && (D = l));
|
|
155
|
+
}
|
|
156
|
+
if (e === "G92") {
|
|
157
|
+
Number.isNaN(t) || (f = t), Number.isNaN(a) || (u = a), Number.isNaN(r) || (m = r), Number.isNaN(i) || (L = i);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const k = Number.isNaN(t) ? f : x ? t : f + t, A = Number.isNaN(a) ? u : x ? a : u + a, Z = Number.isNaN(r) ? m : x ? r : m + r, K = Number.isNaN(i) ? 0 : v ? i - L : i;
|
|
161
|
+
if (e === "G2" || e === "G3") {
|
|
162
|
+
const h = f + F, n = u + D, l = Math.hypot(f - h, u - n), _ = Math.atan2(u - n, f - h);
|
|
163
|
+
let M = Math.atan2(A - n, k - h);
|
|
164
|
+
const T = e === "G3";
|
|
165
|
+
T && M <= _ + 1e-6 && (M += 2 * Math.PI), !T && M >= _ - 1e-6 && (M -= 2 * Math.PI);
|
|
166
|
+
const y = Math.max(1, Math.min(360, Math.ceil(Math.abs(M - _) * l / 0.3)));
|
|
167
|
+
let X = f, Y = u, J = m;
|
|
168
|
+
for (let G = 1; G <= y; G++) {
|
|
169
|
+
const U = _ + (M - _) * G / y, $ = G === y ? k : h + l * Math.cos(U), B = G === y ? A : n + l * Math.sin(U), Q = m + (Z - m) * G / y;
|
|
170
|
+
C(X, Y, J, $, B, Q, K / y), X = $, Y = B, J = Q;
|
|
171
|
+
}
|
|
172
|
+
} else
|
|
173
|
+
C(f, u, m, k, A, Z, K);
|
|
174
|
+
f = k, u = A, m = Z, Number.isNaN(i) || (L = v ? i : L + i);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
layers: g.map((s) => ({ z: s.z, paths: Float32Array.from(s.p), widths: Float32Array.from(s.w) })),
|
|
179
|
+
stats: {
|
|
180
|
+
layers: g.length,
|
|
181
|
+
path_segments: q,
|
|
182
|
+
travel_segments: H,
|
|
183
|
+
filament_mm: O,
|
|
184
|
+
tools: [...j].sort((s, o) => s - o)
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
export {
|
|
189
|
+
rt as parseGcode
|
|
190
|
+
};
|
|
@@ -7,3 +7,10 @@
|
|
|
7
7
|
export function makeSlicerWorker() {
|
|
8
8
|
return new Worker(new URL('../../engine/src/slicer.worker.js', import.meta.url), { type: 'module' })
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
// 3MF parsing worker. Unlike the slicer worker this one points INTO dist/ — the viewer's `src/` is not published
|
|
12
|
+
// (packages/package.json `files` ships `viewer/dist` only), so the worker is a lib entry of the viewer's own build
|
|
13
|
+
// and lands beside this file. The static `new Worker(new URL(…))` pattern is what matters either way.
|
|
14
|
+
export function makeParse3mfWorker() {
|
|
15
|
+
return new Worker(new URL('./parse_3mf.worker.js', import.meta.url), { type: 'module' })
|
|
16
|
+
}
|
|
@@ -1,256 +1,184 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { OBJLoader as
|
|
3
|
-
import { PLYLoader as
|
|
4
|
-
import { AMFLoader as
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const z = /<vertex\s+x="([^"]*)"\s+y="([^"]*)"\s+z="([^"]*)"/g, I = /<triangle\s+v1="([^"]*)"\s+v2="([^"]*)"\s+v3="([^"]*)"/g;
|
|
25
|
-
function J(t) {
|
|
26
|
-
const e = [];
|
|
27
|
-
z.lastIndex = 0;
|
|
28
|
-
let s;
|
|
29
|
-
for (; s = z.exec(t); ) e.push(+s[1], +s[2], +s[3]);
|
|
30
|
-
if (!e.length)
|
|
31
|
-
for (const o of t.match(/<vertex\b[^>]*>/g) || []) e.push(+w(o, "x"), +w(o, "y"), +w(o, "z"));
|
|
32
|
-
if (e.length < 9) return null;
|
|
33
|
-
const n = [];
|
|
34
|
-
for (I.lastIndex = 0; s = I.exec(t); ) n.push(+s[1], +s[2], +s[3]);
|
|
35
|
-
if (!n.length)
|
|
36
|
-
for (const o of t.match(/<triangle\b[^>]*>/g) || []) n.push(+w(o, "v1"), +w(o, "v2"), +w(o, "v3"));
|
|
37
|
-
return n.length ? { verts: e, tris: n } : null;
|
|
38
|
-
}
|
|
39
|
-
function Y(t) {
|
|
40
|
-
const e = /* @__PURE__ */ new Map(), s = /<object\b([^>]*)>([\s\S]*?)<\/object>/g;
|
|
41
|
-
let n;
|
|
42
|
-
for (; n = s.exec(t); ) {
|
|
43
|
-
const i = w(n[1], "id");
|
|
44
|
-
if (!i) continue;
|
|
45
|
-
const c = n[2], p = [];
|
|
46
|
-
for (const d of c.match(/<component\b[^>]*>/g) || []) {
|
|
47
|
-
const h = w(d, "objectid");
|
|
48
|
-
h && p.push({ objectid: h, path: w(d, "p:path") || w(d, "path"), transform: R(w(d, "transform")) });
|
|
49
|
-
}
|
|
50
|
-
e.set(i, p.length ? { components: p } : { mesh: J(c) });
|
|
1
|
+
import * as L from "three";
|
|
2
|
+
import { OBJLoader as T } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
3
|
+
import { PLYLoader as v } from "three/examples/jsm/loaders/PLYLoader.js";
|
|
4
|
+
import { AMFLoader as P } from "three/examples/jsm/loaders/AMFLoader.js";
|
|
5
|
+
import { p as E } from "./parse_3mf-8oCnCJNK.js";
|
|
6
|
+
import { makeParse3mfWorker as W } from "./make_worker.js";
|
|
7
|
+
let h = null, M = !1, $ = 0;
|
|
8
|
+
const y = /* @__PURE__ */ new Map();
|
|
9
|
+
function B() {
|
|
10
|
+
if (M || typeof Worker > "u") return null;
|
|
11
|
+
if (h) return h;
|
|
12
|
+
try {
|
|
13
|
+
h = W(), h.onmessage = (t) => {
|
|
14
|
+
const { id: r, objects: s, project: o, error: n } = t.data || {}, i = y.get(r);
|
|
15
|
+
i && (y.delete(r), n ? i.reject(new Error(n)) : i.resolve({ objects: s, project: o }));
|
|
16
|
+
}, h.onerror = () => {
|
|
17
|
+
M = !0;
|
|
18
|
+
for (const [, t] of y) t.reject(new Error("3MF parse worker failed"));
|
|
19
|
+
y.clear(), h = null;
|
|
20
|
+
};
|
|
21
|
+
} catch {
|
|
22
|
+
M = !0, h = null;
|
|
51
23
|
}
|
|
52
|
-
|
|
53
|
-
if (u)
|
|
54
|
-
for (const i of u[1].match(/<item\b[^>]*>/g) || []) {
|
|
55
|
-
const c = w(i, "objectid");
|
|
56
|
-
c && o.push({ objectid: c, path: w(i, "p:path") || w(i, "path"), transform: R(w(i, "transform")) });
|
|
57
|
-
}
|
|
58
|
-
return { objects: e, items: o };
|
|
24
|
+
return h;
|
|
59
25
|
}
|
|
60
|
-
function
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const m = L(a);
|
|
69
|
-
if (i.has(m)) return i.get(m);
|
|
70
|
-
const l = o.get(m), M = l ? Y(u.decode(l)) : null;
|
|
71
|
-
return i.set(m, M), M;
|
|
72
|
-
};
|
|
73
|
-
let p = "3D/3dmodel.model";
|
|
74
|
-
const d = o.get("_rels/.rels");
|
|
75
|
-
if (d) {
|
|
76
|
-
for (const a of u.decode(d).match(/<Relationship\b[^>]*>/g) || [])
|
|
77
|
-
if ((w(a, "Type") || "").endsWith("/3dmodel")) {
|
|
78
|
-
p = L(w(a, "Target"));
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
26
|
+
async function C(t, r) {
|
|
27
|
+
const s = B();
|
|
28
|
+
if (!s) return E(t, r);
|
|
29
|
+
try {
|
|
30
|
+
const o = ++$, n = new Promise((i, c) => y.set(o, { resolve: i, reject: c }));
|
|
31
|
+
return s.postMessage({ id: o, buffer: t, baseName: r }), await n;
|
|
32
|
+
} catch {
|
|
33
|
+
return E(t, r);
|
|
81
34
|
}
|
|
82
|
-
const h = c(p);
|
|
83
|
-
if (!h) throw new Error(`3MF root model not found: ${p}`);
|
|
84
|
-
const r = [], f = (a, m, l, M, $) => {
|
|
85
|
-
if ($ > 16) return;
|
|
86
|
-
const T = c(m), E = T == null ? void 0 : T.objects.get(a);
|
|
87
|
-
if (!E) return;
|
|
88
|
-
if (E.components) {
|
|
89
|
-
for (const y of E.components) f(y.objectid, y.path || m, X(y.transform, l), M, $ + 1);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (!E.mesh) return;
|
|
93
|
-
const { verts: v, tris: S } = E.mesh;
|
|
94
|
-
for (let y = 0; y < S.length; y++) {
|
|
95
|
-
const A = S[y] * 3, b = v[A], j = v[A + 1], F = v[A + 2];
|
|
96
|
-
M.push(
|
|
97
|
-
b * l[0] + j * l[3] + F * l[6] + l[9],
|
|
98
|
-
b * l[1] + j * l[4] + F * l[7] + l[10],
|
|
99
|
-
b * l[2] + j * l[5] + F * l[8] + l[11]
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}, g = h.items.length ? h.items : [...h.objects.keys()].filter((a) => h.objects.get(a).mesh).map((a) => ({ objectid: a, path: p, transform: x }));
|
|
103
|
-
return g.forEach((a, m) => {
|
|
104
|
-
const l = [];
|
|
105
|
-
f(a.objectid, a.path || p, a.transform, l, 0), l.length >= 9 && r.push({ name: g.length > 1 ? `${e}#${m + 1}` : e, tris: new Float32Array(l) });
|
|
106
|
-
}), r;
|
|
107
35
|
}
|
|
108
|
-
const
|
|
109
|
-
function
|
|
110
|
-
for (const s of (Array.isArray(t) ? t : String(t).split(",")).map((
|
|
111
|
-
|
|
36
|
+
const F = ["stl", "obj", "3mf", "amf", "ply"], x = /* @__PURE__ */ new Map();
|
|
37
|
+
function R(t, r) {
|
|
38
|
+
for (const s of (Array.isArray(t) ? t : String(t).split(",")).map((o) => o.trim().toLowerCase()))
|
|
39
|
+
x.set(s, r), F.includes(s) || F.push(s);
|
|
112
40
|
}
|
|
113
|
-
function
|
|
114
|
-
const
|
|
115
|
-
return
|
|
41
|
+
function D(t) {
|
|
42
|
+
const r = t.lastIndexOf(".");
|
|
43
|
+
return r < 0 ? "" : t.slice(r + 1).toLowerCase();
|
|
116
44
|
}
|
|
117
|
-
function
|
|
118
|
-
const
|
|
45
|
+
function I(t) {
|
|
46
|
+
const r = new DataView(t);
|
|
119
47
|
if (t.byteLength >= 84) {
|
|
120
|
-
const
|
|
121
|
-
if (t.byteLength === 84 +
|
|
122
|
-
const
|
|
123
|
-
let
|
|
124
|
-
for (let
|
|
125
|
-
|
|
126
|
-
for (let
|
|
127
|
-
|
|
128
|
-
|
|
48
|
+
const c = r.getUint32(80, !0);
|
|
49
|
+
if (t.byteLength === 84 + c * 50) {
|
|
50
|
+
const a = new Float32Array(c * 9);
|
|
51
|
+
let u = 84, d = 0;
|
|
52
|
+
for (let p = 0; p < c; p++) {
|
|
53
|
+
u += 12;
|
|
54
|
+
for (let e = 0; e < 3; e++)
|
|
55
|
+
a[d++] = r.getFloat32(u, !0), a[d++] = r.getFloat32(u + 4, !0), a[d++] = r.getFloat32(u + 8, !0), u += 12;
|
|
56
|
+
u += 2;
|
|
129
57
|
}
|
|
130
|
-
return
|
|
58
|
+
return a;
|
|
131
59
|
}
|
|
132
60
|
}
|
|
133
|
-
const s = new TextDecoder().decode(t),
|
|
134
|
-
let
|
|
135
|
-
for (;
|
|
136
|
-
return
|
|
61
|
+
const s = new TextDecoder().decode(t), o = /vertex\s+([-\d.eE+]+)\s+([-\d.eE+]+)\s+([-\d.eE+]+)/g, n = [];
|
|
62
|
+
let i;
|
|
63
|
+
for (; i = o.exec(s); ) n.push(+i[1], +i[2], +i[3]);
|
|
64
|
+
return n.length < 9 ? null : new Float32Array(n);
|
|
137
65
|
}
|
|
138
|
-
function
|
|
66
|
+
function A(t, r) {
|
|
139
67
|
var d;
|
|
140
68
|
const s = (d = t == null ? void 0 : t.attributes) == null ? void 0 : d.position;
|
|
141
69
|
if (!s || s.count < 3) return null;
|
|
142
|
-
const
|
|
143
|
-
let
|
|
144
|
-
const
|
|
145
|
-
|
|
70
|
+
const o = t.index, n = new L.Vector3(), i = Math.floor((o ? o.count : s.count) / 3), c = new Float32Array(i * 9);
|
|
71
|
+
let a = 0;
|
|
72
|
+
const u = (p) => {
|
|
73
|
+
n.fromBufferAttribute(s, p), r && n.applyMatrix4(r), c[a++] = n.x, c[a++] = n.y, c[a++] = n.z;
|
|
146
74
|
};
|
|
147
|
-
if (
|
|
148
|
-
for (let
|
|
75
|
+
if (o)
|
|
76
|
+
for (let p = 0; p < i * 3; p++) u(o.getX(p));
|
|
149
77
|
else
|
|
150
|
-
for (let
|
|
151
|
-
return
|
|
78
|
+
for (let p = 0; p < i * 3; p++) u(p);
|
|
79
|
+
return c;
|
|
152
80
|
}
|
|
153
|
-
function
|
|
81
|
+
function j(t) {
|
|
154
82
|
t.updateMatrixWorld(!0);
|
|
155
|
-
const
|
|
83
|
+
const r = [];
|
|
156
84
|
return t.traverse((s) => {
|
|
157
|
-
s.isMesh && s.geometry &&
|
|
158
|
-
}),
|
|
85
|
+
s.isMesh && s.geometry && r.push({ geometry: s.geometry, matrix: s.matrixWorld });
|
|
86
|
+
}), r;
|
|
159
87
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
if (!
|
|
163
|
-
if (s &&
|
|
164
|
-
return
|
|
165
|
-
if (
|
|
166
|
-
let
|
|
167
|
-
for (const
|
|
168
|
-
const
|
|
169
|
-
let
|
|
170
|
-
for (const
|
|
171
|
-
|
|
172
|
-
return [{ name: t, modelPos:
|
|
88
|
+
function k(t, r, s) {
|
|
89
|
+
const o = r.map((a) => A(a.geometry, a.matrix)).filter(Boolean);
|
|
90
|
+
if (!o.length) return [];
|
|
91
|
+
if (s && o.length > 1)
|
|
92
|
+
return o.map((a, u) => ({ name: `${t}#${u + 1}`, modelPos: a }));
|
|
93
|
+
if (o.length === 1) return [{ name: t, modelPos: o[0] }];
|
|
94
|
+
let n = 0;
|
|
95
|
+
for (const a of o) n += a.length;
|
|
96
|
+
const i = new Float32Array(n);
|
|
97
|
+
let c = 0;
|
|
98
|
+
for (const a of o)
|
|
99
|
+
i.set(a, c), c += a.length;
|
|
100
|
+
return [{ name: t, modelPos: i }];
|
|
173
101
|
}
|
|
174
|
-
async function
|
|
175
|
-
const s =
|
|
102
|
+
async function U(t, r) {
|
|
103
|
+
const s = D(t);
|
|
176
104
|
switch (s) {
|
|
177
105
|
case "stl": {
|
|
178
|
-
const
|
|
179
|
-
if (!
|
|
180
|
-
return [{ name: t, modelPos:
|
|
106
|
+
const o = I(r);
|
|
107
|
+
if (!o) throw new Error("Failed to parse STL");
|
|
108
|
+
return [{ name: t, modelPos: o }];
|
|
181
109
|
}
|
|
182
110
|
case "obj": {
|
|
183
|
-
const
|
|
184
|
-
return
|
|
111
|
+
const o = new T().parse(new TextDecoder().decode(r));
|
|
112
|
+
return k(t, j(o), !1);
|
|
185
113
|
}
|
|
186
114
|
case "ply": {
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
189
|
-
return [{ name: t, modelPos:
|
|
115
|
+
const o = new v().parse(r), n = A(o, null);
|
|
116
|
+
if (!n) throw new Error("No PLY geometry");
|
|
117
|
+
return [{ name: t, modelPos: n }];
|
|
190
118
|
}
|
|
191
119
|
case "3mf": {
|
|
192
|
-
const n =
|
|
193
|
-
if (!
|
|
194
|
-
return
|
|
120
|
+
const { objects: o, project: n } = await C(r, t), i = o.map((c) => ({ name: c.name, modelPos: c.tris, objectid: c.objectid, paint: c.paint, bbox: c.bbox, project: n }));
|
|
121
|
+
if (!i.length) throw new Error("No mesh in 3MF");
|
|
122
|
+
return i;
|
|
195
123
|
}
|
|
196
124
|
case "amf": {
|
|
197
|
-
const
|
|
198
|
-
if (!
|
|
199
|
-
return
|
|
125
|
+
const o = new P().parse(r), n = k(t, j(o), !0);
|
|
126
|
+
if (!n.length) throw new Error("No mesh in AMF");
|
|
127
|
+
return n;
|
|
200
128
|
}
|
|
201
129
|
default: {
|
|
202
|
-
const
|
|
203
|
-
if (!
|
|
204
|
-
const
|
|
205
|
-
if (!(
|
|
206
|
-
return
|
|
130
|
+
const o = x.get(s);
|
|
131
|
+
if (!o) throw new Error(`Unsupported format: .${s}`);
|
|
132
|
+
const n = await o(r, t);
|
|
133
|
+
if (!(n != null && n.length)) throw new Error(`No mesh in .${s}`);
|
|
134
|
+
return n;
|
|
207
135
|
}
|
|
208
136
|
}
|
|
209
137
|
}
|
|
210
|
-
function
|
|
211
|
-
const
|
|
212
|
-
if (
|
|
213
|
-
const s = 1e4,
|
|
214
|
-
for (let
|
|
215
|
-
for (let
|
|
216
|
-
const
|
|
217
|
-
let
|
|
218
|
-
|
|
138
|
+
function V(t) {
|
|
139
|
+
const r = Math.floor(t.length / 9);
|
|
140
|
+
if (r < 2) return null;
|
|
141
|
+
const s = 1e4, o = /* @__PURE__ */ new Map(), n = new Int32Array(r * 3);
|
|
142
|
+
for (let e = 0; e < r; e++)
|
|
143
|
+
for (let l = 0; l < 3; l++) {
|
|
144
|
+
const f = e * 9 + l * 3, m = `${Math.round(t[f] * s)},${Math.round(t[f + 1] * s)},${Math.round(t[f + 2] * s)}`;
|
|
145
|
+
let w = o.get(m);
|
|
146
|
+
w === void 0 && (w = o.size, o.set(m, w)), n[e * 3 + l] = w;
|
|
219
147
|
}
|
|
220
|
-
const
|
|
221
|
-
for (let
|
|
222
|
-
const
|
|
223
|
-
for (;
|
|
224
|
-
|
|
225
|
-
return
|
|
226
|
-
},
|
|
227
|
-
|
|
228
|
-
},
|
|
229
|
-
for (let
|
|
230
|
-
for (let
|
|
231
|
-
const
|
|
232
|
-
|
|
148
|
+
const i = new Int32Array(r);
|
|
149
|
+
for (let e = 0; e < r; e++) i[e] = e;
|
|
150
|
+
const c = (e) => {
|
|
151
|
+
for (; i[e] !== e; )
|
|
152
|
+
i[e] = i[i[e]], e = i[e];
|
|
153
|
+
return e;
|
|
154
|
+
}, a = (e, l) => {
|
|
155
|
+
e = c(e), l = c(l), e !== l && (i[l] = e);
|
|
156
|
+
}, u = /* @__PURE__ */ new Map();
|
|
157
|
+
for (let e = 0; e < r; e++)
|
|
158
|
+
for (let l = 0; l < 3; l++) {
|
|
159
|
+
const f = n[e * 3 + l], m = n[e * 3 + (l + 1) % 3], w = f < m ? f * 4294967296 + m : m * 4294967296 + f, g = u.get(w);
|
|
160
|
+
g === void 0 ? u.set(w, e) : a(e, g);
|
|
233
161
|
}
|
|
234
162
|
const d = /* @__PURE__ */ new Map();
|
|
235
|
-
for (let
|
|
236
|
-
const
|
|
237
|
-
let
|
|
238
|
-
|
|
163
|
+
for (let e = 0; e < r; e++) {
|
|
164
|
+
const l = c(e);
|
|
165
|
+
let f = d.get(l);
|
|
166
|
+
f || (f = [], d.set(l, f)), f.push(e);
|
|
239
167
|
}
|
|
240
|
-
return d.size < 2 ? null : [...d.values()].sort((
|
|
241
|
-
const
|
|
242
|
-
let
|
|
243
|
-
for (const
|
|
244
|
-
const
|
|
245
|
-
for (let
|
|
168
|
+
return d.size < 2 ? null : [...d.values()].sort((e, l) => l.length - e.length).map((e) => {
|
|
169
|
+
const l = new Float32Array(e.length * 9);
|
|
170
|
+
let f = 0;
|
|
171
|
+
for (const m of e) {
|
|
172
|
+
const w = m * 9;
|
|
173
|
+
for (let g = 0; g < 9; g++) l[f++] = t[w + g];
|
|
246
174
|
}
|
|
247
|
-
return
|
|
175
|
+
return l;
|
|
248
176
|
});
|
|
249
177
|
}
|
|
250
178
|
export {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
179
|
+
F as SUPPORTED_EXT,
|
|
180
|
+
D as fileExt,
|
|
181
|
+
U as loadModel,
|
|
182
|
+
R as registerLoader,
|
|
183
|
+
V as splitConnectedComponents
|
|
256
184
|
};
|