3D object positioning
This commit is contained in:
parent
a82f95e903
commit
fcfb3b98bc
@ -197,6 +197,7 @@ sub thread_cleanup {
|
|||||||
*Slic3r::Geometry::BoundingBoxf::DESTROY = sub {};
|
*Slic3r::Geometry::BoundingBoxf::DESTROY = sub {};
|
||||||
*Slic3r::Geometry::BoundingBoxf3::DESTROY = sub {};
|
*Slic3r::Geometry::BoundingBoxf3::DESTROY = sub {};
|
||||||
*Slic3r::Line::DESTROY = sub {};
|
*Slic3r::Line::DESTROY = sub {};
|
||||||
|
*Slic3r::Linef3::DESTROY = sub {};
|
||||||
*Slic3r::Model::DESTROY = sub {};
|
*Slic3r::Model::DESTROY = sub {};
|
||||||
*Slic3r::Model::Object::DESTROY = sub {};
|
*Slic3r::Model::Object::DESTROY = sub {};
|
||||||
*Slic3r::Point::DESTROY = sub {};
|
*Slic3r::Point::DESTROY = sub {};
|
||||||
|
@ -281,6 +281,10 @@ sub new {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$self->{canvas}->update_bed_size;
|
$self->{canvas}->update_bed_size;
|
||||||
|
if ($self->{canvas3D}) {
|
||||||
|
$self->{canvas3D}->update_bed_size;
|
||||||
|
$self->{canvas3D}->zoom_to_bed;
|
||||||
|
}
|
||||||
$self->update;
|
$self->update;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -513,6 +517,11 @@ sub objects_loaded {
|
|||||||
}
|
}
|
||||||
$self->arrange unless $params{no_arrange};
|
$self->arrange unless $params{no_arrange};
|
||||||
$self->update;
|
$self->update;
|
||||||
|
|
||||||
|
# zoom to objects
|
||||||
|
$self->{canvas3D}->zoom_to_volumes
|
||||||
|
if $self->{canvas3D};
|
||||||
|
|
||||||
$self->{list}->Update;
|
$self->{list}->Update;
|
||||||
$self->{list}->Select($obj_idxs->[-1], 1);
|
$self->{list}->Select($obj_idxs->[-1], 1);
|
||||||
$self->object_list_changed;
|
$self->object_list_changed;
|
||||||
@ -665,7 +674,6 @@ sub rotate {
|
|||||||
|
|
||||||
$self->selection_changed; # refresh info (size etc.)
|
$self->selection_changed; # refresh info (size etc.)
|
||||||
$self->update;
|
$self->update;
|
||||||
$self->refresh_canvases;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub flip {
|
sub flip {
|
||||||
@ -1200,6 +1208,7 @@ sub on_config_change {
|
|||||||
$self->{config}->set($opt_key, $config->get($opt_key));
|
$self->{config}->set($opt_key, $config->get($opt_key));
|
||||||
if ($opt_key eq 'bed_shape') {
|
if ($opt_key eq 'bed_shape') {
|
||||||
$self->{canvas}->update_bed_size;
|
$self->{canvas}->update_bed_size;
|
||||||
|
$self->{canvas3D}->update_bed_size if $self->{canvas3D};
|
||||||
$self->update;
|
$self->update;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,6 @@ sub mouse_event {
|
|||||||
} elsif ($event->LeftUp) {
|
} elsif ($event->LeftUp) {
|
||||||
$self->{on_instance_moved}->(@{ $self->{drag_object} })
|
$self->{on_instance_moved}->(@{ $self->{drag_object} })
|
||||||
if $self->{drag_object};
|
if $self->{drag_object};
|
||||||
$self->Refresh;
|
|
||||||
$self->{drag_start_pos} = undef;
|
$self->{drag_start_pos} = undef;
|
||||||
$self->{drag_object} = undef;
|
$self->{drag_object} = undef;
|
||||||
$self->SetCursor(wxSTANDARD_CURSOR);
|
$self->SetCursor(wxSTANDARD_CURSOR);
|
||||||
|
@ -16,11 +16,13 @@ sub new {
|
|||||||
|
|
||||||
my $self = $class->SUPER::new($parent);
|
my $self = $class->SUPER::new($parent);
|
||||||
$self->enable_picking(1);
|
$self->enable_picking(1);
|
||||||
|
$self->enable_moving(1);
|
||||||
|
|
||||||
$self->{objects} = $objects;
|
$self->{objects} = $objects;
|
||||||
$self->{model} = $model;
|
$self->{model} = $model;
|
||||||
$self->{config} = $config;
|
$self->{config} = $config;
|
||||||
$self->{on_select_object} = sub {};
|
$self->{on_select_object} = sub {};
|
||||||
|
$self->{on_instance_moved} = sub {};
|
||||||
|
|
||||||
$self->on_select(sub {
|
$self->on_select(sub {
|
||||||
my ($volume_idx) = @_;
|
my ($volume_idx) = @_;
|
||||||
@ -40,6 +42,21 @@ sub new {
|
|||||||
my $obj_idx = $self->{_volumes_inv}{$volume_idx};
|
my $obj_idx = $self->{_volumes_inv}{$volume_idx};
|
||||||
$self->volumes->[$_]->hover(1) for @{$self->{_volumes}{$obj_idx}};
|
$self->volumes->[$_]->hover(1) for @{$self->{_volumes}{$obj_idx}};
|
||||||
});
|
});
|
||||||
|
$self->on_move(sub {
|
||||||
|
my ($volume_idx) = @_;
|
||||||
|
|
||||||
|
my $volume = $self->volumes->[$volume_idx];
|
||||||
|
my $obj_idx = $self->{_volumes_inv}{$volume_idx};
|
||||||
|
my $model_object = $self->{model}->get_object($obj_idx);
|
||||||
|
$model_object
|
||||||
|
->instances->[$volume->instance_idx]
|
||||||
|
->offset
|
||||||
|
->translate($volume->origin->x, $volume->origin->y); #))
|
||||||
|
$model_object->invalidate_bounding_box;
|
||||||
|
|
||||||
|
$self->{on_instance_moved}->($obj_idx, $volume->instance_idx)
|
||||||
|
if $self->{on_instance_moved};
|
||||||
|
});
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
@ -61,12 +78,7 @@ sub set_on_right_click {
|
|||||||
|
|
||||||
sub set_on_instance_moved {
|
sub set_on_instance_moved {
|
||||||
my ($self, $cb) = @_;
|
my ($self, $cb) = @_;
|
||||||
$self->on_instance_moved(sub {
|
$self->{on_instance_moved} = $cb;
|
||||||
my ($volume_idx, $instance_idx) = @_;
|
|
||||||
|
|
||||||
my $obj_idx = $self->{_volumes_inv}{$volume_idx};
|
|
||||||
return $cb->($obj_idx, $instance_idx);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub update {
|
sub update {
|
||||||
@ -75,10 +87,8 @@ sub update {
|
|||||||
$self->{_volumes} = {}; # obj_idx => [ volume_idx, volume_idx ]
|
$self->{_volumes} = {}; # obj_idx => [ volume_idx, volume_idx ]
|
||||||
$self->{_volumes_inv} = {}; # volume_idx => obj_idx
|
$self->{_volumes_inv} = {}; # volume_idx => obj_idx
|
||||||
$self->reset_objects;
|
$self->reset_objects;
|
||||||
return if $self->{model}->objects_count == 0;
|
|
||||||
|
|
||||||
$self->set_bounding_box($self->{model}->bounding_box);
|
$self->update_bed_size;
|
||||||
$self->set_bed_shape($self->{config}->bed_shape);
|
|
||||||
|
|
||||||
foreach my $obj_idx (0..$#{$self->{model}->objects}) {
|
foreach my $obj_idx (0..$#{$self->{model}->objects}) {
|
||||||
my $model_object = $self->{model}->get_object($obj_idx);
|
my $model_object = $self->{model}->get_object($obj_idx);
|
||||||
@ -94,4 +104,9 @@ sub update {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub update_bed_size {
|
||||||
|
my ($self) = @_;
|
||||||
|
$self->set_bed_shape($self->{config}->bed_shape);
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
@ -88,10 +88,10 @@ 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->set_auto_bed_shape;
|
||||||
$canvas->SetSize([500,500]);
|
$canvas->SetSize([500,500]);
|
||||||
$canvas->SetMinSize($canvas->GetSize);
|
$canvas->SetMinSize($canvas->GetSize);
|
||||||
|
$canvas->zoom_to_volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
@ -70,9 +70,9 @@ 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->set_auto_bed_shape;
|
||||||
$canvas->SetSize([500,500]);
|
$canvas->SetSize([500,500]);
|
||||||
|
$canvas->zoom_to_volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
$self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
@ -12,26 +12,28 @@ use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scal
|
|||||||
use Slic3r::Geometry::Clipper qw(offset_ex intersection_pl);
|
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
|
||||||
object_bounding_box
|
|
||||||
enable_picking
|
enable_picking
|
||||||
enable_moving
|
enable_moving
|
||||||
on_hover
|
on_hover
|
||||||
on_select
|
on_select
|
||||||
on_double_click
|
on_double_click
|
||||||
on_right_click
|
on_right_click
|
||||||
on_instance_moved
|
on_move
|
||||||
volumes
|
volumes
|
||||||
print
|
print
|
||||||
_sphi _stheta
|
_sphi _stheta
|
||||||
cutting_plane_z
|
cutting_plane_z
|
||||||
cut_lines_vertices
|
cut_lines_vertices
|
||||||
|
bed_shape
|
||||||
bed_triangles
|
bed_triangles
|
||||||
bed_grid_lines
|
bed_grid_lines
|
||||||
origin
|
origin
|
||||||
_mouse_pos
|
_mouse_pos
|
||||||
|
_hover_volume_idx
|
||||||
_drag_volume_idx
|
_drag_volume_idx
|
||||||
_drag_start_pos
|
_drag_start_pos
|
||||||
|
_drag_start_xy
|
||||||
_camera_target
|
_camera_target
|
||||||
_zoom
|
_zoom
|
||||||
) );
|
) );
|
||||||
@ -61,20 +63,20 @@ sub new {
|
|||||||
$self->_stheta(45);
|
$self->_stheta(45);
|
||||||
$self->_sphi(45);
|
$self->_sphi(45);
|
||||||
$self->_zoom(1);
|
$self->_zoom(1);
|
||||||
$self->_camera_target(Slic3r::Pointf->new(0,0));
|
|
||||||
|
# 3D point in model space
|
||||||
|
$self->_camera_target(Slic3r::Pointf3->new(0,0,0));
|
||||||
|
|
||||||
$self->reset_objects;
|
$self->reset_objects;
|
||||||
|
|
||||||
EVT_PAINT($self, sub {
|
EVT_PAINT($self, sub {
|
||||||
my $dc = Wx::PaintDC->new($self);
|
my $dc = Wx::PaintDC->new($self);
|
||||||
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->object_bounding_box;
|
|
||||||
$self->Resize( $self->GetSizeWH );
|
$self->Resize( $self->GetSizeWH );
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
});
|
});
|
||||||
@ -82,8 +84,10 @@ sub new {
|
|||||||
my ($self, $e) = @_;
|
my ($self, $e) = @_;
|
||||||
|
|
||||||
# Calculate the zoom delta and apply it to the current zoom factor
|
# Calculate the zoom delta and apply it to the current zoom factor
|
||||||
my $zoom = 1 - ($e->GetWheelRotation() / $e->GetWheelDelta() / 10);
|
my $zoom = $e->GetWheelRotation() / $e->GetWheelDelta();
|
||||||
$self->_zoom($self->_zoom * $zoom);
|
$zoom = max(min($zoom, 4), -4);
|
||||||
|
$zoom /= 10;
|
||||||
|
$self->_zoom($self->_zoom * (1-$zoom));
|
||||||
|
|
||||||
# In order to zoom around the mouse point we need to translate
|
# In order to zoom around the mouse point we need to translate
|
||||||
# the camera target
|
# the camera target
|
||||||
@ -97,9 +101,10 @@ sub new {
|
|||||||
# in the opposite direction by the delta of the length of such vector
|
# in the opposite direction by the delta of the length of such vector
|
||||||
# ($zoom - 1). We then scale everything by 1/$self->_zoom since
|
# ($zoom - 1). We then scale everything by 1/$self->_zoom since
|
||||||
# $self->_camera_target is expressed in terms of model units.
|
# $self->_camera_target is expressed in terms of model units.
|
||||||
-($pos->x - $size->x/2) * ($zoom - 1) / $self->_zoom,
|
-($pos->x - $size->x/2) * ($zoom) / $self->_zoom,
|
||||||
-($pos->y - $size->y/2) * ($zoom - 1) / $self->_zoom,
|
-($pos->y - $size->y/2) * ($zoom) / $self->_zoom,
|
||||||
);
|
0,
|
||||||
|
) if 0;
|
||||||
$self->_dirty(1);
|
$self->_dirty(1);
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
});
|
});
|
||||||
@ -118,8 +123,7 @@ sub mouse_event {
|
|||||||
} elsif ($e->LeftDown || $e->RightDown) {
|
} elsif ($e->LeftDown || $e->RightDown) {
|
||||||
# If user pressed left or right button we first check whether this happened
|
# If user pressed left or right button we first check whether this happened
|
||||||
# on a volume or not.
|
# on a volume or not.
|
||||||
my $volume_idx = first { $self->volumes->[$_]->hover } 0..$#{$self->volumes};
|
my $volume_idx = $self->_hover_volume_idx // -1;
|
||||||
$volume_idx //= -1;
|
|
||||||
|
|
||||||
# select volume in this 3D canvas
|
# select volume in this 3D canvas
|
||||||
if ($self->enable_picking) {
|
if ($self->enable_picking) {
|
||||||
@ -146,25 +150,27 @@ sub mouse_event {
|
|||||||
# get volume being dragged
|
# get volume being dragged
|
||||||
my $volume = $self->volumes->[$self->_drag_volume_idx];
|
my $volume = $self->volumes->[$self->_drag_volume_idx];
|
||||||
|
|
||||||
# get new position and calculate the move vector
|
# get new position at the same Z of the initial click point
|
||||||
my $cur_pos = $self->mouse_to_3d(@$pos);
|
my $mouse_ray = $self->mouse_ray($e->GetX, $e->GetY);
|
||||||
|
my $cur_pos = $mouse_ray->intersect_plane($self->_drag_start_pos->z);
|
||||||
|
|
||||||
|
# calculate the translation vector
|
||||||
my $vector = $self->_drag_start_pos->vector_to($cur_pos);
|
my $vector = $self->_drag_start_pos->vector_to($cur_pos);
|
||||||
|
|
||||||
# apply new temporary volume origin and ignore Z
|
# apply new temporary volume origin and ignore Z
|
||||||
$volume->origin->set_x(-$vector->x);
|
$volume->origin->translate($vector->x, $vector->y, 0); #,,
|
||||||
$volume->origin->set_y(-$vector->y); #))
|
$self->_drag_start_pos($cur_pos);
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
} elsif ($e->Dragging) {
|
} elsif ($e->Dragging && !defined $self->_hover_volume_idx) {
|
||||||
my $volume_idx = first { $self->volumes->[$_]->hover } 0..$#{$self->volumes};
|
if ($e->LeftIsDown) {
|
||||||
$volume_idx //= -1;
|
|
||||||
|
|
||||||
if ($e->LeftIsDown && $volume_idx == -1) {
|
|
||||||
# if dragging over blank area with left button, rotate
|
# if dragging over blank area with left button, rotate
|
||||||
if (defined $self->_drag_start_pos) {
|
if (defined $self->_drag_start_pos) {
|
||||||
my $orig = $self->_drag_start_pos;
|
my $orig = $self->_drag_start_pos;
|
||||||
if (TURNTABLE_MODE) {
|
if (TURNTABLE_MODE) {
|
||||||
$self->_sphi($self->_sphi + ($pos->x - $orig->x) * TRACKBALLSIZE);
|
$self->_sphi($self->_sphi + ($pos->x - $orig->x) * TRACKBALLSIZE);
|
||||||
$self->_stheta($self->_stheta - ($pos->y - $orig->y) * TRACKBALLSIZE); #-
|
$self->_stheta($self->_stheta - ($pos->y - $orig->y) * TRACKBALLSIZE); #-
|
||||||
|
$self->_stheta(150) if $self->_stheta > 150;
|
||||||
|
$self->_stheta(0) if $self->_stheta < 0;
|
||||||
} else {
|
} else {
|
||||||
my $size = $self->GetClientSize;
|
my $size = $self->GetClientSize;
|
||||||
my @quat = trackball(
|
my @quat = trackball(
|
||||||
@ -178,28 +184,27 @@ sub mouse_event {
|
|||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
}
|
}
|
||||||
$self->_drag_start_pos($pos);
|
$self->_drag_start_pos($pos);
|
||||||
} elsif ($e->RightIsDown && $volume_idx == -1) {
|
} elsif ($e->RightIsDown) {
|
||||||
# if dragging over blank area with right button, translate
|
# if dragging over blank area with right button, translate
|
||||||
if (defined $self->_drag_start_pos) {
|
|
||||||
my $orig = $self->_drag_start_pos;
|
if (defined $self->_drag_start_xy) {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
# get point in model space at Z = 0
|
||||||
|
my $cur_pos = $self->mouse_ray($e->GetX, $e->GetY)->intersect_plane(0);
|
||||||
|
my $orig = $self->mouse_ray(@{$self->_drag_start_xy})->intersect_plane(0);
|
||||||
$self->_camera_target->translate(
|
$self->_camera_target->translate(
|
||||||
($pos->x - $orig->x) / $self->_zoom,
|
@{$orig->vector_to($cur_pos)->negative},
|
||||||
($orig->y - $pos->y) / $self->_zoom, #- (converts to upwards Y)
|
|
||||||
);
|
);
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
}
|
}
|
||||||
$self->_drag_start_pos($pos);
|
$self->_drag_start_xy($pos);
|
||||||
}
|
}
|
||||||
} elsif ($e->LeftUp || $e->RightUp) {
|
} elsif ($e->LeftUp || $e->RightUp) {
|
||||||
$self->_drag_start_pos(undef);
|
if ($self->on_move && defined $self->_drag_volume_idx) {
|
||||||
|
$self->on_move->($self->_drag_volume_idx);
|
||||||
if ($self->on_instance_moved && defined $self->_drag_volume_idx) {
|
|
||||||
my $volume = $self->volumes->[$self->_drag_volume_idx];
|
|
||||||
$self->on_instance_moved($self->_drag_volume_idx, $volume->instance_idx);
|
|
||||||
}
|
}
|
||||||
$self->_drag_volume_idx(undef);
|
$self->_drag_volume_idx(undef);
|
||||||
$self->_drag_start_pos(undef);
|
$self->_drag_start_pos(undef);
|
||||||
|
$self->_drag_start_xy(undef);
|
||||||
} elsif ($e->Moving) {
|
} elsif ($e->Moving) {
|
||||||
$self->_mouse_pos($pos);
|
$self->_mouse_pos($pos);
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
@ -215,35 +220,70 @@ sub reset_objects {
|
|||||||
$self->_dirty(1);
|
$self->_dirty(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
# this method accepts a Slic3r::BoudingBox3f object
|
|
||||||
sub set_bounding_box {
|
|
||||||
my ($self, $bb) = @_;
|
|
||||||
|
|
||||||
$self->object_bounding_box($bb);
|
|
||||||
$self->zoom_to_bounding_box;
|
|
||||||
$self->_dirty(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub zoom_to_bounding_box {
|
sub zoom_to_bounding_box {
|
||||||
my ($self) = @_;
|
my ($self, $bb) = @_;
|
||||||
|
|
||||||
# calculate the zoom factor needed to adjust viewport to
|
# calculate the zoom factor needed to adjust viewport to
|
||||||
# bounding box
|
# bounding box
|
||||||
my $max_size = max(@{$self->object_bounding_box->size}) * sqrt(2);
|
my $max_size = max(@{$bb->size}) * 2;
|
||||||
my $min_viewport_size = min($self->GetSizeWH);
|
my $min_viewport_size = min($self->GetSizeWH);
|
||||||
$self->_zoom($min_viewport_size / $max_size / 1.3);
|
$self->_zoom($min_viewport_size / $max_size);
|
||||||
|
|
||||||
# center view around bounding box center
|
# center view around bounding box center
|
||||||
$self->_camera_target->set_x(0);
|
$self->_camera_target($bb->center);
|
||||||
$self->_camera_target->set_y(0);
|
}
|
||||||
|
|
||||||
|
sub zoom_to_bed {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
if ($self->bed_shape) {
|
||||||
|
$self->zoom_to_bounding_box($self->bed_bounding_box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoom_to_volume {
|
||||||
|
my ($self, $volume_idx) = @_;
|
||||||
|
|
||||||
|
my $volume = $self->volumes->[$volume_idx];
|
||||||
|
my $bb = $volume->bounding_box;
|
||||||
|
$self->zoom_to_bounding_box($bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub zoom_to_volumes {
|
||||||
|
my ($self) = @_;
|
||||||
|
$self->zoom_to_bounding_box($self->volumes_bounding_box);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub volumes_bounding_box {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $bb = Slic3r::Geometry::BoundingBoxf3->new;
|
||||||
|
$bb->merge($_->bounding_box) for @{$self->volumes};
|
||||||
|
return $bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub bed_bounding_box {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $bb = Slic3r::Geometry::BoundingBoxf3->new;
|
||||||
|
$bb->merge_point(Slic3r::Pointf3->new(@$_, 0)) for @{$self->bed_shape};
|
||||||
|
return $bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub max_bounding_box {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $bb = $self->bed_bounding_box;
|
||||||
|
$bb->merge($self->volumes_bounding_box);
|
||||||
|
return $bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_auto_bed_shape {
|
sub set_auto_bed_shape {
|
||||||
my ($self, $bed_shape) = @_;
|
my ($self, $bed_shape) = @_;
|
||||||
|
|
||||||
# draw a default square bed around object center
|
# draw a default square bed around object center
|
||||||
my $max_size = max(@{ $self->object_bounding_box->size });
|
my $max_size = max(@{ $self->volumes_bounding_box->size });
|
||||||
my $center = $self->object_bounding_box->center;
|
my $center = $self->volumes_bounding_box->center;
|
||||||
$self->set_bed_shape([
|
$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 ], #--
|
||||||
@ -256,6 +296,8 @@ sub set_auto_bed_shape {
|
|||||||
sub set_bed_shape {
|
sub set_bed_shape {
|
||||||
my ($self, $bed_shape) = @_;
|
my ($self, $bed_shape) = @_;
|
||||||
|
|
||||||
|
$self->bed_shape($bed_shape);
|
||||||
|
|
||||||
# triangulate bed
|
# triangulate bed
|
||||||
my $expolygon = Slic3r::ExPolygon->new([ map [map scale($_), @$_], @$bed_shape ]);
|
my $expolygon = Slic3r::ExPolygon->new([ map [map scale($_), @$_], @$bed_shape ]);
|
||||||
my $bed_bb = $expolygon->bounding_box;
|
my $bed_bb = $expolygon->bounding_box;
|
||||||
@ -318,7 +360,7 @@ sub load_object {
|
|||||||
instance_idx => $instance_idx,
|
instance_idx => $instance_idx,
|
||||||
mesh => $mesh,
|
mesh => $mesh,
|
||||||
color => $color,
|
color => $color,
|
||||||
origin => Slic3r::Pointf3->new(0,0,$z_min),
|
origin => Slic3r::Pointf3->new(0,0,-$z_min),
|
||||||
);
|
);
|
||||||
push @volumes_idx, $#{$self->volumes};
|
push @volumes_idx, $#{$self->volumes};
|
||||||
|
|
||||||
@ -481,18 +523,27 @@ sub mulquats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub mouse_to_3d {
|
sub mouse_to_3d {
|
||||||
my ($self, $x, $y) = @_;
|
my ($self, $x, $y, $z) = @_;
|
||||||
|
|
||||||
my @viewport = glGetIntegerv_p(GL_VIEWPORT); # 4 items
|
my @viewport = glGetIntegerv_p(GL_VIEWPORT); # 4 items
|
||||||
my @mview = glGetDoublev_p(GL_MODELVIEW_MATRIX); # 16 items
|
my @mview = glGetDoublev_p(GL_MODELVIEW_MATRIX); # 16 items
|
||||||
my @proj = glGetDoublev_p(GL_PROJECTION_MATRIX); # 16 items
|
my @proj = glGetDoublev_p(GL_PROJECTION_MATRIX); # 16 items
|
||||||
|
|
||||||
$y = $viewport[3] - $y;
|
$y = $viewport[3] - $y;
|
||||||
my $z = glReadPixels_p($x, $y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT);
|
$z //= glReadPixels_p($x, $y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT);
|
||||||
my @projected = gluUnProject_p($x, $y, $z, @mview, @proj, @viewport);
|
my @projected = gluUnProject_p($x, $y, $z, @mview, @proj, @viewport);
|
||||||
return Slic3r::Pointf3->new(@projected);
|
return Slic3r::Pointf3->new(@projected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub mouse_ray {
|
||||||
|
my ($self, $x, $y) = @_;
|
||||||
|
|
||||||
|
return Slic3r::Linef3->new(
|
||||||
|
$self->mouse_to_3d($x, $y, 0),
|
||||||
|
$self->mouse_to_3d($x, $y, 1),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
sub GetContext {
|
sub GetContext {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
@ -513,16 +564,6 @@ sub SetCurrent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub ResetModelView {
|
|
||||||
my ($self, $factor) = @_;
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
my $win_size = $self->GetClientSize();
|
|
||||||
my $ratio = $factor * min($win_size->width, $win_size->height) / (2 * max(@{ $self->object_bounding_box->size }));
|
|
||||||
glScalef($ratio, $ratio, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub Resize {
|
sub Resize {
|
||||||
my ($self, $x, $y) = @_;
|
my ($self, $x, $y) = @_;
|
||||||
|
|
||||||
@ -539,14 +580,10 @@ sub Resize {
|
|||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(
|
glOrtho(
|
||||||
-$x/2, $x/2, -$y/2, $y/2,
|
-$x/2, $x/2, -$y/2, $y/2,
|
||||||
-200, 10 * max(@{ $self->object_bounding_box->size }),
|
-200, 10 * max(@{ $self->max_bounding_box->size }),
|
||||||
);
|
);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
unless ($self->mview_init) {
|
|
||||||
$self->mview_init(1);
|
|
||||||
$self->ResetModelView(0.9);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub InitGL {
|
sub InitGL {
|
||||||
@ -614,9 +651,6 @@ sub Render {
|
|||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
my $bb = $self->object_bounding_box;
|
|
||||||
my $object_size = $bb->size;
|
|
||||||
glTranslatef(@{ $self->_camera_target }, 0);
|
|
||||||
if (TURNTABLE_MODE) {
|
if (TURNTABLE_MODE) {
|
||||||
glRotatef(-$self->_stheta, 1, 0, 0); # pitch
|
glRotatef(-$self->_stheta, 1, 0, 0); # pitch
|
||||||
glRotatef($self->_sphi, 0, 0, 1); # yaw
|
glRotatef($self->_sphi, 0, 0, 1); # yaw
|
||||||
@ -624,10 +658,7 @@ sub Render {
|
|||||||
my @rotmat = quat_to_rotmatrix($self->quat);
|
my @rotmat = quat_to_rotmatrix($self->quat);
|
||||||
glMultMatrixd_p(@rotmat[0..15]);
|
glMultMatrixd_p(@rotmat[0..15]);
|
||||||
}
|
}
|
||||||
|
glTranslatef(@{ $self->_camera_target->negative });
|
||||||
# center everything around 0,0 since that's where we're looking at (glOrtho())
|
|
||||||
my $center = $bb->center;
|
|
||||||
glTranslatef(-$center->x, -$center->y, 0); #,,
|
|
||||||
|
|
||||||
if ($self->enable_picking) {
|
if ($self->enable_picking) {
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
@ -638,8 +669,10 @@ sub Render {
|
|||||||
if (my $pos = $self->_mouse_pos) {
|
if (my $pos = $self->_mouse_pos) {
|
||||||
my $col = [ glReadPixels_p($pos->x, $self->GetSize->GetHeight - $pos->y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE) ];
|
my $col = [ glReadPixels_p($pos->x, $self->GetSize->GetHeight - $pos->y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE) ];
|
||||||
my $volume_idx = $col->[0] + $col->[1]*256 + $col->[2]*256*256;
|
my $volume_idx = $col->[0] + $col->[1]*256 + $col->[2]*256*256;
|
||||||
|
$self->_hover_volume_idx(undef);
|
||||||
$_->hover(0) for @{$self->volumes};
|
$_->hover(0) for @{$self->volumes};
|
||||||
if ($volume_idx <= $#{$self->volumes}) {
|
if ($volume_idx <= $#{$self->volumes}) {
|
||||||
|
$self->_hover_volume_idx($volume_idx);
|
||||||
$self->volumes->[$volume_idx]->hover(1);
|
$self->volumes->[$volume_idx]->hover(1);
|
||||||
$self->on_hover->($volume_idx) if $self->on_hover;
|
$self->on_hover->($volume_idx) if $self->on_hover;
|
||||||
}
|
}
|
||||||
@ -682,11 +715,16 @@ sub Render {
|
|||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $volumes_bb = $self->volumes_bounding_box;
|
||||||
|
|
||||||
{
|
{
|
||||||
# draw axes
|
# draw axes
|
||||||
$ground_z += 0.02;
|
$ground_z += 0.02;
|
||||||
my $origin = $self->origin;
|
my $origin = $self->origin;
|
||||||
my $axis_len = 2 * max(@{ $object_size });
|
my $axis_len = max(
|
||||||
|
0.3 * max(@{ $self->bed_bounding_box->size }),
|
||||||
|
2 * max(@{ $volumes_bb->size }),
|
||||||
|
);
|
||||||
glLineWidth(2);
|
glLineWidth(2);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
# draw line for x axis
|
# draw line for x axis
|
||||||
@ -707,6 +745,7 @@ sub Render {
|
|||||||
# draw cutting plane
|
# draw cutting plane
|
||||||
if (defined $self->cutting_plane_z) {
|
if (defined $self->cutting_plane_z) {
|
||||||
my $plane_z = $z0 + $self->cutting_plane_z;
|
my $plane_z = $z0 + $self->cutting_plane_z;
|
||||||
|
my $bb = $volumes_bb;
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
@ -804,7 +843,7 @@ sub draw_volumes {
|
|||||||
foreach my $volume_idx (0..$#{$self->volumes}) {
|
foreach my $volume_idx (0..$#{$self->volumes}) {
|
||||||
my $volume = $self->volumes->[$volume_idx];
|
my $volume = $self->volumes->[$volume_idx];
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(@{$volume->origin->negative});
|
glTranslatef(@{$volume->origin});
|
||||||
|
|
||||||
glVertexPointer_p(3, $volume->verts);
|
glVertexPointer_p(3, $volume->verts);
|
||||||
|
|
||||||
@ -850,4 +889,12 @@ has 'norms' => (is => 'rw');
|
|||||||
has 'selected' => (is => 'rw', default => sub { 0 });
|
has 'selected' => (is => 'rw', default => sub { 0 });
|
||||||
has 'hover' => (is => 'rw', default => sub { 0 });
|
has 'hover' => (is => 'rw', default => sub { 0 });
|
||||||
|
|
||||||
|
sub bounding_box {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $bb = $self->mesh->bounding_box;
|
||||||
|
$bb->translate(@{$self->origin});
|
||||||
|
return $bb;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -36,8 +36,8 @@ my %opt = ();
|
|||||||
$app->{canvas}->enable_picking(1);
|
$app->{canvas}->enable_picking(1);
|
||||||
$app->{canvas}->enable_moving($opt{enable_moving});
|
$app->{canvas}->enable_moving($opt{enable_moving});
|
||||||
$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}->set_auto_bed_shape;
|
||||||
|
$app->{canvas}->zoom_to_volumes;
|
||||||
$app->{canvas}->SetCuttingPlane($opt{cut}) if defined $opt{cut};
|
$app->{canvas}->SetCuttingPlane($opt{cut}) if defined $opt{cut};
|
||||||
$app->MainLoop;
|
$app->MainLoop;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,7 @@ for my $class (qw(
|
|||||||
Slic3r::Layer::Region
|
Slic3r::Layer::Region
|
||||||
Slic3r::Layer::Support
|
Slic3r::Layer::Support
|
||||||
Slic3r::Line
|
Slic3r::Line
|
||||||
|
Slic3r::Linef3
|
||||||
Slic3r::Model
|
Slic3r::Model
|
||||||
Slic3r::Model::Instance
|
Slic3r::Model::Instance
|
||||||
Slic3r::Model::Material
|
Slic3r::Model::Material
|
||||||
|
@ -184,4 +184,18 @@ Line::to_SV_pureperl() const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Pointf3
|
||||||
|
Linef3::intersect_plane(double z) const
|
||||||
|
{
|
||||||
|
return Pointf3(
|
||||||
|
this->a.x + (this->b.x - this->a.x) * (z - this->a.z) / (this->b.z - this->a.z),
|
||||||
|
this->a.y + (this->b.y - this->a.y) * (z - this->a.z) / (this->b.z - this->a.z),
|
||||||
|
z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SLIC3RXS
|
||||||
|
REGISTER_CLASS(Linef3, "Linef3");
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class Line;
|
class Line;
|
||||||
|
class Linef3;
|
||||||
class Polyline;
|
class Polyline;
|
||||||
|
|
||||||
class Line
|
class Line
|
||||||
@ -46,6 +47,22 @@ class Line
|
|||||||
|
|
||||||
typedef std::vector<Line> Lines;
|
typedef std::vector<Line> Lines;
|
||||||
|
|
||||||
|
class Linef3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Pointf3 a;
|
||||||
|
Pointf3 b;
|
||||||
|
Linef3() {};
|
||||||
|
explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {};
|
||||||
|
Pointf3 intersect_plane(double z) const;
|
||||||
|
|
||||||
|
#ifdef SLIC3RXS
|
||||||
|
void from_SV(SV* line_sv);
|
||||||
|
void from_SV_check(SV* line_sv);
|
||||||
|
SV* to_SV_pureperl() const;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
|
@ -83,6 +83,7 @@ new_from_points(CLASS, points)
|
|||||||
Clone<BoundingBoxf3> clone()
|
Clone<BoundingBoxf3> clone()
|
||||||
%code{% RETVAL = THIS; %};
|
%code{% RETVAL = THIS; %};
|
||||||
void merge(BoundingBoxf3* bb) %code{% THIS->merge(*bb); %};
|
void merge(BoundingBoxf3* bb) %code{% THIS->merge(*bb); %};
|
||||||
|
void merge_point(Pointf3* point) %code{% THIS->merge(*point); %};
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
Clone<Pointf3> size();
|
Clone<Pointf3> size();
|
||||||
|
@ -66,3 +66,17 @@ Line::coincides_with(line_sv)
|
|||||||
|
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
%name{Slic3r::Linef3} class Linef3 {
|
||||||
|
Linef3(Pointf3* a, Pointf3* b)
|
||||||
|
%code{% RETVAL = new Linef3(*a, *b); %};
|
||||||
|
~Linef3();
|
||||||
|
Clone<Linef3> clone()
|
||||||
|
%code{% RETVAL = THIS; %};
|
||||||
|
Ref<Pointf3> a()
|
||||||
|
%code{% RETVAL = &THIS->a; %};
|
||||||
|
Ref<Pointf3> b()
|
||||||
|
%code{% RETVAL = &THIS->b; %};
|
||||||
|
Clone<Pointf3> intersect_plane(double z);
|
||||||
|
};
|
||||||
|
@ -125,6 +125,7 @@ Point::coincides_with(point_sv)
|
|||||||
void set_z(double val)
|
void set_z(double val)
|
||||||
%code{% THIS->z = val; %};
|
%code{% THIS->z = val; %};
|
||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
|
void scale(double factor);
|
||||||
double distance_to(Pointf3* point)
|
double distance_to(Pointf3* point)
|
||||||
%code{% RETVAL = THIS->distance_to(*point); %};
|
%code{% RETVAL = THIS->distance_to(*point); %};
|
||||||
Clone<Pointf3> negative()
|
Clone<Pointf3> negative()
|
||||||
|
@ -73,6 +73,10 @@ Line* O_OBJECT_SLIC3R
|
|||||||
Ref<Line> O_OBJECT_SLIC3R_T
|
Ref<Line> O_OBJECT_SLIC3R_T
|
||||||
Clone<Line> O_OBJECT_SLIC3R_T
|
Clone<Line> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
|
Linef3* O_OBJECT_SLIC3R
|
||||||
|
Ref<Linef3> O_OBJECT_SLIC3R_T
|
||||||
|
Clone<Linef3> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
Polyline* O_OBJECT_SLIC3R
|
Polyline* O_OBJECT_SLIC3R
|
||||||
Ref<Polyline> O_OBJECT_SLIC3R_T
|
Ref<Polyline> O_OBJECT_SLIC3R_T
|
||||||
Clone<Polyline> O_OBJECT_SLIC3R_T
|
Clone<Polyline> O_OBJECT_SLIC3R_T
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
%typemap{Line*};
|
%typemap{Line*};
|
||||||
%typemap{Ref<Line>}{simple};
|
%typemap{Ref<Line>}{simple};
|
||||||
%typemap{Clone<Line>}{simple};
|
%typemap{Clone<Line>}{simple};
|
||||||
|
%typemap{Linef3*};
|
||||||
|
%typemap{Ref<Linef3>}{simple};
|
||||||
|
%typemap{Clone<Linef3>}{simple};
|
||||||
%typemap{Polyline*};
|
%typemap{Polyline*};
|
||||||
%typemap{Ref<Polyline>}{simple};
|
%typemap{Ref<Polyline>}{simple};
|
||||||
%typemap{Clone<Polyline>}{simple};
|
%typemap{Clone<Polyline>}{simple};
|
||||||
|
Loading…
Reference in New Issue
Block a user