From e0a3d2577c7d0b29963caf9fb4cffc0e55d0bd2c Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 15 Jan 2015 20:06:30 +0100 Subject: [PATCH] Initial work for 3D rendering of toolpaths --- lib/Slic3r/GUI/3DScene.pm | 118 +++++++++++++++++- utils/view-toolpaths.pl | 3 +- xs/src/libslic3r/ExtrusionEntity.cpp | 19 +++ xs/src/libslic3r/ExtrusionEntity.hpp | 3 + .../libslic3r/ExtrusionEntityCollection.cpp | 11 ++ .../libslic3r/ExtrusionEntityCollection.hpp | 1 + xs/src/libslic3r/Line.cpp | 7 ++ xs/src/libslic3r/Line.hpp | 1 + xs/xsp/ExtrusionEntityCollection.xsp | 1 + xs/xsp/ExtrusionLoop.xsp | 1 + xs/xsp/ExtrusionPath.xsp | 1 + xs/xsp/Line.xsp | 2 + 12 files changed, 166 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 1ffe09a12..5d262dc41 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -891,7 +891,7 @@ use base qw(Slic3r::GUI::3DScene::Base); use OpenGL qw(:glconstants :gluconstants :glufunctions); use List::Util qw(first); -use Slic3r::Geometry qw(unscale); +use Slic3r::Geometry qw(scale unscale); use constant COLORS => [ [1,1,0,1], [1,0.5,0.5,1], [0.5,1,0.5,1], [0.5,0.5,1,1] ]; @@ -1038,6 +1038,41 @@ sub load_print_object_slices { ); } +sub load_print_object_toolpaths { + my ($self, $object) = @_; + + my @quad_verts = (); + my @quad_norms = (); + foreach my $layer (@{$object->layers}) { + my $top_z = $layer->print_z; + my $bottom_z = $layer->print_z - $layer->height; + + foreach my $copy (@{ $object->_shifted_copies }) { + foreach my $layerm (@{$layer->regions}) { + foreach my $entity (map @$_, @{$layerm->perimeters}) { + if ($entity->isa('Slic3r::ExtrusionPath')) { + $self->_extrusionpath_to_verts($entity, $top_z, $copy, \@quad_verts, \@quad_norms); + } else { + $self->_extrusionpath_to_verts($_, $top_z, $copy, \@quad_verts, \@quad_norms) for @$entity; + } + } + } + } + } + + my $obb = $object->bounding_box; + my $bb = Slic3r::Geometry::BoundingBoxf3->new; + $bb->merge_point(Slic3r::Pointf3->new_unscale(@{$obb->min_point}, 0)); + $bb->merge_point(Slic3r::Pointf3->new_unscale(@{$obb->max_point}, $object->size->z)); + + push @{$self->volumes}, my $v = Slic3r::GUI::3DScene::Volume->new( + bounding_box => $bb, + color => COLORS->[0], + quad_verts => OpenGL::Array->new_list(GL_FLOAT, @quad_verts), + quad_norms => OpenGL::Array->new_list(GL_FLOAT, @quad_norms), + ); +} + sub _expolygons_to_verts { my ($self, $expolygons, $z, $verts, $norms) = @_; @@ -1066,6 +1101,87 @@ sub _expolygons_to_verts { gluDeleteTess($tess); } +sub _extrusionpath_to_verts { + my ($self, $path, $top_z, $copy, $verts, $norms) = @_; + + my $bottom_z = $top_z - $path->height; + my $middle_z = ($top_z + $bottom_z) / 2; + my $dist = scale $path->width/2; + + foreach my $line (@{$path->polyline->lines}) { + my $len = $line->length; + next if $len == 0; + $line->translate(@$copy); + + my $v = Slic3r::Pointf3->new_unscale(@{$line->vector}); + $v->scale(1/unscale $len); + + my $a = $line->a; + my $b = $line->b; + my $a1 = $a->clone; + my $a2 = $a->clone; + $a1->translate(+$dist*$v->y, -$dist*$v->x); #,, + $a2->translate(-$dist*$v->y, +$dist*$v->x); #,, + my $b1 = $b->clone; + my $b2 = $b->clone; + $b1->translate(+$dist*$v->y, -$dist*$v->x); #,, + $b2->translate(-$dist*$v->y, +$dist*$v->x); #,, + + # calculate normal going to the right + my $xy_normal = Slic3r::Pointf3->new_unscale(@{$line->normal}, 0); + $xy_normal->scale(1/unscale $len); + + # bottom-right face + { + # normal going downwards + push @$norms, (0,0,-1), (0,0,-1); + push @$verts, (map unscale($_), @$a), $bottom_z; + push @$verts, (map unscale($_), @$b), $bottom_z; + + push @$norms, @$xy_normal, @$xy_normal; + push @$verts, (map unscale($_), @$b1), $middle_z; + push @$verts, (map unscale($_), @$a1), $middle_z; + } + + # top-right face + { + push @$norms, @$xy_normal, @$xy_normal; + push @$verts, (map unscale($_), @$a1), $middle_z; + push @$verts, (map unscale($_), @$b1), $middle_z; + + # normal going upwards + push @$norms, (0,0,1), (0,0,1); + push @$verts, (map unscale($_), @$b), $top_z; + push @$verts, (map unscale($_), @$a), $top_z; + } + + # top-left face + { + push @$norms, (0,0,1), (0,0,1); + push @$verts, (map unscale($_), @$a), $top_z; + push @$verts, (map unscale($_), @$b), $top_z; + + # calculate normal going to the left + $xy_normal->scale(-1); + push @$norms, @$xy_normal, @$xy_normal; + push @$verts, (map unscale($_), @$b2), $middle_z; + push @$verts, (map unscale($_), @$a2), $middle_z; + } + + # bottom-left face + { + push @$norms, @$xy_normal, @$xy_normal; + push @$verts, (map unscale($_), @$a2), $middle_z; + push @$verts, (map unscale($_), @$b2), $middle_z; + + # normal going downwards + push @$norms, (0,0,-1), (0,0,-1); + push @$verts, (map unscale($_), @$b), $bottom_z; + push @$verts, (map unscale($_), @$a), $bottom_z; + } + } +} + sub object_idx { my ($self, $volume_idx) = @_; return $self->_objects_by_volumes->{$volume_idx}[0]; diff --git a/utils/view-toolpaths.pl b/utils/view-toolpaths.pl index a49421718..7e1d305bc 100755 --- a/utils/view-toolpaths.pl +++ b/utils/view-toolpaths.pl @@ -86,7 +86,8 @@ sub OnInit { $canvas->set_bed_shape($print->config->bed_shape); foreach my $object (@{$print->objects}) { - $canvas->load_print_object_slices($object); + #$canvas->load_print_object_slices($object); + $canvas->load_print_object_toolpaths($object); #$canvas->load_object($object->model_object); } $canvas->zoom_to_volumes; diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp index 843dfda29..38a5b94ae 100644 --- a/xs/src/libslic3r/ExtrusionEntity.cpp +++ b/xs/src/libslic3r/ExtrusionEntity.cpp @@ -164,6 +164,14 @@ ExtrusionPath::gcode(Extruder* extruder, double e, double F, return stream.str(); } +Polygons +ExtrusionPath::grow() const +{ + Polygons pp; + offset(this->polyline, &pp, +this->width/2); + return pp; +} + ExtrusionLoop::operator Polygon() const { Polygon polygon; @@ -363,6 +371,17 @@ ExtrusionLoop::is_solid_infill() const || this->paths.front().role == erTopSolidInfill; } +Polygons +ExtrusionLoop::grow() const +{ + Polygons pp; + for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) { + Polygons path_pp = path->grow(); + pp.insert(pp.end(), path_pp.begin(), path_pp.end()); + } + return pp; +} + #ifdef SLIC3RXS REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop"); #endif diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index c40291190..4fba7fec7 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -43,6 +43,7 @@ class ExtrusionEntity virtual void reverse() = 0; virtual Point first_point() const = 0; virtual Point last_point() const = 0; + virtual Polygons grow() const = 0; }; typedef std::vector ExtrusionEntitiesPtr; @@ -73,6 +74,7 @@ class ExtrusionPath : public ExtrusionEntity std::string gcode(Extruder* extruder, double e, double F, double xofs, double yofs, std::string extrusion_axis, std::string gcode_line_suffix) const; + Polygons grow() const; private: void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; @@ -106,6 +108,7 @@ class ExtrusionLoop : public ExtrusionEntity bool is_perimeter() const; bool is_infill() const; bool is_solid_infill() const; + Polygons grow() const; }; } diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.cpp b/xs/src/libslic3r/ExtrusionEntityCollection.cpp index 4e3c596cf..4ceef0387 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.cpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.cpp @@ -110,6 +110,17 @@ ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEntityCo } } +Polygons +ExtrusionEntityCollection::grow() const +{ + Polygons pp; + for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) { + Polygons entity_pp = (*it)->grow(); + pp.insert(pp.end(), entity_pp.begin(), entity_pp.end()); + } + return pp; +} + #ifdef SLIC3RXS // there is no ExtrusionLoop::Collection or ExtrusionEntity::Collection REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection"); diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/xs/src/libslic3r/ExtrusionEntityCollection.hpp index bc660611b..be557bb5f 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.hpp @@ -22,6 +22,7 @@ class ExtrusionEntityCollection : public ExtrusionEntity void reverse(); Point first_point() const; Point last_point() const; + Polygons grow() const; }; } diff --git a/xs/src/libslic3r/Line.cpp b/xs/src/libslic3r/Line.cpp index 3cce6c971..b98208325 100644 --- a/xs/src/libslic3r/Line.cpp +++ b/xs/src/libslic3r/Line.cpp @@ -201,6 +201,13 @@ Linef3::intersect_plane(double z) const ); } +void +Linef3::scale(double factor) +{ + this->a.scale(factor); + this->b.scale(factor); +} + #ifdef SLIC3RXS REGISTER_CLASS(Linef3, "Linef3"); #endif diff --git a/xs/src/libslic3r/Line.hpp b/xs/src/libslic3r/Line.hpp index 76c385ce6..0b9cc6302 100644 --- a/xs/src/libslic3r/Line.hpp +++ b/xs/src/libslic3r/Line.hpp @@ -55,6 +55,7 @@ class Linef3 Linef3() {}; explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {}; Pointf3 intersect_plane(double z) const; + void scale(double factor); #ifdef SLIC3RXS void from_SV(SV* line_sv); diff --git a/xs/xsp/ExtrusionEntityCollection.xsp b/xs/xsp/ExtrusionEntityCollection.xsp index a5214e939..a7c5a8be0 100644 --- a/xs/xsp/ExtrusionEntityCollection.xsp +++ b/xs/xsp/ExtrusionEntityCollection.xsp @@ -28,6 +28,7 @@ %code{% RETVAL = THIS->entities.empty(); %}; std::vector orig_indices() %code{% RETVAL = THIS->orig_indices; %}; + Polygons grow(); %{ void diff --git a/xs/xsp/ExtrusionLoop.xsp b/xs/xsp/ExtrusionLoop.xsp index 2a8d1f9f4..9319fc24b 100644 --- a/xs/xsp/ExtrusionLoop.xsp +++ b/xs/xsp/ExtrusionLoop.xsp @@ -31,6 +31,7 @@ bool is_perimeter(); bool is_infill(); bool is_solid_infill(); + Polygons grow(); %{ SV* diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index 4fbaea2d6..57fee2b61 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -29,6 +29,7 @@ std::string gcode(Extruder* extruder, double e, double F, double xofs, double yofs, std::string extrusion_axis, std::string gcode_line_suffix); + Polygons grow(); %{ ExtrusionPath* diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index 69d9fbce1..004f9fae2 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -33,6 +33,7 @@ Polyline* as_polyline() %code{% RETVAL = new Polyline(*THIS); %}; Clone normal(); + Clone vector(); %{ Line* @@ -79,4 +80,5 @@ Line::coincides_with(line_sv) Ref b() %code{% RETVAL = &THIS->b; %}; Clone intersect_plane(double z); + void scale(double factor); };