add tilt tray for .goo and new elegoo targets
This commit is contained in:
parent
f32af7eeb1
commit
b65d4ae57e
6 changed files with 131 additions and 22 deletions
|
|
@ -32,7 +32,7 @@
|
|||
| **Other Binary Formats** |
|
||||
| AnetFile | ✓ | ✓ | n4, n7 | 3 | Yes (N4/N7) | RLE | Anet printers |
|
||||
| FDGFile | ✓ | ✓ | fdg | 2 | No | RLE | Voxelab |
|
||||
| GooFile | ✓ | ✓ | goo, prz | - | No | RLE+delim | Elegoo/Phrozen |
|
||||
| GooFile | ✓ | ✓ | goo, prz | - | No | Chunked RLE + checksum | Elegoo/Phrozen |
|
||||
| LGSFile | ✓ | ✓ | lgs, lgs30, lgs120, lgs4k | - | Yes | Struct | Longer Orange |
|
||||
| MDLPFile | ✓ | ✓ | mdlp | 1 | No | Vector | Makerbase MKS |
|
||||
| GR1File | ✓ | ✓ | gr1 | - | No | Vector | GR Workshop |
|
||||
|
|
@ -559,6 +559,8 @@ Non-delta maximum repeat: 0x0FFFFFFF pixels.
|
|||
Layer record delimiter after payload: 0x0D 0x0A.
|
||||
```
|
||||
|
||||
**Tilt-vat motion:** Mars 5 Ultra and Saturn 4 Ultra GOO files are treated as tilt-vat machines. UVtools identifies them by machine name and substitutes tiny synthetic motion values before encode: lift height `0.05`, lift speed `0.05`, retract height `0`, retract speed `0.05`, with about 4 seconds of motor time in print-time estimates. Kiri models this as `sla_motion: "tilt"` on the device profile instead of overloading user peel distance/speed fields.
|
||||
|
||||
### CXDLP (Creality)
|
||||
|
||||
**Extension:** `.cxdlp`
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ function device_from_code(code,mode) {
|
|||
slaFormatVersion: valueOf(set.sla_format_version, 1),
|
||||
slaMachineEditable: valueOf(set.sla_machine_editable, false),
|
||||
slaMachineName: valueOf(set.sla_machine_name, ''),
|
||||
slaMotion: valueOf(set.sla_motion, ''),
|
||||
deviceZMax: valueOf(set.z_move_max, 0),
|
||||
gcodeTime: valueOf(set.time_factor, 1),
|
||||
maxHeight: valueOf(set.build_height || set.max_height, 150),
|
||||
|
|
|
|||
17
src/kiri/dev/sla/Elegoo.Mars.5.Ultra.GOO.json
Normal file
17
src/kiri/dev/sla/Elegoo.Mars.5.Ultra.GOO.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"no_clone": true,
|
||||
"cmd": {},
|
||||
"settings": {
|
||||
"bed_width": 153.36,
|
||||
"bed_depth": 77.76,
|
||||
"bed_height": 1,
|
||||
"max_height": 165,
|
||||
"resolution_x": 8520,
|
||||
"resolution_y": 4320,
|
||||
"sla_format": "goo",
|
||||
"sla_file_ext": "goo",
|
||||
"sla_machine_name": "Mars 5 Ultra",
|
||||
"sla_motion": "tilt",
|
||||
"sla_format_version": 3
|
||||
}
|
||||
}
|
||||
17
src/kiri/dev/sla/Elegoo.Saturn.4.Ultra.12K.GOO.json
Normal file
17
src/kiri/dev/sla/Elegoo.Saturn.4.Ultra.12K.GOO.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"no_clone": true,
|
||||
"cmd": {},
|
||||
"settings": {
|
||||
"bed_width": 218.88,
|
||||
"bed_depth": 122.88,
|
||||
"bed_height": 1,
|
||||
"max_height": 220,
|
||||
"resolution_x": 11520,
|
||||
"resolution_y": 5120,
|
||||
"sla_format": "goo",
|
||||
"sla_file_ext": "goo",
|
||||
"sla_machine_name": "Saturn 4 Ultra 12K",
|
||||
"sla_motion": "tilt",
|
||||
"sla_format_version": 3
|
||||
}
|
||||
}
|
||||
17
src/kiri/dev/sla/Elegoo.Saturn.4.Ultra.16K.GOO.json
Normal file
17
src/kiri/dev/sla/Elegoo.Saturn.4.Ultra.16K.GOO.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"no_clone": true,
|
||||
"cmd": {},
|
||||
"settings": {
|
||||
"bed_width": 211.68,
|
||||
"bed_depth": 118.37,
|
||||
"bed_height": 1,
|
||||
"max_height": 220,
|
||||
"resolution_x": 15120,
|
||||
"resolution_y": 6230,
|
||||
"sla_format": "goo",
|
||||
"sla_file_ext": "goo",
|
||||
"sla_machine_name": "Saturn 4 Ultra 16K",
|
||||
"sla_motion": "tilt",
|
||||
"sla_format_version": 3
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,13 @@ const HEADER_SIZE = 195477;
|
|||
const LAYER_DEF_SIZE = 70;
|
||||
const FOOTER_SIZE = 11;
|
||||
const MAX_RUN = 0x0fffffff;
|
||||
const TILT_MOTION = {
|
||||
liftHeight: 0.05,
|
||||
liftSpeed: 0.05,
|
||||
retractHeight: 0,
|
||||
retractSpeed: 0.05,
|
||||
motorTime: 4
|
||||
};
|
||||
|
||||
const FORMAT_RECORDS = {
|
||||
goo: { ext: "goo", machine: "Elegoo GOO", notes: "Elegoo GOO" },
|
||||
|
|
@ -40,8 +47,9 @@ function encodeGOO(print, progress, photon, rec) {
|
|||
|
||||
let { ctx, volume } = renderRasterLayers(print, photon, params => {
|
||||
let { index, rendered, bottom, z, ctx } = params;
|
||||
let { process, width, height } = ctx;
|
||||
let raster = imageToRowMajor(rendered.image, width, height, value => value ? 255 : 0);
|
||||
let { device, process, width, height } = ctx;
|
||||
let motion = layerMotion(device, process, bottom);
|
||||
let raster = imageToRowMajor(rendered.image, width, height, normalizePixel);
|
||||
|
||||
accumulatePreview(previewSmall, rendered.image, width, height);
|
||||
accumulatePreview(previewLarge, rendered.image, width, height);
|
||||
|
|
@ -56,12 +64,12 @@ function encodeGOO(print, progress, photon, rec) {
|
|||
waitTimeAfterCure: 0,
|
||||
waitTimeAfterLift: 0,
|
||||
waitTimeBeforeCure: bottom ? process.slaBaseOff : process.slaLayerOff,
|
||||
liftHeight: bottom ? process.slaBasePeelDist : process.slaPeelDist,
|
||||
liftSpeed: (bottom ? process.slaBasePeelLiftRate : process.slaPeelLiftRate) * 60,
|
||||
liftHeight: motion.liftHeight,
|
||||
liftSpeed: motion.liftSpeed,
|
||||
liftHeight2: 0,
|
||||
liftSpeed2: 0,
|
||||
retractHeight: bottom ? process.slaBasePeelDist : process.slaPeelDist,
|
||||
retractSpeed: (bottom ? process.slaBasePeelDropRate : process.slaPeelDropRate) * 60,
|
||||
retractHeight: motion.retractHeight,
|
||||
retractSpeed: motion.retractSpeed,
|
||||
retractHeight2: 0,
|
||||
retractSpeed2: 0,
|
||||
lightPWM: 255
|
||||
|
|
@ -101,6 +109,8 @@ function writeHeader(writer, params) {
|
|||
let { device, process, width, height } = ctx;
|
||||
let bottomOff = process.slaBaseOff || 0;
|
||||
let layerOff = process.slaLayerOff || 0;
|
||||
let bottomMotion = layerMotion(device, process, true);
|
||||
let layerMotionValue = layerMotion(device, process, false);
|
||||
|
||||
writer.writeString(FILE_VERSION, 4);
|
||||
writer.writeBytes(FILE_MAGIC);
|
||||
|
|
@ -137,19 +147,19 @@ function writeHeader(writer, params) {
|
|||
writer.writeF32(layerOff);
|
||||
writer.writeF32(process.slaBaseOn);
|
||||
writer.writeU32(process.slaBaseLayers || 0);
|
||||
writer.writeF32(process.slaBasePeelDist);
|
||||
writer.writeF32(process.slaBasePeelLiftRate * 60);
|
||||
writer.writeF32(process.slaPeelDist);
|
||||
writer.writeF32(process.slaPeelLiftRate * 60);
|
||||
writer.writeF32(process.slaBasePeelDist);
|
||||
writer.writeF32(process.slaBasePeelDropRate * 60);
|
||||
writer.writeF32(process.slaPeelDist);
|
||||
writer.writeF32(process.slaPeelDropRate * 60);
|
||||
writer.writeF32(bottomMotion.liftHeight);
|
||||
writer.writeF32(bottomMotion.liftSpeed);
|
||||
writer.writeF32(layerMotionValue.liftHeight);
|
||||
writer.writeF32(layerMotionValue.liftSpeed);
|
||||
writer.writeF32(bottomMotion.retractHeight);
|
||||
writer.writeF32(bottomMotion.retractSpeed);
|
||||
writer.writeF32(layerMotionValue.retractHeight);
|
||||
writer.writeF32(layerMotionValue.retractSpeed);
|
||||
for (let i=0; i<8; i++) writer.writeF32(0);
|
||||
writer.writeU16(255);
|
||||
writer.writeU16(255);
|
||||
writer.writeU8(0);
|
||||
writer.writeU32(estimatePrintTime(process, layers.length));
|
||||
writer.writeU32(estimatePrintTime(device, process, layers.length));
|
||||
writer.writeF32(round(volume));
|
||||
writer.writeF32(0);
|
||||
writer.writeF32(0);
|
||||
|
|
@ -187,6 +197,20 @@ function writeLayer(writer, layer) {
|
|||
writer.writeBytes(DELIMITER);
|
||||
}
|
||||
|
||||
function layerMotion(device, process, bottom) {
|
||||
if (device.slaMotion === "tilt") {
|
||||
return TILT_MOTION;
|
||||
}
|
||||
|
||||
return {
|
||||
liftHeight: bottom ? process.slaBasePeelDist : process.slaPeelDist,
|
||||
liftSpeed: (bottom ? process.slaBasePeelLiftRate : process.slaPeelLiftRate) * 60,
|
||||
retractHeight: bottom ? process.slaBasePeelDist : process.slaPeelDist,
|
||||
retractSpeed: (bottom ? process.slaBasePeelDropRate : process.slaPeelDropRate) * 60,
|
||||
motorTime: 0
|
||||
};
|
||||
}
|
||||
|
||||
function writeFooter(writer) {
|
||||
writer.writeU8(0);
|
||||
writer.writeU8(0);
|
||||
|
|
@ -307,6 +331,7 @@ function decodeLayer(view, layer, pixelCount) {
|
|||
|
||||
function encodeRLE(input) {
|
||||
let output = [LAYER_MAGIC];
|
||||
let previous = 0;
|
||||
let current = input[0] || 0;
|
||||
let run = 0;
|
||||
|
||||
|
|
@ -315,20 +340,38 @@ function encodeRLE(input) {
|
|||
if (value === current && run < MAX_RUN) {
|
||||
run++;
|
||||
} else {
|
||||
writeRun(output, current, run);
|
||||
writeRun(output, current, previous, run);
|
||||
previous = current;
|
||||
current = value;
|
||||
run = 1;
|
||||
}
|
||||
}
|
||||
writeRun(output, current, run);
|
||||
writeRun(output, current, previous, run);
|
||||
output.push(checksum(output));
|
||||
|
||||
return Uint8Array.from(output);
|
||||
}
|
||||
|
||||
function writeRun(output, color, run) {
|
||||
function writeRun(output, color, previous, run) {
|
||||
while (run > 0) {
|
||||
let stride = Math.min(run, MAX_RUN);
|
||||
let diff = Math.abs(color - previous);
|
||||
if (color > 0 && color < 255 && diff <= 0x0f && stride <= 0xff) {
|
||||
let first = 0x80 | (diff & 0x0f);
|
||||
if (stride > 1) {
|
||||
first |= 0x10;
|
||||
}
|
||||
if (color < previous) {
|
||||
first |= 0x20;
|
||||
}
|
||||
output.push(first);
|
||||
if (stride > 1) {
|
||||
output.push(stride);
|
||||
}
|
||||
run -= stride;
|
||||
continue;
|
||||
}
|
||||
|
||||
let lengthCode = stride <= 0x0f ? 0
|
||||
: stride <= 0x0fff ? 1
|
||||
: stride <= 0x0fffff ? 2
|
||||
|
|
@ -350,6 +393,17 @@ function writeRun(output, color, run) {
|
|||
}
|
||||
}
|
||||
|
||||
function normalizePixel(value) {
|
||||
value = value || 0;
|
||||
if (value === 0 || value === 255) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// The JS fallback rasterizer paints red at 200, so rescale that range to
|
||||
// retain binary cure strength while preserving antialiased edge values.
|
||||
return Math.min(255, Math.round(value * 255 / 200));
|
||||
}
|
||||
|
||||
function decodeRLE(input, pixelCount) {
|
||||
let rle = input instanceof Uint8Array ? input : new Uint8Array(input);
|
||||
if (rle[0] !== LAYER_MAGIC) {
|
||||
|
|
@ -452,11 +506,12 @@ function accumulatePreview(preview, image, width, height) {
|
|||
}
|
||||
}
|
||||
|
||||
function estimatePrintTime(process, layers) {
|
||||
function estimatePrintTime(device, process, layers) {
|
||||
let bottom = Math.min(process.slaBaseLayers || 0, layers);
|
||||
let normal = Math.max(0, layers - bottom);
|
||||
let bottomTime = number(process.slaBaseOn) + number(process.slaBaseOff);
|
||||
let normalTime = number(process.slaLayerOn) + number(process.slaLayerOff);
|
||||
let motorTime = device.slaMotion === "tilt" ? TILT_MOTION.motorTime : 0;
|
||||
let bottomTime = number(process.slaBaseOn) + number(process.slaBaseOff) + motorTime;
|
||||
let normalTime = number(process.slaLayerOn) + number(process.slaLayerOff) + motorTime;
|
||||
return Math.ceil(bottom * bottomTime + normal * normalTime);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue