Don't produce incorrect results when models extend beyond build volume
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v0.2.1 — Coming Soon?
|
||||||
|
|
||||||
|
- Don't produce invalid results when models extend beyond build volume
|
||||||
|
|
||||||
## v0.2.0 — Feb 19, 2025
|
## v0.2.0 — Feb 19, 2025
|
||||||
|
|
||||||
- Convert slice operation window to a dockable panel
|
- Convert slice operation window to a dockable panel
|
||||||
|
@@ -14,7 +14,7 @@ use common::{
|
|||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
use crate::{format::FormatSliceResult, mesh::Mesh, segments::Segments1D, Pos};
|
use crate::{format::FormatSliceResult, mesh::Mesh, segments::Segments1D};
|
||||||
|
|
||||||
/// Used to slice a mesh.
|
/// Used to slice a mesh.
|
||||||
pub struct Slicer {
|
pub struct Slicer {
|
||||||
@@ -40,14 +40,14 @@ pub struct ProgressInner {
|
|||||||
impl Slicer {
|
impl Slicer {
|
||||||
/// Creates a new slicer given a slice config and list of models.
|
/// Creates a new slicer given a slice config and list of models.
|
||||||
pub fn new(slice_config: SliceConfig, models: Vec<Mesh>) -> Self {
|
pub fn new(slice_config: SliceConfig, models: Vec<Mesh>) -> Self {
|
||||||
let max = models.iter().fold(Pos::zeros(), |max, model| {
|
let max_z = models.iter().fold(0_f32, |max, model| {
|
||||||
let f = model.vertices().iter().fold(Pos::zeros(), |max, &f| {
|
let verts = model.vertices().iter();
|
||||||
let f = model.transform(&f);
|
let z = verts.fold(0_f32, |max, &f| max.max(model.transform(&f).z));
|
||||||
Pos::new(max.x.max(f.x), max.y.max(f.y), max.z.max(f.z))
|
max.max(z)
|
||||||
});
|
|
||||||
Pos::new(max.x.max(f.x), max.y.max(f.y), max.z.max(f.z))
|
|
||||||
});
|
});
|
||||||
let layers = (max.z / slice_config.slice_height).ceil() as u32;
|
|
||||||
|
let layers = (max_z / slice_config.slice_height).ceil() as u32;
|
||||||
|
let max_layers = (slice_config.platform_size.z / slice_config.slice_height).ceil() as u32;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
slice_config,
|
slice_config,
|
||||||
@@ -55,7 +55,7 @@ impl Slicer {
|
|||||||
progress: Progress {
|
progress: Progress {
|
||||||
inner: Arc::new(ProgressInner {
|
inner: Arc::new(ProgressInner {
|
||||||
completed: AtomicU32::new(0),
|
completed: AtomicU32::new(0),
|
||||||
total: layers,
|
total: layers.min(max_layers),
|
||||||
|
|
||||||
notify: Condvar::new(),
|
notify: Condvar::new(),
|
||||||
last_completed: Mutex::new(0),
|
last_completed: Mutex::new(0),
|
||||||
@@ -77,8 +77,8 @@ impl Slicer {
|
|||||||
|
|
||||||
/// Actually runs the slicing operation, it is multithreaded.
|
/// Actually runs the slicing operation, it is multithreaded.
|
||||||
pub fn slice<Layer: EncodableLayer>(&self) -> SliceResult<Layer::Output> {
|
pub fn slice<Layer: EncodableLayer>(&self) -> SliceResult<Layer::Output> {
|
||||||
let pixels = (self.slice_config.platform_resolution.x
|
let platform_resolution = self.slice_config.platform_resolution;
|
||||||
* self.slice_config.platform_resolution.y) as u64;
|
let pixels = (platform_resolution.x * platform_resolution.y) as u64;
|
||||||
|
|
||||||
// A segment contains a reference to all of the triangles it contains. By
|
// A segment contains a reference to all of the triangles it contains. By
|
||||||
// splitting the mesh into segments, not all triangles need to be tested
|
// splitting the mesh into segments, not all triangles need to be tested
|
||||||
@@ -124,7 +124,7 @@ impl Slicer {
|
|||||||
// across and mark that as an intersection to then be run-length
|
// across and mark that as an intersection to then be run-length
|
||||||
// encoded. There is probably a better polygon filling algo, but
|
// encoded. There is probably a better polygon filling algo, but
|
||||||
// this one works surprisingly fast.
|
// this one works surprisingly fast.
|
||||||
for y in 0..self.slice_config.platform_resolution.y {
|
for y in 0..platform_resolution.y {
|
||||||
let yf = y as f32;
|
let yf = y as f32;
|
||||||
let mut intersections = segments
|
let mut intersections = segments
|
||||||
.iter()
|
.iter()
|
||||||
@@ -155,14 +155,14 @@ impl Slicer {
|
|||||||
depth += (dir as i32) * 2 - 1;
|
depth += (dir as i32) * 2 - 1;
|
||||||
|
|
||||||
if (depth == 0) ^ (prev_depth == 0) {
|
if (depth == 0) ^ (prev_depth == 0) {
|
||||||
filtered.push(pos);
|
filtered.push(pos.clamp(0.0, platform_resolution.x as f32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the intersections into runs of white pixels to be
|
// Convert the intersections into runs of white pixels to be
|
||||||
// encoded into the layer
|
// encoded into the layer
|
||||||
for span in filtered.chunks_exact(2) {
|
for span in filtered.chunks_exact(2) {
|
||||||
let y_offset = (self.slice_config.platform_resolution.x * y) as u64;
|
let y_offset = (platform_resolution.x * y) as u64;
|
||||||
|
|
||||||
let a = span[0].round() as u64;
|
let a = span[0].round() as u64;
|
||||||
let b = span[1].round() as u64;
|
let b = span[1].round() as u64;
|
||||||
|
Reference in New Issue
Block a user