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()); API.event.emit('slice.begin', getMode());
let slicing = WIDGETS.slice().filter(w => !w.track.ignore), let slicing = WIDGETS.slice().filter(w => !w.track.ignore),
countdown = slicing.length,
totalProgress, totalProgress,
track = {}, track = {},
mode = settings.mode, mode = settings.mode,
@ -1029,16 +1028,29 @@
segNumber = 0, segNumber = 0,
errored = false, errored = false,
startTime = Date.now(), startTime = Date.now(),
toSlice = slicing.slice(),
camOrLaser = mode === 'CAM' || mode === 'LASER',
lastMsg; lastMsg;
// for each widget, slice for (let widget of toSlice) {
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);
widget.stats.progress = 0; widget.stats.progress = 0;
widget.setColor(color.slicing); 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.slice(settings, function(sliced, error) {
widget.rotinfo = null; widget.rotinfo = null;
let mark = Date.now(); let mark = Date.now();
@ -1059,13 +1071,34 @@
KIRI.client.restart(); KIRI.client.restart();
API.event.emit('slice.error', error); API.event.emit('slice.error', error);
} }
// discard remaining errors
if (errored) { 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; let alert = null;
// on the last exit, update ui and call the callback
if (--countdown === 0) {
if (scale === 1 && feature.work_alerts) { if (scale === 1 && feature.work_alerts) {
alert = API.show.alert("Rendering"); alert = API.show.alert("Rendering");
}; };
@ -1106,24 +1139,6 @@
callback(); 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) { function preparePreview(callback, scale = 1, offset = 0) {

View file

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