update sla driver code format
This commit is contained in:
parent
e22fe7d483
commit
ce031cdd84
7 changed files with 1843 additions and 1820 deletions
2
app.js
2
app.js
|
|
@ -432,6 +432,7 @@ const script = {
|
||||||
"kiri/pack",
|
"kiri/pack",
|
||||||
"kiri/utils",
|
"kiri/utils",
|
||||||
"kiri/slice",
|
"kiri/slice",
|
||||||
|
"kiri/print",
|
||||||
"kiri/layers",
|
"kiri/layers",
|
||||||
"kiri-mode/fdm/fill",
|
"kiri-mode/fdm/fill",
|
||||||
"kiri-mode/fdm/driver",
|
"kiri-mode/fdm/driver",
|
||||||
|
|
@ -454,7 +455,6 @@ const script = {
|
||||||
"kiri-mode/cam/animate",
|
"kiri-mode/cam/animate",
|
||||||
"kiri-mode/laser/driver",
|
"kiri-mode/laser/driver",
|
||||||
"kiri/widget",
|
"kiri/widget",
|
||||||
"kiri/print",
|
|
||||||
"kiri/codec",
|
"kiri/codec",
|
||||||
"kiri/worker"
|
"kiri/worker"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -2,94 +2,101 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
// dep: geo.base
|
||||||
|
// dep: kiri-mode.sla.driver
|
||||||
|
gapp.register("kiri-mode.sla.client", [], (root, exports) => {
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const { base, kiri } = root;
|
||||||
BASE = self.base,
|
const { driver } = kiri;
|
||||||
UTIL = BASE.util,
|
const { util } = base;
|
||||||
SLA = KIRI.driver.SLA;
|
const { SLA } = driver;
|
||||||
|
|
||||||
SLA.init = function(kiri, api) {
|
gapp.overlay(SLA, {
|
||||||
api.event.on("mode.set", (mode) => {
|
init,
|
||||||
if (mode === 'SLA') {
|
printDownload
|
||||||
api.ui.func.preview.classList.add('hide');
|
});
|
||||||
} else {
|
|
||||||
api.ui.func.preview.classList.remove('hide');
|
function init(kiri, api) {
|
||||||
|
api.event.on("mode.set", (mode) => {
|
||||||
|
if (mode === 'SLA') {
|
||||||
|
api.ui.func.preview.classList.add('hide');
|
||||||
|
} else {
|
||||||
|
api.ui.func.preview.classList.remove('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function printDownload(output, api, names) {
|
||||||
|
const { file, width, height, layers, volume } = output;
|
||||||
|
const fileroot = names[0] || "print";
|
||||||
|
const filename = `${fileroot}-${new Date().getTime().toString(36)}`;
|
||||||
|
|
||||||
|
api.ajax("/kiri/output-sla.html", html => {
|
||||||
|
api.ui.print.innerHTML = html;
|
||||||
|
|
||||||
|
let settings = api.conf.get(),
|
||||||
|
process = settings.process,
|
||||||
|
device = settings.device,
|
||||||
|
print_sec = (process.slaBaseLayers * process.slaBaseOn) +
|
||||||
|
(layers - process.slaBaseLayers) * process.slaLayerOn;
|
||||||
|
|
||||||
|
// add peel lift/drop times to total print time
|
||||||
|
for (let i=0; i<layers; i++) {
|
||||||
|
let dist = process.slaPeelDist,
|
||||||
|
lift = process.slaPeelLiftRate,
|
||||||
|
drop = process.slaPeelDropRate,
|
||||||
|
off = process.slaLayerOff;
|
||||||
|
if (i < process.slaBaseLayers) {
|
||||||
|
dist = process.slaBasePeelDist;
|
||||||
|
lift = process.slaBasePeelLiftRate;
|
||||||
|
off = process.slaBaseOff;
|
||||||
}
|
}
|
||||||
});
|
print_sec += (dist * lift) / 60;
|
||||||
};
|
print_sec += (dist * drop) / 60;
|
||||||
|
print_sec += off;
|
||||||
|
}
|
||||||
|
|
||||||
SLA.printDownload = function(output, API, names) {
|
let print_min = Math.floor(print_sec/60),
|
||||||
const { file, width, height, layers, volume } = output;
|
print_hrs = Math.floor(print_min/60),
|
||||||
const fileroot = names[0] || "print";
|
download = $('print-sla');
|
||||||
const filename = `${fileroot}-${new Date().getTime().toString(36)}`;
|
|
||||||
|
|
||||||
API.ajax("/kiri/output-sla.html", html => {
|
// add lift/drop time
|
||||||
API.ui.print.innerHTML = html;
|
print_sec -= (print_min * 60);
|
||||||
|
print_min -= (print_hrs * 60);
|
||||||
|
print_sec = Math.round(print_sec).toString().padStart(2,'0');
|
||||||
|
print_min = print_min.toString().padStart(2,'0');
|
||||||
|
print_hrs = print_hrs.toString().padStart(2,'0');
|
||||||
|
|
||||||
let settings = API.conf.get(),
|
$('print-filename').value = filename;
|
||||||
process = settings.process,
|
$('print-volume').value = (volume/1000).round(2);
|
||||||
device = settings.device,
|
$('print-layers').value = layers;
|
||||||
print_sec = (process.slaBaseLayers * process.slaBaseOn) +
|
$('print-time').value = `${print_hrs}:${print_min}:${print_sec}`;
|
||||||
(layers - process.slaBaseLayers) * process.slaLayerOn;
|
|
||||||
|
|
||||||
// add peel lift/drop times to total print time
|
switch (device.deviceName) {
|
||||||
for (let i=0; i<layers; i++) {
|
case 'Anycubic.Photon':
|
||||||
let dist = process.slaPeelDist,
|
download.innerText += " .photon";
|
||||||
lift = process.slaPeelLiftRate,
|
download.onclick = () => { saveFile(api, file, ".photon") };
|
||||||
drop = process.slaPeelDropRate,
|
break;
|
||||||
off = process.slaLayerOff;
|
case 'Anycubic.Photon.S':
|
||||||
if (i < process.slaBaseLayers) {
|
download.innerText += " .photons";
|
||||||
dist = process.slaBasePeelDist;
|
download.onclick = () => { saveFile(api, file, ".photons") };
|
||||||
lift = process.slaBasePeelLiftRate;
|
break;
|
||||||
off = process.slaBaseOff;
|
case 'Creality.Halot.Sky':
|
||||||
}
|
default:
|
||||||
print_sec += (dist * lift) / 60;
|
download.innerText += " .cxdlp";
|
||||||
print_sec += (dist * drop) / 60;
|
download.onclick = () => { saveFile(api, file, ".cxdlp") };
|
||||||
print_sec += off;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let print_min = Math.floor(print_sec/60),
|
api.modal.show('print');
|
||||||
print_hrs = Math.floor(print_min/60),
|
});
|
||||||
download = $('print-sla');
|
}
|
||||||
|
|
||||||
// add lift/drop time
|
function saveFile(api, file, ext) {
|
||||||
print_sec -= (print_min * 60);
|
saveAs(
|
||||||
print_min -= (print_hrs * 60);
|
new Blob([file], { type: "application/octet-stream" }),
|
||||||
print_sec = Math.round(print_sec).toString().padStart(2,'0');
|
$('print-filename').value + ext);
|
||||||
print_min = print_min.toString().padStart(2,'0');
|
api.modal.hide();
|
||||||
print_hrs = print_hrs.toString().padStart(2,'0');
|
}
|
||||||
|
|
||||||
$('print-filename').value = filename;
|
});
|
||||||
$('print-volume').value = (volume/1000).round(2);
|
|
||||||
$('print-layers').value = layers;
|
|
||||||
$('print-time').value = `${print_hrs}:${print_min}:${print_sec}`;
|
|
||||||
|
|
||||||
switch (device.deviceName) {
|
|
||||||
case 'Anycubic.Photon':
|
|
||||||
download.innerText += " .photon";
|
|
||||||
download.onclick = () => { saveFile(API, file, ".photon") };
|
|
||||||
break;
|
|
||||||
case 'Anycubic.Photon.S':
|
|
||||||
download.innerText += " .photons";
|
|
||||||
download.onclick = () => { saveFile(API, file, ".photons") };
|
|
||||||
break;
|
|
||||||
case 'Creality.Halot.Sky':
|
|
||||||
default:
|
|
||||||
download.innerText += " .cxdlp";
|
|
||||||
download.onclick = () => { saveFile(API, file, ".cxdlp") };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
API.modal.show('print');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveFile(API, file, ext) {
|
|
||||||
saveAs(
|
|
||||||
new Blob([file], { type: "application/octet-stream" }),
|
|
||||||
$('print-filename').value + ext);
|
|
||||||
API.modal.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
|
||||||
|
|
@ -2,48 +2,48 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
// use: kiri.print
|
||||||
|
// use: kiri.worker
|
||||||
|
gapp.register("kiri-mode.sla.driver", [], (root, exports) => {
|
||||||
|
|
||||||
if (!self.kiri.driver) self.kiri.driver = { };
|
const { kiri } = root
|
||||||
if (self.kiri.driver.SLA) return;
|
const { driver } = kiri;
|
||||||
|
|
||||||
const KIRI = self.kiri,
|
const SLA = driver.SLA = {
|
||||||
SLA = KIRI.driver.SLA = {
|
prepare,
|
||||||
// init, // src/mode/sla/client.js
|
legacy: false
|
||||||
// slice, // src/mode/sla/slice.js
|
};
|
||||||
prepare,
|
|
||||||
// export, // src/mode/sla/export.js
|
|
||||||
// printDownload, // src/mode/sla/client.js
|
|
||||||
legacy: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (SLA.legacy) console.log("SLA Driver in Legacy Mode");
|
if (SLA.legacy) {
|
||||||
|
console.log("SLA Driver in Legacy Mode");
|
||||||
|
}
|
||||||
|
|
||||||
// runs in worker. would usually be in src/mode/sla/prepare.js
|
// runs in worker. would usually be in src/mode/sla/prepare.js
|
||||||
function prepare(widgets, settings, update) {
|
// but the SLA driver skips the prepare step because there is no path routing
|
||||||
self.worker.print = KIRI.newPrint(settings, widgets);
|
function prepare(widgets, settings, update) {
|
||||||
if (!SLA.wasm) {
|
root.worker.print = kiri.newPrint(settings, widgets);
|
||||||
fetch('/wasm/kiri-sla.wasm')
|
if (!SLA.wasm) {
|
||||||
.then(response => response.arrayBuffer())
|
fetch('/wasm/kiri-sla.wasm')
|
||||||
.then(bytes => WebAssembly.instantiate(bytes, {
|
.then(response => response.arrayBuffer())
|
||||||
env: {
|
.then(bytes => WebAssembly.instantiate(bytes, {
|
||||||
reportf: (a,b) => { console.log('[f]',a,b) },
|
env: {
|
||||||
reporti: (a,b) => { console.log('[i]',a,b) }
|
reportf: (a,b) => { console.log('[f]',a,b) },
|
||||||
}
|
reporti: (a,b) => { console.log('[i]',a,b) }
|
||||||
}))
|
}
|
||||||
.then(results => {
|
}))
|
||||||
let {module, instance} = results;
|
.then(results => {
|
||||||
let {exports} = instance;
|
let {module, instance} = results;
|
||||||
let heap = new Uint8Array(exports.memory.buffer);
|
let {exports} = instance;
|
||||||
SLA.wasm = {
|
let heap = new Uint8Array(exports.memory.buffer);
|
||||||
heap,
|
SLA.wasm = {
|
||||||
memory: exports.memory,
|
heap,
|
||||||
render: exports.render,
|
memory: exports.memory,
|
||||||
rle_encode: exports.rle_encode
|
render: exports.render,
|
||||||
};
|
rle_encode: exports.rle_encode
|
||||||
});
|
};
|
||||||
}
|
});
|
||||||
update(1);
|
|
||||||
}
|
}
|
||||||
|
update(1);
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,169 +2,173 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
// dep: geo.base
|
||||||
|
// dep: kiri-mode.sla.driver
|
||||||
|
// dep: kiri-mode.sla.x_cxdlp
|
||||||
|
// dep: kiri-mode.sla.x_photons
|
||||||
|
gapp.register("kiri-mode.sla.export", [], (root, exports) => {
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const { base, kiri } = root
|
||||||
BASE = self.base,
|
const { driver } = kiri;
|
||||||
UTIL = BASE.util,
|
const { util } = base;
|
||||||
SLA = KIRI.driver.SLA;
|
const { SLA } = driver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRIVER PRINT CONTRACT - runs in worker
|
* DRIVER CONTRACT - runs in worker
|
||||||
* @param {Object} print state object
|
* @param {Object} print state object
|
||||||
* @param {Function} online streaming reply
|
* @param {Function} online streaming reply
|
||||||
* @param {Function} ondone last reply
|
* @param {Function} ondone last reply
|
||||||
*/
|
*/
|
||||||
SLA.export = function(print, online, ondone) {
|
SLA.export = function(print, online, ondone) {
|
||||||
let widgets = print.widgets,
|
let widgets = print.widgets,
|
||||||
settings = print.settings,
|
settings = print.settings,
|
||||||
device = settings.device,
|
device = settings.device,
|
||||||
process = settings.process,
|
process = settings.process,
|
||||||
width = device.resolutionX,
|
width = device.resolutionX,
|
||||||
height = device.resolutionY,
|
height = device.resolutionY,
|
||||||
scaleX = width / device.bedWidth,
|
scaleX = width / device.bedWidth,
|
||||||
scaleY = height / device.bedDepth,
|
scaleY = height / device.bedDepth,
|
||||||
layerZ = process.slaSlice,
|
layerZ = process.slaSlice,
|
||||||
alias = process.slaAntiAlias || 1,
|
alias = process.slaAntiAlias || 1,
|
||||||
mark = Date.now(),
|
mark = Date.now(),
|
||||||
layermax = 0,
|
layermax = 0,
|
||||||
volume = 0;
|
volume = 0;
|
||||||
|
|
||||||
// filter ignored widgets
|
// filter ignored widgets
|
||||||
widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled);
|
widgets = widgets.filter(w => !w.track.ignore && !w.meta.disabled);
|
||||||
|
|
||||||
// find max layer count
|
// find max layer count
|
||||||
widgets.forEach(widget => {
|
widgets.forEach(widget => {
|
||||||
layermax = Math.max(widget.slices.length);
|
layermax = Math.max(widget.slices.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
let isPhoton = false;
|
let isPhoton = false;
|
||||||
|
|
||||||
switch (device.deviceName) {
|
switch (device.deviceName) {
|
||||||
case 'Anycubic.Photon':
|
case 'Anycubic.Photon':
|
||||||
case 'Anycubic.Photon.S':
|
case 'Anycubic.Photon.S':
|
||||||
isPhoton = true;
|
isPhoton = true;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (isPhoton) {
|
|
||||||
let legacyMode = SLA.legacy || alias > 1,
|
|
||||||
part1 = legacyMode ? 0.25 : 0.85,
|
|
||||||
part2 = (1 - part1),
|
|
||||||
images = [],
|
|
||||||
slices = [];
|
|
||||||
|
|
||||||
// generate layer bitmaps
|
|
||||||
// in wasm mode, rle layers generated here, too
|
|
||||||
let d = 8 / alias;
|
|
||||||
let masks = [];
|
|
||||||
for (let i=0; i<alias; i++) {
|
|
||||||
masks.push((1 << (8 - i * d)) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let render = legacyMode ? photon.renderLayer : photon.renderLayerWasm;
|
|
||||||
|
|
||||||
for (let index=0; index < layermax; index++) {
|
|
||||||
let param = { index, width, height, widgets, scaleX, scaleY, masks };
|
|
||||||
let { image, layers, end, area } = render(param);
|
|
||||||
volume += (area * layerZ);
|
|
||||||
images.push(image);
|
|
||||||
slices.push(layers);
|
|
||||||
online({
|
|
||||||
progress: (index / layermax) * part1,
|
|
||||||
message: "image_gen",
|
|
||||||
});
|
|
||||||
if (end) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let exp_func = {
|
|
||||||
'Anycubic.Photon': photon.generatePhoton,
|
|
||||||
'Anycubic.Photon.S': photon.generatePhotons,
|
|
||||||
}[device.deviceName] || photon.generatePhoton;
|
|
||||||
|
|
||||||
let file = exp_func(print, {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
small: SLA.previewSmall.data,
|
|
||||||
large: SLA.previewLarge.data,
|
|
||||||
lines: images,
|
|
||||||
slices: slices
|
|
||||||
}, (progress, message) => {
|
|
||||||
online({progress: progress * part2 + part1, message});
|
|
||||||
});
|
|
||||||
ondone({ width, height, file, layers: images.length, volume }, [file]);
|
|
||||||
} else {
|
|
||||||
let part1 = 0.95;
|
|
||||||
let part2 = 1 - part1;
|
|
||||||
let slices = [];
|
|
||||||
|
|
||||||
for (let index=0; index < layermax; index++) {
|
|
||||||
let param = { index, width, height, widgets, scaleX, scaleY };
|
|
||||||
let { lines, area } = CXDLP.render(param);
|
|
||||||
volume += (area * layerZ);
|
|
||||||
slices.push(lines);
|
|
||||||
online({
|
|
||||||
progress: (index / layermax) * part1,
|
|
||||||
message: "image_gen"
|
|
||||||
});
|
|
||||||
// bail on an empty layer
|
|
||||||
if (lines.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate thumb, preview1, preview2
|
|
||||||
let thumb = [];
|
|
||||||
let tdata = SLA.previewSmall.data;
|
|
||||||
for (let x=0; x<116; x++) {
|
|
||||||
for (let y=0; y<116; y++) {
|
|
||||||
let p = (x * 116 + y) * 4;
|
|
||||||
let r = (tdata[p + 0] >> 3) << 11;
|
|
||||||
let g = (tdata[p + 1] >> 2) << 5;
|
|
||||||
let b = (tdata[p + 2] >> 3);
|
|
||||||
let v = (r | g | b) & 0xffff;
|
|
||||||
thumb.push((v >> 8) & 0xff);
|
|
||||||
thumb.push(v & 0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let preview1 = [];
|
|
||||||
let pdata = SLA.previewLarge.data;
|
|
||||||
for (let x=0; x<290; x++) {
|
|
||||||
for (let y=0; y<290; y++) {
|
|
||||||
let p = (x * 290 + y) * 4;
|
|
||||||
let r = (pdata[p + 0] >> 3) << 11;
|
|
||||||
let g = (pdata[p + 1] >> 2) << 5;
|
|
||||||
let b = (pdata[p + 2] >> 3);
|
|
||||||
let v = (r | g | b) & 0xffff;
|
|
||||||
preview1.push((v >> 8) & 0xff);
|
|
||||||
preview1.push(v & 0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let preview2 = preview1;
|
|
||||||
|
|
||||||
let file = CXDLP.export({
|
|
||||||
settings,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
slices,
|
|
||||||
thumb,
|
|
||||||
preview1,
|
|
||||||
preview2
|
|
||||||
});
|
|
||||||
ondone({
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
file: file,
|
|
||||||
layers: slices.length,
|
|
||||||
volume
|
|
||||||
}, [file]);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('print.export', Date.now() - mark);
|
|
||||||
};
|
|
||||||
|
|
||||||
function generateCXDLP(print, conf, progress) {
|
|
||||||
console.log({generateCXDLP: print, conf, progress});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
if (isPhoton) {
|
||||||
|
let legacyMode = SLA.legacy || alias > 1,
|
||||||
|
part1 = legacyMode ? 0.25 : 0.85,
|
||||||
|
part2 = (1 - part1),
|
||||||
|
images = [],
|
||||||
|
slices = [];
|
||||||
|
|
||||||
|
// generate layer bitmaps
|
||||||
|
// in wasm mode, rle layers generated here, too
|
||||||
|
let d = 8 / alias;
|
||||||
|
let masks = [];
|
||||||
|
for (let i=0; i<alias; i++) {
|
||||||
|
masks.push((1 << (8 - i * d)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let render = legacyMode ? photon.renderLayer : photon.renderLayerWasm;
|
||||||
|
|
||||||
|
for (let index=0; index < layermax; index++) {
|
||||||
|
let param = { index, width, height, widgets, scaleX, scaleY, masks };
|
||||||
|
let { image, layers, end, area } = render(param);
|
||||||
|
volume += (area * layerZ);
|
||||||
|
images.push(image);
|
||||||
|
slices.push(layers);
|
||||||
|
online({
|
||||||
|
progress: (index / layermax) * part1,
|
||||||
|
message: "image_gen",
|
||||||
|
});
|
||||||
|
if (end) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let exp_func = {
|
||||||
|
'Anycubic.Photon': photon.generatePhoton,
|
||||||
|
'Anycubic.Photon.S': photon.generatePhotons,
|
||||||
|
}[device.deviceName] || photon.generatePhoton;
|
||||||
|
|
||||||
|
let file = exp_func(print, {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
small: SLA.previewSmall.data,
|
||||||
|
large: SLA.previewLarge.data,
|
||||||
|
lines: images,
|
||||||
|
slices: slices
|
||||||
|
}, (progress, message) => {
|
||||||
|
online({progress: progress * part2 + part1, message});
|
||||||
|
});
|
||||||
|
ondone({ width, height, file, layers: images.length, volume }, [file]);
|
||||||
|
} else {
|
||||||
|
let part1 = 0.95;
|
||||||
|
let part2 = 1 - part1;
|
||||||
|
let slices = [];
|
||||||
|
|
||||||
|
for (let index=0; index < layermax; index++) {
|
||||||
|
let param = { index, width, height, widgets, scaleX, scaleY };
|
||||||
|
let { lines, area } = CXDLP.render(param);
|
||||||
|
volume += (area * layerZ);
|
||||||
|
slices.push(lines);
|
||||||
|
online({
|
||||||
|
progress: (index / layermax) * part1,
|
||||||
|
message: "image_gen"
|
||||||
|
});
|
||||||
|
// bail on an empty layer
|
||||||
|
if (lines.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate thumb, preview1, preview2
|
||||||
|
let thumb = [];
|
||||||
|
let tdata = SLA.previewSmall.data;
|
||||||
|
for (let x=0; x<116; x++) {
|
||||||
|
for (let y=0; y<116; y++) {
|
||||||
|
let p = (x * 116 + y) * 4;
|
||||||
|
let r = (tdata[p + 0] >> 3) << 11;
|
||||||
|
let g = (tdata[p + 1] >> 2) << 5;
|
||||||
|
let b = (tdata[p + 2] >> 3);
|
||||||
|
let v = (r | g | b) & 0xffff;
|
||||||
|
thumb.push((v >> 8) & 0xff);
|
||||||
|
thumb.push(v & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let preview1 = [];
|
||||||
|
let pdata = SLA.previewLarge.data;
|
||||||
|
for (let x=0; x<290; x++) {
|
||||||
|
for (let y=0; y<290; y++) {
|
||||||
|
let p = (x * 290 + y) * 4;
|
||||||
|
let r = (pdata[p + 0] >> 3) << 11;
|
||||||
|
let g = (pdata[p + 1] >> 2) << 5;
|
||||||
|
let b = (pdata[p + 2] >> 3);
|
||||||
|
let v = (r | g | b) & 0xffff;
|
||||||
|
preview1.push((v >> 8) & 0xff);
|
||||||
|
preview1.push(v & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let preview2 = preview1;
|
||||||
|
|
||||||
|
let file = CXDLP.export({
|
||||||
|
settings,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
slices,
|
||||||
|
thumb,
|
||||||
|
preview1,
|
||||||
|
preview2
|
||||||
|
});
|
||||||
|
ondone({
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
file: file,
|
||||||
|
layers: slices.length,
|
||||||
|
volume
|
||||||
|
}, [file]);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('print.export', Date.now() - mark);
|
||||||
|
};
|
||||||
|
|
||||||
|
function generateCXDLP(print, conf, progress) {
|
||||||
|
console.log({generateCXDLP: print, conf, progress});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,450 +1,455 @@
|
||||||
(function() {
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
const default_values = {
|
"use strict";
|
||||||
magic1: 'CXSW3DV2',
|
|
||||||
magic2: 'CXSW3DV2',
|
|
||||||
model: 'CL-89',
|
|
||||||
version: 1,
|
|
||||||
layer_count: 0,
|
|
||||||
res_x: 3840,
|
|
||||||
res_y: 2400,
|
|
||||||
height: 0,
|
|
||||||
thumb: undefined,
|
|
||||||
preview1: undefined,
|
|
||||||
preview2: undefined,
|
|
||||||
dim_x: '192.000000',
|
|
||||||
dim_y: '120.000000',
|
|
||||||
layer: '0.050000',
|
|
||||||
light_on: 6,
|
|
||||||
light_off: 2,
|
|
||||||
light_pwm: 255,
|
|
||||||
lift_dist: 6,
|
|
||||||
lift_speed: 60,
|
|
||||||
down_speed: 150,
|
|
||||||
base_layers: 8,
|
|
||||||
base_light_on: 60,
|
|
||||||
base_light_pwm: 255,
|
|
||||||
base_lift_dist: 5,
|
|
||||||
base_lift_speed: 60
|
|
||||||
};
|
|
||||||
const data_term = 0x0d0a;
|
|
||||||
|
|
||||||
// https://github.com/sn4k3/UVtools/blob/v2.20.4/UVtools.Core/FileFormats/CXDLPFile.cs
|
gapp.register("kiri-mode.sla.x_cxdlp", [], (root, exports) => {
|
||||||
// CL-60 1620 x 2560
|
|
||||||
// CL-89 3840 x 2400
|
|
||||||
// CL-133 3840 x 2160
|
|
||||||
|
|
||||||
class CXDLP {
|
const default_values = {
|
||||||
constructor() {
|
magic1: 'CXSW3DV2',
|
||||||
Object.assign(this, default_values);
|
magic2: 'CXSW3DV2',
|
||||||
|
model: 'CL-89',
|
||||||
|
version: 1,
|
||||||
|
layer_count: 0,
|
||||||
|
res_x: 3840,
|
||||||
|
res_y: 2400,
|
||||||
|
height: 0,
|
||||||
|
thumb: undefined,
|
||||||
|
preview1: undefined,
|
||||||
|
preview2: undefined,
|
||||||
|
dim_x: '192.000000',
|
||||||
|
dim_y: '120.000000',
|
||||||
|
layer: '0.050000',
|
||||||
|
light_on: 6,
|
||||||
|
light_off: 2,
|
||||||
|
light_pwm: 255,
|
||||||
|
lift_dist: 6,
|
||||||
|
lift_speed: 60,
|
||||||
|
down_speed: 150,
|
||||||
|
base_layers: 8,
|
||||||
|
base_light_on: 60,
|
||||||
|
base_light_pwm: 255,
|
||||||
|
base_lift_dist: 5,
|
||||||
|
base_lift_speed: 60
|
||||||
|
};
|
||||||
|
const data_term = 0x0d0a;
|
||||||
|
|
||||||
|
// https://github.com/sn4k3/UVtools/blob/v2.20.4/UVtools.Core/FileFormats/CXDLPFile.cs
|
||||||
|
// CL-60 1620 x 2560
|
||||||
|
// CL-89 3840 x 2400
|
||||||
|
// CL-133 3840 x 2160
|
||||||
|
|
||||||
|
class CXDLP {
|
||||||
|
constructor() {
|
||||||
|
Object.assign(this, default_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// takes a DataView Object
|
||||||
|
read(view) {
|
||||||
|
let read = new DataReader(view, 0);
|
||||||
|
|
||||||
|
function read_string(dbl) {
|
||||||
|
let len = read.readU32();
|
||||||
|
let str = '';
|
||||||
|
while (--len > 0) {
|
||||||
|
if (dbl) {
|
||||||
|
read.readU8();
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
str += String.fromCharCode(read.readU8());
|
||||||
|
}
|
||||||
|
if (!dbl) {
|
||||||
|
read.skip(1); // null term on byte strings
|
||||||
|
}
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes a DataView Object
|
let meta = {
|
||||||
read(view) {
|
view,
|
||||||
let read = new DataReader(view, 0);
|
magic1: read_string(),
|
||||||
|
version: read.readU16(),
|
||||||
|
model: read_string(),
|
||||||
|
layer_count: read.readU16(),
|
||||||
|
res_x: read.readU16(),
|
||||||
|
res_y: read.readU16(),
|
||||||
|
height: read.readU32(),
|
||||||
|
skip: read.skip(60),
|
||||||
|
thumb: read.readBytes(26912),
|
||||||
|
skip: read.skip(2), // 0xd0a term
|
||||||
|
preview1: read.readBytes(168200),
|
||||||
|
skip: read.skip(2), // 0xd0a term
|
||||||
|
preview2: read.readBytes(168200),
|
||||||
|
skip: read.skip(2), // 0xd0a term
|
||||||
|
dim_x: read_string(true),
|
||||||
|
dim_y: read_string(true),
|
||||||
|
layer: read_string(true),
|
||||||
|
light_on: read.readU16(),
|
||||||
|
light_off: read.readU16(),
|
||||||
|
base_light_on: read.readU16(),
|
||||||
|
base_layers: read.readU16(),
|
||||||
|
base_lift_dist: read.readU16(),
|
||||||
|
base_lift_speed: read.readU16(),
|
||||||
|
lift_dist: read.readU16(),
|
||||||
|
lift_speed: read.readU16(),
|
||||||
|
down_speed: read.readU16(),
|
||||||
|
base_light_pwm: read.readU16(),
|
||||||
|
light_pwm: read.readU16()
|
||||||
|
};
|
||||||
|
|
||||||
function read_string(dbl) {
|
// read layer record lengths
|
||||||
let len = read.readU32();
|
let layers = this.layers = [];
|
||||||
let str = '';
|
for (let i=0; i<meta.layer_count; i++) {
|
||||||
while (--len > 0) {
|
layers.push({ length: read.readU32() });
|
||||||
if (dbl) {
|
}
|
||||||
read.readU8();
|
if (read.readU16() !== data_term) {
|
||||||
len--;
|
throw `invalid data term @ ${read.pos - 2}`;
|
||||||
}
|
}
|
||||||
str += String.fromCharCode(read.readU8());
|
|
||||||
}
|
// read layer meta data, not line data
|
||||||
if (!dbl) {
|
for (let i=0; i<meta.layer_count; i++) {
|
||||||
read.skip(1); // null term on byte strings
|
let size = read.readU32();
|
||||||
}
|
if (size !== layers[i].length) {
|
||||||
return str;
|
throw `layer length mismatch: ${size} != ${layers[i].length} @ i=${i}`;
|
||||||
}
|
|
||||||
|
|
||||||
let meta = {
|
|
||||||
view,
|
|
||||||
magic1: read_string(),
|
|
||||||
version: read.readU16(),
|
|
||||||
model: read_string(),
|
|
||||||
layer_count: read.readU16(),
|
|
||||||
res_x: read.readU16(),
|
|
||||||
res_y: read.readU16(),
|
|
||||||
height: read.readU32(),
|
|
||||||
skip: read.skip(60),
|
|
||||||
thumb: read.readBytes(26912),
|
|
||||||
skip: read.skip(2), // 0xd0a term
|
|
||||||
preview1: read.readBytes(168200),
|
|
||||||
skip: read.skip(2), // 0xd0a term
|
|
||||||
preview2: read.readBytes(168200),
|
|
||||||
skip: read.skip(2), // 0xd0a term
|
|
||||||
dim_x: read_string(true),
|
|
||||||
dim_y: read_string(true),
|
|
||||||
layer: read_string(true),
|
|
||||||
light_on: read.readU16(),
|
|
||||||
light_off: read.readU16(),
|
|
||||||
base_light_on: read.readU16(),
|
|
||||||
base_layers: read.readU16(),
|
|
||||||
base_lift_dist: read.readU16(),
|
|
||||||
base_lift_speed: read.readU16(),
|
|
||||||
lift_dist: read.readU16(),
|
|
||||||
lift_speed: read.readU16(),
|
|
||||||
down_speed: read.readU16(),
|
|
||||||
base_light_pwm: read.readU16(),
|
|
||||||
light_pwm: read.readU16()
|
|
||||||
};
|
|
||||||
|
|
||||||
// read layer record lengths
|
|
||||||
let layers = this.layers = [];
|
|
||||||
for (let i=0; i<meta.layer_count; i++) {
|
|
||||||
layers.push({ length: read.readU32() });
|
|
||||||
}
|
}
|
||||||
|
let lines = read.readU32();
|
||||||
|
layers[i].lines = lines;
|
||||||
|
layers[i].pos = read.pos; // store line data position
|
||||||
|
// skip line data and check data term is valid
|
||||||
|
read.skip(lines * 6);
|
||||||
if (read.readU16() !== data_term) {
|
if (read.readU16() !== data_term) {
|
||||||
throw `invalid data term @ ${read.pos - 2}`;
|
throw `invalid data term @ ${read.pos - 2}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read layer meta data, not line data
|
|
||||||
for (let i=0; i<meta.layer_count; i++) {
|
|
||||||
let size = read.readU32();
|
|
||||||
if (size !== layers[i].length) {
|
|
||||||
throw `layer length mismatch: ${size} != ${layers[i].length} @ i=${i}`;
|
|
||||||
}
|
|
||||||
let lines = read.readU32();
|
|
||||||
layers[i].lines = lines;
|
|
||||||
layers[i].pos = read.pos; // store line data position
|
|
||||||
// skip line data and check data term is valid
|
|
||||||
read.skip(lines * 6);
|
|
||||||
if (read.readU16() !== data_term) {
|
|
||||||
throw `invalid data term @ ${read.pos - 2}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read trailing magic
|
|
||||||
meta.magic2 = read_string();
|
|
||||||
|
|
||||||
// compute checksum and verify
|
|
||||||
let cksum = 0;
|
|
||||||
for (let i=0; i<read.pos; i++) {
|
|
||||||
cksum = cksum ^ view.getUint8(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta.checksum = cksum;
|
|
||||||
|
|
||||||
if (cksum !== read.readU32()) {
|
|
||||||
throw `checksum mismatch`;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete meta.skip;
|
|
||||||
Object.assign(this, meta);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_layer_lines(layer) {
|
// read trailing magic
|
||||||
if (this.view) {
|
meta.magic2 = read_string();
|
||||||
if (layer > this.layers.length) {
|
|
||||||
throw `layer out of range 0-${this.layers.length}`;
|
// compute checksum and verify
|
||||||
}
|
let cksum = 0;
|
||||||
let out = [];
|
for (let i=0; i<read.pos; i++) {
|
||||||
let rec = this.layers[layer];
|
cksum = cksum ^ view.getUint8(i);
|
||||||
let { lines, pos } = rec;
|
|
||||||
for (let j=0; j<lines; j++) {
|
|
||||||
let d1 = this.view.getUint16(pos); pos += 2;
|
|
||||||
let d2 = this.view.getUint16(pos); pos += 2;
|
|
||||||
let d3 = this.view.getUint16(pos); pos += 2;
|
|
||||||
let y_start = d1 >> 3;
|
|
||||||
let y_end = ((d1 & 0b111) << 10) | (d2 >> 6);
|
|
||||||
let x_end = ((d2 & 0b111111) << 8) | (d3 >> 8);
|
|
||||||
let color = d3 & 0xff;
|
|
||||||
out.push({y_start, y_end, x_end, color});
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
} else {
|
|
||||||
throw "missing data view";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write() {
|
meta.checksum = cksum;
|
||||||
let output = new ArrayWriter();
|
|
||||||
|
|
||||||
output.write_string = function write_string(str, dbl = false) {
|
if (cksum !== read.readU32()) {
|
||||||
let len = str.length;
|
throw `checksum mismatch`;
|
||||||
output.writeU32(dbl ? len * 2 : len + 1);
|
}
|
||||||
let pos = 0;
|
|
||||||
while (pos < len) {
|
delete meta.skip;
|
||||||
if (dbl) {
|
Object.assign(this, meta);
|
||||||
output.writeU8(0);
|
|
||||||
}
|
return this;
|
||||||
output.writeU8(str.charCodeAt(pos++));
|
}
|
||||||
}
|
|
||||||
if (!dbl) {
|
get_layer_lines(layer) {
|
||||||
|
if (this.view) {
|
||||||
|
if (layer > this.layers.length) {
|
||||||
|
throw `layer out of range 0-${this.layers.length}`;
|
||||||
|
}
|
||||||
|
let out = [];
|
||||||
|
let rec = this.layers[layer];
|
||||||
|
let { lines, pos } = rec;
|
||||||
|
for (let j=0; j<lines; j++) {
|
||||||
|
let d1 = this.view.getUint16(pos); pos += 2;
|
||||||
|
let d2 = this.view.getUint16(pos); pos += 2;
|
||||||
|
let d3 = this.view.getUint16(pos); pos += 2;
|
||||||
|
let y_start = d1 >> 3;
|
||||||
|
let y_end = ((d1 & 0b111) << 10) | (d2 >> 6);
|
||||||
|
let x_end = ((d2 & 0b111111) << 8) | (d3 >> 8);
|
||||||
|
let color = d3 & 0xff;
|
||||||
|
out.push({y_start, y_end, x_end, color});
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
} else {
|
||||||
|
throw "missing data view";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write() {
|
||||||
|
let output = new ArrayWriter();
|
||||||
|
|
||||||
|
output.write_string = function write_string(str, dbl = false) {
|
||||||
|
let len = str.length;
|
||||||
|
output.writeU32(dbl ? len * 2 : len + 1);
|
||||||
|
let pos = 0;
|
||||||
|
while (pos < len) {
|
||||||
|
if (dbl) {
|
||||||
output.writeU8(0);
|
output.writeU8(0);
|
||||||
}
|
}
|
||||||
|
output.writeU8(str.charCodeAt(pos++));
|
||||||
}
|
}
|
||||||
|
if (!dbl) {
|
||||||
|
output.writeU8(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
output.write_bytes = function(array, len) {
|
output.write_bytes = function(array, len) {
|
||||||
if (!array) {
|
if (!array) {
|
||||||
output.skip(len);
|
output.skip(len);
|
||||||
} else if (array.byteLength) {
|
} else if (array.byteLength) {
|
||||||
if (len !== array.byteLength) {
|
if (len !== array.byteLength) {
|
||||||
throw `invalid array length: ${array.byteLength} != ${len}`;
|
throw `invalid array length: ${array.byteLength} != ${len}`;
|
||||||
}
|
|
||||||
// ArrayBuffer
|
|
||||||
let read = new DataReader(array);
|
|
||||||
for (let i=0; i<array.byteLength; i++) {
|
|
||||||
output.writeU8(read.readU8());
|
|
||||||
}
|
|
||||||
} else if (array.length) {
|
|
||||||
if (len !== array.length) {
|
|
||||||
throw `invalid array length: ${array.length} != ${len}`;
|
|
||||||
}
|
|
||||||
// standard array
|
|
||||||
output.writeBytes(array);
|
|
||||||
} else {
|
|
||||||
throw "invalid byte array";
|
|
||||||
}
|
}
|
||||||
};
|
// ArrayBuffer
|
||||||
|
let read = new DataReader(array);
|
||||||
let layers = this.layers;
|
for (let i=0; i<array.byteLength; i++) {
|
||||||
this.layer_count = layers.length;
|
output.writeU8(read.readU8());
|
||||||
output.write_string(this.magic1);
|
|
||||||
output.writeU16(this.version);
|
|
||||||
output.write_string(this.model);
|
|
||||||
output.writeU16(this.layer_count);
|
|
||||||
output.writeU16(this.res_x);
|
|
||||||
output.writeU16(this.res_y);
|
|
||||||
output.writeU32(this.height);
|
|
||||||
output.skip(60);
|
|
||||||
output.write_bytes(this.thumb, 26912); // thumb
|
|
||||||
output.writeU16(data_term);
|
|
||||||
output.write_bytes(this.preview1, 168200); // preview1
|
|
||||||
output.writeU16(data_term);
|
|
||||||
output.write_bytes(this.preview2, 168200); // preview1
|
|
||||||
output.writeU16(data_term);
|
|
||||||
output.write_string(this.dim_x, true);
|
|
||||||
output.write_string(this.dim_y, true);
|
|
||||||
output.write_string(this.layer, true);
|
|
||||||
output.writeU16(this.light_on);
|
|
||||||
output.writeU16(this.light_off);
|
|
||||||
output.writeU16(this.base_light_on);
|
|
||||||
output.writeU16(this.base_layers);
|
|
||||||
output.writeU16(this.base_lift_dist);
|
|
||||||
output.writeU16(this.base_lift_speed);
|
|
||||||
output.writeU16(this.lift_dist);
|
|
||||||
output.writeU16(this.lift_speed);
|
|
||||||
output.writeU16(this.down_speed);
|
|
||||||
output.writeU16(this.base_light_pwm);
|
|
||||||
output.writeU16(this.light_pwm);
|
|
||||||
|
|
||||||
// write placeholder layer length to capture position
|
|
||||||
for (let layer of layers) {
|
|
||||||
layer.l1 = output.pos;
|
|
||||||
output.writeU32(0);
|
|
||||||
}
|
|
||||||
output.writeU16(data_term);
|
|
||||||
|
|
||||||
// write out encoded layers
|
|
||||||
for (let layer of layers) {
|
|
||||||
layer.l2 = output.pos;
|
|
||||||
// placeholder to be written post
|
|
||||||
output.writeU32(0);
|
|
||||||
output.writeU32(layer.lines.length);
|
|
||||||
let start = output.pos;
|
|
||||||
for (let line of layer.lines) {
|
|
||||||
let b1 = (line.y_start >> 5);
|
|
||||||
let b2 = ((line.y_start << 3) | (line.y_end >> 10)) & 0xff;
|
|
||||||
let b3 = (line.y_end >> 2) & 0xff;
|
|
||||||
let b4 = ((line.y_end << 6) | (line.x_end >> 8)) & 0xff;
|
|
||||||
let b5 = (line.x_end) & 0xff;
|
|
||||||
output.writeU8(b1);
|
|
||||||
output.writeU8(b2);
|
|
||||||
output.writeU8(b3);
|
|
||||||
output.writeU8(b4);
|
|
||||||
output.writeU8(b5);
|
|
||||||
output.writeU8(line.color);
|
|
||||||
}
|
}
|
||||||
layer.length = output.pos - start;
|
} else if (array.length) {
|
||||||
output.writeU16(data_term);
|
if (len !== array.length) {
|
||||||
|
throw `invalid array length: ${array.length} != ${len}`;
|
||||||
|
}
|
||||||
|
// standard array
|
||||||
|
output.writeBytes(array);
|
||||||
|
} else {
|
||||||
|
throw "invalid byte array";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
output.write_string(this.magic2);
|
let layers = this.layers;
|
||||||
let ckpos = output.pos;
|
this.layer_count = layers.length;
|
||||||
|
output.write_string(this.magic1);
|
||||||
|
output.writeU16(this.version);
|
||||||
|
output.write_string(this.model);
|
||||||
|
output.writeU16(this.layer_count);
|
||||||
|
output.writeU16(this.res_x);
|
||||||
|
output.writeU16(this.res_y);
|
||||||
|
output.writeU32(this.height);
|
||||||
|
output.skip(60);
|
||||||
|
output.write_bytes(this.thumb, 26912); // thumb
|
||||||
|
output.writeU16(data_term);
|
||||||
|
output.write_bytes(this.preview1, 168200); // preview1
|
||||||
|
output.writeU16(data_term);
|
||||||
|
output.write_bytes(this.preview2, 168200); // preview1
|
||||||
|
output.writeU16(data_term);
|
||||||
|
output.write_string(this.dim_x, true);
|
||||||
|
output.write_string(this.dim_y, true);
|
||||||
|
output.write_string(this.layer, true);
|
||||||
|
output.writeU16(this.light_on);
|
||||||
|
output.writeU16(this.light_off);
|
||||||
|
output.writeU16(this.base_light_on);
|
||||||
|
output.writeU16(this.base_layers);
|
||||||
|
output.writeU16(this.base_lift_dist);
|
||||||
|
output.writeU16(this.base_lift_speed);
|
||||||
|
output.writeU16(this.lift_dist);
|
||||||
|
output.writeU16(this.lift_speed);
|
||||||
|
output.writeU16(this.down_speed);
|
||||||
|
output.writeU16(this.base_light_pwm);
|
||||||
|
output.writeU16(this.light_pwm);
|
||||||
|
|
||||||
// retrace and write layer lengths
|
// write placeholder layer length to capture position
|
||||||
for (let layer of layers) {
|
for (let layer of layers) {
|
||||||
output.seek(layer.l1);
|
layer.l1 = output.pos;
|
||||||
output.writeU32(layer.length);
|
output.writeU32(0);
|
||||||
output.seek(layer.l2);
|
}
|
||||||
output.writeU32(layer.length);
|
output.writeU16(data_term);
|
||||||
|
|
||||||
|
// write out encoded layers
|
||||||
|
for (let layer of layers) {
|
||||||
|
layer.l2 = output.pos;
|
||||||
|
// placeholder to be written post
|
||||||
|
output.writeU32(0);
|
||||||
|
output.writeU32(layer.lines.length);
|
||||||
|
let start = output.pos;
|
||||||
|
for (let line of layer.lines) {
|
||||||
|
let b1 = (line.y_start >> 5);
|
||||||
|
let b2 = ((line.y_start << 3) | (line.y_end >> 10)) & 0xff;
|
||||||
|
let b3 = (line.y_end >> 2) & 0xff;
|
||||||
|
let b4 = ((line.y_end << 6) | (line.x_end >> 8)) & 0xff;
|
||||||
|
let b5 = (line.x_end) & 0xff;
|
||||||
|
output.writeU8(b1);
|
||||||
|
output.writeU8(b2);
|
||||||
|
output.writeU8(b3);
|
||||||
|
output.writeU8(b4);
|
||||||
|
output.writeU8(b5);
|
||||||
|
output.writeU8(line.color);
|
||||||
}
|
}
|
||||||
|
layer.length = output.pos - start;
|
||||||
|
output.writeU16(data_term);
|
||||||
|
}
|
||||||
|
|
||||||
output.seek(ckpos);
|
output.write_string(this.magic2);
|
||||||
// compute xor checksum
|
let ckpos = output.pos;
|
||||||
let cksum = 0;
|
|
||||||
let array = output.array;
|
// retrace and write layer lengths
|
||||||
for (let i=0; i<array.length; i++) {
|
for (let layer of layers) {
|
||||||
cksum = cksum ^ (array[i] || 0);
|
output.seek(layer.l1);
|
||||||
|
output.writeU32(layer.length);
|
||||||
|
output.seek(layer.l2);
|
||||||
|
output.writeU32(layer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.seek(ckpos);
|
||||||
|
// compute xor checksum
|
||||||
|
let cksum = 0;
|
||||||
|
let array = output.array;
|
||||||
|
for (let i=0; i<array.length; i++) {
|
||||||
|
cksum = cksum ^ (array[i] || 0);
|
||||||
|
}
|
||||||
|
output.writeU32(cksum);
|
||||||
|
|
||||||
|
return output.toBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CXDLP.export = function(params) {
|
||||||
|
let { settings, width, height, slices } = params;
|
||||||
|
let { thumb, preview1, preview2 } = params;
|
||||||
|
let { device, process } = settings;
|
||||||
|
|
||||||
|
let cxdlp = new CXDLP();
|
||||||
|
|
||||||
|
if (width === 1620 && height === 2560) {
|
||||||
|
cxdlp.model = "CL-60";
|
||||||
|
} else
|
||||||
|
if (width === 3840 && height === 2400) {
|
||||||
|
cxdlp.model = "CL-89";
|
||||||
|
} else
|
||||||
|
if (width === 3840 && height === 2160) {
|
||||||
|
cxdlp.model = "CL-133";
|
||||||
|
} else {
|
||||||
|
throw `invalid printer dimensions ${width} x ${height}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
cxdlp.layers = slices.map(a => {return { lines: a }});
|
||||||
|
cxdlp.res_x = device.resolutionX;
|
||||||
|
cxdlp.res_y = device.resolutionY;
|
||||||
|
cxdlp.dim_x = device.bedWidth.toFixed(5);
|
||||||
|
cxdlp.dim_y = device.bedDepth.toFixed(5);
|
||||||
|
cxdlp.layer = process.slaSlice.toFixed(5);
|
||||||
|
cxdlp.thumb = thumb;
|
||||||
|
cxdlp.preview1 = preview1;
|
||||||
|
cxdlp.preview2 = preview2;
|
||||||
|
cxdlp.light_on = process.slaLayerOn;
|
||||||
|
cxdlp.light_off = process.slaLayerOff;
|
||||||
|
// cxdlp.light_pwm = 255;
|
||||||
|
cxdlp.lift_dist = process.slaPeelDist;
|
||||||
|
cxdlp.lift_speed = process.slaPeelLiftRate * 60;
|
||||||
|
cxdlp.base_layers = process.slaBaseLayers;
|
||||||
|
cxdlp.base_light_on = process.slaBaseOn;
|
||||||
|
// cxdlp.base_light_pwm = 255;
|
||||||
|
cxdlp.base_lift_dist = process.slaBasePeelDist;
|
||||||
|
cxdlp.base_lift_speed = process.slaBasePeelLiftRate * 60;
|
||||||
|
|
||||||
|
return cxdlp.write();
|
||||||
|
};
|
||||||
|
|
||||||
|
CXDLP.render = function(params) {
|
||||||
|
let { width, height, index, widgets, scaleX, scaleY } = params;
|
||||||
|
let width2 = width / 2, height2 = height / 2;
|
||||||
|
let array = [];
|
||||||
|
let count = 0;
|
||||||
|
let area = 0;
|
||||||
|
|
||||||
|
function scaleMovePoly(poly) {
|
||||||
|
let points = poly.points;
|
||||||
|
poly._bounds = undefined;
|
||||||
|
for (let i=0, il=points.length; i<il; i++) {
|
||||||
|
let p = points[i];
|
||||||
|
p.y = height - (p.y * scaleY + height2);
|
||||||
|
p.x = p.x * scaleX + width2;
|
||||||
|
}
|
||||||
|
if (poly.inner) {
|
||||||
|
for (let i=0, ia=poly.inner, il=poly.inner.length; i<il; i++) {
|
||||||
|
scaleMovePoly(ia[i]);
|
||||||
}
|
}
|
||||||
output.writeU32(cksum);
|
|
||||||
|
|
||||||
return output.toBuffer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CXDLP.export = function(params) {
|
// serialize poly into wasm heap memory
|
||||||
let { settings, width, height, slices } = params;
|
function writePoly(writer, poly) {
|
||||||
let { thumb, preview1, preview2 } = params;
|
let pos = writer.skip(2);
|
||||||
let { device, process } = settings;
|
let inner = poly.inner;
|
||||||
|
writer.writeU16(inner ? inner.length : 0, true);
|
||||||
let cxdlp = new CXDLP();
|
let points = poly.points;
|
||||||
|
let bounds = poly.bounds;
|
||||||
if (width === 1620 && height === 2560) {
|
writer.writeU16(points.length, true);
|
||||||
cxdlp.model = "CL-60";
|
writer.writeU16(bounds.minx, true);
|
||||||
} else
|
writer.writeU16(bounds.maxx, true);
|
||||||
if (width === 3840 && height === 2400) {
|
writer.writeU16(bounds.miny, true);
|
||||||
cxdlp.model = "CL-89";
|
writer.writeU16(bounds.maxy, true);
|
||||||
} else
|
for (let j=0, jl=points.length; j<jl; j++) {
|
||||||
if (width === 3840 && height === 2160) {
|
let point = points[j];
|
||||||
cxdlp.model = "CL-133";
|
writer.writeF32(point.x, true);
|
||||||
} else {
|
writer.writeF32(point.y, true);
|
||||||
throw `invalid printer dimensions ${width} x ${height}`;
|
|
||||||
}
|
}
|
||||||
|
if (inner && inner.length) {
|
||||||
cxdlp.layers = slices.map(a => {return { lines: a }});
|
for (let i=0, il=inner.length; i<il; i++) {
|
||||||
cxdlp.res_x = device.resolutionX;
|
writePoly(writer, inner[i]);
|
||||||
cxdlp.res_y = device.resolutionY;
|
|
||||||
cxdlp.dim_x = device.bedWidth.toFixed(5);
|
|
||||||
cxdlp.dim_y = device.bedDepth.toFixed(5);
|
|
||||||
cxdlp.layer = process.slaSlice.toFixed(5);
|
|
||||||
cxdlp.thumb = thumb;
|
|
||||||
cxdlp.preview1 = preview1;
|
|
||||||
cxdlp.preview2 = preview2;
|
|
||||||
cxdlp.light_on = process.slaLayerOn;
|
|
||||||
cxdlp.light_off = process.slaLayerOff;
|
|
||||||
// cxdlp.light_pwm = 255;
|
|
||||||
cxdlp.lift_dist = process.slaPeelDist;
|
|
||||||
cxdlp.lift_speed = process.slaPeelLiftRate * 60;
|
|
||||||
cxdlp.base_layers = process.slaBaseLayers;
|
|
||||||
cxdlp.base_light_on = process.slaBaseOn;
|
|
||||||
// cxdlp.base_light_pwm = 255;
|
|
||||||
cxdlp.base_lift_dist = process.slaBasePeelDist;
|
|
||||||
cxdlp.base_lift_speed = process.slaBasePeelLiftRate * 60;
|
|
||||||
|
|
||||||
return cxdlp.write();
|
|
||||||
};
|
|
||||||
|
|
||||||
CXDLP.render = function(params) {
|
|
||||||
let { width, height, index, widgets, scaleX, scaleY } = params;
|
|
||||||
let width2 = width / 2, height2 = height / 2;
|
|
||||||
let array = [];
|
|
||||||
let count = 0;
|
|
||||||
let area = 0;
|
|
||||||
|
|
||||||
function scaleMovePoly(poly) {
|
|
||||||
let points = poly.points;
|
|
||||||
poly._bounds = undefined;
|
|
||||||
for (let i=0, il=points.length; i<il; i++) {
|
|
||||||
let p = points[i];
|
|
||||||
p.y = height - (p.y * scaleY + height2);
|
|
||||||
p.x = p.x * scaleX + width2;
|
|
||||||
}
|
|
||||||
if (poly.inner) {
|
|
||||||
for (let i=0, ia=poly.inner, il=poly.inner.length; i<il; i++) {
|
|
||||||
scaleMovePoly(ia[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// write total struct length at struct head
|
||||||
// serialize poly into wasm heap memory
|
writer.view.setUint16(pos, writer.pos - pos, true);
|
||||||
function writePoly(writer, poly) {
|
|
||||||
let pos = writer.skip(2);
|
|
||||||
let inner = poly.inner;
|
|
||||||
writer.writeU16(inner ? inner.length : 0, true);
|
|
||||||
let points = poly.points;
|
|
||||||
let bounds = poly.bounds;
|
|
||||||
writer.writeU16(points.length, true);
|
|
||||||
writer.writeU16(bounds.minx, true);
|
|
||||||
writer.writeU16(bounds.maxx, true);
|
|
||||||
writer.writeU16(bounds.miny, true);
|
|
||||||
writer.writeU16(bounds.maxy, true);
|
|
||||||
for (let j=0, jl=points.length; j<jl; j++) {
|
|
||||||
let point = points[j];
|
|
||||||
writer.writeF32(point.x, true);
|
|
||||||
writer.writeF32(point.y, true);
|
|
||||||
}
|
|
||||||
if (inner && inner.length) {
|
|
||||||
for (let i=0, il=inner.length; i<il; i++) {
|
|
||||||
writePoly(writer, inner[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// write total struct length at struct head
|
|
||||||
writer.view.setUint16(pos, writer.pos - pos, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
widgets.forEach(widget => {
|
|
||||||
let slice = widget.slices[index];
|
|
||||||
if (slice) {
|
|
||||||
if (slice.synth) count++;
|
|
||||||
let polys = slice.unioned;
|
|
||||||
if (!polys) polys = slice.tops.map(t => t.poly);
|
|
||||||
if (slice.supports) polys.appendAll(slice.supports);
|
|
||||||
array.appendAll(polys.map(poly => {
|
|
||||||
return poly.clone(true).move(widget.track.pos);
|
|
||||||
}));
|
|
||||||
count += polys.length;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let wasm = kiri.driver.SLA.wasm;
|
|
||||||
let imagelen = width * height;
|
|
||||||
let writer = new self.DataWriter(new DataView(wasm.memory.buffer), imagelen);
|
|
||||||
writer.writeU16(width, true);
|
|
||||||
writer.writeU16(height, true);
|
|
||||||
writer.writeU16(array.length, true);
|
|
||||||
|
|
||||||
// scale and move all polys to fit in rendered platform coordinates
|
|
||||||
for (let i=0, il=array.length; i<il; i++) {
|
|
||||||
let poly = array[i];
|
|
||||||
area += poly.areaDeep();
|
|
||||||
scaleMovePoly(poly);
|
|
||||||
writePoly(writer, poly);
|
|
||||||
}
|
|
||||||
wasm.render(0, imagelen, 0);
|
|
||||||
let image = wasm.heap;//.slice(0, imagelen);
|
|
||||||
let lines = [];
|
|
||||||
for (let x=0; x<width; x++) {
|
|
||||||
let y_start = 0;
|
|
||||||
let lastv = 0;
|
|
||||||
for (let y=0; y<height; y++) {
|
|
||||||
let v = image[x * height + y];
|
|
||||||
if (v !== lastv) {
|
|
||||||
if (lastv) {
|
|
||||||
// emit any non-zero sequence
|
|
||||||
lines.push({y_start, y_end: y, x_end: x, color: lastv});
|
|
||||||
}
|
|
||||||
if (v) {
|
|
||||||
// start a new sequence
|
|
||||||
y_start = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastv = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { lines, area };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.navigator && self.process && self.process.env) {
|
widgets.forEach(widget => {
|
||||||
let fs = require('fs');
|
let slice = widget.slices[index];
|
||||||
eval(fs.readFileSync("src/add/class.js").toString());
|
if (slice) {
|
||||||
let args = process.argv.slice(2);
|
if (slice.synth) count++;
|
||||||
let file = args.shift();
|
let polys = slice.unioned;
|
||||||
// let fpos = 0;
|
if (!polys) polys = slice.tops.map(t => t.poly);
|
||||||
let view = new DataView(fs.readFileSync(file).buffer);
|
if (slice.supports) polys.appendAll(slice.supports);
|
||||||
let read = new DataReader(view, 0);
|
array.appendAll(polys.map(poly => {
|
||||||
let cxdlp = new CXDLP().read(view);
|
return poly.clone(true).move(widget.track.pos);
|
||||||
console.log({
|
}));
|
||||||
cxdlp,
|
count += polys.length;
|
||||||
layers5: cxdlp.layers.slice(0,5),
|
}
|
||||||
lines1: cxdlp.get_layer_lines(1)
|
});
|
||||||
});
|
|
||||||
} else if (self.navigator) {
|
let wasm = kiri.driver.SLA.wasm;
|
||||||
self.CXDLP = CXDLP;
|
let imagelen = width * height;
|
||||||
|
let writer = new self.DataWriter(new DataView(wasm.memory.buffer), imagelen);
|
||||||
|
writer.writeU16(width, true);
|
||||||
|
writer.writeU16(height, true);
|
||||||
|
writer.writeU16(array.length, true);
|
||||||
|
|
||||||
|
// scale and move all polys to fit in rendered platform coordinates
|
||||||
|
for (let i=0, il=array.length; i<il; i++) {
|
||||||
|
let poly = array[i];
|
||||||
|
area += poly.areaDeep();
|
||||||
|
scaleMovePoly(poly);
|
||||||
|
writePoly(writer, poly);
|
||||||
}
|
}
|
||||||
}());
|
wasm.render(0, imagelen, 0);
|
||||||
|
let image = wasm.heap;//.slice(0, imagelen);
|
||||||
|
let lines = [];
|
||||||
|
for (let x=0; x<width; x++) {
|
||||||
|
let y_start = 0;
|
||||||
|
let lastv = 0;
|
||||||
|
for (let y=0; y<height; y++) {
|
||||||
|
let v = image[x * height + y];
|
||||||
|
if (v !== lastv) {
|
||||||
|
if (lastv) {
|
||||||
|
// emit any non-zero sequence
|
||||||
|
lines.push({y_start, y_end: y, x_end: x, color: lastv});
|
||||||
|
}
|
||||||
|
if (v) {
|
||||||
|
// start a new sequence
|
||||||
|
y_start = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastv = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { lines, area };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.navigator && self.process && self.process.env) {
|
||||||
|
let fs = require('fs');
|
||||||
|
eval(fs.readFileSync("src/add/class.js").toString());
|
||||||
|
let args = process.argv.slice(2);
|
||||||
|
let file = args.shift();
|
||||||
|
// let fpos = 0;
|
||||||
|
let view = new DataView(fs.readFileSync(file).buffer);
|
||||||
|
let read = new DataReader(view, 0);
|
||||||
|
let cxdlp = new CXDLP().read(view);
|
||||||
|
console.log({
|
||||||
|
cxdlp,
|
||||||
|
layers5: cxdlp.layers.slice(0,5),
|
||||||
|
lines1: cxdlp.get_layer_lines(1)
|
||||||
|
});
|
||||||
|
} else if (self.navigator) {
|
||||||
|
self.CXDLP = CXDLP;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue