checkpoint prototype

This commit is contained in:
Stewart Allen 2023-01-09 14:55:17 -05:00
commit 849a55439b
12 changed files with 169 additions and 50 deletions

View file

@ -227,6 +227,12 @@ for (let i in AP) {
}); });
} }
Float32Array.prototype.toShared = function() {
const newvert = new Float32Array(new SharedArrayBuffer(this.buffer.byteLength));
newvert.set(this);
return newvert;
};
String.prototype.reverse = function() { String.prototype.reverse = function() {
return this.split('').reverse().join(''); return this.split('').reverse().join('');
}; };

View file

@ -82,7 +82,7 @@ kiri.load(api => {
if (!widget.tool) { if (!widget.tool) {
let tool = widget.tool = new mesh.tool(); let tool = widget.tool = new mesh.tool();
let translate = index ? true : false; let translate = index ? true : false;
tool.index(widget.getGeoVertices(true, translate)); tool.index(widget.getGeoVertices({ unroll: true, translate }));
} }
}; };

View file

@ -1136,7 +1136,7 @@ class OpPocket extends CamOp {
} }
} }
let surfaces = op.surfaces[widget.id] || []; let surfaces = op.surfaces[widget.id] || [];
let vert = widget.getGeoVertices(true,true).map(v => v.round(4)); let vert = widget.getGeoVertices({ unroll: true, translate: true }).map(v => v.round(4));
// let vert = widget.getVertices().array.map(v => v.round(4)); // let vert = widget.getVertices().array.map(v => v.round(4));
let outline = []; let outline = [];
let faces = CAM.surface_find(widget, surfaces); let faces = CAM.surface_find(widget, surfaces);

View file

@ -245,7 +245,7 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
tracker.rotation = isIndexed ? axisRotation : 0; tracker.rotation = isIndexed ? axisRotation : 0;
// setup new state when indexing the workspace // setup new state when indexing the workspace
if (true && op.op.type === "index") { if (true && op.op.type === "index") {
let points = base.verticesToPoints(widget.getGeoVertices(true, true)); let points = base.verticesToPoints(widget.getGeoVertices({ unroll: true, translate: true }));
state.slicer = new kiri.cam_slicer(points, { state.slicer = new kiri.cam_slicer(points, {
zlist: true, zlist: true,
zline: true zline: true

View file

@ -3,8 +3,10 @@
"use strict"; "use strict";
/** /**
* Slicing engine used by CAM * Slicing engine used by CAM Topo
*/ */
// dep: moto.broker
// dep: kiri.slice // dep: kiri.slice
gapp.register("kiri-mode.cam.slicer2", [], (root, exports) => { gapp.register("kiri-mode.cam.slicer2", [], (root, exports) => {
@ -13,6 +15,10 @@ const { config, newOrderedLine, newPoint } = base;
class Slicer { class Slicer {
static intersectPoints = intersectPoints;
static checkOverUnderOn = checkOverUnderOn;
static removeDuplicateLines = removeDuplicateLines;
constructor() { constructor() {
this.min = Infinity; this.min = Infinity;
this.max = -Infinity; this.max = -Infinity;
@ -311,9 +317,56 @@ function removeDuplicateLines(lines, debug) {
return output; return output;
} }
Slicer.checkOverUnderOn = checkOverUnderOn; moto.broker.subscribe("worker.started", msg => {
Slicer.intersectPoints = intersectPoints; const { dispatch, minions } = msg;
// console.log({ cam_slicer2_worker: dispatch });
kiri.topo_slice = async (widget, resolution) => {
console.log({ topo_slice: widget, resolution });
const vertices = widget.getGeoVertices().toShared();
const range = { min: Infinity, max: -Infinity };
for (let i=0,l=vertices.length; i<l; i += 3) {
const x = vertices[i];
const z = vertices[i + 2];
vertices[i] = z;
vertices[i + 2] = x;
range.min = Math.min(range.min, x);
range.max = Math.max(range.max, x);
}
// define sharded ranges
if (false && minions.concurrent) {
dispatch.putCache({ key: widget.id, data: vertices }, { done: data => {
console.log({ put_cache_done: data });
}});
kiri.cam_slicer2 = Slicer; dispatch.clearCache({}, { done: data => {
console.log({ clear_cache_done: data });
}});
return [];
} else {
console.time('nuslice');
// iterate over shards, merge output
const output = new Slicer()
.setFromArray(vertices)
.slice(resolution)
.map(rec => {
const slice = kiri.newSlice(rec.z);
slice.lines = rec.lines;
for (let line of rec.lines) {
const { p1, p2 } = line;
if (!p1.swapped) { p1.swapXZ(); p1.swapped = true }
if (!p2.swapped) { p2.swapXZ(); p2.swapped = true }
}
return slice;
});
console.log({ output });
console.timeEnd('nuslice');
return output;
}
};
});
moto.broker.subscribe("minion.started", funcs => {
// console.log({ cam_slicer2_minion: funcs });
});
}); });

View file

@ -439,7 +439,16 @@ class Topo {
ondone(newslices); ondone(newslices);
} }
let points = base.verticesToPoints(widget.getGeoVertices(true, true)); console.log('get vertices and points');
let points = base.verticesToPoints(widget.getGeoVertices({ unroll: true, translate: true }));
console.log('topo slice 2');
const slices2 = await kiri.topo_slice(widget, resolution);
console.log({ topo_slice_done: slices2 });
processSlices(slices2);
return this;
console.log('old slice setup')
let slicer = new kiri.cam_slicer(points, { let slicer = new kiri.cam_slicer(points, {
swapX: true, emptyok: true, notopok: true swapX: true, emptyok: true, notopok: true
}); });
@ -448,12 +457,15 @@ class Topo {
if (contourX) stepsTotal += Math.round((maxY-minY) / toolStep); if (contourX) stepsTotal += Math.round((maxY-minY) / toolStep);
if (contourY) stepsTotal += Math.round((maxX-minX) / toolStep); if (contourY) stepsTotal += Math.round((maxX-minX) / toolStep);
console.log('old slice run', stepsTotal)
let slices = topo.slices = topo.slices || slicer.slice(sindex, { each: (data, index, total) => { let slices = topo.slices = topo.slices || slicer.slice(sindex, { each: (data, index, total) => {
onupdate(++stepsTaken, stepsTotal, "topo slice"); onupdate(++stepsTaken, stepsTotal, "topo slice");
}, genso: true }); }, genso: true });
console.log('process slices', stepsTaken)
processSlices(slices.filter(s => s.lines).map(data => data.slice)); processSlices(slices.filter(s => s.lines).map(data => data.slice));
console.log('process done', stepsTaken)
// const t0 = Date.now(); // const t0 = Date.now();
// for (let point of points) point.swapXZ(); // for (let point of points) point.swapXZ();
// let lines = new kiri.cam_slicer2().setFromPoints(points).slice(resolution); // let lines = new kiri.cam_slicer2().setFromPoints(points).slice(resolution);

View file

@ -3,6 +3,7 @@
"use strict"; "use strict";
// dep: moto.license // dep: moto.license
// dep: moto.broker
// dep: geo.base // dep: geo.base
// dep: geo.polygons // dep: geo.polygons
// dep: geo.slicer // dep: geo.slicer
@ -10,6 +11,7 @@
// dep: kiri.codec // dep: kiri.codec
// dep: kiri-mode.fdm.post // dep: kiri-mode.fdm.post
// use: kiri-mode.cam.slicer // use: kiri-mode.cam.slicer
// dep: kiri-mode.cam.slicer2
// dep: ext.clip2 // dep: ext.clip2
gapp.register("kiri-run.minion", [], (root, exports) => { gapp.register("kiri-run.minion", [], (root, exports) => {
@ -22,8 +24,8 @@ const clib = self.ClipperLib;
const ctyp = clib.ClipType; const ctyp = clib.ClipType;
const ptyp = clib.PolyType; const ptyp = clib.PolyType;
const cfil = clib.PolyFillType; const cfil = clib.PolyFillType;
const cache = self.cache = {};
let cache = self.cache = {};
let name = "unknown"; let name = "unknown";
// catch clipper alerts and convert to console messages // catch clipper alerts and convert to console messages
@ -45,7 +47,7 @@ function log() {
console.log(`[${name}]`, ...arguments); console.log(`[${name}]`, ...arguments);
} }
const funcs = { const funcs = self.minion = {
label(data, seq) { label(data, seq) {
name = data.name; name = data.name;
}, },
@ -138,19 +140,20 @@ const funcs = {
}); });
}, },
camSetPoints: data => { putCache: msg => {
const points = new Float32Array(data.data); const { key, data } = msg;
let i = 0, p = 0, realp = new Array(points.length / 3); log({ minion_putCache: key, data });
while (i < points.length) { if (data) {
realp[p++] = base.newPoint(points[i++], points[i++], points[i++]).round(3); console.log({ minion_put_cache: key, data });
cache[key] = data;
} else {
console.log({ minion_del_cache: key });
delete cache[key];
} }
// log({ camSetPoints: points, realp });
cache.camPoints = realp;
}, },
camClearPoints: data => { clearCache: msg => {
// log({ camClearPoints: data }); cache = self.cache = [];
delete cache.camPoints;
}, },
wasm: data => { wasm: data => {
@ -166,4 +169,6 @@ const funcs = {
} }
}; };
moto.broker.publish("minion.started", funcs);
}); });

View file

@ -8,6 +8,7 @@
// dep: kiri.codec // dep: kiri.codec
// dep: kiri.slice // dep: kiri.slice
// dep: moto.license // dep: moto.license
// dep: moto.broker
// use: load.png // use: load.png
// use: ext.jszip // use: ext.jszip
// use: kiri.render // use: kiri.render
@ -230,19 +231,10 @@ kiri.minions = {
} }
}, },
wasm(enable) {
for (let minion of minions) {
minion.postMessage({
cmd: "wasm",
enable
});
}
},
broadcast(cmd, data, direct) { broadcast(cmd, data, direct) {
for (let minion of minions) { for (let minion of minions) {
minion.postMessage({ minion.postMessage({
cmd, data cmd, ...data
}, direct); }, direct);
} }
} }
@ -252,6 +244,7 @@ console.log(`kiri | init work | ${gapp.version || "rogue"}`);
// code is running in the worker / server context // code is running in the worker / server context
const dispatch = const dispatch =
self.worker =
kiri.server = kiri.server =
kiri.worker = { kiri.worker = {
pool_start(data, send) { pool_start(data, send) {
@ -326,8 +319,11 @@ kiri.worker = {
group.id = data.group; group.id = data.group;
wgroup[data.group] = group; wgroup[data.group] = group;
} }
let vertices = new Float32Array(data.vertices),
widget = kiri.newWidget(data.id, group).loadVertices(vertices).setInWorker(); let vertices = data.vertices,
widget = kiri.newWidget(data.id, group)
.setInWorker()
.loadVertices(vertices);
// do it here so cancel can work // do it here so cancel can work
wcache[data.id] = widget; wcache[data.id] = widget;
@ -623,8 +619,26 @@ kiri.worker = {
} else { } else {
wasm_ctrl.disable(); wasm_ctrl.disable();
} }
minwork.wasm(data.enable); minwork.broadcast("wasm", { enable: data.enable ? true : false });
send.done({ wasm: data }); send.done({ wasm: data });
},
putCache(msg, send) {
const { key, data } = msg;
console.log({ worker_putCache: key, data });
if (data) {
pcache[key] = data;
} else {
delete pcache[key];
}
minwork.broadcast("putCache", msg);
send.done({ ok: true });
},
clearCache(msg, send) {
pcache = {};
minwork.broadcast("clearCache", msg);
send.done({ ok: true });
} }
}; };
@ -686,6 +700,8 @@ dispatch.onmessage = self.onmessage = function(e) {
} }
}; };
moto.broker.publish("worker.started", { dispatch, minions: minwork });
}); });
// load kiri modules // load kiri modules

View file

@ -18,6 +18,7 @@ let loc = self.location,
syncd = {}, syncd = {},
running = {}, running = {},
worker = null, worker = null,
minions = false,
restarting = false restarting = false
// occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}), // occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}),
; ;
@ -56,10 +57,12 @@ const client = exports({
pool: { pool: {
start() { start() {
minions = true;
send("pool_start", {}, noop); send("pool_start", {}, noop);
}, },
stop() { stop() {
minions = false;
send("pool_stop", {}, noop); send("pool_stop", {}, noop);
} }
}, },
@ -126,6 +129,11 @@ const client = exports({
} }
}; };
// restart minions if they were running
if (minions) {
client.pool.start();
}
restarting = false; restarting = false;
}, },
@ -166,7 +174,7 @@ const client = exports({
widgets.forEach(widget => { widgets.forEach(widget => {
if (widget.modified || !syncd[widget.id]) { if (widget.modified || !syncd[widget.id]) {
syncd[widget.id] = true; syncd[widget.id] = true;
let vertices = widget.getGeoVertices().buffer.slice(0); let vertices = widget.getGeoVertices();
send("sync", { send("sync", {
id: widget.id, id: widget.id,
meta: widget.meta, meta: widget.meta,
@ -176,7 +184,7 @@ const client = exports({
position: widget.mesh.position, position: widget.mesh.position,
}, done => { }, done => {
widget.modified = false; widget.modified = false;
}, [vertices]); });
} }
}); });
}, },
@ -303,6 +311,19 @@ const client = exports({
send("wasm", {enable}, reply => { send("wasm", {enable}, reply => {
// console.log({wasm_worker_said: reply}); // console.log({wasm_worker_said: reply});
}); });
},
putCache(key, data) {
console.log({ putCache: key, data });
send("putCache", {key, data}, reply => {
// console.log({ putCache_reply: reply });
});
},
clearCache() {
send("clearCache", {}, reply => {
// console.log({ clearCache_reply: reply });
});
} }
}); });

View file

@ -73,6 +73,8 @@ class Files {
* @param {Function} [callback] * @param {Function} [callback]
*/ */
putFile(name, vertices, callback) { putFile(name, vertices, callback) {
console.log({ putFile: name, vertices });
let mark = Date.now(); let mark = Date.now();
let store = this; let store = this;
let pdb = store.db.promise(); let pdb = store.db.promise();

View file

@ -104,7 +104,7 @@ class Widget {
} }
const widget = this; const widget = this;
const mark = time(); const mark = time();
const vertices = this.getGeoVertices(true); const vertices = widget.getGeoVertices({ unroll: true }).slice();
widget.meta.file = filename; widget.meta.file = filename;
widget.meta.save = mark; widget.meta.save = mark;
catalog().putFile(filename, vertices, () => { catalog().putFile(filename, vertices, () => {
@ -123,8 +123,9 @@ class Widget {
return; return;
} }
const widget = this; const widget = this;
console.log({ saveState: widget.id });
index().put('ws-save-'+this.id, { index().put('ws-save-'+this.id, {
geo: widget.getGeoVertices(false), geo: widget.getGeoVertices({ unroll: false }).slice(),
track: widget.track, track: widget.track,
group: this.group.id, group: this.group.id,
meta: this.meta, meta: this.meta,
@ -152,6 +153,7 @@ class Widget {
* @returns {Widget} * @returns {Widget}
*/ */
loadVertices(data, options = { index: false }) { loadVertices(data, options = { index: false }) {
// console.log({ loadVertices: this.id, worker: this.inWorker, data });
let vertices, let vertices,
autoscale = false; autoscale = false;
if (ArrayBuffer.isView(data) || typeof(data) != 'object') { if (ArrayBuffer.isView(data) || typeof(data) != 'object') {
@ -160,12 +162,12 @@ class Widget {
vertices = data.vertices; vertices = data.vertices;
throw "deprecated vertex data format"; throw "deprecated vertex data format";
} }
// will not serialize into indexeddb -- need a performance sensitive workaround if (!(vertices.buffer && vertices.buffer instanceof SharedArrayBuffer)) {
// if (window.SharedArrayBuffer) { // console.log('converting to shared vertices');
// let newvert = new Float32Array(new SharedArrayBuffer(vertices.buffer.byteLength)); let newvert = new Float32Array(new SharedArrayBuffer(vertices.buffer.byteLength));
// newvert.set(vertices); newvert.set(vertices);
// vertices = newvert; vertices = newvert;
// } }
switch (typeof(autoscale)) { switch (typeof(autoscale)) {
case 'boolean': case 'boolean':
autoscale = options; autoscale = options;
@ -610,7 +612,8 @@ class Widget {
this.points = null; this.points = null;
} }
getGeoVertices(unroll, translate) { getGeoVertices(opt = {}) {
const { unroll, translate } = opt;
let geo = this.mesh.geometry; let geo = this.mesh.geometry;
let pos = geo.getAttribute('position'); let pos = geo.getAttribute('position');
// if indexed, return points rotated about X and then offset // if indexed, return points rotated about X and then offset

View file

@ -39,7 +39,7 @@ class Broker {
for (let t of topic) { for (let t of topic) {
this.subscribe(t, listener); this.subscribe(t, listener);
} }
return; return this;
} }
if (typeof topic !== 'string') { if (typeof topic !== 'string') {
console.trace({invalid_topic: topic}); console.trace({invalid_topic: topic});
@ -57,6 +57,7 @@ class Broker {
channel.push(listener); channel.push(listener);
this.publish(".topic.add", topic); this.publish(".topic.add", topic);
} }
return this;
} }
unsubscribe(topic, listener) { unsubscribe(topic, listener) {