serialize widget slicing for threading so supports resolve properly

This commit is contained in:
Stewart Allen 2021-06-25 14:10:00 -04:00
commit 5947dda899
2 changed files with 101 additions and 73 deletions

View file

@ -1002,7 +1002,6 @@
API.event.emit('slice.begin', getMode());
let slicing = WIDGETS.slice().filter(w => !w.track.ignore),
countdown = slicing.length,
totalProgress,
track = {},
mode = settings.mode,
@ -1029,16 +1028,29 @@
segNumber = 0,
errored = false,
startTime = Date.now(),
toSlice = slicing.slice(),
camOrLaser = mode === 'CAM' || mode === 'LASER',
lastMsg;
// for each widget, slice
for (let widget of slicing) {
let camOrLaser = mode === 'CAM' || mode === 'LASER',
stack = widget.stack = STACKS.create(widget.id, widget.mesh),
factor = (widget.getVertices().count / defvert);
for (let widget of toSlice) {
widget.stats.progress = 0;
widget.setColor(color.slicing);
}
sliceNext();
function sliceNext() {
if (toSlice.length) {
sliceWidget(toSlice.shift())
} else {
sliceDone();
}
}
function sliceWidget(widget) {
let stack = widget.stack = STACKS.create(widget.id, widget.mesh),
factor = (widget.getVertices().count / defvert);
widget.slice(settings, function(sliced, error) {
widget.rotinfo = null;
let mark = Date.now();
@ -1059,13 +1071,34 @@
KIRI.client.restart();
API.event.emit('slice.error', error);
}
// discard remaining errors
if (errored) {
return;
// terminate slicing
sliceDone();
} else {
// start next widget slice
sliceNext();
}
}, function(update, msg) {
if (msg && msg !== lastMsg) {
let mark = Date.now();
if (lastMsg) {
segtimes[`${widget.id}_${segNumber++}_${lastMsg}`] = mark - startTime;
}
lastMsg = msg;
startTime = mark;
}
// on update
track[widget.id] = (update || 0) * factor;
totalProgress = 0;
for (let w of slicing) {
totalProgress += (track[w.id] || 0);
}
API.show.progress(offset + (totalProgress / WIDGETS.length) * scale, msg);
});
}
function sliceDone() {
let alert = null;
// on the last exit, update ui and call the callback
if (--countdown === 0) {
if (scale === 1 && feature.work_alerts) {
alert = API.show.alert("Rendering");
};
@ -1106,24 +1139,6 @@
callback();
}
}
}, function(update, msg) {
if (msg && msg !== lastMsg) {
let mark = Date.now();
if (lastMsg) {
segtimes[`${widget.id}_${segNumber++}_${lastMsg}`] = mark - startTime;
}
lastMsg = msg;
startTime = mark;
}
// on update
track[widget.id] = (update || 0) * factor;
totalProgress = 0;
for (let w of slicing) {
totalProgress += (track[w.id] || 0);
}
API.show.progress(offset + (totalProgress / WIDGETS.length) * scale, msg);
});
}
}
function preparePreview(callback, scale = 1, offset = 0) {

View file

@ -67,6 +67,12 @@
let { lines, groups, tops } = data;
let { z, index, total, height, thick } = params;
let { process, isSynth, isDanger, vaseMode, shellOffset, fillOffset } = options.post;
if (isSynth) {
// do not shell synth widgets because
// they will be clipped against peers later
// which requires shelling post-clip
return;
}
let range = getRangeParameters(process, index);
// calculate fractional shells
let shellFrac = (range.sliceShells - (range.sliceShells | 0));
@ -92,11 +98,11 @@
danger: isDanger
}));
}
// add simple (low rez poly) where less accuracy is OK
for (let top of nutops) {
// top.simple = top.poly.clean(true, undefined, CONF.clipper / 10);
top.simple = top.poly.simple();
}
// // add simple (low rez poly) where less accuracy is OK
// for (let top of nutops) {
// // top.simple = top.poly.clean(true, undefined, CONF.clipper / 10);
// top.simple = top.poly.simple();
// }
data.tops = nutops;
};
@ -180,7 +186,8 @@
height: sliceHeight,
minHeight: sliceMinHeight,
firstHeight: sliceHeightBase,
union: controller.healMesh,
// support/synth usually has overlapping boxes
union: controller.healMesh || isSynth,
indices: process.indices,
concurrent: isConcurrent,
post: {
@ -205,8 +212,14 @@
if (widget.shadow) {
return;
}
let root = widget.group[0];
if (root.shadow) {
widget.shadow = root.shadow;
return;
}
// create shadow for clipping supports
let alltops = widget.group
.filter(w => !w.track.synth) // no supports in shadow
.map(w => w.slices).flat()
.map(s => s.tops).flat().map(t => t.simple);
let shadow = isConcurrent ?
@ -216,7 +229,7 @@
if (process.sliceSupportExtra) {
shadow = POLY.offset(shadow, process.sliceSupportExtra);
}
widget.shadow = POLY.setZ(shadow, 0);
widget.shadow = root.shadow = POLY.setZ(shadow, 0);
// slices[0].output()
// .setLayer('shadow', { line: 0xff0000, check: 0xff0000 })
// .addPolys(shadow);
@ -251,21 +264,12 @@
await doShadow(slices);
}
// for synth support widgets, merge tops
// for synth support widgets, clip/offset to other widgets in group
if (isSynth) {
for (let slice of slices) {
// union top support polys
let tops = slice.topPolys();
let union = POLY.union(tops, null, true);
if (union.length < tops.length) {
slice.tops = [];
for (let u of union) {
slice.addTop(u);
}
}
let gap = sliceHeight * (isBelt ? 0 : process.sliceSupportGap);
// clip tops to other widgets in group
tops = slice.topPolys();
let tops = slice.topPolys();
for (let peer of widget.group) {
// skip self
if (peer === widget || !peer.slices) {
@ -293,6 +297,7 @@
for (let t of tops) {
slice.addTop(t);
}
doShells(slice, 1, shellOffset / 2);
}
}
@ -508,17 +513,18 @@
});
}
} else if (isSynth) {
// fill supports differently
// fill manual supports differently
let promises = isConcurrent ? [] : undefined;
let resolve = [];
forSlices(0.5, promises ? 0.6 : 0.7, slice => {
let params = slice.params || process;
let density = params.sliceSupportDensity;
if (density)
for (let top of slice.tops) {
let offset = [];
POLY.expand(top.shells, -nozzleSize/4, slice.z, offset);
POLY.expand(top.shells || [], -nozzleSize/4, slice.z, offset);
fillSupportPolys(promises, offset, lineWidth, density, slice.z);
top.fill_lines = offset.map(o => o.fill).flat().filter(v => v);
resolve.push({top, offset});
}
}, "infill");
if (promises) {
@ -526,6 +532,9 @@
trackupdate(i / t, 0.6, 0.7);
});
}
for (let rec of resolve) {
rec.top.fill_lines = rec.offset.map(o => o.fill).flat().filter(v => v);
}
}
// auto support generation
@ -678,6 +687,10 @@
top = { poly: top };
}
// add simple (low rez poly) where less accuracy is OK
// top.simple = top.poly.clean(true, undefined, CONF.clipper / 10);
top.simple = top.poly.simple();
let top_poly = [ top.poly ];
if (opt.vase) {