add new assembly preference for enabling wasm testing

This commit is contained in:
Stewart Allen 2021-07-07 21:09:34 -04:00
commit 841df7b5a9
16 changed files with 178 additions and 100 deletions

3
app.js
View file

@ -287,7 +287,7 @@ const script = {
"add/three", "add/three",
"add/class", "add/class",
"geo/base", "geo/base",
// "geo/wasm", "geo/wasm",
"geo/point", "geo/point",
"geo/points", "geo/points",
"geo/slope", "geo/slope",
@ -331,6 +331,7 @@ const script = {
"add/array", "add/array",
"add/class", "add/class",
"geo/base", "geo/base",
"geo/wasm",
"geo/point", "geo/point",
"geo/points", "geo/points",
"geo/slope", "geo/slope",

View file

@ -102,9 +102,9 @@
* @param {Point} p3 * @param {Point} p3
* @returns {boolean} * @returns {boolean}
*/ */
function isCollinear(p1, p2, p3) { // function isCollinear(p1, p2, p3) {
return inCloseRange(area2(p1, p2, p3), -0.00001, 0.00001); // return inCloseRange(area2(p1, p2, p3), -0.00001, 0.00001);
} // }
function pac(p1, p2) { function pac(p1, p2) {
return (p2.x - p1.x) * (p2.y + p1.y); return (p2.x - p1.x) * (p2.y + p1.y);
@ -521,7 +521,7 @@
inRange, inRange,
isCloseTo, isCloseTo,
inCloseRange, inCloseRange,
isCollinear, // isCollinear,
isClockwise, isClockwise,
isCounterClockwise, isCounterClockwise,
doCombinations, doCombinations,

View file

@ -72,6 +72,7 @@
}; };
/** /**
* faulty when line doubles back at 180?
* @param {Line} line * @param {Line} line
* @returns {boolean} * @returns {boolean}
*/ */
@ -85,7 +86,7 @@
d2x = (p4.x - p3.x), d2x = (p4.x - p3.x),
d2y = (p4.y - p3.y); d2y = (p4.y - p3.y);
return Math.abs( (d2y * d1x) - (d2x * d1y) ) < 0.000001; return Math.abs( (d2y * d1x) - (d2x * d1y) ) < 0.0001;
}; };
/** ****************************************************************** /** ******************************************************************

View file

@ -1503,9 +1503,6 @@
* @returns {?Polygon[]} returns output array provided as input or new array if not provided * @returns {?Polygon[]} returns output array provided as input or new array if not provided
*/ */
PRO.offset = function(offset, output) { PRO.offset = function(offset, output) {
// let offs = geo.poly.offset([this], -offset, this.getZ());
// if (output) output.appendAll(offs);
// return output || offs;
return POLY().expand([this], -offset, this.getZ(), output); return POLY().expand([this], -offset, this.getZ(), output);
}; };

View file

@ -18,7 +18,7 @@
newPoint = BASE.newPoint, newPoint = BASE.newPoint,
numOrDefault = UTIL.numOrDefault; numOrDefault = UTIL.numOrDefault;
BASE.polygons = { const POLYS = BASE.polygons = {
rayIntersect, rayIntersect,
alignWindings, alignWindings,
setWinding, setWinding,
@ -527,6 +527,9 @@
mina = numOrDefault(opts.minArea, 0.1), mina = numOrDefault(opts.minArea, 0.1),
zed = opts.z || 0; zed = opts.z || 0;
if (opts.wasm && geo.wasm) {
polys = geo.wasm.js.offset(polys, offs, zed);
} else {
// setup offset // setup offset
for (let poly of polys) { for (let poly of polys) {
// convert to clipper format // convert to clipper format
@ -539,6 +542,8 @@
coff.Execute(ctre, offs * CONF.clipper); coff.Execute(ctre, offs * CONF.clipper);
// convert back from clipper output format // convert back from clipper output format
polys = fromClipperTree(ctre, zed, null, null, mina); polys = fromClipperTree(ctre, zed, null, null, mina);
}
// if specified, perform offset gap analysis // if specified, perform offset gap analysis
if (opts.gaps && polys.length) { if (opts.gaps && polys.length) {
@ -583,15 +588,15 @@
* as performing subtractive analysis between initial layer shell (ref) * as performing subtractive analysis between initial layer shell (ref)
* and last offset (cmp) to produce gap candidates (for thinfill) * and last offset (cmp) to produce gap candidates (for thinfill)
*/ */
function inset(polys, dist, count, z) { function inset(polys, dist, count, z, wasm) {
let total = count; let total = count;
let layers = []; let layers = [];
let ref = polys; let ref = polys;
let depth = 0; let depth = 0;
while (count-- > 0 && ref && ref.length) { while (count-- > 0 && ref && ref.length) {
let off = offset(ref, -dist, {z}); let off = offset(ref, -dist, {z, wasm});
let mid = offset(off, dist / 2, {z}); let mid = offset(off, dist / 2, {z, wasm});
let cmp = offset(off, dist, {z}); let cmp = offset(off, dist, {z, wasm});
let gap = []; let gap = [];
let aref = ref.map(p => p.areaDeep()).reduce((a,p) => a +p); let aref = ref.map(p => p.areaDeep()).reduce((a,p) => a +p);
let cref = cmp.length ? cmp.map(p => p.areaDeep()).reduce((a,p) => a + p) : 0; let cref = cmp.length ? cmp.map(p => p.areaDeep()).reduce((a,p) => a + p) : 0;

View file

@ -5,7 +5,15 @@
// only active in workers // only active in workers
if (!self.window) (function() { if (!self.window) (function() {
if (!self.geo) self.geo = {}; if (!self.geo) self.geo = {
enable,
disable,
count: {
offset: 0,
union: 0,
diff: 0
}
};
const factor = self.base.config.clipper; const factor = self.base.config.clipper;
const geo = self.geo; const geo = self.geo;
@ -69,6 +77,7 @@ if (!self.window) (function() {
} }
function polyOffset(polys, offset, z) { function polyOffset(polys, offset, z) {
geo.count.offset++;
let wasm = geo.wasm, let wasm = geo.wasm,
buffer = geo.wasm.shared, buffer = geo.wasm.shared,
pcount = writePolys(new DataWriter(wasm.heap, buffer), polys), pcount = writePolys(new DataWriter(wasm.heap, buffer), polys),
@ -78,6 +87,7 @@ if (!self.window) (function() {
} }
function polyUnion(polys, z) { function polyUnion(polys, z) {
geo.count.union++;
let wasm = geo.wasm, let wasm = geo.wasm,
buffer = geo.wasm.shared, buffer = geo.wasm.shared,
pcount = writePolys(new DataWriter(wasm.heap, buffer), polys), pcount = writePolys(new DataWriter(wasm.heap, buffer), polys),
@ -87,6 +97,7 @@ if (!self.window) (function() {
} }
function polyDiff(polysA, polysB, z, AB, BA) { function polyDiff(polysA, polysB, z, AB, BA) {
geo.count.diff++;
let wasm = geo.wasm, let wasm = geo.wasm,
buffer = geo.wasm.shared, buffer = geo.wasm.shared,
writer = new DataWriter(wasm.heap, buffer), writer = new DataWriter(wasm.heap, buffer),
@ -143,6 +154,11 @@ if (!self.window) (function() {
console.log('offs',{o1:o1[0].points}); console.log('offs',{o1:o1[0].points});
} }
function enable() {
if (geo.wasm || geo._wasm) {
return;
}
geo._wasm = 'loading';
fetch('/wasm/kiri-geo.wasm') fetch('/wasm/kiri-geo.wasm')
.then(response => response.arrayBuffer()) .then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, { .then(bytes => WebAssembly.instantiate(bytes, {
@ -160,6 +176,8 @@ if (!self.window) (function() {
} }
})) }))
.then(results => { .then(results => {
// console.log({enabled: geo.wasm});
delete geo._wasm;
let { module, instance } = results; let { module, instance } = results;
let { exports } = instance; let { exports } = instance;
let heap = new DataView(exports.memory.buffer); let heap = new DataView(exports.memory.buffer);
@ -172,7 +190,7 @@ if (!self.window) (function() {
free: exports.mem_clr, free: exports.mem_clr,
set_debug: exports.set_debug set_debug: exports.set_debug
}; };
wasm.shared = wasm.malloc(1024 * 1024 * 10), wasm.shared = wasm.malloc(1024 * 1024 * 32),
wasm.fn = { wasm.fn = {
diff: exports.poly_diff, diff: exports.poly_diff,
union: exports.poly_union, union: exports.poly_union,
@ -185,10 +203,16 @@ if (!self.window) (function() {
}; };
if (debug) { if (debug) {
wasm.set_debug(1); wasm.set_debug(1);
for (let i=0; i<100; i++) {
runTests(); runTests();
} }
}
}); });
}
function disable() {
if (geo.wasm) {
delete geo.wasm;
// console.log({disabled: geo});
}
}
})(); })();

View file

@ -287,6 +287,12 @@ KIRI.work = {
output(reply); output(reply);
} }
}); });
},
wasm: function(enable) {
send("wasm", {enable}, reply => {
// console.log({wasm_worker_said: reply});
});
} }
}; };

View file

@ -692,6 +692,7 @@
animesh: "200", animesh: "200",
healMesh: false, healMesh: false,
threaded: false, threaded: false,
assembly: false,
ortho: false, ortho: false,
devel: false devel: false
}, },

View file

@ -142,6 +142,9 @@
let control = settings().controller; let control = settings().controller;
let isDark = control.dark; let isDark = control.dark;
let doAlert = UI.ortho.checked !== control.ortho; let doAlert = UI.ortho.checked !== control.ortho;
if (control.assembly != UI.assembly.checked) {
KIRI.client.wasm(UI.assembly.checked);
}
control.decals = UI.decals.checked; control.decals = UI.decals.checked;
control.danger = UI.danger.checked; control.danger = UI.danger.checked;
control.showOrigin = UI.showOrigin.checked; control.showOrigin = UI.showOrigin.checked;
@ -158,6 +161,7 @@
control.decimate = UI.decimate.checked; control.decimate = UI.decimate.checked;
control.healMesh = UI.healMesh.checked; control.healMesh = UI.healMesh.checked;
control.threaded = UI.threaded.checked; control.threaded = UI.threaded.checked;
control.assembly = UI.assembly.checked;
control.ortho = UI.ortho.checked; control.ortho = UI.ortho.checked;
control.devel = UI.devel.checked; control.devel = UI.devel.checked;
SPACE.view.setZoom(control.reverseZoom, control.zoomSpeed); SPACE.view.setZoom(control.reverseZoom, control.zoomSpeed);
@ -1647,6 +1651,7 @@
decimate: UC.newBoolean(LANG.pt_deci_s, booleanSave, {title: LANG.pt_deci_l}), decimate: UC.newBoolean(LANG.pt_deci_s, booleanSave, {title: LANG.pt_deci_l}),
healMesh: UC.newBoolean(LANG.pt_heal_s, booleanSave, {title: LANG.pt_heal_l}), healMesh: UC.newBoolean(LANG.pt_heal_s, booleanSave, {title: LANG.pt_heal_l}),
threaded: UC.newBoolean(LANG.pt_thrd_s, booleanSave, {title: LANG.pt_thrd_l, modes:FDM_SLA}), threaded: UC.newBoolean(LANG.pt_thrd_s, booleanSave, {title: LANG.pt_thrd_l, modes:FDM_SLA}),
assembly: UC.newBoolean(LANG.pt_assy_s, booleanSave, {title: LANG.pt_assy_l, modes:FDM_SLA}),
prefadd: UC.checkpoint($('prefs-add')), prefadd: UC.checkpoint($('prefs-add')),
@ -2439,6 +2444,7 @@
UI.decimate.checked = control.decimate; UI.decimate.checked = control.decimate;
UI.healMesh.checked = control.healMesh; UI.healMesh.checked = control.healMesh;
UI.threaded.checked = control.threaded; UI.threaded.checked = control.threaded;
UI.assembly.checked = control.assembly;
UI.ortho.checked = control.ortho; UI.ortho.checked = control.ortho;
UI.devel.checked = control.devel; UI.devel.checked = control.devel;
lineTypeSave(); lineTypeSave();
@ -2471,6 +2477,9 @@
// update everything dependent on the platform size // update everything dependent on the platform size
platform.update_size(); platform.update_size();
// load wasm if indicated
KIRI.client.wasm(control.assembly);
}; };
UI.sync(); UI.sync();

View file

@ -102,6 +102,14 @@ const funcs = {
reply({ seq, output: CODEC.encode(output) }); reply({ seq, output: CODEC.encode(output) });
}, },
wasm: data => {
if (data.enable) {
geo.enable();
} else {
geo.disable();
}
},
bad: (data, seq) => { bad: (data, seq) => {
reply({ seq, error: "invalid command" }); reply({ seq, error: "invalid command" });
} }

View file

@ -847,7 +847,10 @@
// merge collinear lines // merge collinear lines
for (let point of points) { for (let point of points) {
if (point.group.length != 2) continue; // only merge when point connects to exactly one other point
if (point.group.length != 2) {
continue;
}
let l1 = point.group[0], let l1 = point.group[0],
l2 = point.group[1]; l2 = point.group[1];
if (l1.isCollinear(l2)) { if (l1.isCollinear(l2)) {

View file

@ -173,6 +173,15 @@ KIRI.minions = {
}; };
minion.postMessage(qrec.work, qrec.direct); minion.postMessage(qrec.work, qrec.direct);
} }
},
wasm: function(enable) {
for (let minion of minions) {
minion.postMessage({
cmd: "wasm",
enable
});
}
} }
}; };
@ -727,6 +736,16 @@ KIRI.worker = {
}).then(output => { }).then(output => {
send.done(output); send.done(output);
}); });
},
wasm: function(data, send) {
if (data.enable) {
geo.enable();
} else {
geo.disable();
}
minwork.wasm(data.enable);
send.done({ wasm: data });
} }
}; };

View file

@ -402,7 +402,6 @@
addto.belt.touch = false; addto.belt.touch = false;
let z = addto.z; let z = addto.z;
let y = z - smin - (nozzleSize / 2); let y = z - smin - (nozzleSize / 2);
// let splat = BASE.newPolygon().add(wb.min.x, y, z).add(wb.max.x, y, z).setOpen();
let splat = BASE.newPolygon().add(minx, y, z).add(maxx, y, z).setOpen(); let splat = BASE.newPolygon().add(minx, y, z).add(maxx, y, z).setOpen();
let snew = addto.addTop(splat).fill_sparse = [ splat ]; let snew = addto.addTop(splat).fill_sparse = [ splat ];
adds.push(snew); adds.push(snew);
@ -726,7 +725,7 @@
if (opt.danger && opt.thin) { if (opt.danger && opt.thin) {
top.thin_fill = []; top.thin_fill = [];
top.fill_sparse = []; top.fill_sparse = [];
let layers = POLY.inset(top_poly, offsetN, count, z); let layers = POLY.inset(top_poly, offsetN, count, z, true);
last = layers.last().mid; last = layers.last().mid;
top.shells = layers.map(r => r.mid).flat(); top.shells = layers.map(r => r.mid).flat();
top.gaps = layers.map(r => r.gap).flat(); top.gaps = layers.map(r => r.gap).flat();
@ -740,7 +739,7 @@
} }
} else if (opt.thin) { } else if (opt.thin) {
top.thin_fill = []; top.thin_fill = [];
let oso = {z, count, gaps: [], outs: [], minArea: 0.05}; let oso = {z, count, gaps: [], outs: [], minArea: 0.05, wasm: true};
POLY.offset(top_poly, [-offset1, -offsetN], oso); POLY.offset(top_poly, [-offset1, -offsetN], oso);
oso.outs.forEach((polys, i) => { oso.outs.forEach((polys, i) => {
@ -762,7 +761,7 @@
// slice.solids.trimmed = slice.solids.trimmed || []; // slice.solids.trimmed = slice.solids.trimmed || [];
oso.gaps.forEach((polys, i) => { oso.gaps.forEach((polys, i) => {
let off = (i == 0 ? offset1 : offsetN); let off = (i == 0 ? offset1 : offsetN);
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0}); polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0, wasm: true});
top.thin_fill.appendAll(cullIntersections( top.thin_fill.appendAll(cullIntersections(
fillArea(polys, 45, off/2, [], 0.01, off*2), fillArea(polys, 45, off/2, [], 0.01, off*2),
fillArea(polys, 135, off/2, [], 0.01, off*2), fillArea(polys, 135, off/2, [], 0.01, off*2),
@ -771,30 +770,33 @@
}); });
} else { } else {
// standard wall offsetting strategy // standard wall offsetting strategy
POLY.expand( POLY.offset(
top_poly, // reference polygon(s) top_poly,
-offset1, // first inset distance [-offset1, -offsetN],
z, // set new polys to this z {
top.shells, // accumulator array z,
count, // number of insets to perform outs: top.shells,
-offsetN, // subsequent inset distance flat: true,
// on each new offset trace ... wasm: true,
function(polys, countNow) { call: (polys, onCount) => {
last = polys; last = polys;
// mark each poly with depth (offset #) starting at 0 // mark each poly with depth (offset #) starting at 0
polys.forEach(function(p) { for (let p of polys) {
p.depth = count - countNow; p.depth = count - onCount;
if (p.fill_off) p.fill_off.forEach(function(pi) { if (p.fill_off) p.fill_off.forEach(function(pi) {
// use negative offset for inners // use negative offset for inners
pi.depth = -(count - countNow); pi.depth = -(count - onCount);
}); });
// mark inner depth to match parent
if (p.inner) { if (p.inner) {
for (let pi of p.inner) { for (let pi of p.inner) {
pi.depth = p.depth; pi.depth = p.depth;
} }
} }
}); }
}); }
}
);
} }
} }
} else { } else {
@ -1372,7 +1374,7 @@
// angle based on width/height ratio // angle based on width/height ratio
let angle = (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0; let angle = (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0;
// inset support poly for fill lines 33% of nozzle width // inset support poly for fill lines 33% of nozzle width
let inset = POLY.offset([poly], -linewidth/3, {flat: true, z}); let inset = POLY.offset([poly], -linewidth/3, {flat: true, z, wasm: true});
// do the fill // do the fill
if (inset && inset.length > 0) { if (inset && inset.length > 0) {
doFillArea(promises, inset, angle, spacing, poly.fill = []); doFillArea(promises, inset, angle, spacing, poly.fill = []);

Binary file not shown.

View file

@ -4,7 +4,7 @@ kiri-sla.wasm: kiri-sla.c
emcc --no-entry -o kiri-sla.wasm kiri-sla.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0 emcc --no-entry -o kiri-sla.wasm kiri-sla.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0
kiri-geo.wasm: kiri-geo.cpp kiri-geo.wasm: kiri-geo.cpp
emcc --no-entry -o kiri-geo.wasm clipper.cpp kiri-geo.cpp -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 emcc --no-entry -o kiri-geo.wasm clipper.cpp kiri-geo.cpp -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s TOTAL_MEMORY=40mb
kiri-ani.wasm: kiri-ani.c kiri-ani.wasm: kiri-ani.c
emcc --no-entry -o kiri-ani.wasm kiri-ani.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0 emcc --no-entry -o kiri-ani.wasm kiri-ani.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0

View file

@ -246,6 +246,8 @@ kiri.lang['en-us'] = {
pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"], pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"],
pt_thrd_s: "threaded", pt_thrd_s: "threaded",
pt_thrd_l: ["use parallel processing","when browser permits"], pt_thrd_l: ["use parallel processing","when browser permits"],
pt_assy_s: "assembly",
pt_assy_l: ["use web assembly","when browser permits"],
xp_menu: "exports", xp_menu: "exports",