Display bed shape in 3D plater

This commit is contained in:
Alessandro Ranellucci 2014-07-15 21:58:03 +02:00
parent aa723db39b
commit 983cf09ee5
6 changed files with 135 additions and 70 deletions

View file

@ -36,6 +36,7 @@ sub update {
return if $self->{model}->objects_count == 0; return if $self->{model}->objects_count == 0;
$self->set_bounding_box($self->{model}->bounding_box); $self->set_bounding_box($self->{model}->bounding_box);
$self->set_bed_shape($self->{config}->bed_shape);
foreach my $model_object (@{$self->{model}->objects}) { foreach my $model_object (@{$self->{model}->objects}) {
$self->load_object($model_object, 1); $self->load_object($model_object, 1);

View file

@ -88,6 +88,8 @@ sub new {
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::PreviewCanvas->new($self); $canvas = $self->{canvas} = Slic3r::GUI::PreviewCanvas->new($self);
$canvas->load_object($self->{model_object}); $canvas->load_object($self->{model_object});
$canvas->set_bounding_box($self->{model_object}->bounding_box);
$canvas->set_auto_bed_shape;
$canvas->SetSize([500,500]); $canvas->SetSize([500,500]);
$canvas->SetMinSize($canvas->GetSize); $canvas->SetMinSize($canvas->GetSize);
} }

View file

@ -70,6 +70,8 @@ sub new {
if ($Slic3r::GUI::have_OpenGL) { if ($Slic3r::GUI::have_OpenGL) {
$canvas = $self->{canvas} = Slic3r::GUI::PreviewCanvas->new($self); $canvas = $self->{canvas} = Slic3r::GUI::PreviewCanvas->new($self);
$canvas->load_object($self->{model_object}); $canvas->load_object($self->{model_object});
$canvas->set_bounding_box($self->{model_object}->bounding_box);
$canvas->set_auto_bed_shape;
$canvas->SetSize([500,500]); $canvas->SetSize([500,500]);
} }

View file

@ -15,6 +15,8 @@ sub new {
my $canvas = Slic3r::GUI::PreviewCanvas->new($self); my $canvas = Slic3r::GUI::PreviewCanvas->new($self);
$canvas->load_object($self->{model_object}); $canvas->load_object($self->{model_object});
$canvas->set_bounding_box($self->{model_object}->bounding_box);
$canvas->set_auto_bed_shape;
my $sizer = Wx::BoxSizer->new(wxVERTICAL); my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$sizer->Add($canvas, 1, wxEXPAND, 0); $sizer->Add($canvas, 1, wxEXPAND, 0);

View file

@ -9,19 +9,23 @@ use base qw(Wx::GLCanvas Class::Accessor);
use Math::Trig qw(asin); use Math::Trig qw(asin);
use List::Util qw(reduce min max first); use List::Util qw(reduce min max first);
use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scale unscale); use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scale unscale);
use Slic3r::Geometry::Clipper qw(offset_ex); use Slic3r::Geometry::Clipper qw(offset_ex intersection_pl);
use Wx::GLCanvas qw(:all); use Wx::GLCanvas qw(:all);
__PACKAGE__->mk_accessors( qw(quat dirty init mview_init __PACKAGE__->mk_accessors( qw(quat dirty init mview_init
object_bounding_box object_shift object_bounding_box
volumes initpos volumes initpos
sphi stheta sphi stheta
cutting_plane_z cutting_plane_z
cut_lines_vertices cut_lines_vertices
bed_triangles
bed_grid_lines
origin
) ); ) );
use constant TRACKBALLSIZE => 0.8; use constant TRACKBALLSIZE => 0.8;
use constant TURNTABLE_MODE => 1; use constant TURNTABLE_MODE => 1;
use constant GROUND_Z => 0.02;
use constant SELECTED_COLOR => [0,1,0,1]; use constant SELECTED_COLOR => [0,1,0,1];
use constant COLORS => [ [1,1,0], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ]; use constant COLORS => [ [1,1,0], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ];
@ -43,14 +47,14 @@ sub new {
EVT_PAINT($self, sub { EVT_PAINT($self, sub {
my $dc = Wx::PaintDC->new($self); my $dc = Wx::PaintDC->new($self);
return if !@{$self->volumes}; return if !$self->object_bounding_box;
$self->Render($dc); $self->Render($dc);
}); });
EVT_SIZE($self, sub { $self->dirty(1) }); EVT_SIZE($self, sub { $self->dirty(1) });
EVT_IDLE($self, sub { EVT_IDLE($self, sub {
return unless $self->dirty; return unless $self->dirty;
return if !$self->IsShownOnScreen; return if !$self->IsShownOnScreen;
return if !@{$self->volumes}; return if !$self->object_bounding_box;
$self->Resize( $self->GetSizeWH ); $self->Resize( $self->GetSizeWH );
$self->Refresh; $self->Refresh;
}); });
@ -92,19 +96,62 @@ sub reset_objects {
sub set_bounding_box { sub set_bounding_box {
my ($self, $bb) = @_; my ($self, $bb) = @_;
my $center = $bb->center;
$self->object_shift(Slic3r::Pointf3->new(-$center->x, -$center->y, -$bb->z_min)); #,,
$bb->translate(@{ $self->object_shift });
$self->object_bounding_box($bb); $self->object_bounding_box($bb);
$self->dirty(1); $self->dirty(1);
} }
sub set_auto_bed_shape {
my ($self, $bed_shape) = @_;
# draw a default square bed around object center
my $max_size = max(@{ $self->object_bounding_box->size });
my $center = $self->object_bounding_box->center;
$self->set_bed_shape([
[ $center->x - $max_size, $center->y - $max_size ], #--
[ $center->x + $max_size, $center->y - $max_size ], #--
[ $center->x + $max_size, $center->y + $max_size ], #++
[ $center->x - $max_size, $center->y + $max_size ], #++
]);
$self->origin(Slic3r::Pointf->new(@$center[X,Y]));
}
sub set_bed_shape {
my ($self, $bed_shape) = @_;
# triangulate bed
my $expolygon = Slic3r::ExPolygon->new([ map [map scale($_), @$_], @$bed_shape ]);
my $bed_bb = $expolygon->bounding_box;
{
my @points = ();
foreach my $triangle (@{ $expolygon->triangulate }) {
push @points, map {+ unscale($_->x), unscale($_->y), GROUND_Z } @$triangle; #))
}
$self->bed_triangles(OpenGL::Array->new_list(GL_FLOAT, @points));
}
{
my @lines = ();
for (my $x = $bed_bb->x_min; $x <= $bed_bb->x_max; $x += scale 10) {
push @lines, Slic3r::Polyline->new([$x,$bed_bb->y_min], [$x,$bed_bb->y_max]);
}
for (my $y = $bed_bb->y_min; $y <= $bed_bb->y_max; $y += scale 10) {
push @lines, Slic3r::Polyline->new([$bed_bb->x_min,$y], [$bed_bb->x_max,$y]);
}
@lines = @{intersection_pl(\@lines, [ @$expolygon ])};
my @points = ();
foreach my $polyline (@lines) {
push @points, map {+ unscale($_->x), unscale($_->y), GROUND_Z } @$polyline; #))
}
$self->bed_grid_lines(OpenGL::Array->new_list(GL_FLOAT, @points));
}
$self->origin(Slic3r::Pointf->new(0,0));
}
sub load_object { sub load_object {
my ($self, $object, $all_instances) = @_; my ($self, $object, $all_instances) = @_;
$self->set_bounding_box($object->instance_bounding_box)
if !$all_instances;
# group mesh(es) by material # group mesh(es) by material
my @materials = (); my @materials = ();
@ -115,8 +162,7 @@ sub load_object {
foreach my $instance (@instances) { foreach my $instance (@instances) {
my $mesh = $volume->mesh->clone; my $mesh = $volume->mesh->clone;
$instance->transform_mesh($mesh); $instance->transform_mesh($mesh);
$mesh->translate(@{ $self->object_shift });
my $material_id = $volume->material_id // '_'; my $material_id = $volume->material_id // '_';
my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials; my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials;
if (!defined $color_idx) { if (!defined $color_idx) {
@ -338,6 +384,8 @@ sub ZoomTo {
sub Zoom { sub Zoom {
my ($self, $factor) = @_; my ($self, $factor) = @_;
glMatrixMode(GL_MODELVIEW);
glScalef($factor, $factor, 1); glScalef($factor, $factor, 1);
} }
@ -367,7 +415,7 @@ sub ResetModelView {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
my $win_size = $self->GetClientSize(); my $win_size = $self->GetClientSize();
my $ratio = $factor * min($win_size->width, $win_size->height) / max(@{ $self->object_bounding_box->size }); my $ratio = $factor * min($win_size->width, $win_size->height) / (2 * max(@{ $self->object_bounding_box->size }));
glScalef($ratio, $ratio, 1); glScalef($ratio, $ratio, 1);
} }
@ -384,7 +432,7 @@ sub Resize {
glLoadIdentity(); glLoadIdentity();
glOrtho( glOrtho(
-$x/2, $x/2, -$y/2, $y/2, -$x/2, $x/2, -$y/2, $y/2,
0.5, 5 * max(@{ $self->object_bounding_box->size }), -200, 10 * max(@{ $self->object_bounding_box->size }),
); );
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -450,73 +498,81 @@ sub Render {
glClearDepth(1); glClearDepth(1);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
my $object_size = $self->object_bounding_box->size; my $bb = $self->object_bounding_box;
my $object_size = $bb->size;
glTranslatef(0, 0, -max(@$object_size[0..1])); glTranslatef(0, 0, -max(@$object_size[0..1]));
my @rotmat = quat_to_rotmatrix($self->quat); my @rotmat = quat_to_rotmatrix($self->quat);
glMultMatrixd_p(@rotmat[0..15]); glMultMatrixd_p(@rotmat[0..15]);
glRotatef($self->stheta, 1, 0, 0); glRotatef($self->stheta, 1, 0, 0);
glRotatef($self->sphi, 0, 0, 1); glRotatef($self->sphi, 0, 0, 1);
my $center = $self->object_bounding_box->center; # center everything around 0,0 since that's where we're looking at (glOrtho())
glTranslatef(-$center->x, -$center->y, -$center->z); #,, my $center = $bb->center;
glTranslatef(-$center->x, -$center->y, 0); #,,
# draw objects
$self->draw_mesh; $self->draw_mesh;
glDisable(GL_LIGHTING); # raise everything so that we draw our plane at Z = 0
glTranslatef(0, 0, +$bb->z_min);
# draw ground and axes
glDisable(GL_LIGHTING);
my $z0 = 0; my $z0 = 0;
# draw axes
{ {
my $axis_len = 2 * max(@{ $object_size });
glLineWidth(2);
glBegin(GL_LINES);
# draw line for x axis
glColor3f(1, 0, 0);
glVertex3f(0, 0, $z0);
glVertex3f($axis_len, 0, $z0);
# draw line for y axis
glColor3f(0, 1, 0);
glVertex3f(0, 0, $z0);
glVertex3f(0, $axis_len, $z0);
# draw line for Z axis
glColor3f(0, 0, 1);
glVertex3f(0, 0, $z0);
glVertex3f(0, 0, $z0+$axis_len);
glEnd();
# draw ground # draw ground
my $ground_z = $z0-0.02; my $ground_z = GROUND_Z;
glDisable(GL_CULL_FACE); if ($self->bed_triangles) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS); glEnable(GL_CULL_FACE);
glColor4f(0.5, 0.5, 0.5, 0.3);
glNormal3d(0,0,1); glEnableClientState(GL_VERTEX_ARRAY);
glVertex3f(-$axis_len, -$axis_len, $ground_z); glColor4f(0.5, 0.5, 0.5, 0.3);
glVertex3f($axis_len, -$axis_len, $ground_z); glNormal3d(0,0,1);
glVertex3f($axis_len, $axis_len, $ground_z); glVertexPointer_p(3, $self->bed_triangles);
glVertex3f(-$axis_len, $axis_len, $ground_z); glDrawArrays(GL_TRIANGLES, 0, $self->bed_triangles->elements / 3);
glEnd(); glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE); glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
# draw grid # draw grid
glLineWidth(3); glTranslatef(0, 0, 0.02);
glColor3f(1.0, 1.0, 1.0); glLineWidth(3);
glBegin(GL_LINES); glColor3f(1.0, 1.0, 1.0);
$ground_z += 0.02; glEnableClientState(GL_VERTEX_ARRAY);
for (my $x = -$axis_len; $x <= $axis_len; $x += 10) { glVertexPointer_p(3, $self->bed_grid_lines);
glVertex3f($x, -$axis_len, $ground_z); glDrawArrays(GL_LINES, 0, $self->bed_grid_lines->elements / 3);
glVertex3f($x, $axis_len, $ground_z); glDisableClientState(GL_VERTEX_ARRAY);
} }
for (my $y = -$axis_len; $y <= $axis_len; $y += 10) {
glVertex3f(-$axis_len, $y, $ground_z); {
glVertex3f($axis_len, $y, $ground_z); # draw axes
$ground_z += 0.02;
my $origin = $self->origin;
my $axis_len = 2 * max(@{ $object_size });
glLineWidth(2);
glBegin(GL_LINES);
# draw line for x axis
glColor3f(1, 0, 0);
glVertex3f(@$origin, $ground_z);
glVertex3f($origin->x + $axis_len, $origin->y, $ground_z); #,,
# draw line for y axis
glColor3f(0, 1, 0);
glVertex3f(@$origin, $ground_z);
glVertex3f($origin->x, $origin->y + $axis_len, $ground_z); #++
# draw line for Z axis
glColor3f(0, 0, 1);
glVertex3f(@$origin, $ground_z);
glVertex3f(@$origin, $ground_z+$axis_len);
glEnd();
} }
glEnd();
# draw cutting plane # draw cutting plane
if (defined $self->cutting_plane_z) { if (defined $self->cutting_plane_z) {
@ -526,10 +582,10 @@ sub Render {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glColor4f(0.8, 0.8, 0.8, 0.5); glColor4f(0.8, 0.8, 0.8, 0.5);
glVertex3f(-$axis_len, -$axis_len, $plane_z); glVertex3f($bb->x_min-20, $bb->y_min-20, $plane_z);
glVertex3f($axis_len, -$axis_len, $plane_z); glVertex3f($bb->x_max+20, $bb->y_min-20, $plane_z);
glVertex3f($axis_len, $axis_len, $plane_z); glVertex3f($bb->x_max+20, $bb->y_max+20, $plane_z);
glVertex3f(-$axis_len, $axis_len, $plane_z); glVertex3f($bb->x_min-20, $bb->y_max+20, $plane_z);
glEnd(); glEnd();
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glDisable(GL_BLEND); glDisable(GL_BLEND);
@ -537,7 +593,7 @@ sub Render {
} }
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glPopMatrix(); glPopMatrix();
glFlush(); glFlush();

View file

@ -33,6 +33,8 @@ my %opt = ();
my $app = Slic3r::ViewMesh->new; my $app = Slic3r::ViewMesh->new;
$app->{canvas}->load_object($model->objects->[0]); $app->{canvas}->load_object($model->objects->[0]);
$app->{canvas}->set_bounding_box($model->objects->[0]->bounding_box);
$app->{canvas}->set_auto_bed_shape;
$app->{canvas}->SetCuttingPlane($opt{cut}) if defined $opt{cut}; $app->{canvas}->SetCuttingPlane($opt{cut}) if defined $opt{cut};
$app->MainLoop; $app->MainLoop;
} }