Compare commits

4 Commits
main ... sane

Author SHA1 Message Date
70e7e2a35a slicer: implement --rotate-{xy,xz,yz} CLI arguments
Some checks failed
Build / build (ubuntu-latest) (push) Has been cancelled
Build / build (windows-latest) (push) Has been cancelled
Build / build (macos-latest) (push) Has been cancelled
2025-04-01 06:08:26 +00:00
b6b6620105 slicer: warn if the model would overflow the print platform 2025-04-01 05:56:47 +00:00
18d15b0abe slicer: implement minimal argument parsing 2025-04-01 05:48:19 +00:00
5c85efedde add nix build files 2025-04-01 05:40:54 +00:00
6 changed files with 135 additions and 4 deletions

1
Cargo.lock generated
View File

@@ -4491,6 +4491,7 @@ name = "slicer"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"common",
"criterion",
"goo_format",

47
default.nix Normal file
View File

@@ -0,0 +1,47 @@
{
libglvnd,
libxkbcommon,
rustPlatform,
vulkan-loader,
wayland,
}:
rustPlatform.buildRustPackage {
name = "mslicer";
src = ./.;
cargoHash = "sha256-mRbEwxR6bMkybxe7H1dX4Qa1elGiw/lSSz9sSTtp1zw=";
useFetchCargoVendor = true;
buildInputs = [
libglvnd
libxkbcommon
vulkan-loader
wayland
];
NIX_LDFLAGS = [
"--push-state"
"--no-as-needed"
"-lEGL"
"-lvulkan"
"-lwayland-client"
"-lxkbcommon"
"--pop-state"
];
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
# spot-check the binaries
$out/bin/goo_format --help
# these other binaries can't be invoked w/ interactivity or real data:
test -x $out/bin/mslicer
test -x $out/bin/remote_send
test -x $out/bin/slicer
runHook postInstallCheck
'';
strictDeps = true;
}

26
flake.lock generated Normal file
View File

@@ -0,0 +1,26 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1743315132,
"narHash": "sha256-6hl6L/tRnwubHcA4pfUUtk542wn2Om+D4UnDhlDW9BE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "52faf482a3889b7619003c0daec593a1912fddc1",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

19
flake.nix Normal file
View File

@@ -0,0 +1,19 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
};
in
{
packages.${system}.default = pkgs.callPackage ./default.nix { };
devShells.${system}.default = with pkgs; mkShell {
inputsFrom = [ self.packages.${system}.default ];
};
};
}

View File

@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
anyhow.workspace = true
clap.workspace = true
image.workspace = true
nalgebra.workspace = true
obj-rs.workspace = true

View File

@@ -1,11 +1,13 @@
use std::{
fs::{self, File},
io::{stdout, BufReader, Write},
path::PathBuf,
thread,
time::Instant,
};
use anyhow::Result;
use clap::Parser;
use nalgebra::{Vector2, Vector3};
use common::{
@@ -16,9 +18,26 @@ use common::{
use goo_format::{File as GooFile, LayerEncoder};
use slicer::{mesh::load_mesh, slicer::Slicer, Pos};
#[derive(Parser)]
struct Args {
/// Path to the .stl file
input_file: PathBuf,
/// Path to the .goo file
output_file: PathBuf,
/// Rotate the model (in degrees, about the z axis) before slicing it
#[clap(long)]
rotate_xy: Option<f32>,
/// Rotate the model (in degrees, about the y axis) before slicing it
#[clap(long)]
rotate_xz: Option<f32>,
/// Rotate the model (in degrees, about the x axis) before slicing it
#[clap(long)]
rotate_yz: Option<f32>,
}
fn main() -> Result<()> {
const FILE_PATH: &str = "teapot.stl";
const OUTPUT_PATH: &str = "output.goo";
let args = Args::parse();
let slice_config = SliceConfig {
format: Format::Goo,
@@ -39,9 +58,22 @@ fn main() -> Result<()> {
transition_layers: 10,
};
let file = File::open(FILE_PATH)?;
let file = File::open(args.input_file)?;
let mut buf = BufReader::new(file);
let mut mesh = load_mesh(&mut buf, "stl")?;
let mut rotate = mesh.rotation();
if let Some(r) = args.rotate_xy {
rotate.z += r.to_radians();
}
if let Some(r) = args.rotate_xz {
rotate.y += r.to_radians();
}
if let Some(r) = args.rotate_yz {
rotate.x += r.to_radians();
}
mesh.set_rotation(rotate);
let (min, max) = mesh.bounds();
// Scale the model into printer-space (mm => px)
@@ -52,6 +84,11 @@ fn main() -> Result<()> {
real_scale,
));
let mesh_size = max - min;
if mesh_size.x > slice_config.platform_size.x || mesh_size.y > slice_config.platform_size.y || mesh_size.z > slice_config.platform_size.z {
eprintln!("WARNING: model bounds ({}) exceeds printer bounds ({}); print may be truncated", mesh_size, slice_config.platform_size);
}
// Center the model
let center = slice_config.platform_resolution / 2;
let mesh_center = (min + max) / 2.0;
@@ -90,7 +127,7 @@ fn main() -> Result<()> {
// Once slicing is complete write to a .goo file
let mut serializer = DynamicSerializer::new();
goo.join().unwrap().serialize(&mut serializer);
fs::write(OUTPUT_PATH, serializer.into_inner())?;
fs::write(args.output_file, serializer.into_inner())?;
println!("\nDone. Elapsed: {:.1}s", now.elapsed().as_secs_f32());