/** Copyright Stewart Allen -- All Rights Reserved */ const default_values = { 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 // CL-60 1620 x 2560 // CL-89 3840 x 2400 // CL-133 3840 x 2160 export 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; } 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 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> 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(str.charCodeAt(pos++)); } if (!dbl) { output.writeU8(0); } } output.write_bytes = function(array, len) { if (!array) { output.skip(len); } else if (array.byteLength) { if (len !== array.byteLength) { throw `invalid array length: ${array.byteLength} != ${len}`; } // ArrayBuffer let read = new DataReader(array); for (let i=0; i> 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.write_string(this.magic2); let ckpos = output.pos; // retrace and write layer lengths for (let layer of layers) { 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 {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 { 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