diff --git a/lib/Slic3r/GUI/Plater/ObjectDialog.pm b/lib/Slic3r/GUI/Plater/ObjectDialog.pm index 9b851ff7..c7f46f2a 100644 --- a/lib/Slic3r/GUI/Plater/ObjectDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectDialog.pm @@ -119,7 +119,7 @@ sub new { $self->{object} = $params{object}; my $sizer = Wx::BoxSizer->new(wxVERTICAL); - $sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object->mesh), 1, wxEXPAND, 0); + $sizer->Add(Slic3r::GUI::PreviewCanvas->new($self, $self->{object}->get_model_object), 1, wxEXPAND, 0); $self->SetSizer($sizer); $sizer->SetSizeHints($self); diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm index 493d3f0f..065027e8 100644 --- a/lib/Slic3r/GUI/PreviewCanvas.pm +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -7,37 +7,56 @@ use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL use OpenGL qw(:glconstants :glfunctions :glufunctions); use base qw(Wx::GLCanvas Class::Accessor); use Math::Trig qw(asin); -use List::Util qw(reduce min max); +use List::Util qw(reduce min max first); use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan); use Wx::GLCanvas qw(:all); __PACKAGE__->mk_accessors( qw(quat dirty init mview_init - mesh_center mesh_size - verts norms initpos + object_center object_size + volumes initpos sphi stheta) ); use constant TRACKBALLSIZE => 0.8; use constant TURNTABLE_MODE => 1; +use constant COLORS => [ [1,1,1], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ]; sub new { - my ($class, $parent, $mesh) = @_; + my ($class, $parent, $object) = @_; my $self = $class->SUPER::new($parent); $self->quat((0, 0, 0, 1)); $self->sphi(45); $self->stheta(-45); - # prepare mesh - { - $mesh->align_to_origin; - $self->mesh_center($mesh->center); - $self->mesh_size($mesh->size); + $object->align_to_origin; + $self->object_center($object->center); + $self->object_size($object->size); + + # group mesh(es) by material + my @materials = (); + $self->volumes([]); + foreach my $volume (@{$object->volumes}) { + my $mesh = $volume->mesh; - my @verts = map @{ $mesh->vertices->[$_] }, map @$_, @{$mesh->facets}; - $self->verts(OpenGL::Array->new_list(GL_FLOAT, @verts)); + my $material_id = $volume->material_id // '_'; + my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials; + if (!defined $color_idx) { + push @materials, $material_id; + $color_idx = $#materials; + } + push @{$self->volumes}, my $v = { + color => COLORS->[ $color_idx % scalar(@{&COLORS}) ], + }; - my @norms = map { @$_, @$_, @$_ } map normalize(triangle_normal(map $mesh->vertices->[$_], @$_)), @{$mesh->facets}; - $self->norms(OpenGL::Array->new_list(GL_FLOAT, @norms)); + { + my @verts = map @{ $mesh->vertices->[$_] }, map @$_, @{$mesh->facets}; + $v->{verts} = OpenGL::Array->new_list(GL_FLOAT, @verts); + } + + { + my @norms = map { @$_, @$_, @$_ } map normalize(triangle_normal(map $mesh->vertices->[$_], @$_)), @{$mesh->facets}; + $v->{norms} = OpenGL::Array->new_list(GL_FLOAT, @norms); + } } EVT_PAINT($self, sub { @@ -277,7 +296,7 @@ sub ResetModelView { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); my $win_size = $self->GetClientSize(); - my $ratio = $factor * min($win_size->width, $win_size->height) / max(@{ $self->mesh_size }); + my $ratio = $factor * min($win_size->width, $win_size->height) / max(@{ $self->object_size }); glScalef($ratio, $ratio, 1); } @@ -292,8 +311,8 @@ sub Resize { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - my $mesh_size = $self->mesh_size; - glOrtho(-$x/2, $x/2, -$y/2, $y/2, 0.5, 2 * max(@$mesh_size)); + my $object_size = $self->object_size; + glOrtho(-$x/2, $x/2, -$y/2, $y/2, 0.5, 2 * max(@$object_size)); glMatrixMode(GL_MODELVIEW); unless ($self->mview_init) { @@ -350,19 +369,19 @@ sub Render { glPushMatrix(); - my $mesh_size = $self->mesh_size; - glTranslatef(0, 0, -max(@$mesh_size[0..1])); + my $object_size = $self->object_size; + glTranslatef(0, 0, -max(@$object_size[0..1])); my @rotmat = quat_to_rotmatrix($self->quat); glMultMatrixd_p(@rotmat[0..15]); glRotatef($self->stheta, 1, 0, 0); glRotatef($self->sphi, 0, 0, 1); - glTranslatef(map -$_, @{ $self->mesh_center }); + glTranslatef(map -$_, @{ $self->object_center }); $self->draw_mesh; # draw axes { - my $axis_len = 2 * max(@{ $self->mesh_size }); + my $axis_len = 2 * max(@{ $self->object_size }); glLineWidth(2); glBegin(GL_LINES); # draw line for x axis @@ -421,12 +440,14 @@ sub draw_mesh { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer_p(3, $self->verts); - - glCullFace(GL_BACK); - glNormalPointer_p($self->norms); - glColor3f(1, 1, 1); - glDrawArrays(GL_TRIANGLES, 0, $self->verts->elements / 3); + foreach my $volume (@{$self->volumes}) { + glVertexPointer_p(3, $volume->{verts}); + + glCullFace(GL_BACK); + glNormalPointer_p($volume->{norms}); + glColor3f(@{ $volume->{color} }); + glDrawArrays(GL_TRIANGLES, 0, $volume->{verts}->elements / 3); + } glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/utils/view-mesh.pl b/utils/view-mesh.pl index 3e4d2723..e4d36267 100644 --- a/utils/view-mesh.pl +++ b/utils/view-mesh.pl @@ -27,7 +27,7 @@ my %opt = (); { my $model = Slic3r::Model->read_from_file($ARGV[0]); - $Slic3r::ViewMesh::mesh = $model->mesh; + $Slic3r::ViewMesh::object = $model->objects->[0]; my $app = Slic3r::ViewMesh->new; $app->MainLoop; } @@ -49,7 +49,7 @@ package Slic3r::ViewMesh; use Wx qw(:sizer); use base qw(Wx::App); -our $mesh; +our $object; sub OnInit { my $self = shift; @@ -58,7 +58,7 @@ sub OnInit { my $panel = Wx::Panel->new($frame, -1); my $sizer = Wx::BoxSizer->new(wxVERTICAL); - $sizer->Add(Slic3r::GUI::PreviewCanvas->new($panel, $mesh), 1, wxEXPAND, 0); + $sizer->Add(Slic3r::GUI::PreviewCanvas->new($panel, $object), 1, wxEXPAND, 0); $panel->SetSizer($sizer); $sizer->SetSizeHints($panel);