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() {
return this.split('').reverse().join('');
};

View file

@ -82,7 +82,7 @@ kiri.load(api => {
if (!widget.tool) {
let tool = widget.tool = new mesh.tool();
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 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 outline = [];
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;
// setup new state when indexing the workspace
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, {
zlist: true,
zline: true

View file

@ -3,8 +3,10 @@
"use strict";
/**
* Slicing engine used by CAM
* Slicing engine used by CAM Topo
*/
// dep: moto.broker
// dep: kiri.slice
gapp.register("kiri-mode.cam.slicer2", [], (root, exports) => {
@ -13,6 +15,10 @@ const { config, newOrderedLine, newPoint } = base;
class Slicer {
static intersectPoints = intersectPoints;
static checkOverUnderOn = checkOverUnderOn;
static removeDuplicateLines = removeDuplicateLines;
constructor() {
this.min = Infinity;
this.max = -Infinity;
@ -80,13 +86,13 @@ class Slicer {
const zMax = this.max;
const phash = {};
const lines = [];
let { under, over, both } = options;
let p1, p2, p3;
// default to 'over' selection with 2 points on a line
if (!under && !both) over = true;
// iterate over matching buckets for this z offset
for (let i = 0; i < points.length; ) {
p1 = points[i++];
@ -127,11 +133,11 @@ class Slicer {
}
}
}
if (lines.length == 0 && options.noEmpty) {
return;
}
return removeDuplicateLines(lines);
}
@ -311,9 +317,56 @@ function removeDuplicateLines(lines, debug) {
return output;
}
Slicer.checkOverUnderOn = checkOverUnderOn;
Slicer.intersectPoints = intersectPoints;
moto.broker.subscribe("worker.started", msg => {
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);
}
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, {
swapX: true, emptyok: true, notopok: true
});
@ -448,12 +457,15 @@ class Topo {
if (contourX) stepsTotal += Math.round((maxY-minY) / 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) => {
onupdate(++stepsTaken, stepsTotal, "topo slice");
}, genso: true });
console.log('process slices', stepsTaken)
processSlices(slices.filter(s => s.lines).map(data => data.slice));
console.log('process done', stepsTaken)
// const t0 = Date.now();
// for (let point of points) point.swapXZ();
// let lines = new kiri.cam_slicer2().setFromPoints(points).slice(resolution);

View file

@ -3,6 +3,7 @@
"use strict";
// dep: moto.license
// dep: moto.broker
// dep: geo.base
// dep: geo.polygons
// dep: geo.slicer
@ -10,6 +11,7 @@
// dep: kiri.codec
// dep: kiri-mode.fdm.post
// use: kiri-mode.cam.slicer
// dep: kiri-mode.cam.slicer2
// dep: ext.clip2
gapp.register("kiri-run.minion", [], (root, exports) => {
@ -22,8 +24,8 @@ const clib = self.ClipperLib;
const ctyp = clib.ClipType;
const ptyp = clib.PolyType;
const cfil = clib.PolyFillType;
const cache = self.cache = {};
let cache = self.cache = {};
let name = "unknown";
// catch clipper alerts and convert to console messages
@ -45,7 +47,7 @@ function log() {
console.log(`[${name}]`, ...arguments);
}
const funcs = {
const funcs = self.minion = {
label(data, seq) {
name = data.name;
},
@ -138,19 +140,20 @@ const funcs = {
});
},
camSetPoints: data => {
const points = new Float32Array(data.data);
let i = 0, p = 0, realp = new Array(points.length / 3);
while (i < points.length) {
realp[p++] = base.newPoint(points[i++], points[i++], points[i++]).round(3);
putCache: msg => {
const { key, data } = msg;
log({ minion_putCache: key, data });
if (data) {
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 => {
// log({ camClearPoints: data });
delete cache.camPoints;
clearCache: msg => {
cache = self.cache = [];
},
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.slice
// dep: moto.license
// dep: moto.broker
// use: load.png
// use: ext.jszip
// 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) {
for (let minion of minions) {
minion.postMessage({
cmd, data
cmd, ...data
}, direct);
}
}
@ -252,6 +244,7 @@ console.log(`kiri | init work | ${gapp.version || "rogue"}`);
// code is running in the worker / server context
const dispatch =
self.worker =
kiri.server =
kiri.worker = {
pool_start(data, send) {
@ -326,8 +319,11 @@ kiri.worker = {
group.id = data.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
wcache[data.id] = widget;
@ -623,8 +619,26 @@ kiri.worker = {
} else {
wasm_ctrl.disable();
}
minwork.wasm(data.enable);
minwork.broadcast("wasm", { enable: data.enable ? true : false });
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

View file

@ -18,6 +18,7 @@ let loc = self.location,
syncd = {},
running = {},
worker = null,
minions = false,
restarting = false
// occ = new Worker("/kiri/ext/occ-worker.js", {type:"module"}),
;
@ -56,10 +57,12 @@ const client = exports({
pool: {
start() {
minions = true;
send("pool_start", {}, noop);
},
stop() {
minions = false;
send("pool_stop", {}, noop);
}
},
@ -126,6 +129,11 @@ const client = exports({
}
};
// restart minions if they were running
if (minions) {
client.pool.start();
}
restarting = false;
},
@ -166,7 +174,7 @@ const client = exports({
widgets.forEach(widget => {
if (widget.modified || !syncd[widget.id]) {
syncd[widget.id] = true;
let vertices = widget.getGeoVertices().buffer.slice(0);
let vertices = widget.getGeoVertices();
send("sync", {
id: widget.id,
meta: widget.meta,
@ -176,7 +184,7 @@ const client = exports({
position: widget.mesh.position,
}, done => {
widget.modified = false;
}, [vertices]);
});
}
});
},
@ -303,6 +311,19 @@ const client = exports({
send("wasm", {enable}, 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]
*/
putFile(name, vertices, callback) {
console.log({ putFile: name, vertices });
let mark = Date.now();
let store = this;
let pdb = store.db.promise();

View file

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

View file

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