diff --git a/; b/; new file mode 100644 index 0000000..81e7cee --- /dev/null +++ b/; @@ -0,0 +1,177 @@ +use super::{ + axis::Axis, + base_slices::BaseSlice, + line::Line3, + slice_path::{SlicePath, SurfacePathIterator}, + triangle::Triangle, + FloatValue, +}; +use bvh::{ + aabb::Aabb, + bvh::{Bvh, BvhNode}, +}; + +#[derive(Debug)] +pub struct Mesh { + pub aabb: Aabb, + pub bvh: Bvh, + pub triangles: Vec, +} + +impl From> for Mesh { + fn from(mut triangles: Vec) -> Self { + Self { + aabb: triangles + .get(0) + .map(|triangle| { + let mut aabb = triangle.aabb; + for triangle in triangles.iter().skip(1) { + aabb.join_mut(&triangle.aabb); + } + aabb + }) + .unwrap_or_else(|| Aabb::empty()), + bvh: Bvh::build(&mut triangles), + triangles, + } + } +} + +impl Mesh { + pub fn slice_paths<'a>( + self: &'a Mesh, + axis: Axis, + slice_height: FloatValue, + ) -> impl Iterator> + 'a { + self.slice_base_slices(axis, slice_height) + .map(|slice| slice.find_paths()) + .filter(|paths| !paths.is_empty()) + } + + pub fn slice_surface(&self, axis: Axis, nozzle_width: FloatValue) -> SurfacePathIterator { + SurfacePathIterator::new(self, axis, nozzle_width) + } + + pub fn slice_base_slices<'a>( + self: &'a Mesh, + axis: Axis, + slice_height: FloatValue, + ) -> impl Iterator + 'a { + let layer_count = ((self.aabb.max[axis as usize] - self.aabb.min[axis as usize]) + / slice_height) + .floor() as usize; + + (0..layer_count).map(move |i| { + let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize]; + let mut base_slice = BaseSlice { + i, + d: layer, + axis, + lines: vec![], + }; + + let mut stack = Vec::::with_capacity(self.bvh.nodes.len()); + stack.push(0); + while let Some(i) = stack.pop() { + match self.bvh.nodes[i] { + BvhNode::Node { + parent_index: _, + child_l_index, + child_l_aabb, + child_r_index, + child_r_aabb, + } => { + assert!(child_l_aabb.min[axis as usize] <= child_l_aabb.max[axis as usize]); + assert!(child_r_aabb.min[axis as usize] <= child_r_aabb.max[axis as usize]); + if layer >= child_l_aabb.min[axis as usize] + && layer <= child_l_aabb.max[axis as usize] + { + stack.push(child_l_index); + } + if layer >= child_r_aabb.min[axis as usize] + && layer <= child_r_aabb.max[axis as usize] + { + stack.push(child_r_index); + } + } + BvhNode::Leaf { + parent_index: _, + shape_index, + } => { + for line in self.triangles[shape_index].intersect(layer, axis as usize) { + base_slice.lines.push(line); + } + } + } + } + + base_slice + }) + } + + pub fn outline_base_slice(&self, axis: Axis) -> BaseSlice { + let mut base_slice = BaseSlice { + i: 0, + d: 0.0, + axis, + lines: vec![], + }; + 'triangle: for (i, triangle) in self.triangles.iter().enumerate() { + let mut stack = Vec::::with_capacity(self.bvh.nodes.len()); + stack.push(0); + let mut ab = false; + let mut ac = false; + let mut bc = false; + while let Some(i) = stack.pop() { + match self.bvh.nodes[i] { + BvhNode::Node { + parent_index: _, + child_l_index, + child_l_aabb, + child_r_index, + child_r_aabb, + } => { + let coords = [triangle.a, triangle.b, triangle.c]; + macro_rules! match_aabb { + ($side:expr) => { + coords + .iter() + .map(|point| { + $side.approx_contains_eps(point, FloatValue::EPSILON) as i32 + }) + .sum::() + >= 2 + }; + } + if match_aabb!(child_l_aabb) { + stack.push(child_l_index); + } + if match_aabb!(child_r_aabb) { + stack.push(child_r_index); + } + } + BvhNode::Leaf { + parent_index: _, + shape_index, + } => { + if i == shape_index { + continue; + } + let other = &self.triangles[shape_index]; + let a = triangle.has_point(other.a); + let b = triangle.has_point(other.b); + let c = triangle.has_point(other.c); + ab = ab || (a && b); + ac = ac || (a && c); + bc = bc || (b && c); + + if ab && ac && bc { + continue 'triangle; + } + } + } + } + } + base_slice + } +} diff --git a/bampy/src/lib.rs b/bampy/src/lib.rs index ddced13..b06a7ea 100644 --- a/bampy/src/lib.rs +++ b/bampy/src/lib.rs @@ -1,7 +1,11 @@ +#![feature(extract_if)] +use std::collections::VecDeque; + use approx::relative_eq; use nalgebra::{point, vector, Vector3}; +use num::Float; use result::{Slice, SliceOptions, SliceResult}; -use slicer::axis::Axis; +use slicer::{axis::Axis, slice_path::SlicePath, trace_surface::trace_surface}; use wasm_bindgen::prelude::wasm_bindgen; use crate::slicer::{mesh::Mesh, split_surface::split_surface, triangle::Triangle, FloatValue}; @@ -48,13 +52,10 @@ pub fn slice( ); slicable_triangles.push(triangle); - let angle = triangle.normal.angle(&BED_NORMAL); - let opposite_angle = std::f64::consts::PI - angle; - if angle <= max_angle - || relative_eq!(angle, max_angle) - || opposite_angle <= max_angle - || relative_eq!(opposite_angle, max_angle) - { + let mut normal = triangle.normal.clone(); + normal.z = normal.z.abs(); + let angle = normal.angle(&BED_NORMAL); + if angle <= max_angle || relative_eq!(angle, max_angle) { surface_triangles.push(triangle); } } @@ -62,45 +63,130 @@ pub fn slice( surface_triangles.shrink_to_fit(); console_log!("Creating Surfaces"); - let surfaces = split_surface(surface_triangles).into_iter().map(|mesh| { - mesh.slice_surface(Axis::X, nozzle_diameter).filter(|path| { - let mut length = 0.0; - for pair in path.path.windows(2) { - length += (pair[0].coords - pair[1].coords).norm(); - if length >= min_surface_path_length { + let min_surface_area = std::f64::consts::PI * (nozzle_diameter / 2.0).powi(2); + let mut surfaces = split_surface(surface_triangles) + .into_iter() + .filter(|mesh| { + let mut surface_area = 0.0; + for triangle in &mesh.triangles { + surface_area += triangle.area(); + if surface_area >= min_surface_area { return true; } } return false; }) - }); + .map(|mesh| { + let outline = mesh + .outline_base_slice(Axis::Z) + .find_paths() + .into_iter() + .filter(|path| path.closed) + .collect::>(); + let surface = mesh + .slice_surface(Axis::X, nozzle_diameter) + .filter(|path| { + let mut length = 0.0; + for pair in path.path.windows(2) { + length += (pair[0].coords - pair[1].coords).norm(); + if length >= min_surface_path_length { + return true; + } + } + return false; + }) + .collect::>(); + (mesh, outline, surface) + }) + .collect::>(); + surfaces + .sort_unstable_by(|(a, _, _), (b, _, _)| a.aabb.min.z.partial_cmp(&b.aabb.min.z).unwrap()); console_log!("Creating Walls"); let wallMesh = Mesh::from(slicable_triangles); - let walls = wallMesh.slice_paths(Axis::Z, layer_height); + let mut walls = wallMesh + .slice_paths(Axis::Z, layer_height) + .flat_map(|paths| paths.into_iter().filter(|path| path.closed)) + .collect::>(); + let mut active_surfaces = Vec::new(); + let mut out = Vec::new(); - /*console_log!("Tracing Surfaces"); - let a = max_angle.tan(); - for slice in &mut slices { - for surface in &surfaces { - if surface.aabb.min.z <= slice.z && surface.aabb.max.z > slice.z { - trace_surface(slice, surface, a); + console_log!("Resolving dependencies"); + while let Some(mut wall) = walls.pop_front() { + active_surfaces.extend( + surfaces + .extract_if(|surface| surface.0.aabb.min.z <= wall.aabb.max.z) + .map(|surface| (surface, Vec::new())), + ); + + let deactivate = + active_surfaces.extract_if(|element| element.0 .0.aabb.max.z < wall.aabb.min.z); + for (surface, surface_walls) in deactivate { + for ring in surface.1 { + out.push(ring.points); + } + for path in surface.2 { + out.push(path.path); + } + for wall in surface_walls { + walls.push_front(wall); } } - }*/ + + for surface in active_surfaces.iter_mut() { + let held = wall + .points + .extract_if(|point| !trace_surface(&point, &surface.0 .0, max_angle)) + .collect::>(); + if !held.is_empty() { + surface.1.push(SlicePath { + points: held, + ..wall + }); + } + } + + if !wall.points.is_empty() { + out.push(wall.points); + } + } console_log!("Done"); SliceResult { - slices: surfaces - .flatten() + slices: out + .into_iter() .map(|slice| Slice::Ring { position: slice - .path .into_iter() .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) .collect(), }) - /*.chain(walls.flatten().map(|slice| { + .collect(), + } + /*SliceResult { + slices: surfaces + .into_iter() + .flat_map(|(_, outlines, slices)| { + outlines + .into_iter() + .map(|slice| Slice::Ring { + position: slice + .points + .into_iter() + .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) + .collect(), + }) + .chain(slices.into_iter().map(|slice| { + Slice::Ring { + position: slice + .path + .into_iter() + .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) + .collect(), + } + })) + }) + .chain(walls.flatten().map(|slice| { Slice::Ring { position: slice .points @@ -108,28 +194,7 @@ pub fn slice( .flat_map(|point| [point.x as f32, point.y as f32, point.z as f32]) .collect(), } - }))*/ - /*.chain(surfaces.into_iter().map(|surface| { - Slice::Surface { - position: surface - .triangles - .into_iter() - .flat_map(|triangle| { - [ - triangle.a.x as f32, - triangle.a.y as f32, - triangle.a.z as f32, - triangle.b.x as f32, - triangle.b.y as f32, - triangle.b.z as f32, - triangle.c.x as f32, - triangle.c.y as f32, - triangle.c.z as f32, - ] - }) - .collect(), - } - }))*/ + })) .collect(), - } + }*/ } diff --git a/bampy/src/slicer/axis.rs b/bampy/src/slicer/axis.rs index a0bba49..b187196 100644 --- a/bampy/src/slicer/axis.rs +++ b/bampy/src/slicer/axis.rs @@ -2,9 +2,10 @@ use nalgebra::Vector3; use super::FloatValue; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[repr(usize)] pub enum Axis { + #[default] X = 0, Y = 1, Z = 2, diff --git a/bampy/src/slicer/line.rs b/bampy/src/slicer/line.rs index 065f5b3..28e7716 100644 --- a/bampy/src/slicer/line.rs +++ b/bampy/src/slicer/line.rs @@ -13,6 +13,10 @@ pub struct Line3 { } impl Line3 { + pub fn new(start: Point3, end: Point3) -> Self { + Self { start, end } + } + pub fn norm(&self) -> FloatValue { (self.end - self.start).norm() } diff --git a/bampy/src/slicer/mesh.rs b/bampy/src/slicer/mesh.rs index d58dc32..704e3a8 100644 --- a/bampy/src/slicer/mesh.rs +++ b/bampy/src/slicer/mesh.rs @@ -1,6 +1,7 @@ use super::{ axis::Axis, base_slices::BaseSlice, + line::Line3, slice_path::{SlicePath, SurfacePathIterator}, triangle::Triangle, FloatValue, @@ -60,7 +61,7 @@ impl Mesh { / slice_height) .floor() as usize; - (0..layer_count).map(move |i| { + (0..=layer_count).map(move |i| { let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize]; let mut base_slice = BaseSlice { i, @@ -107,4 +108,79 @@ impl Mesh { base_slice }) } + + pub fn outline_base_slice(&self, axis: Axis) -> BaseSlice { + let mut base_slice = BaseSlice { + i: 0, + d: 0.0, + axis, + lines: vec![], + }; + 'triangle: for (triangle_index, triangle) in self.triangles.iter().enumerate() { + let mut stack = Vec::::with_capacity(self.bvh.nodes.len()); + stack.push(0); + let mut ab = false; + let mut ac = false; + let mut bc = false; + while let Some(i) = stack.pop() { + match self.bvh.nodes[i] { + BvhNode::Node { + parent_index: _, + child_l_index, + child_l_aabb, + child_r_index, + child_r_aabb, + } => { + let coords = [triangle.a, triangle.b, triangle.c]; + macro_rules! match_aabb { + ($side:expr) => { + coords + .iter() + .map(|point| { + $side.approx_contains_eps(point, FloatValue::EPSILON) as i32 + }) + .sum::() + >= 2 + }; + } + if match_aabb!(child_l_aabb) { + stack.push(child_l_index); + } + if match_aabb!(child_r_aabb) { + stack.push(child_r_index); + } + } + BvhNode::Leaf { + parent_index: _, + shape_index, + } => { + if triangle_index == shape_index { + continue; + } + let other = &self.triangles[shape_index]; + let a = other.has_point(triangle.a); + let b = other.has_point(triangle.b); + let c = other.has_point(triangle.c); + ab = ab || (a && b); + ac = ac || (a && c); + bc = bc || (b && c); + + if ab && ac && bc { + continue 'triangle; + } + } + } + } + if !ab { + base_slice.lines.push(Line3::new(triangle.a, triangle.b)); + } + if !ac { + base_slice.lines.push(Line3::new(triangle.a, triangle.c)); + } + if !bc { + base_slice.lines.push(Line3::new(triangle.b, triangle.c)); + } + } + base_slice + } } diff --git a/bampy/src/slicer/sdf.rs b/bampy/src/slicer/sdf.rs index 25c30e7..0ed95a0 100644 --- a/bampy/src/slicer/sdf.rs +++ b/bampy/src/slicer/sdf.rs @@ -4,7 +4,7 @@ use nalgebra::{vector, Point, TAffine, Transform, Vector2, Vector3}; use super::FloatValue; pub trait Sdf { - fn sdf(&self, p: Point) -> FloatValue; + fn sdf(&self, p: &Point) -> FloatValue; } #[derive(Debug, Clone, Copy)] @@ -19,7 +19,7 @@ impl SdfSphere { } impl Sdf<3> for SdfSphere { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { p.coords.norm() - self.radius } } @@ -36,7 +36,7 @@ impl SdfBox { } impl Sdf<3> for SdfBox { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { let q = p.coords.abs() - self.size.coords; q.sup(&Vector3::zeros()).add_scalar(q.max().min(0.0)).norm() } @@ -56,7 +56,7 @@ impl SdfInfiniteCone { } impl Sdf<3> for SdfInfiniteCone { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { let q = vector![p.coords.xy().norm(), p.z]; let d = (q - self.angle.scale(q.dot(&self.angle).max(0.0))).norm(); if q.x * self.angle.y - q.y * self.angle.x > 0.0 { @@ -80,8 +80,8 @@ impl> SdfTransform { } impl> Sdf<3> for SdfTransform { - fn sdf(&self, p: Point) -> FloatValue { - self.sdf.sdf(self.transform.inverse_transform_point(&p)) + fn sdf(&self, p: &Point) -> FloatValue { + self.sdf.sdf(&self.transform.inverse_transform_point(p)) } } @@ -98,8 +98,8 @@ impl> SdfScale { } impl> Sdf for SdfScale { - fn sdf(&self, p: Point) -> FloatValue { - self.sdf.sdf(p / self.scale) * self.scale + fn sdf(&self, p: &Point) -> FloatValue { + self.sdf.sdf(&(p / self.scale)) * self.scale } } @@ -116,7 +116,7 @@ impl> SdfOnion { } impl> Sdf<3> for SdfOnion { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { self.sdf.sdf(p).abs() - self.thickness } } @@ -134,7 +134,7 @@ impl, U: Sdf> SdfUnion { } impl, U: Sdf> Sdf for SdfUnion { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { self.sdf_a.sdf(p).min(self.sdf_b.sdf(p)) } } @@ -152,7 +152,7 @@ impl, U: Sdf> SdfIntersection { } impl, U: Sdf> Sdf for SdfIntersection { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { self.sdf_a.sdf(p).max(self.sdf_b.sdf(p)) } } @@ -170,7 +170,7 @@ impl, U: Sdf> SdfDifference { } impl, U: Sdf> Sdf for SdfDifference { - fn sdf(&self, p: Point) -> FloatValue { + fn sdf(&self, p: &Point) -> FloatValue { self.sdf_a.sdf(p).max(-self.sdf_b.sdf(p)) } } diff --git a/bampy/src/slicer/slice_path.rs b/bampy/src/slicer/slice_path.rs index a0bc4fb..fa42a7c 100644 --- a/bampy/src/slicer/slice_path.rs +++ b/bampy/src/slicer/slice_path.rs @@ -1,4 +1,4 @@ -use std::ops::RangeInclusive; +use std::{collections::VecDeque, ops::RangeInclusive}; use approx::relative_eq; use bvh::aabb::Aabb; @@ -6,7 +6,7 @@ use nalgebra::Point3; use super::{axis::Axis, mesh::Mesh, FloatValue}; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct SlicePath { pub i: usize, pub d: FloatValue, @@ -75,6 +75,34 @@ impl SurfacePathIterator { } } +fn squish(points: &mut Vec>, axis: Axis, d: FloatValue) { + macro_rules! ax { + ($p: expr) => { + $p.coords[axis as usize] + }; + } + let first = ax!(points.first().unwrap()); + let left = points.iter().position(|p| first - ax!(p) > d); + let last = ax!(points.last().unwrap()); + let right = points.iter().rposition(|p| ax!(p) - last > d); + + if let (Some(left), Some(right)) = (left, right) { + if left > right { + // TODO + return; + } + let total = ax!(points[left + 1]) - first; + let delta = ax!(points[left]) - ax!(points[left + 1]); + points.splice( + 0..left, + vec![points[left].lerp(&points[left + 1], (d - total) / delta)], + ); + + let total = last - ax!(points[right + 1]); + let delta = ax!(points[right + 1]) - ax!(points[right]); + } +} + impl Iterator for SurfacePathIterator { type Item = SurfacePath; @@ -82,8 +110,10 @@ impl Iterator for SurfacePathIterator { self.slices.retain_mut(|slice| !slice.is_empty()); let (h_axis, _) = self.axis.other(); + let mut iter = self.slices.iter_mut(); - let ring = self.slices.first_mut()?.pop()?; + let mut ring = iter.next()?.pop()?; + // TODO: squish(&mut ring.points, h_axis, self.nozzle_width); let mut item = Self::Item { i: ring.i..=ring.i, d: ring.d..=ring.d, @@ -92,7 +122,7 @@ impl Iterator for SurfacePathIterator { path: ring.points, }; - for slice in self.slices.iter_mut().skip(1) { + for slice in iter { if *item.i.end() != slice[0].i - 1 { break; } @@ -136,9 +166,11 @@ impl Iterator for SurfacePathIterator { } if let Some(mut ring) = index.map(|i| slice.remove(i)) { + // TODO: squish(&mut ring.points, h_axis, self.nozzle_width); if needs_reverse { ring.points.reverse(); } + item.i = *item.i.start()..=ring.i; item.d = *item.d.start()..=ring.d; item.path.append(&mut ring.points); diff --git a/bampy/src/slicer/trace_surface.rs b/bampy/src/slicer/trace_surface.rs index 56965fe..a794e10 100644 --- a/bampy/src/slicer/trace_surface.rs +++ b/bampy/src/slicer/trace_surface.rs @@ -1,47 +1,48 @@ use bvh::bvh::BvhNode; +use nalgebra::Point3; -use super::{mesh::Mesh, slice_path::SlicePath, z_projection::ToolpathIntersects, FloatValue}; +use crate::slicer::sdf::Sdf3dModifiers; -pub fn trace_surface(slice: &mut SlicePath, surface: &Mesh, a: FloatValue) { - slice.points.retain_mut(|point| { - let mut stack = Vec::::new(); - stack.push(0); - while let Some(i) = stack.pop() { - match surface.bvh.nodes[i] { - BvhNode::Node { - parent_index: _, - child_l_index, - child_l_aabb, - child_r_index, - child_r_aabb, - } => { - if child_l_aabb.toolpath_intersects(point, a) { - stack.push(child_l_index); - } - if child_r_aabb.toolpath_intersects(point, a) { - stack.push(child_r_index); - } +use super::{ + mesh::Mesh, + sdf::{Sdf, SdfInfiniteCone}, + z_projection::ToolpathIntersects, + FloatValue, +}; + +pub fn trace_surface(point: &Point3, surface: &Mesh, a: FloatValue) -> bool { + let sdf = SdfInfiniteCone::new(a); + let mut stack = Vec::::new(); + stack.push(0); + while let Some(i) = stack.pop() { + match surface.bvh.nodes[i] { + BvhNode::Node { + parent_index: _, + child_l_index, + child_l_aabb, + child_r_index, + child_r_aabb, + } => { + if child_l_aabb.toolpath_intersects(point, a) { + stack.push(child_l_index); } - BvhNode::Leaf { - parent_index: _, - shape_index, - } => { - let triangle = &surface.triangles[shape_index]; - macro_rules! check { - ( $var:ident ) => {{ - let x = point.x - triangle.$var.x; - let y = point.y - triangle.$var.y; - (point.z > triangle.aabb.min.z - && FloatValue::sqrt(x * x + y * y) - < (triangle.$var.z - point.z).abs() * a) - }}; - } - if check!(a) || check!(b) || check!(c) { - return false; - } + if child_r_aabb.toolpath_intersects(point, a) { + stack.push(child_r_index); + } + } + BvhNode::Leaf { + parent_index: _, + shape_index, + } => { + let triangle = &surface.triangles[shape_index]; + if sdf.translate(triangle.a).sdf(point) < 0.0 + || sdf.translate(triangle.b).sdf(point) < 0.0 + || sdf.translate(triangle.c).sdf(point) < 0.0 + { + return false; } } } - true - }); + } + return true; } diff --git a/bampy/src/slicer/triangle.rs b/bampy/src/slicer/triangle.rs index 94ceb5e..6cc4a29 100644 --- a/bampy/src/slicer/triangle.rs +++ b/bampy/src/slicer/triangle.rs @@ -26,7 +26,7 @@ impl Triangle { a, b, c, - normal: (b - a).cross(&(c - a)).into(), + normal: (b - a).cross(&(c - a)).normalize(), node_index: 0, aabb, } @@ -44,13 +44,6 @@ impl Triangle { self.has_point(other.a) || self.has_point(other.b) || self.has_point(other.c) } - pub fn shares_edge_with_triangle(&self, other: Triangle) -> bool { - let a = self.has_point(other.a); - let b = self.has_point(other.b); - let c = self.has_point(other.c); - a && b || a && c || b && c - } - pub fn intersect(&self, value: FloatValue, axis: usize) -> Option { let mut intersection = Vec::>::with_capacity(3); let mut last = &self.c; diff --git a/flake.nix b/flake.nix index 2f78f9d..d6cc9ab 100644 --- a/flake.nix +++ b/flake.nix @@ -4,59 +4,77 @@ rust-overlay.url = "github:oxalica/rust-overlay"; flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { - self, - nixpkgs, - flake-utils, - rust-overlay, - }: - flake-utils.lib.eachDefaultSystem (system: let - overlays = [(import rust-overlay)]; - pkgs = import nixpkgs {inherit system overlays;}; - rust-bin = pkgs.rust-bin.stable.latest.default.override { - targets = [ "wasm32-unknown-unknown" ]; - extensions = ["rust-src" "rust-std" "clippy" "rust-analyzer"]; - }; - fontMin = pkgs.python311.withPackages (ps: with ps; [brotli fonttools] ++ (with fonttools.optional-dependencies; [woff])); - tauriPkgs = nixpkgs.legacyPackages.${system}; - libraries = with tauriPkgs; [ - webkitgtk - gtk3 - cairo - gdk-pixbuf - glib - dbus - openssl_3 - librsvg - ]; - packages = - (with pkgs; [ - nodejs_18 - nodePackages.pnpm - rust-bin - fontMin - wasm-pack - ]) - ++ (with tauriPkgs; [ - curl - wget - pkg-config + outputs = + { + self, + nixpkgs, + flake-utils, + rust-overlay, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + rust-bin = pkgs.rust-bin.nightly.latest.default.override { + targets = [ "wasm32-unknown-unknown" ]; + extensions = [ + "rust-src" + "rust-std" + "clippy" + "rust-analyzer" + ]; + }; + fontMin = pkgs.python311.withPackages ( + ps: + with ps; + [ + brotli + fonttools + ] + ++ (with fonttools.optional-dependencies; [ woff ]) + ); + tauriPkgs = nixpkgs.legacyPackages.${system}; + libraries = with tauriPkgs; [ + webkitgtk + gtk3 + cairo + gdk-pixbuf + glib dbus openssl_3 - glib - gtk3 - libsoup - webkitgtk librsvg - # serial plugin - udev - ]); - in { - devShell = pkgs.mkShell { - buildInputs = packages; - shellHook = '' - export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath libraries}:$LD_LIBRARY_PATH - ''; - }; - }); + ]; + packages = + (with pkgs; [ + nodejs_18 + nodePackages.pnpm + rust-bin + fontMin + wasm-pack + ]) + ++ (with tauriPkgs; [ + curl + wget + pkg-config + dbus + openssl_3 + glib + gtk3 + libsoup + webkitgtk + librsvg + # serial plugin + udev + ]); + in + { + devShell = pkgs.mkShell { + buildInputs = packages; + shellHook = '' + export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath libraries}:$LD_LIBRARY_PATH + ''; + }; + } + ); } diff --git a/src/lib/components/Scene.svelte b/src/lib/components/Scene.svelte index 6f0dd05..bb1b9af 100644 --- a/src/lib/components/Scene.svelte +++ b/src/lib/components/Scene.svelte @@ -33,16 +33,17 @@ progressLayer.set(event.data.layer); break; } - case 'layer': { + case 'result': { layers.update((layers) => { - const layer = event.data.data; - if (layer.type === 'ring' || layer.type === 'path') { - layers.push( - Array.from({ length: layer.position.length / 3 }, (_, i) => - new Vector3().fromArray(layer.position, i * 3) - ) - ); - } else if (layer.type === 'surface') { + for (const layer of event.data.data.slices) { + if (layer.type === 'ring' || layer.type === 'path') { + layers.push( + Array.from({ length: layer.position.length / 3 }, (_, i) => + new Vector3().fromArray(layer.position, i * 3) + ) + ); + } else if (layer.type === 'surface') { + } } return layers; }); @@ -81,7 +82,7 @@ tolerance, maxNonPlanarAngle, nozzleDiameter, - minSurfacePathLength: nozzleDiameter * 4, + minSurfacePathLength: nozzleDiameter * 2, bedNormal: bedNormal.toArray() } } satisfies SliceEvent); @@ -111,7 +112,7 @@ - + {/each} diff --git a/src/lib/slicer/worker.ts b/src/lib/slicer/worker.ts index a9d21df..e75159e 100644 --- a/src/lib/slicer/worker.ts +++ b/src/lib/slicer/worker.ts @@ -22,11 +22,9 @@ addEventListener('message', async (event: MessageEvent) => { nozzleDiameter: event.data.data.nozzleDiameter, minSurfacePathLength: event.data.data.minSurfacePathLength }); - for (const layer of result.slices) { - self.postMessage({ - type: 'layer', - data: layer - }); - } + self.postMessage({ + type: 'result', + data: result + }); } });