From 95e7d96f522886002bfc515797a91ad9e9758c91 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 4 Jun 2018 12:26:39 +0200 Subject: 3DScene paint event handler moved to c++ --- lib/Slic3r/GUI/3DScene.pm | 341 +++++++++++++++----------------- xs/src/slic3r/GUI/GLCanvas3D.cpp | 106 ++++++---- xs/src/slic3r/GUI/GLCanvas3D.hpp | 14 +- xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 16 +- 4 files changed, 261 insertions(+), 216 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index eca90890e..c13cd48ad 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -17,7 +17,6 @@ use warnings; use Wx qw(wxTheApp :timer :bitmap :icon :dialog); #============================================================================================================================== -use Wx::Event qw(EVT_PAINT EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); #use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS EVT_CHAR EVT_TIMER); #============================================================================================================================== # must load OpenGL *before* Wx::GLCanvas @@ -82,11 +81,9 @@ __PACKAGE__->mk_accessors( qw(init # _mouse_dragging # # ) ); -#============================================================================================================================== - -use constant TRACKBALLSIZE => 0.8; -use constant TURNTABLE_MODE => 1; -#============================================================================================================================== +# +#use constant TRACKBALLSIZE => 0.8; +#use constant TURNTABLE_MODE => 1; #use constant GROUND_Z => -0.02; ## For mesh selection: Not selected - bright yellow. #use constant DEFAULT_COLOR => [1,1,0]; @@ -109,17 +106,17 @@ use constant TURNTABLE_MODE => 1; #use constant MANIPULATION_LAYER_HEIGHT => 2; # #use constant GIMBALL_LOCK_THETA_MAX => 180; +# +#use constant VARIABLE_LAYER_THICKNESS_BAR_WIDTH => 70; +#use constant VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT => 22; +# +## make OpenGL::Array thread-safe +#{ +# no warnings 'redefine'; +# *OpenGL::Array::CLONE_SKIP = sub { 1 }; +#} #============================================================================================================================== -use constant VARIABLE_LAYER_THICKNESS_BAR_WIDTH => 70; -use constant VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT => 22; - -# make OpenGL::Array thread-safe -{ - no warnings 'redefine'; - *OpenGL::Array::CLONE_SKIP = sub { 1 }; -} - sub new { my ($class, $parent) = @_; @@ -192,13 +189,11 @@ sub new { # $self->{layer_height_edit_last_action} = 0; # # $self->reset_objects; -#============================================================================================================================== - - EVT_PAINT($self, sub { - my $dc = Wx::PaintDC->new($self); - $self->Render($dc); - }); -#======================================================================================================================= +# +# EVT_PAINT($self, sub { +# my $dc = Wx::PaintDC->new($self); +# $self->Render($dc); +# }); # EVT_SIZE($self, sub { $self->_dirty(1) }); # EVT_IDLE($self, sub { # return unless $self->_dirty; @@ -970,116 +965,114 @@ sub Destroy { # } # $self->cut_lines_vertices(OpenGL::Array->new_list(GL_FLOAT, @verts)); #} -#============================================================================================================================== - -# Given an axis and angle, compute quaternion. -sub axis_to_quat { - my ($ax, $phi) = @_; - - my $lena = sqrt(reduce { $a + $b } (map { $_ * $_ } @$ax)); - my @q = map { $_ * (1 / $lena) } @$ax; - @q = map { $_ * sin($phi / 2.0) } @q; - $q[$#q + 1] = cos($phi / 2.0); - return @q; -} - -# Project a point on the virtual trackball. -# If it is inside the sphere, map it to the sphere, if it outside map it -# to a hyperbola. -sub project_to_sphere { - my ($r, $x, $y) = @_; - - my $d = sqrt($x * $x + $y * $y); - if ($d < $r * 0.70710678118654752440) { # Inside sphere - return sqrt($r * $r - $d * $d); - } else { # On hyperbola - my $t = $r / 1.41421356237309504880; - return $t * $t / $d; - } -} - -sub cross { - my ($v1, $v2) = @_; - - return (@$v1[1] * @$v2[2] - @$v1[2] * @$v2[1], - @$v1[2] * @$v2[0] - @$v1[0] * @$v2[2], - @$v1[0] * @$v2[1] - @$v1[1] * @$v2[0]); -} - -# Simulate a track-ball. Project the points onto the virtual trackball, -# then figure out the axis of rotation, which is the cross product of -# P1 P2 and O P1 (O is the center of the ball, 0,0,0) Note: This is a -# deformed trackball-- is a trackball in the center, but is deformed -# into a hyperbolic sheet of rotation away from the center. -# It is assumed that the arguments to this routine are in the range -# (-1.0 ... 1.0). -sub trackball { - my ($p1x, $p1y, $p2x, $p2y) = @_; - - if ($p1x == $p2x && $p1y == $p2y) { - # zero rotation - return (0.0, 0.0, 0.0, 1.0); - } - - # First, figure out z-coordinates for projection of P1 and P2 to - # deformed sphere - my @p1 = ($p1x, $p1y, project_to_sphere(TRACKBALLSIZE, $p1x, $p1y)); - my @p2 = ($p2x, $p2y, project_to_sphere(TRACKBALLSIZE, $p2x, $p2y)); - - # axis of rotation (cross product of P1 and P2) - my @a = cross(\@p2, \@p1); - - # Figure out how much to rotate around that axis. - my @d = map { $_ * $_ } (map { $p1[$_] - $p2[$_] } 0 .. $#p1); - my $t = sqrt(reduce { $a + $b } @d) / (2.0 * TRACKBALLSIZE); - - # Avoid problems with out-of-control values... - $t = 1.0 if ($t > 1.0); - $t = -1.0 if ($t < -1.0); - my $phi = 2.0 * asin($t); - - return axis_to_quat(\@a, $phi); -} - -# Build a rotation matrix, given a quaternion rotation. -sub quat_to_rotmatrix { - my ($q) = @_; - - my @m = (); - - $m[0] = 1.0 - 2.0 * (@$q[1] * @$q[1] + @$q[2] * @$q[2]); - $m[1] = 2.0 * (@$q[0] * @$q[1] - @$q[2] * @$q[3]); - $m[2] = 2.0 * (@$q[2] * @$q[0] + @$q[1] * @$q[3]); - $m[3] = 0.0; - - $m[4] = 2.0 * (@$q[0] * @$q[1] + @$q[2] * @$q[3]); - $m[5] = 1.0 - 2.0 * (@$q[2] * @$q[2] + @$q[0] * @$q[0]); - $m[6] = 2.0 * (@$q[1] * @$q[2] - @$q[0] * @$q[3]); - $m[7] = 0.0; - - $m[8] = 2.0 * (@$q[2] * @$q[0] - @$q[1] * @$q[3]); - $m[9] = 2.0 * (@$q[1] * @$q[2] + @$q[0] * @$q[3]); - $m[10] = 1.0 - 2.0 * (@$q[1] * @$q[1] + @$q[0] * @$q[0]); - $m[11] = 0.0; - - $m[12] = 0.0; - $m[13] = 0.0; - $m[14] = 0.0; - $m[15] = 1.0; - - return @m; -} - -sub mulquats { - my ($q1, $rq) = @_; - - return (@$q1[3] * @$rq[0] + @$q1[0] * @$rq[3] + @$q1[1] * @$rq[2] - @$q1[2] * @$rq[1], - @$q1[3] * @$rq[1] + @$q1[1] * @$rq[3] + @$q1[2] * @$rq[0] - @$q1[0] * @$rq[2], - @$q1[3] * @$rq[2] + @$q1[2] * @$rq[3] + @$q1[0] * @$rq[1] - @$q1[1] * @$rq[0], - @$q1[3] * @$rq[3] - @$q1[0] * @$rq[0] - @$q1[1] * @$rq[1] - @$q1[2] * @$rq[2]) -} - -#============================================================================================================================== +# +## Given an axis and angle, compute quaternion. +#sub axis_to_quat { +# my ($ax, $phi) = @_; +# +# my $lena = sqrt(reduce { $a + $b } (map { $_ * $_ } @$ax)); +# my @q = map { $_ * (1 / $lena) } @$ax; +# @q = map { $_ * sin($phi / 2.0) } @q; +# $q[$#q + 1] = cos($phi / 2.0); +# return @q; +#} +# +## Project a point on the virtual trackball. +## If it is inside the sphere, map it to the sphere, if it outside map it +## to a hyperbola. +#sub project_to_sphere { +# my ($r, $x, $y) = @_; +# +# my $d = sqrt($x * $x + $y * $y); +# if ($d < $r * 0.70710678118654752440) { # Inside sphere +# return sqrt($r * $r - $d * $d); +# } else { # On hyperbola +# my $t = $r / 1.41421356237309504880; +# return $t * $t / $d; +# } +#} +# +#sub cross { +# my ($v1, $v2) = @_; +# +# return (@$v1[1] * @$v2[2] - @$v1[2] * @$v2[1], +# @$v1[2] * @$v2[0] - @$v1[0] * @$v2[2], +# @$v1[0] * @$v2[1] - @$v1[1] * @$v2[0]); +#} +# +## Simulate a track-ball. Project the points onto the virtual trackball, +## then figure out the axis of rotation, which is the cross product of +## P1 P2 and O P1 (O is the center of the ball, 0,0,0) Note: This is a +## deformed trackball-- is a trackball in the center, but is deformed +## into a hyperbolic sheet of rotation away from the center. +## It is assumed that the arguments to this routine are in the range +## (-1.0 ... 1.0). +#sub trackball { +# my ($p1x, $p1y, $p2x, $p2y) = @_; +# +# if ($p1x == $p2x && $p1y == $p2y) { +# # zero rotation +# return (0.0, 0.0, 0.0, 1.0); +# } +# +# # First, figure out z-coordinates for projection of P1 and P2 to +# # deformed sphere +# my @p1 = ($p1x, $p1y, project_to_sphere(TRACKBALLSIZE, $p1x, $p1y)); +# my @p2 = ($p2x, $p2y, project_to_sphere(TRACKBALLSIZE, $p2x, $p2y)); +# +# # axis of rotation (cross product of P1 and P2) +# my @a = cross(\@p2, \@p1); +# +# # Figure out how much to rotate around that axis. +# my @d = map { $_ * $_ } (map { $p1[$_] - $p2[$_] } 0 .. $#p1); +# my $t = sqrt(reduce { $a + $b } @d) / (2.0 * TRACKBALLSIZE); +# +# # Avoid problems with out-of-control values... +# $t = 1.0 if ($t > 1.0); +# $t = -1.0 if ($t < -1.0); +# my $phi = 2.0 * asin($t); +# +# return axis_to_quat(\@a, $phi); +#} +# +## Build a rotation matrix, given a quaternion rotation. +#sub quat_to_rotmatrix { +# my ($q) = @_; +# +# my @m = (); +# +# $m[0] = 1.0 - 2.0 * (@$q[1] * @$q[1] + @$q[2] * @$q[2]); +# $m[1] = 2.0 * (@$q[0] * @$q[1] - @$q[2] * @$q[3]); +# $m[2] = 2.0 * (@$q[2] * @$q[0] + @$q[1] * @$q[3]); +# $m[3] = 0.0; +# +# $m[4] = 2.0 * (@$q[0] * @$q[1] + @$q[2] * @$q[3]); +# $m[5] = 1.0 - 2.0 * (@$q[2] * @$q[2] + @$q[0] * @$q[0]); +# $m[6] = 2.0 * (@$q[1] * @$q[2] - @$q[0] * @$q[3]); +# $m[7] = 0.0; +# +# $m[8] = 2.0 * (@$q[2] * @$q[0] - @$q[1] * @$q[3]); +# $m[9] = 2.0 * (@$q[1] * @$q[2] + @$q[0] * @$q[3]); +# $m[10] = 1.0 - 2.0 * (@$q[1] * @$q[1] + @$q[0] * @$q[0]); +# $m[11] = 0.0; +# +# $m[12] = 0.0; +# $m[13] = 0.0; +# $m[14] = 0.0; +# $m[15] = 1.0; +# +# return @m; +#} +# +#sub mulquats { +# my ($q1, $rq) = @_; +# +# return (@$q1[3] * @$rq[0] + @$q1[0] * @$rq[3] + @$q1[1] * @$rq[2] - @$q1[2] * @$rq[1], +# @$q1[3] * @$rq[1] + @$q1[1] * @$rq[3] + @$q1[2] * @$rq[0] - @$q1[0] * @$rq[2], +# @$q1[3] * @$rq[2] + @$q1[2] * @$rq[3] + @$q1[0] * @$rq[1] - @$q1[1] * @$rq[0], +# @$q1[3] * @$rq[3] - @$q1[0] * @$rq[0] - @$q1[1] * @$rq[1] - @$q1[2] * @$rq[2]) +#} +# ## Convert the screen space coordinate to an object space coordinate. ## If the Z screen space coordinate is not provided, a depth buffer value is substituted. #sub mouse_to_3d { @@ -1196,20 +1189,14 @@ sub InitGL { $self->init(1); #============================================================================================================================== - Slic3r::GUI::_3DScene::init_gl; -#============================================================================================================================== - - # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized - # first when an OpenGL widget is shown for the first time. How ugly. - # In that case the volumes are wainting to be moved to Vertex Buffer Objects - # after the OpenGL context is being initialized. - $self->volumes->finalize_geometry(1) - if ($^O eq 'linux' && $self->UseVBOs); - -#============================================================================================================================== - Slic3r::GUI::_3DScene::zoom_to_bed($self); - Slic3r::GUI::_3DScene::init($self, $self->UseVBOs); - +# +## # This is a special path for wxWidgets on GTK, where an OpenGL context is initialized +## # first when an OpenGL widget is shown for the first time. How ugly. +## # In that case the volumes are wainting to be moved to Vertex Buffer Objects +## # after the OpenGL context is being initialized. +## $self->volumes->finalize_geometry(1) +## if ($^O eq 'linux' && $self->UseVBOs); +# # $self->zoom_to_bed; # # glClearColor(0, 0, 0, 1); @@ -1870,38 +1857,36 @@ sub Render { # # return $out; #} -#============================================================================================================================== - -sub _report_opengl_state -{ - my ($self, $comment) = @_; - my $err = glGetError(); - return 0 if ($err == 0); - - # gluErrorString() hangs. Don't use it. -# my $errorstr = gluErrorString(); - my $errorstr = ''; - if ($err == 0x0500) { - $errorstr = 'GL_INVALID_ENUM'; - } elsif ($err == GL_INVALID_VALUE) { - $errorstr = 'GL_INVALID_VALUE'; - } elsif ($err == GL_INVALID_OPERATION) { - $errorstr = 'GL_INVALID_OPERATION'; - } elsif ($err == GL_STACK_OVERFLOW) { - $errorstr = 'GL_STACK_OVERFLOW'; - } elsif ($err == GL_OUT_OF_MEMORY) { - $errorstr = 'GL_OUT_OF_MEMORY'; - } else { - $errorstr = 'unknown'; - } - if (defined($comment)) { - printf("OpenGL error at %s, nr %d (0x%x): %s\n", $comment, $err, $err, $errorstr); - } else { - printf("OpenGL error nr %d (0x%x): %s\n", $err, $err, $errorstr); - } -} - -#=================================================================================================================================== +# +#sub _report_opengl_state +#{ +# my ($self, $comment) = @_; +# my $err = glGetError(); +# return 0 if ($err == 0); +# +# # gluErrorString() hangs. Don't use it. +## my $errorstr = gluErrorString(); +# my $errorstr = ''; +# if ($err == 0x0500) { +# $errorstr = 'GL_INVALID_ENUM'; +# } elsif ($err == GL_INVALID_VALUE) { +# $errorstr = 'GL_INVALID_VALUE'; +# } elsif ($err == GL_INVALID_OPERATION) { +# $errorstr = 'GL_INVALID_OPERATION'; +# } elsif ($err == GL_STACK_OVERFLOW) { +# $errorstr = 'GL_STACK_OVERFLOW'; +# } elsif ($err == GL_OUT_OF_MEMORY) { +# $errorstr = 'GL_OUT_OF_MEMORY'; +# } else { +# $errorstr = 'unknown'; +# } +# if (defined($comment)) { +# printf("OpenGL error at %s, nr %d (0x%x): %s\n", $comment, $err, $err, $errorstr); +# } else { +# printf("OpenGL error nr %d (0x%x): %s\n", $err, $err, $errorstr); +# } +#} +# #sub _vertex_shader_Gouraud { # return <<'VERTEX'; ##version 110 diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 50913ae3a..008324a62 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -185,7 +185,7 @@ GLCanvas3D::Camera::Camera() : type(Ortho) , zoom(1.0f) , phi(45.0f) - , distance(0.0f) +// , distance(0.0f) , target(0.0, 0.0, 0.0) , m_theta(45.0f) { @@ -198,8 +198,8 @@ std::string GLCanvas3D::Camera::get_type_as_string() const default: case Unknown: return "unknown"; - case Perspective: - return "perspective"; +// case Perspective: +// return "perspective"; case Ortho: return "ortho"; }; @@ -942,6 +942,8 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) , m_config(nullptr) , m_print(nullptr) , m_dirty(true) + , m_use_VBOs(false) + , m_late_init(false) , m_apply_zoom_to_volumes_filter(false) , m_hover_volume_id(-1) , m_warning_texture_enabled(false) @@ -968,6 +970,9 @@ GLCanvas3D::~GLCanvas3D() bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) { + if (!set_current()) + return false; + ::glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ::glClearDepth(1.0f); @@ -990,16 +995,12 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) ::glEnable(GL_LIGHT1); // light from camera - GLfloat position[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; - ::glLightfv(GL_LIGHT1, GL_POSITION, position); GLfloat specular[4] = { 0.3f, 0.3f, 0.3f, 1.0f }; ::glLightfv(GL_LIGHT1, GL_SPECULAR, specular); GLfloat diffuse[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; ::glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); // light from above - GLfloat position1[4] = { -0.5f, -0.5f, 1.0f, 0.0f }; - ::glLightfv(GL_LIGHT0, GL_POSITION, position1); GLfloat specular1[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; ::glLightfv(GL_LIGHT0, GL_SPECULAR, specular1); GLfloat diffuse1[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; @@ -1021,6 +1022,7 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) if (useVBOs && !m_layers_editing.init("variable_layer_height.vs", "variable_layer_height.fs")) return false; + m_use_VBOs = useVBOs; m_layers_editing.set_use_legacy_opengl(!use_legacy_opengl); return true; @@ -1251,17 +1253,32 @@ void GLCanvas3D::update_volumes_colors_by_extruder() m_volumes->update_colors_by_extruder(m_config); } -void GLCanvas3D::render(bool useVBOs) const +void GLCanvas3D::render() { if (m_canvas == nullptr) return; + if (!is_shown_on_screen()) + return; + + if (!set_current()) + return; + + if (!m_late_init) + _late_init(); + _camera_tranform(); + + GLfloat position[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; + ::glLightfv(GL_LIGHT1, GL_POSITION, position); + GLfloat position1[4] = { -0.5f, -0.5f, 1.0f, 0.0f }; + ::glLightfv(GL_LIGHT0, GL_POSITION, position1); + _picking_pass(); _render_background(); _render_bed(); _render_axes(); - _render_objects(useVBOs); + _render_objects(); _render_cutting_plane(); _render_warning_texture(); _render_legend_texture(); @@ -1677,6 +1694,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) evt.Skip(); } +void GLCanvas3D::on_paint(wxPaintEvent& evt) +{ + render(); +} + Size GLCanvas3D::get_canvas_size() const { int w = 0; @@ -1697,6 +1719,24 @@ Point GLCanvas3D::get_local_mouse_position() const return Point(mouse_pos.x, mouse_pos.y); } +void GLCanvas3D::_late_init() +{ + // This is a special path for wxWidgets on GTK, where an OpenGL context is initialized + // first when an OpenGL widget is shown for the first time.How ugly. + // In that case the volumes are wainting to be moved to Vertex Buffer Objects + // after the OpenGL context is being initialized. +#if defined(__LINUX__) + if (() && m_use_VBOs && (m_volumes != nullptr) + { + m_volumes->finalize_geometry(m_use_VBOs); + if ($^O eq 'linux' && $self->UseVBOs); + } +#endif // __LINUX__ + + zoom_to_bed(); + m_late_init = true; +} + void GLCanvas3D::_resize(unsigned int w, unsigned int h) { if (m_context == nullptr) @@ -1730,28 +1770,28 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) break; } - case Camera::Perspective: - { - float bbox_r = (float)bbox.radius(); - float fov = PI * 45.0f / 180.0f; - float fov_tan = tan(0.5f * fov); - float cam_distance = 0.5f * bbox_r / fov_tan; - m_camera.distance = cam_distance; - - float nr = cam_distance - bbox_r * 1.1f; - float fr = cam_distance + bbox_r * 1.1f; - if (nr < 1.0f) - nr = 1.0f; - - if (fr < nr + 1.0f) - fr = nr + 1.0f; - - float h2 = fov_tan * nr; - float w2 = h2 * w / h; - ::glFrustum(-w2, w2, -h2, h2, nr, fr); - - break; - } +// case Camera::Perspective: +// { +// float bbox_r = (float)bbox.radius(); +// float fov = PI * 45.0f / 180.0f; +// float fov_tan = tan(0.5f * fov); +// float cam_distance = 0.5f * bbox_r / fov_tan; +// m_camera.distance = cam_distance; +// +// float nr = cam_distance - bbox_r * 1.1f; +// float fr = cam_distance + bbox_r * 1.1f; +// if (nr < 1.0f) +// nr = 1.0f; +// +// if (fr < nr + 1.0f) +// fr = nr + 1.0f; +// +// float h2 = fov_tan * nr; +// float w2 = h2 * w / h; +// ::glFrustum(-w2, w2, -h2, h2, nr, fr); +// +// break; +// } default: { throw std::runtime_error("Invalid camera type."); @@ -2008,7 +2048,7 @@ void GLCanvas3D::_render_axes() const m_axes.render(); } -void GLCanvas3D::_render_objects(bool useVBOs) const +void GLCanvas3D::_render_objects() const { if ((m_volumes == nullptr) || m_volumes->empty()) return; @@ -2017,7 +2057,7 @@ void GLCanvas3D::_render_objects(bool useVBOs) const if (!m_shader_enabled) _render_volumes(false); - else if (useVBOs) + else if (m_use_VBOs) { if (m_picking_enabled) { diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 1caf69c0c..8e2cc1d0a 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -13,6 +13,7 @@ class wxIdleEvent; class wxKeyEvent; class wxMouseEvent; class wxTimerEvent; +class wxPaintEvent; namespace Slic3r { @@ -86,7 +87,7 @@ public: enum EType : unsigned char { Unknown, - Perspective, +// Perspective, Ortho, Num_types }; @@ -94,7 +95,7 @@ public: EType type; float zoom; float phi; - float distance; +// float distance; Pointf3 target; private: @@ -301,6 +302,8 @@ private: Print* m_print; bool m_dirty; + bool m_use_VBOs; + bool m_late_init; bool m_apply_zoom_to_volumes_filter; mutable int m_hover_volume_id; bool m_warning_texture_enabled; @@ -369,7 +372,7 @@ public: void update_volumes_colors_by_extruder(); - void render(bool useVBOs) const; + void render(); void render_texture(unsigned int tex_id, float left, float right, float bottom, float top) const; void register_on_viewport_changed_callback(void* callback); @@ -385,11 +388,14 @@ public: void on_mouse_wheel(wxMouseEvent& evt); void on_timer(wxTimerEvent& evt); void on_mouse(wxMouseEvent& evt); + void on_paint(wxPaintEvent& evt); Size get_canvas_size() const; Point get_local_mouse_position() const; private: + void _late_init(); + void _resize(unsigned int w, unsigned int h); BoundingBoxf3 _max_bounding_box() const; @@ -407,7 +413,7 @@ private: void _render_background() const; void _render_bed() const; void _render_axes() const; - void _render_objects(bool useVBOs) const; + void _render_objects() const; void _render_cutting_plane() const; void _render_warning_texture() const; void _render_legend_texture() const; diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 10f825201..4a35d61fd 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -138,6 +138,19 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas, wxGLContext* context) if (canvas3D == nullptr) return false; + if (!m_gl_initialized) + { + canvas3D->set_current(); + init_gl(); + } + + if (!canvas3D->init(m_use_VBOs, m_use_legacy_opengl)) + { + delete canvas3D; + canvas3D = nullptr; + return false; + } + canvas->Bind(wxEVT_SIZE, [canvas3D](wxSizeEvent& evt) { canvas3D->on_size(evt); }); canvas->Bind(wxEVT_IDLE, [canvas3D](wxIdleEvent& evt) { canvas3D->on_idle(evt); }); canvas->Bind(wxEVT_CHAR, [canvas3D](wxKeyEvent& evt) { canvas3D->on_char(evt); }); @@ -155,6 +168,7 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas, wxGLContext* context) canvas->Bind(wxEVT_LEFT_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); }); canvas->Bind(wxEVT_MIDDLE_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); }); canvas->Bind(wxEVT_RIGHT_DCLICK, [canvas3D](wxMouseEvent& evt) { canvas3D->on_mouse(evt); }); + canvas->Bind(wxEVT_PAINT, [canvas3D](wxPaintEvent& evt) { canvas3D->on_paint(evt); }); m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D)); @@ -417,7 +431,7 @@ void GLCanvas3DManager::render(wxGLCanvas* canvas) const { CanvasesMap::const_iterator it = _get_canvas(canvas); if (it != m_canvases.end()) - it->second->render(m_use_VBOs); + it->second->render(); } void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback) -- cgit v1.2.3