From 5947dda899582ddec88f5c4c3e71962a3d400dde Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Fri, 25 Jun 2021 14:10:00 -0400 Subject: [PATCH] serialize widget slicing for threading so supports resolve properly --- src/kiri/main.js | 119 ++++++++++++++++++++++++------------------ src/mode/fdm/slice.js | 55 +++++++++++-------- 2 files changed, 101 insertions(+), 73 deletions(-) diff --git a/src/kiri/main.js b/src/kiri/main.js index 5ff4a348..b83f6b7c 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -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,52 +1071,12 @@ KIRI.client.restart(); API.event.emit('slice.error', error); } - // discard remaining errors if (errored) { - return; - } - 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"); - }; - KIRI.client.unrotate(settings, () => { - for (let widget of slicing) { - // on done - segtimes[`${widget.id}_${segNumber++}_draw`] = widget.render(widget.stack); - // rotate stack for belt beds - if (widget.rotinfo) { - widget.stack.obj.rotate(widget.rotinfo); - } - if (scale === 1) { - // clear wireframe - widget.setWireframe(false, color.wireframe, color.wireframe_opacity); - widget.setOpacity(camOrLaser ? color.cam_sliced_opacity : color.sliced_opacity); - widget.setColor(color.deselected); - API.hide.alert(alert); - } - } - updateSliderMax(true); - setVisibleLayer(-1, 0); - if (scale === 1) { - updateStackLabelState(); - } - }); - if (scale === 1) { - API.show.progress(0); - } - // cause visuals to update - SPACE.scene.active(); - // mark slicing complete for prep/preview - complete.slice = true; - API.event.emit('slice.end', getMode()); - // print stats - segtimes.total = Date.now() - now; - DBUG.log(segtimes); - if (callback && typeof callback === 'function') { - callback(); - } + // terminate slicing + sliceDone(); + } else { + // start next widget slice + sliceNext(); } }, function(update, msg) { if (msg && msg !== lastMsg) { @@ -1124,6 +1096,49 @@ API.show.progress(offset + (totalProgress / WIDGETS.length) * scale, msg); }); } + + function sliceDone() { + let alert = null; + if (scale === 1 && feature.work_alerts) { + alert = API.show.alert("Rendering"); + }; + KIRI.client.unrotate(settings, () => { + for (let widget of slicing) { + // on done + segtimes[`${widget.id}_${segNumber++}_draw`] = widget.render(widget.stack); + // rotate stack for belt beds + if (widget.rotinfo) { + widget.stack.obj.rotate(widget.rotinfo); + } + if (scale === 1) { + // clear wireframe + widget.setWireframe(false, color.wireframe, color.wireframe_opacity); + widget.setOpacity(camOrLaser ? color.cam_sliced_opacity : color.sliced_opacity); + widget.setColor(color.deselected); + API.hide.alert(alert); + } + } + updateSliderMax(true); + setVisibleLayer(-1, 0); + if (scale === 1) { + updateStackLabelState(); + } + }); + if (scale === 1) { + API.show.progress(0); + } + // cause visuals to update + SPACE.scene.active(); + // mark slicing complete for prep/preview + complete.slice = true; + API.event.emit('slice.end', getMode()); + // print stats + segtimes.total = Date.now() - now; + DBUG.log(segtimes); + if (callback && typeof callback === 'function') { + callback(); + } + } } function preparePreview(callback, scale = 1, offset = 0) { diff --git a/src/mode/fdm/slice.js b/src/mode/fdm/slice.js index 7da70c8f..da50cb00 100644 --- a/src/mode/fdm/slice.js +++ b/src/mode/fdm/slice.js @@ -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) {