From 50c51084a644d6fdd44641c21c68b2160a937937 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Mon, 9 Nov 2020 00:00:57 -0500 Subject: [PATCH] add multi-colored paths within the same geometry --- src/geo/polygon.js | 2 +- src/kiri/codec.js | 12 ++++-------- src/kiri/main.js | 2 +- src/kiri/print.js | 14 +++++++++++--- src/kiri/render.js | 20 ++++++++++++++++++-- src/kiri/stacks.js | 33 ++++++++++++++++++++++----------- src/mode/fdm/prepare.js | 34 +++++++++++++++++++++++++--------- src/mode/fdm/slice.js | 2 +- src/mode/sla/slice.js | 2 +- 9 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/geo/polygon.js b/src/geo/polygon.js index f827b901..0d0b56ef 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1378,7 +1378,7 @@ union.fillang = fillang; return union; } else { - console.log({check_union_call_path: union, this: this, poly}); + console.trace({check_union_call_path: union, this: this, poly}); } } diff --git a/src/kiri/codec.js b/src/kiri/codec.js index 48af2178..6f39f5cd 100644 --- a/src/kiri/codec.js +++ b/src/kiri/codec.js @@ -114,13 +114,8 @@ lines: encodePointArray(layer.lines, state), faces: codec.allocFloat32Array(layer.faces), color: layer.color, - paths: layer.paths.map(path => { - return { - index: path.index, - faces: path.faces, - z: path.z - } - }) + paths: layer.paths, + cpath: layer.cpath } }) }; return enc; @@ -134,7 +129,8 @@ lines: decodePointArray(v.data[i].lines), faces: v.data[i].faces, color: v.data[i].color, - paths: v.data[i].paths + paths: v.data[i].paths, + cpath: v.data[i].cpath }; } return render; diff --git a/src/kiri/main.js b/src/kiri/main.js index 85e2bc54..6601db73 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -1929,7 +1929,7 @@ KIRI.work.clear(); STACKS.clear(); hideSlider(); - updateSliderMax(); + setVisibleLayer(0,0); setWidgetVisibility(true); setOpacity(1); break; diff --git a/src/kiri/print.js b/src/kiri/print.js index 75142dab..b1f7537f 100644 --- a/src/kiri/print.js +++ b/src/kiri/print.js @@ -25,6 +25,8 @@ let lastPoint = null, lastEmit = null; + KIRI.Print = Print; + KIRI.newPrint = function(settings, widgets, id) { return new Print(settings, widgets, id); }; @@ -51,9 +53,11 @@ this.bounds = null; this.imported = null; - this.hsv2rgb = hsv2rgb; + // this.hsv2rgb = hsv2rgb; } + Print.hsv2rgb = hsv2rgb; + PRO.addOutput = addOutput; PRO.tip2tipEmit = tip2tipEmit; PRO.extrudePerMM = extrudePerMM; @@ -245,7 +249,7 @@ } // hsv values all = 0 to 1 - function hsv2rgb(hsv) { + function hsv2rgb(hsv, hex) { let seg = Math.floor(hsv.h * 6), rem = hsv.h - (seg * (1/6)), p = hsv.v * (1.0 - (hsv.s)), @@ -285,7 +289,11 @@ break; } - return out; + return hex ? ( + ((out.r * 255) << 16) || + ((out.g * 255) << 8) || + (out.b * 255) + ) : out; } // PRO.getLayerCount = function() { diff --git a/src/kiri/render.js b/src/kiri/render.js index 78f96aef..5f6e2615 100644 --- a/src/kiri/render.js +++ b/src/kiri/render.js @@ -161,7 +161,8 @@ contour.push(new THREE.Vector2(p.x, p.y)); }); const {index, faces} = ProfiledContourGeometry(profile, contour, poly.isClosed()); - const one = this.current.paths[0]; + const cur = this.current; + const one = cur.paths[0]; if (one) { // merge all contour geometry for massive speed gain const add = one.faces.length / 3; @@ -169,12 +170,27 @@ index[i] += add; } const feces = new Float32Array(one.faces.length + faces.length); + const indln = one.index.length; feces.set(one.faces); feces.set(faces, one.faces.length); one.faces = feces; one.index.appendAll(index); + // allow changing colors + if (opts.color) { + if (!cur.cpath) { + // seed + cur.cpath = [ Object.assign({ start: 0, count: indln - 1 }, cur.color) ]; + } else { + // rewrite last color count if color or opacity have changed + const pc = cur.cpath[cur.cpath.length - 1]; + if (pc.face !== opts.color.face || pc.opacity !== opts.color.opacity) { + pc.count = indln - 1; + cur.cpath.push(Object.assign({ start: indln, count: Infinity }, opts.color)); + } + } + } } else { - this.current.paths.push({ index, faces, z: poly.getZ() }); + cur.paths.push({ index, faces, z: poly.getZ() }); } this.stats.contour++; }); diff --git a/src/kiri/stacks.js b/src/kiri/stacks.js index e30f390b..2dfe04a8 100644 --- a/src/kiri/stacks.js +++ b/src/kiri/stacks.js @@ -10,7 +10,7 @@ emissive = 0x101010, metalness = 0, roughness = 0.3, - newMesh = createPhongMesh; + newMat = createPhongMat; let stacks = {}, tallest = 0, @@ -108,11 +108,11 @@ const ctrl = DYN[label]; ctrl.toggle.checked = true; - const { polys, lines, faces, paths } = data; + const { polys, lines, faces, paths, cpath } = data; if (polys.length || lines.length) { const mat = new THREE.LineBasicMaterial({ transparent: data.color.opacity != 1, - opacity: data.color.opacity, + opacity: data.color.opacity || 1, color: data.color.line }); const geo = new THREE.Geometry(), vert = geo.vertices; @@ -129,7 +129,7 @@ ctrl.group.push(mat); } if (faces.length) { - const mat = newMesh(data); + const mat = newMat(data); const geo = new THREE.BufferGeometry(); geo.setAttribute('position', new THREE.BufferAttribute(faces, 3)); geo.computeFaceNormals(); @@ -141,43 +141,54 @@ ctrl.group.push(mat); } if (paths.length) { - const mat = newMesh(data); + let mat = []; + if (cpath) { + cpath.forEach(c => { mat.push(newMat({ color: c })) }); + } else { + mat.push(newMat(data)); + } + // const mat = newMat(data); paths.forEach((path, i) => { - const { index, faces, z } = path; + const { index, faces, z, colors } = path; const geo = new THREE.BufferGeometry(); geo.setAttribute('position', new THREE.BufferAttribute(faces, 3)); geo.setIndex(index); geo.computeFaceNormals(); geo.computeVertexNormals(); + if (cpath) { + cpath.forEach((c, i) => geo.addGroup(c.start, c.count, i)); + } else { + geo.addGroup(0, Infinity, 0); + } const mesh = new THREE.Mesh(geo, mat); mesh.position.z = z; mesh.castShadow = true; mesh.receiveShadow = true; group.add(mesh); }); - ctrl.group.push(mat); + ctrl.group.appendAll(mat); } } }; - function createStandardMesh(data) { + function createStandardMat(data) { return new THREE.MeshStandardMaterial({ emissive, roughness, metalness, transparent: data.color.opacity != 1, - opacity: data.color.opacity, + opacity: data.color.opacity || 1, color: data.color.face, side: THREE.DoubleSide }); } - function createPhongMesh(data) { + function createPhongMat(data) { return new THREE.MeshPhongMaterial({ shininess, specular, transparent: data.color.opacity != 1, - opacity: data.color.opacity, + opacity: data.color.opacity || 1, color: data.color.face, side: THREE.DoubleSide }); diff --git a/src/mode/fdm/prepare.js b/src/mode/fdm/prepare.js index bef76d73..cfd4ac26 100644 --- a/src/mode/fdm/prepare.js +++ b/src/mode/fdm/prepare.js @@ -24,9 +24,9 @@ let device = settings.device, nozzle = device.extruders[0].extNozzle, process = settings.process, + bounds = settings.bounds, mode = settings.mode, output = [], - bounds = settings.bounds, printPoint = newPoint(0,0,0), firstLayerHeight = process.firstSliceHeight || process.sliceHeight, maxLayers = 0, @@ -388,6 +388,10 @@ const moveColor = opts.move >= 0 ? opts.move : 0xaaaaaa; const printColor = opts.print >= 0 ? opts.print : 0x777700; const layers = []; + const hsv2rgb = KIRI.Print.hsv2rgb; + const maxspd = levels.map(level => { + return level.map(o => o.speed || 0).reduce((a, v) => Math.max(a,v)); + }).reduce((a, v) => Math.max(a, v)); let lastOut = null; let current = null; @@ -395,6 +399,8 @@ levels.forEach((level, index) => { const prints = {}; const moves = []; + const output = new KIRI.Render(); + layers.push(output); const pushPrint = (toolid, poly) => { toolid = toolid || 0; @@ -414,9 +420,10 @@ } if (lastOut) { if (out.emit) { - if (!lastOut.emit) { + if (!lastOut.emit || out.speed !== lastOut.speed) { current = newPolygon().setOpen(); current.push(lastOut.point); + current.color = hsv2rgb({h:out.speed/maxspd, s:1, v:1}, true); pushPrint(out.tool, current); } current.push(out.point); @@ -432,6 +439,7 @@ current = newPolygon().setOpen(); current.push(out.point); if (out.emit) { + current.color = hsv2rgb({h:out.speed/maxspd, s:1, v:1}, true); pushPrint(out.tool, current); } else { moves.push(current); @@ -445,17 +453,25 @@ moves.push(current); } - const output = new KIRI.Render(); - layers.push(output); output .setLayer('move', moveColor) .addPolys(moves, { thin: true, z: opts.z }); Object.values(prints).forEach(array => { - output - .setLayer(opts.action || 'print', printColor) - .addPolys(array, thin ? - { thin, z: opts.z } : - { offset: array.width, height, z: opts.z }) + array.forEach(poly => { + output + .setLayer(opts.action || 'print', printColor) + .addPolys([ poly ], thin ? { thin, z: opts.z } : + { + offset: array.width, height, z: opts.z, + color: { face: poly.color, line: poly.color } + }) + }) + // output + // .setLayer(opts.action || 'print', printColor) + // .addPolys(array, thin ? { thin, z: opts.z } : + // { offset: array.width, height, z: opts.z, + // xcolor: { face: hsv2rgb({h:index/levels.length, s:1, v:1}, true) } + // }) }); update(index / output.length); diff --git a/src/mode/fdm/slice.js b/src/mode/fdm/slice.js index 62aeb423..6b37d953 100644 --- a/src/mode/fdm/slice.js +++ b/src/mode/fdm/slice.js @@ -671,7 +671,7 @@ let minarea = minArea || 1, tops = slice.tops, solids = slice.solids, - unioned = POLY.union(solids), + unioned = POLY.union(solids, undefined, true).flat(), // TODO verify isSLA = (spacing === undefined && angle === undefined); if (solids.length === 0) return false; diff --git a/src/mode/sla/slice.js b/src/mode/sla/slice.js index 55568f4e..9341a674 100644 --- a/src/mode/sla/slice.js +++ b/src/mode/sla/slice.js @@ -160,7 +160,7 @@ let traces = POLY.nest(POLY.flatten(slice.topShells())); let trims = slice.solids || []; traces.appendAll(trims); - let union = POLY.union(traces); + let union = POLY.union(traces, undefined, true); slice.unioned = union; }, "solid"); } else {