three-slicer-viewer 0.3.2 → 0.3.4
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/TOOLPATH_SPEC.md +8 -1
- package/VIEWER.md +24 -0
- package/data/config-schema-lean.json +1 -1
- package/dist/components.js +47 -43
- package/dist/gcode_parse.js +154 -111
- package/dist/index.js +4409 -4069
- package/dist/{model_loaders-DxlFNFOu.js → model_loaders-Dk9rqXFb.js} +27 -27
- package/dist/model_loaders.js +2 -2
- package/dist/parse_3mf-CpbA-6Iq.js +666 -0
- package/dist/parse_3mf.worker.js +67 -5
- package/dist/sl1_encode.worker.js +1 -1
- package/dist/sl1_write-B6nWmCUu.js +313 -0
- package/dist/sla_slice.worker.js +1 -1
- package/dist/toolpath.js +303 -177
- package/package.json +6 -1
- package/src/core/paint_tools.js +8 -0
- package/src/settings/bed_frame.js +28 -0
- package/src/settings/index.js +1 -0
- package/src/settings/kernel_setting_keys.js +79 -0
- package/src/settings/settings_core.js +194 -8
- package/types/gcode.d.ts +13 -0
- package/types/paint.d.ts +7 -0
- package/types/settings.d.ts +14 -1
- package/types/toolpath.d.ts +6 -0
- package/types/viewer.d.ts +1 -1
- package/dist/parse_3mf-BZISF3eW.js +0 -327
- package/dist/sl1_write-BovHbg3k.js +0 -303
package/dist/toolpath.js
CHANGED
|
@@ -1,113 +1,133 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { b as
|
|
3
|
-
import { r as
|
|
4
|
-
import { T as
|
|
5
|
-
const
|
|
6
|
-
for (const t of Object.keys(
|
|
7
|
-
function
|
|
1
|
+
import { a as R, b as Bt, p as lt, h as _t, T as wt, r as kt, D as Ot } from "./toolpath_palette-B8xEl-qa.js";
|
|
2
|
+
import { b as Vt, a as jt } from "./viewer_defaults-B7UUZ582.js";
|
|
3
|
+
import { r as At, S as ct, R as ot, t as Tt } from "./toolpath_encoding-BuYs95qZ.js";
|
|
4
|
+
import { T as Ut } from "./theme-2oyfMuvf.js";
|
|
5
|
+
const ft = {};
|
|
6
|
+
for (const t of Object.keys(R)) ft[t] = lt(R[t]);
|
|
7
|
+
function Wt(t) {
|
|
8
8
|
const e = new Float32Array(t.length);
|
|
9
9
|
for (let n = 0; n < t.length; n++) {
|
|
10
|
-
const
|
|
11
|
-
e[n] =
|
|
10
|
+
const o = Number(t[n]?.z) || 0, r = n > 0 && Number(t[n - 1]?.z) || 0, l = n > 0 ? o - r : o;
|
|
11
|
+
e[n] = l > 1e-6 ? l : jt;
|
|
12
12
|
}
|
|
13
13
|
return e;
|
|
14
14
|
}
|
|
15
|
-
const
|
|
16
|
-
const e =
|
|
17
|
-
return e ? Math.floor(e.length /
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
const ut = (t) => t?.paths?.length ? t.paths : null, Lt = (t) => {
|
|
16
|
+
const e = ut(t);
|
|
17
|
+
return e ? Math.floor(e.length / ct) : 0;
|
|
18
|
+
}, xt = (t, e) => {
|
|
19
|
+
const n = e * 8, o = n + 4;
|
|
20
|
+
return Math.atan2(t[o + 1] - t[n + 1], t[o] - t[n]);
|
|
21
|
+
}, Mt = (t, e) => {
|
|
22
|
+
const n = e * 8, o = n + 4;
|
|
23
|
+
return Math.hypot(t[o] - t[n], t[o + 1] - t[n + 1]);
|
|
24
|
+
}, zt = (t, e, n) => t[e] === t[n] && t[e + 1] === t[n + 1] && t[e + 2] === t[n + 2];
|
|
25
|
+
function Dt(t, e, n, o) {
|
|
26
|
+
const r = (a, h) => {
|
|
27
|
+
e[a * 8 + 4 + 2] = xt(t, h), e[h * 8 + 2] = xt(t, a);
|
|
28
|
+
}, l = (a, h) => n[a * 2] === n[h * 2] && zt(t, a * 8 + 4, h * 8) && Mt(t, a) > 0 && Mt(t, h) > 0;
|
|
29
|
+
let m = 0;
|
|
30
|
+
for (let a = 0; a < o; a++) {
|
|
31
|
+
if (a + 1 < o && l(a, a + 1)) {
|
|
32
|
+
r(a, a + 1);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
m < a && l(a, m) && r(a, m), m = a + 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function le(t, e) {
|
|
39
|
+
const n = Array.isArray(t) ? t : [], o = n.length, r = Number(e) > 0 ? Number(e) : Vt, l = Wt(n), m = new Uint32Array(o + 1), a = new Uint32Array(o + 1), h = new Uint32Array(o + 1);
|
|
40
|
+
let p = 0, s = 0, d = 0;
|
|
41
|
+
for (let u = 0; u < o; u++) {
|
|
42
|
+
const v = ut(n[u]), g = Lt(n[u]);
|
|
43
|
+
for (let M = 0; M < g; M++)
|
|
44
|
+
At(v[M * ct + 3]) === ot.TRAVEL ? s++ : p++;
|
|
45
|
+
d += g, m[u + 1] = p, a[u + 1] = s, h[u + 1] = d;
|
|
27
46
|
}
|
|
28
|
-
const
|
|
29
|
-
let
|
|
30
|
-
for (let
|
|
31
|
-
const
|
|
32
|
-
for (let
|
|
33
|
-
const
|
|
34
|
-
if (Number.isFinite(
|
|
35
|
-
const
|
|
36
|
-
|
|
47
|
+
const c = p * 2, L = new Float32Array(c * 4), S = new Float32Array(c * 4), W = new Uint32Array(c * 2), b = new Uint8Array(c), H = new Uint8Array(c), B = new Float32Array(c), _ = new Float32Array(c), E = new Int32Array(c), F = new Float32Array(s * 6), I = new Float32Array(d * 3), z = new Uint8Array(d), D = new Float64Array(16);
|
|
48
|
+
let it = !1, K = 0, G = 1 / 0, Z = 1 / 0, N = 1 / 0, q = -1 / 0, k = -1 / 0, O = -1 / 0, x = 0, J = 0, st = 0, i = 0;
|
|
49
|
+
for (let u = 0; u < o; u++) {
|
|
50
|
+
const v = n[u], g = ut(v), M = Lt(v), V = v?.widths, X = l[u], tt = X / 2;
|
|
51
|
+
for (let Y = 0; Y < M; Y++) {
|
|
52
|
+
const w = Y * ct, $ = g[w], P = g[w + 1], y = g[w + 2], A = g[w + 4], j = g[w + 5], T = g[w + 6], mt = g[w + 3] | 0, et = At(mt), It = Tt(mt);
|
|
53
|
+
if (Number.isFinite($ + P + y + A + j + T) || (it = !0), z[i] = et === ot.TRAVEL ? 0 : 1, I[i * 3] = A, I[i * 3 + 1] = j, I[i * 3 + 2] = T, i++, et === ot.TRAVEL) {
|
|
54
|
+
const C = st * 6;
|
|
55
|
+
F[C] = $, F[C + 1] = P, F[C + 2] = y, F[C + 3] = A, F[C + 4] = j, F[C + 5] = T, st++;
|
|
37
56
|
continue;
|
|
38
57
|
}
|
|
39
|
-
const
|
|
40
|
-
Number.isFinite(
|
|
41
|
-
const
|
|
42
|
-
for (const [
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
58
|
+
const at = V ? Number(V[Y]) : NaN, dt = Number.isFinite(at) && at > 0 ? at : r, vt = A - $, yt = j - P, Nt = Math.atan2(yt, vt), pt = Math.hypot(vt, yt, T - y);
|
|
59
|
+
Number.isFinite(pt) && (D[et] += pt);
|
|
60
|
+
const Pt = ft[et] ?? ft[1];
|
|
61
|
+
for (const [C, Q, bt] of [[$, P, y], [A, j, T]]) {
|
|
62
|
+
const U = x * 4;
|
|
63
|
+
L[U] = C, L[U + 1] = Q, L[U + 2] = bt - tt, L[U + 3] = 0, S[U] = X, S[U + 1] = dt, S[U + 2] = Nt, S[U + 3] = Pt, W[x * 2] = J, W[x * 2 + 1] = u, b[x] = et, H[x] = It, B[x] = dt, _[x] = X, E[x] = u, x++;
|
|
64
|
+
const nt = bt - tt;
|
|
65
|
+
C < G && (G = C), C > q && (q = C), Q < Z && (Z = Q), Q > k && (k = Q), nt < N && (N = nt), nt > O && (O = nt);
|
|
66
|
+
const gt = Math.max(Math.abs(C), Math.abs(Q), Math.abs(nt));
|
|
67
|
+
gt > K && (K = gt);
|
|
49
68
|
}
|
|
50
|
-
|
|
69
|
+
J++;
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
|
-
|
|
72
|
+
Dt(L, S, E, p);
|
|
73
|
+
const f = c > 0 && Number.isFinite(G) ? { min: [G, Z, N], max: [q, k, O] } : null;
|
|
54
74
|
return {
|
|
55
|
-
position:
|
|
56
|
-
hwa:
|
|
57
|
-
segIndex:
|
|
58
|
-
nV:
|
|
59
|
-
nSeg:
|
|
60
|
-
layerSegPrefix:
|
|
61
|
-
travelPos:
|
|
62
|
-
travelPrefix:
|
|
63
|
-
nTrav:
|
|
64
|
-
movePos:
|
|
65
|
-
moveKind:
|
|
66
|
-
movePrefix:
|
|
67
|
-
layerCount:
|
|
68
|
-
maxAbs:
|
|
69
|
-
hasNaN:
|
|
70
|
-
typeLengths:
|
|
71
|
-
bbox:
|
|
72
|
-
meta: { vType:
|
|
75
|
+
position: L,
|
|
76
|
+
hwa: S,
|
|
77
|
+
segIndex: W,
|
|
78
|
+
nV: c,
|
|
79
|
+
nSeg: p,
|
|
80
|
+
layerSegPrefix: m,
|
|
81
|
+
travelPos: F,
|
|
82
|
+
travelPrefix: a,
|
|
83
|
+
nTrav: s,
|
|
84
|
+
movePos: I,
|
|
85
|
+
moveKind: z,
|
|
86
|
+
movePrefix: h,
|
|
87
|
+
layerCount: o,
|
|
88
|
+
maxAbs: K,
|
|
89
|
+
hasNaN: it,
|
|
90
|
+
typeLengths: D,
|
|
91
|
+
bbox: f,
|
|
92
|
+
meta: { vType: b, vTool: H, vWidth: B, vHeight: _, vLayer: E }
|
|
73
93
|
};
|
|
74
94
|
}
|
|
75
|
-
function
|
|
95
|
+
function ce(t) {
|
|
76
96
|
const e = t ?? [];
|
|
77
97
|
let n = 0;
|
|
78
|
-
for (let
|
|
98
|
+
for (let r = 0; r < 16; r++) n += Number(e[r]) || 0;
|
|
79
99
|
if (n <= 0) return [];
|
|
80
|
-
const
|
|
81
|
-
for (let
|
|
82
|
-
const
|
|
83
|
-
|
|
100
|
+
const o = [];
|
|
101
|
+
for (let r = 0; r < 16; r++) {
|
|
102
|
+
const l = Number(e[r]) || 0;
|
|
103
|
+
l <= 0 || o.push({ type: r, label: Bt[r] ?? String(r), pct: l / n * 100, color: R[r] ?? R[1] });
|
|
84
104
|
}
|
|
85
|
-
return
|
|
105
|
+
return o.sort((r, l) => l.pct - r.pct);
|
|
86
106
|
}
|
|
87
|
-
const
|
|
88
|
-
function
|
|
89
|
-
return
|
|
107
|
+
const ht = (t, e) => e >= 0 && e < t.layerCount ? t.movePrefix[e + 1] - t.movePrefix[e] : 0;
|
|
108
|
+
function fe(t, e) {
|
|
109
|
+
return ht(t, e);
|
|
90
110
|
}
|
|
91
|
-
function
|
|
92
|
-
const
|
|
93
|
-
for (let
|
|
111
|
+
function Gt(t, e, n) {
|
|
112
|
+
const o = Math.min(n, t.layerCount - 1);
|
|
113
|
+
for (let r = o; r >= e; r--) if (ht(t, r) > 0) return r;
|
|
94
114
|
return e;
|
|
95
115
|
}
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
let
|
|
99
|
-
for (let
|
|
100
|
-
t.moveKind[
|
|
101
|
-
if (
|
|
102
|
-
const
|
|
116
|
+
function Jt(t, e, n) {
|
|
117
|
+
const o = ht(t, e), r = Math.max(0, Math.min(Number(n) || 0, o)), l = e >= 0 && e < t.layerCount ? t.movePrefix[e] : 0;
|
|
118
|
+
let m = 0, a = 0;
|
|
119
|
+
for (let p = 0; p < r; p++)
|
|
120
|
+
t.moveKind[l + p] === 0 ? a++ : m++;
|
|
121
|
+
if (r === 0) return { point: null, segCount: 0, travCount: 0, onTravel: !1 };
|
|
122
|
+
const h = l + r - 1;
|
|
103
123
|
return {
|
|
104
|
-
point: [t.movePos[
|
|
105
|
-
segCount:
|
|
106
|
-
travCount:
|
|
107
|
-
onTravel: t.moveKind[
|
|
124
|
+
point: [t.movePos[h * 3], t.movePos[h * 3 + 1], t.movePos[h * 3 + 2]],
|
|
125
|
+
segCount: m,
|
|
126
|
+
travCount: a,
|
|
127
|
+
onTravel: t.moveKind[h] === 0
|
|
108
128
|
};
|
|
109
129
|
}
|
|
110
|
-
const
|
|
130
|
+
const Ct = [
|
|
111
131
|
{ key: "feature", label: "Feature type", cont: !1, unit: "" },
|
|
112
132
|
{ key: "speed", label: "Speed", cont: !0, unit: "mm/s" },
|
|
113
133
|
{ key: "height", label: "Layer Height", cont: !0, unit: "mm" },
|
|
@@ -119,47 +139,51 @@ const At = [
|
|
|
119
139
|
// extruder index is a label, and a heatmap over it would imply tool 2 sits "between" tools 1 and 3.
|
|
120
140
|
{ key: "filament", label: "Filament", cont: !1, unit: "" }
|
|
121
141
|
];
|
|
122
|
-
function
|
|
123
|
-
const
|
|
142
|
+
function Xt(t, e, n, o) {
|
|
143
|
+
const r = e.vType[n], l = e.vLayer[n], m = l === 0;
|
|
124
144
|
switch (t) {
|
|
125
145
|
case "height":
|
|
126
146
|
return e.vHeight[n];
|
|
127
147
|
case "width":
|
|
128
148
|
return e.vWidth[n];
|
|
129
149
|
case "speed":
|
|
130
|
-
return
|
|
150
|
+
return m ? o.firstLayerSpeed : o.speedByType[r] ?? o.speedByType[1];
|
|
131
151
|
case "fan":
|
|
132
|
-
return
|
|
152
|
+
return l < o.closeFanLayers ? 0 : r === 9 ? 100 : o.fanNormal;
|
|
133
153
|
case "temp":
|
|
134
|
-
return
|
|
154
|
+
return m ? o.tempFirst : o.tempNormal;
|
|
135
155
|
default:
|
|
136
156
|
return 0;
|
|
137
157
|
}
|
|
138
158
|
}
|
|
139
|
-
function
|
|
140
|
-
const { meta:
|
|
141
|
-
if (!
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
return
|
|
145
|
-
} : (
|
|
146
|
-
for (let
|
|
147
|
-
return { color:
|
|
159
|
+
function ue(t, e, n) {
|
|
160
|
+
const { meta: o, nV: r } = t, l = new Float32Array(r * 4), m = Ct.find((s) => s.key === e) || Ct[0];
|
|
161
|
+
if (!m.cont) {
|
|
162
|
+
const s = (n?.toolColors ?? []).map((c) => c && _t(c)), d = m.key === "filament" ? (c) => {
|
|
163
|
+
const L = o.vTool ? o.vTool[c] : 0;
|
|
164
|
+
return s[L] || wt[L % wt.length];
|
|
165
|
+
} : (c) => R[o.vType[c]] || R[1];
|
|
166
|
+
for (let c = 0; c < r; c++) l[c * 4] = lt(d(c));
|
|
167
|
+
return { color: l, min: 0, max: 0, viewType: e, label: m.label, unit: m.unit, cont: !1 };
|
|
148
168
|
}
|
|
149
|
-
let
|
|
150
|
-
const
|
|
151
|
-
for (let
|
|
152
|
-
const
|
|
153
|
-
|
|
169
|
+
let a = 1 / 0, h = -1 / 0;
|
|
170
|
+
const p = new Float32Array(r);
|
|
171
|
+
for (let s = 0; s < r; s++) {
|
|
172
|
+
const d = Xt(e, o, s, n), c = Number.isFinite(d) ? d : 0;
|
|
173
|
+
p[s] = c, c < a && (a = c), c > h && (h = c);
|
|
154
174
|
}
|
|
155
|
-
Number.isFinite(
|
|
156
|
-
for (let
|
|
157
|
-
const
|
|
158
|
-
s
|
|
175
|
+
Number.isFinite(a) || (a = 0, h = 1);
|
|
176
|
+
for (let s = 0; s < r; s++) {
|
|
177
|
+
const d = kt(p[s], a, h, Ot);
|
|
178
|
+
l[s * 4] = lt(d);
|
|
159
179
|
}
|
|
160
|
-
return { color:
|
|
180
|
+
return { color: l, min: a, max: h, viewType: e, label: m.label, unit: m.unit, cont: !0 };
|
|
181
|
+
}
|
|
182
|
+
const rt = 4096, Yt = 140 * Math.PI / 180, $t = 45 * Math.PI / 180, St = (t) => Math.round((t + Math.PI) / (2 * Math.PI) * (rt - 1));
|
|
183
|
+
function Kt(t, e) {
|
|
184
|
+
return St(t) * rt + St(e);
|
|
161
185
|
}
|
|
162
|
-
const
|
|
186
|
+
const Zt = `
|
|
163
187
|
precision highp float;
|
|
164
188
|
|
|
165
189
|
uniform mat4 projectionMatrix;
|
|
@@ -173,6 +197,7 @@ in vec3 iEnd;
|
|
|
173
197
|
in vec2 iHW; // [height, width]
|
|
174
198
|
in float iColor; // r<<16 | g<<8 | b
|
|
175
199
|
in float iLayer;
|
|
200
|
+
in float iJoin; // packJoin(start heading, end heading)
|
|
176
201
|
|
|
177
202
|
out vec3 vColor;
|
|
178
203
|
out vec3 vNormal;
|
|
@@ -199,8 +224,26 @@ void main() {
|
|
|
199
224
|
vec3 axis = iEnd - iStart;
|
|
200
225
|
// A zero-length segment has no direction to orient against; pick one rather than emitting NaN.
|
|
201
226
|
vec2 flat2 = axis.xy;
|
|
202
|
-
vec2 dir =
|
|
203
|
-
|
|
227
|
+
vec2 dir = vec2(1.0, 0.0);
|
|
228
|
+
if (length(flat2) > 1e-9) dir = normalize(flat2);
|
|
229
|
+
vec2 ownSide = vec2(-dir.y, dir.x);
|
|
230
|
+
|
|
231
|
+
float joinStart = floor(iJoin / ${rt}.0);
|
|
232
|
+
float joined = joinStart;
|
|
233
|
+
if (tpl.x > 0.5) joined = iJoin - joinStart * ${rt}.0;
|
|
234
|
+
joined = joined * (6.283185307179586 / ${rt - 1}.0) - 3.141592653589793;
|
|
235
|
+
vec2 bisector = dir + vec2(cos(joined), sin(joined));
|
|
236
|
+
vec2 side2 = ownSide;
|
|
237
|
+
vec2 facing2 = ownSide;
|
|
238
|
+
if (length(bisector) > 1e-6) {
|
|
239
|
+
vec2 tangent = normalize(bisector);
|
|
240
|
+
vec2 miterSide = vec2(-tangent.y, tangent.x);
|
|
241
|
+
float halfTurnCos = dot(miterSide, ownSide);
|
|
242
|
+
if (halfTurnCos > ${Math.cos(Yt / 2)}) side2 = miterSide / halfTurnCos;
|
|
243
|
+
if (halfTurnCos > ${Math.cos($t / 2)}) facing2 = miterSide;
|
|
244
|
+
}
|
|
245
|
+
vec3 side = vec3(side2, 0.0);
|
|
246
|
+
vec3 facing = vec3(facing2, 0.0);
|
|
204
247
|
vec3 up = vec3(0.0, 0.0, 1.0);
|
|
205
248
|
|
|
206
249
|
float halfHeight = iHW.x * 0.5;
|
|
@@ -208,18 +251,19 @@ void main() {
|
|
|
208
251
|
|
|
209
252
|
float ring = tpl.y;
|
|
210
253
|
vec3 offset;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
else if (ring <
|
|
214
|
-
else
|
|
254
|
+
vec3 normal;
|
|
255
|
+
if (ring < 0.5) { offset = side * halfWidth; normal = facing; }
|
|
256
|
+
else if (ring < 1.5) { offset = up * halfHeight; normal = up; }
|
|
257
|
+
else if (ring < 2.5) { offset = -side * halfWidth; normal = -facing; }
|
|
258
|
+
else { offset = -up * halfHeight; normal = -up; }
|
|
215
259
|
|
|
216
260
|
vec3 world = mix(iStart, iEnd, tpl.x) + offset;
|
|
217
261
|
|
|
218
|
-
vNormal = normalize(mat3(modelViewMatrix) *
|
|
262
|
+
vNormal = normalize(mat3(modelViewMatrix) * normal);
|
|
219
263
|
vColor = unpackColor(iColor);
|
|
220
264
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(world, 1.0);
|
|
221
265
|
}
|
|
222
|
-
`,
|
|
266
|
+
`, qt = `
|
|
223
267
|
precision highp float;
|
|
224
268
|
|
|
225
269
|
in vec3 vColor;
|
|
@@ -227,15 +271,48 @@ in vec3 vNormal;
|
|
|
227
271
|
out vec4 fragColor;
|
|
228
272
|
|
|
229
273
|
void main() {
|
|
230
|
-
//
|
|
274
|
+
// Front faces only (the material culls the rest), so the normal never needs flipping.
|
|
231
275
|
vec3 n = normalize(vNormal);
|
|
232
|
-
if (!gl_FrontFacing) n = -n;
|
|
233
276
|
// A single head-on light plus a generous ambient. The point is to read the bead's ROUNDING — which
|
|
234
277
|
// face is up, which is the side — not to look lit.
|
|
235
278
|
float lambert = max(dot(n, normalize(vec3(0.35, 0.35, 1.0))), 0.0);
|
|
236
279
|
fragColor = vec4(vColor * (0.55 + 0.45 * lambert), 1.0);
|
|
237
280
|
}
|
|
238
|
-
`,
|
|
281
|
+
`, Ft = [2, 4], Qt = 1.5;
|
|
282
|
+
function Rt(t, e) {
|
|
283
|
+
let n = 0;
|
|
284
|
+
for (let o = 0; o < t.length; o += 2)
|
|
285
|
+
(t[o] === ot.RAFT || t[o] === ot.SKIRT) && e[o] > n && (n = e[o]);
|
|
286
|
+
return n;
|
|
287
|
+
}
|
|
288
|
+
function Ht(t, e, n, o) {
|
|
289
|
+
let r = 0;
|
|
290
|
+
for (let s = 0; s < e; s++) t(s) > r && (r = t(s));
|
|
291
|
+
const l = (s) => s <= o || (r - s) % n === 0;
|
|
292
|
+
let m = 0;
|
|
293
|
+
for (let s = 0; s < e; s++) l(t(s)) && m++;
|
|
294
|
+
const a = new Uint32Array(m), h = new Uint8Array(m);
|
|
295
|
+
let p = 0;
|
|
296
|
+
for (let s = 0; s < e; s++) {
|
|
297
|
+
const d = t(s);
|
|
298
|
+
l(d) && (a[p] = s, h[p] = 1, d > o && (h[p] = Math.min(n, d - o)), p++);
|
|
299
|
+
}
|
|
300
|
+
return { source: a, layers: h };
|
|
301
|
+
}
|
|
302
|
+
function Et(t, e) {
|
|
303
|
+
const n = Math.max(1, Math.floor(e / 4096)), o = [];
|
|
304
|
+
for (let r = 0; r < e; r += n) o.push(t(r));
|
|
305
|
+
return o.length ? (o.sort((r, l) => r - l), o[o.length >> 1]) : 0;
|
|
306
|
+
}
|
|
307
|
+
function te(t, e, n, o) {
|
|
308
|
+
return e > 0 ? t * (o / 2) / (e * Math.tan(n * Math.PI / 360)) : 1 / 0;
|
|
309
|
+
}
|
|
310
|
+
function ee(t, e = Ft) {
|
|
311
|
+
let n = 1;
|
|
312
|
+
for (const o of e) o * t <= Qt && o > n && (n = o);
|
|
313
|
+
return n;
|
|
314
|
+
}
|
|
315
|
+
const ne = new Float32Array([
|
|
239
316
|
0,
|
|
240
317
|
0,
|
|
241
318
|
0,
|
|
@@ -254,80 +331,129 @@ void main() {
|
|
|
254
331
|
1,
|
|
255
332
|
3
|
|
256
333
|
// end ring
|
|
257
|
-
]),
|
|
334
|
+
]), oe = (() => {
|
|
258
335
|
const t = [];
|
|
259
336
|
for (let e = 0; e < 4; e++) {
|
|
260
|
-
const n = e,
|
|
261
|
-
t.push(n,
|
|
337
|
+
const n = e, o = (e + 1) % 4, r = 4 + (e + 1) % 4, l = 4 + e;
|
|
338
|
+
t.push(n, o, r, n, r, l);
|
|
262
339
|
}
|
|
263
340
|
return t;
|
|
264
341
|
})();
|
|
265
|
-
function
|
|
266
|
-
const { nSeg: n, nV:
|
|
267
|
-
for (let
|
|
268
|
-
const
|
|
269
|
-
|
|
342
|
+
function he(t, e) {
|
|
343
|
+
const { nSeg: n, nV: o, position: r, hwa: l, travelPos: m, travelPrefix: a, layerCount: h, meta: p } = e, s = new Float32Array(n * 3), d = new Float32Array(n * 3), c = new Float32Array(n * 2), L = new Float32Array(n), S = new Float32Array(n), W = new Float32Array(n);
|
|
344
|
+
for (let i = 0; i < n; i++) {
|
|
345
|
+
const f = i * 2 * 4, u = (i * 2 + 1) * 4;
|
|
346
|
+
s[i * 3] = r[f], s[i * 3 + 1] = r[f + 1], s[i * 3 + 2] = r[f + 2], d[i * 3] = r[u], d[i * 3 + 1] = r[u + 1], d[i * 3 + 2] = r[u + 2], c[i * 2] = l[f], c[i * 2 + 1] = l[f + 1], L[i] = l[f + 3], S[i] = p.vLayer[i * 2], W[i] = Kt(l[f + 2], l[u + 2]);
|
|
270
347
|
}
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
vertexShader:
|
|
277
|
-
fragmentShader:
|
|
348
|
+
const b = new t.InstancedBufferGeometry();
|
|
349
|
+
b.setAttribute("tpl", new t.BufferAttribute(ne, 2)), b.setIndex(oe), b.setAttribute("iStart", new t.InstancedBufferAttribute(s, 3)), b.setAttribute("iEnd", new t.InstancedBufferAttribute(d, 3)), b.setAttribute("iHW", new t.InstancedBufferAttribute(c, 2));
|
|
350
|
+
const H = new t.InstancedBufferAttribute(L, 1);
|
|
351
|
+
b.setAttribute("iColor", H), b.setAttribute("iLayer", new t.InstancedBufferAttribute(S, 1)), b.setAttribute("iJoin", new t.InstancedBufferAttribute(W, 1)), b.instanceCount = n, b.boundingSphere = new t.Sphere(new t.Vector3(0, 0, 0), (e.maxAbs || 1) * 2);
|
|
352
|
+
const B = new t.RawShaderMaterial({
|
|
353
|
+
vertexShader: Zt,
|
|
354
|
+
fragmentShader: qt,
|
|
278
355
|
glslVersion: t.GLSL3,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
356
|
+
// Every face of the template winds outward (test_toolpath_contract.mjs), so a back face is only ever the
|
|
357
|
+
// inside of a bead seen through its open end. Drawing those doubled the GPU time of a frame: measured on a
|
|
358
|
+
// 14.6M-segment scene (6 plates, M5 Pro, DPR 2), 53.6 -> 29.4 ms with back faces culled.
|
|
359
|
+
side: t.FrontSide,
|
|
360
|
+
uniforms: { uLayerLo: { value: 0 }, uLayerHi: { value: Math.max(0, h - 1) } }
|
|
361
|
+
}), _ = new t.Mesh(b, B);
|
|
362
|
+
_.frustumCulled = !1;
|
|
363
|
+
const E = Rt(p.vType, p.vLayer), F = Ft.map((i) => {
|
|
364
|
+
const { source: f, layers: u } = Ht((y) => S[y], n, i, E), v = f.length, g = new Float32Array(v * 3), M = new Float32Array(v * 3), V = new Float32Array(v * 2), X = new Float32Array(v), tt = new Float32Array(v), Y = new Float32Array(v);
|
|
365
|
+
for (let y = 0; y < v; y++) {
|
|
366
|
+
const A = f[y], j = c[A * 2], T = (u[y] - 1) * j / 2;
|
|
367
|
+
g[y * 3] = s[A * 3], g[y * 3 + 1] = s[A * 3 + 1], g[y * 3 + 2] = s[A * 3 + 2] - T, M[y * 3] = d[A * 3], M[y * 3 + 1] = d[A * 3 + 1], M[y * 3 + 2] = d[A * 3 + 2] - T, V[y * 2] = j * u[y], V[y * 2 + 1] = c[A * 2 + 1], X[y] = L[A], tt[y] = S[A], Y[y] = W[A];
|
|
368
|
+
}
|
|
369
|
+
const w = new t.InstancedBufferGeometry();
|
|
370
|
+
w.setAttribute("tpl", b.attributes.tpl), w.setIndex(b.index), w.setAttribute("iStart", new t.InstancedBufferAttribute(g, 3)), w.setAttribute("iEnd", new t.InstancedBufferAttribute(M, 3)), w.setAttribute("iHW", new t.InstancedBufferAttribute(V, 2));
|
|
371
|
+
const $ = new t.InstancedBufferAttribute(X, 1);
|
|
372
|
+
w.setAttribute("iColor", $), w.setAttribute("iLayer", new t.InstancedBufferAttribute(tt, 1)), w.setAttribute("iJoin", new t.InstancedBufferAttribute(Y, 1)), w.instanceCount = v;
|
|
373
|
+
const P = new t.Mesh(w, B);
|
|
374
|
+
return P.frustumCulled = !1, P.visible = !1, _.add(P), { k: i, mesh: P, source: f, colors: X, colorAttr: $ };
|
|
375
|
+
});
|
|
376
|
+
let I = 1, z = !0;
|
|
377
|
+
const D = (i) => {
|
|
378
|
+
if (i !== I) {
|
|
379
|
+
I = i;
|
|
380
|
+
for (const f of F) f.mesh.visible = f.k === i;
|
|
381
|
+
b.instanceCount = 0, i === 1 && (b.instanceCount = n);
|
|
382
|
+
}
|
|
383
|
+
}, it = Et((i) => c[i * 2], n), K = e.bbox && new t.Box3(new t.Vector3(...e.bbox.min), new t.Vector3(...e.bbox.max)), G = new t.Box3(), Z = (i, f) => {
|
|
384
|
+
if (!z || !K || !i?.isPerspectiveCamera) {
|
|
385
|
+
D(1);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
G.copy(K).applyMatrix4(_.matrixWorld), D(ee(te(it, G.distanceToPoint(i.position), i.fov, f)));
|
|
389
|
+
};
|
|
390
|
+
_.userData.updateLod = Z;
|
|
283
391
|
const N = new t.BufferGeometry();
|
|
284
|
-
N.setAttribute("position", new t.BufferAttribute(
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
392
|
+
N.setAttribute("position", new t.BufferAttribute(m, 3));
|
|
393
|
+
const q = new t.LineBasicMaterial({ color: Ut.travel, transparent: !0, opacity: 0.6 }), k = new t.LineSegments(N, q);
|
|
394
|
+
k.visible = !1, k.frustumCulled = !1;
|
|
395
|
+
let O = 0, x = Math.max(0, h - 1);
|
|
396
|
+
const J = (i, f) => {
|
|
397
|
+
const u = Math.max(0, h - 1), v = Math.max(0, Math.min(i | 0, u)), g = Math.max(v, Math.min(f | 0, u));
|
|
398
|
+
O = v, x = g, I === 1 && (b.instanceCount = n), B.uniforms.uLayerLo.value = v, B.uniforms.uLayerHi.value = g, z = v === 0 && g === u, z || D(1);
|
|
399
|
+
const M = a[v] * 2, V = a[g + 1] * 2;
|
|
400
|
+
N.setDrawRange(M, Math.max(0, V - M));
|
|
292
401
|
};
|
|
293
|
-
return
|
|
294
|
-
mesh:
|
|
295
|
-
travLines:
|
|
296
|
-
setLayerRange:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
402
|
+
return J(0, h - 1), {
|
|
403
|
+
mesh: _,
|
|
404
|
+
travLines: k,
|
|
405
|
+
setLayerRange: J,
|
|
406
|
+
setMoveRange: (i) => {
|
|
407
|
+
if (i == null)
|
|
408
|
+
return J(O, x), null;
|
|
409
|
+
const f = Gt(e, O, x), u = Jt(e, f, i);
|
|
410
|
+
z = !1, D(1), b.instanceCount = e.layerSegPrefix[f] + u.segCount;
|
|
411
|
+
const v = a[O] * 2;
|
|
412
|
+
return N.setDrawRange(v, Math.max(0, (a[f] + u.travCount) * 2 - v)), { ...u, layer: f };
|
|
413
|
+
},
|
|
414
|
+
data: e,
|
|
415
|
+
setVisibleLayers: (i) => J(0, (i | 0) - 1),
|
|
416
|
+
setTravelVisible: (i) => {
|
|
417
|
+
k.visible = !!i;
|
|
300
418
|
},
|
|
301
419
|
/** color is Float32Array(nV*4) with the packed value in .r — computeColors' output shape. One instance
|
|
302
420
|
* takes the colour of its first vertex; the two agree, since a segment is one colour. */
|
|
303
|
-
setColors: (
|
|
304
|
-
if (!(!
|
|
305
|
-
for (let
|
|
306
|
-
|
|
421
|
+
setColors: (i) => {
|
|
422
|
+
if (!(!i || i.length < o * 4)) {
|
|
423
|
+
for (let f = 0; f < n; f++) L[f] = i[f * 2 * 4];
|
|
424
|
+
H.needsUpdate = !0;
|
|
425
|
+
for (const f of F) {
|
|
426
|
+
for (let u = 0; u < f.source.length; u++) f.colors[u] = L[f.source[u]];
|
|
427
|
+
f.colorAttr.needsUpdate = !0;
|
|
428
|
+
}
|
|
307
429
|
}
|
|
308
430
|
},
|
|
431
|
+
/** Call once per frame before rendering; viewportPixels is the drawing buffer's height. */
|
|
432
|
+
updateLod: Z,
|
|
433
|
+
lodLevel: () => I,
|
|
309
434
|
dispose: () => {
|
|
310
|
-
|
|
435
|
+
for (const i of F) i.mesh.geometry.dispose();
|
|
436
|
+
b.dispose(), B.dispose(), N.dispose(), q.dispose();
|
|
311
437
|
},
|
|
312
438
|
nSeg: n,
|
|
313
|
-
layerCount:
|
|
439
|
+
layerCount: h
|
|
314
440
|
};
|
|
315
441
|
}
|
|
316
442
|
export {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
443
|
+
Ot as DEFAULT_RANGES_COLORS,
|
|
444
|
+
wt as TOOL_COLOR,
|
|
445
|
+
R as TYPE_COLOR,
|
|
446
|
+
Bt as TYPE_LABEL,
|
|
447
|
+
oe as VERTEX_DATA,
|
|
448
|
+
Ct as VIEW_TYPES,
|
|
449
|
+
le as buildSegmentData,
|
|
450
|
+
ue as computeColors,
|
|
451
|
+
_t as hexToRgb,
|
|
452
|
+
fe as layerMoveCount,
|
|
453
|
+
he as makeToolpath,
|
|
454
|
+
Jt as moveCursor,
|
|
455
|
+
lt as packColor,
|
|
456
|
+
kt as rangeColorAt,
|
|
457
|
+
ce as roleRatios,
|
|
458
|
+
Gt as topMoveLayer
|
|
333
459
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-slicer-viewer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "The three-slicer viewer without the slicer — model loading, G-code parsing, GPU toolpath rendering and the settings transforms, under MIT. Plug a slicer in through the `slicer` prop.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"types": "./types/toggle.d.ts",
|
|
36
36
|
"default": "./src/settings/toggle_eval.js"
|
|
37
37
|
},
|
|
38
|
+
"./paint": {
|
|
39
|
+
"types": "./types/paint.d.ts",
|
|
40
|
+
"default": "./src/core/paint_tools.js"
|
|
41
|
+
},
|
|
38
42
|
"./components": {
|
|
39
43
|
"types": "./types/components.d.ts",
|
|
40
44
|
"default": "./dist/components.js"
|
|
@@ -49,6 +53,7 @@
|
|
|
49
53
|
"VIEWER.md",
|
|
50
54
|
"data",
|
|
51
55
|
"dist",
|
|
56
|
+
"src/core/paint_tools.js",
|
|
52
57
|
"src/data.js",
|
|
53
58
|
"src/settings",
|
|
54
59
|
"types",
|