From c51ce63b9beb02d4a5f426b15f2ed0902795bb36 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 25 May 2018 15:56:14 +0200 Subject: [PATCH] 3DScene layer editing overlay completely moved to c++ --- lib/Slic3r/GUI/3DScene.pm | 234 +++++++++++------------- xs/src/libslic3r/Model.cpp | 5 +- xs/src/libslic3r/Model.hpp | 11 +- xs/src/slic3r/GUI/3DScene.cpp | 16 +- xs/src/slic3r/GUI/3DScene.hpp | 6 +- xs/src/slic3r/GUI/GLCanvas3D.cpp | 140 +++++++++++++- xs/src/slic3r/GUI/GLCanvas3D.hpp | 19 +- xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 17 +- xs/src/slic3r/GUI/GLCanvas3DManager.hpp | 6 +- xs/xsp/GUI_3DScene.xsp | 23 ++- 10 files changed, 331 insertions(+), 146 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 7debb898a..b27b7d55f 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -200,8 +200,8 @@ sub new { # $self->_camera_target(Slic3r::Pointf3->new(0,0,0)); # $self->_camera_distance(0.); # $self->layer_editing_enabled(0); +# $self->{layer_height_edit_band_width} = 2.; #============================================================================================================================== - $self->{layer_height_edit_band_width} = 2.; $self->{layer_height_edit_strength} = 0.005; $self->{layer_height_edit_last_object_id} = -1; $self->{layer_height_edit_last_z} = 0.; @@ -446,7 +446,10 @@ sub _variable_layer_thickness_action { $self->{print}->get_object($self->{layer_height_edit_last_object_id})->adjust_layer_height_profile( $self->{layer_height_edit_last_z}, $self->{layer_height_edit_strength}, - $self->{layer_height_edit_band_width}, +#============================================================================================================================== + Slic3r::GUI::_3DScene::get_layers_editing_band_width($self), +# $self->{layer_height_edit_band_width}, +#============================================================================================================================== $self->{layer_height_edit_last_action}); $self->volumes->[$self->{layer_height_edit_last_object_id}]->generate_layer_height_texture( $self->{print}->get_object($self->{layer_height_edit_last_object_id}), 1); @@ -700,7 +703,10 @@ sub mouse_wheel_event { # A volume is selected. Test, whether hovering over a layer thickness bar. if ($self->_variable_layer_thickness_bar_rect_mouse_inside($e)) { # Adjust the width of the selection. - $self->{layer_height_edit_band_width} = max(min($self->{layer_height_edit_band_width} * (1 + 0.1 * $e->GetWheelRotation() / $e->GetWheelDelta()), 10.), 1.5); +#============================================================================================================================== + Slic3r::GUI::_3DScene::set_layers_editing_band_width($self, max(min(Slic3r::GUI::_3DScene::get_layers_editing_band_width($self) * (1 + 0.1 * $e->GetWheelRotation() / $e->GetWheelDelta()), 10.), 1.5)); +# $self->{layer_height_edit_band_width} = max(min($self->{layer_height_edit_band_width} * (1 + 0.1 * $e->GetWheelRotation() / $e->GetWheelDelta()), 10.), 1.5); +#============================================================================================================================== $self->Refresh; return; } @@ -1471,6 +1477,7 @@ sub Render { Slic3r::GUI::_3DScene::render_cutting_plane($self); Slic3r::GUI::_3DScene::render_warning_texture($self); Slic3r::GUI::_3DScene::render_legend_texture($self); + Slic3r::GUI::_3DScene::render_layer_editing_overlay($self, $self->{print}); # if ($self->enable_picking && !$self->_mouse_dragging) { # if (my $pos = $self->_mouse_pos) { @@ -1651,10 +1658,10 @@ sub Render { # # # draw gcode preview legend # $self->draw_legend; +# +# $self->draw_active_object_annotations; #============================================================================================================================== - $self->draw_active_object_annotations; - $self->SwapBuffers(); } @@ -1711,7 +1718,7 @@ sub mark_volumes_for_layer_height { if (Slic3r::GUI::_3DScene::is_layers_editing_enabled($self) && $shader && $volume->selected && $volume->has_layer_height_texture && $object_id < $self->{print}->object_count) { $volume->set_layer_height_texture_data(Slic3r::GUI::_3DScene::get_layers_editing_z_texture_id($self), $shader->shader_program_id, - $self->{print}->get_object($object_id), $self->_variable_layer_thickness_bar_mouse_cursor_z_relative, $self->{layer_height_edit_band_width}); + $self->{print}->get_object($object_id), $self->_variable_layer_thickness_bar_mouse_cursor_z_relative, Slic3r::GUI::_3DScene::get_layers_editing_band_width($self)); # if ($self->layer_editing_enabled && $volume->selected && $self->{layer_height_edit_shader} && # $volume->has_layer_height_texture && $object_id < $self->{print}->object_count) { @@ -1724,42 +1731,42 @@ sub mark_volumes_for_layer_height { } } -sub _load_image_set_texture { - my ($self, $file_name) = @_; - # Load a PNG with an alpha channel. - my $img = Wx::Image->new; - $img->LoadFile(Slic3r::var($file_name), wxBITMAP_TYPE_PNG); - # Get RGB & alpha raw data from wxImage, interleave them into a Perl array. - my @rgb = unpack 'C*', $img->GetData(); - my @alpha = $img->HasAlpha ? unpack 'C*', $img->GetAlpha() : (255) x (int(@rgb) / 3); - my $n_pixels = int(@alpha); - my @data = (0)x($n_pixels * 4); - for (my $i = 0; $i < $n_pixels; $i += 1) { - $data[$i*4 ] = $rgb[$i*3]; - $data[$i*4+1] = $rgb[$i*3+1]; - $data[$i*4+2] = $rgb[$i*3+2]; - $data[$i*4+3] = $alpha[$i]; - } - # Initialize a raw bitmap data. - my $params = { - loaded => 1, - valid => $n_pixels > 0, - width => $img->GetWidth, - height => $img->GetHeight, - data => OpenGL::Array->new_list(GL_UNSIGNED_BYTE, @data), - texture_id => glGenTextures_p(1) - }; - # Create and initialize a texture with the raw data. - glBindTexture(GL_TEXTURE_2D, $params->{texture_id}); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $params->{width}, $params->{height}, 0, GL_RGBA, GL_UNSIGNED_BYTE, $params->{data}->ptr); - glBindTexture(GL_TEXTURE_2D, 0); - return $params; -} - #============================================================================================================================== +#sub _load_image_set_texture { +# my ($self, $file_name) = @_; +# # Load a PNG with an alpha channel. +# my $img = Wx::Image->new; +# $img->LoadFile(Slic3r::var($file_name), wxBITMAP_TYPE_PNG); +# # Get RGB & alpha raw data from wxImage, interleave them into a Perl array. +# my @rgb = unpack 'C*', $img->GetData(); +# my @alpha = $img->HasAlpha ? unpack 'C*', $img->GetAlpha() : (255) x (int(@rgb) / 3); +# my $n_pixels = int(@alpha); +# my @data = (0)x($n_pixels * 4); +# for (my $i = 0; $i < $n_pixels; $i += 1) { +# $data[$i*4 ] = $rgb[$i*3]; +# $data[$i*4+1] = $rgb[$i*3+1]; +# $data[$i*4+2] = $rgb[$i*3+2]; +# $data[$i*4+3] = $alpha[$i]; +# } +# # Initialize a raw bitmap data. +# my $params = { +# loaded => 1, +# valid => $n_pixels > 0, +# width => $img->GetWidth, +# height => $img->GetHeight, +# data => OpenGL::Array->new_list(GL_UNSIGNED_BYTE, @data), +# texture_id => glGenTextures_p(1) +# }; +# # Create and initialize a texture with the raw data. +# glBindTexture(GL_TEXTURE_2D, $params->{texture_id}); +# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); +# glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $params->{width}, $params->{height}, 0, GL_RGBA, GL_UNSIGNED_BYTE, $params->{data}->ptr); +# glBindTexture(GL_TEXTURE_2D, 0); +# return $params; +#} +# #sub _variable_layer_thickness_load_overlay_image { # my ($self) = @_; # $self->{layer_preview_annotation} = $self->_load_image_set_texture('variable_layer_height_tooltip.png') @@ -1800,92 +1807,69 @@ sub _load_image_set_texture { # glDisable(GL_BLEND); # glEnable(GL_LIGHTING); #} -#============================================================================================================================== - -sub draw_active_object_annotations { - # $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking. - my ($self) = @_; - -#============================================================================================================================== - return if (!Slic3r::GUI::_3DScene::is_layers_editing_enabled($self)); +# +#sub draw_active_object_annotations { +# # $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking. +# my ($self) = @_; +# # return if (! $self->{layer_height_edit_shader} || ! $self->layer_editing_enabled); -#============================================================================================================================== - - # Find the selected volume, over which the layer editing is active. - my $volume; - foreach my $volume_idx (0..$#{$self->volumes}) { - my $v = $self->volumes->[$volume_idx]; - if ($v->selected && $v->has_layer_height_texture) { - $volume = $v; - last; - } - } - return if (! $volume); - - # If the active object was not allocated at the Print, go away. This should only be a momentary case between an object addition / deletion - # and an update by Platter::async_apply_config. - my $object_idx = int($volume->select_group_id / 1000000); - return if $object_idx >= $self->{print}->object_count; - - # The viewport and camera are set to complete view and glOrtho(-$x/2, $x/2, -$y/2, $y/2, -$depth, $depth), - # where x, y is the window size divided by $self->_zoom. - my ($bar_left, $bar_bottom, $bar_right, $bar_top) = $self->_variable_layer_thickness_bar_rect_viewport; - my ($reset_left, $reset_bottom, $reset_right, $reset_top) = $self->_variable_layer_thickness_reset_rect_viewport; - my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative; - - my $print_object = $self->{print}->get_object($object_idx); - my $z_max = $print_object->model_object->bounding_box->z_max; - -#============================================================================================================================== - my $shader = Slic3r::GUI::_3DScene::get_layers_editing_shader($self); - $shader->enable; - $shader->set_uniform('z_to_texture_row', $volume->layer_height_texture_z_to_row_id); - $shader->set_uniform('z_texture_row_to_normalized', 1. / $volume->layer_height_texture_height); - $shader->set_uniform('z_cursor', $z_max * $z_cursor_relative); - $shader->set_uniform('z_cursor_band_width', $self->{layer_height_edit_band_width}); - - +# +# # Find the selected volume, over which the layer editing is active. +# my $volume; +# foreach my $volume_idx (0..$#{$self->volumes}) { +# my $v = $self->volumes->[$volume_idx]; +# if ($v->selected && $v->has_layer_height_texture) { +# $volume = $v; +# last; +# } +# } +# return if (! $volume); +# +# # If the active object was not allocated at the Print, go away. This should only be a momentary case between an object addition / deletion +# # and an update by Platter::async_apply_config. +# my $object_idx = int($volume->select_group_id / 1000000); +# return if $object_idx >= $self->{print}->object_count; +# +# # The viewport and camera are set to complete view and glOrtho(-$x/2, $x/2, -$y/2, $y/2, -$depth, $depth), +# # where x, y is the window size divided by $self->_zoom. +# my ($bar_left, $bar_bottom, $bar_right, $bar_top) = $self->_variable_layer_thickness_bar_rect_viewport; +# my ($reset_left, $reset_bottom, $reset_right, $reset_top) = $self->_variable_layer_thickness_reset_rect_viewport; +# my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative; +# +# my $print_object = $self->{print}->get_object($object_idx); +# my $z_max = $print_object->model_object->bounding_box->z_max; +# # $self->{layer_height_edit_shader}->enable; # $self->{layer_height_edit_shader}->set_uniform('z_to_texture_row', $volume->layer_height_texture_z_to_row_id); # $self->{layer_height_edit_shader}->set_uniform('z_texture_row_to_normalized', 1. / $volume->layer_height_texture_height); # $self->{layer_height_edit_shader}->set_uniform('z_cursor', $z_max * $z_cursor_relative); # $self->{layer_height_edit_shader}->set_uniform('z_cursor_band_width', $self->{layer_height_edit_band_width}); -#============================================================================================================================== -#============================================================================================================================== - glBindTexture(GL_TEXTURE_2D, Slic3r::GUI::_3DScene::get_layers_editing_z_texture_id($self)); # glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_z_texture_id}); -#============================================================================================================================== - glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $volume->layer_height_texture_width, $volume->layer_height_texture_height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D_c(GL_TEXTURE_2D, 1, GL_RGBA8, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexSubImage2D_c(GL_TEXTURE_2D, 0, 0, 0, $volume->layer_height_texture_width, $volume->layer_height_texture_height, - GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level0); - glTexSubImage2D_c(GL_TEXTURE_2D, 1, 0, 0, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, - GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level1); - - # Render the color bar. - glDisable(GL_DEPTH_TEST); - # The viewport and camera are set to complete view and glOrtho(-$x/2, $x/2, -$y/2, $y/2, -$depth, $depth), - # where x, y is the window size divided by $self->_zoom. - glPushMatrix(); - glLoadIdentity(); - # Paint the overlay. - glBegin(GL_QUADS); - glVertex3f($bar_left, $bar_bottom, 0); - glVertex3f($bar_right, $bar_bottom, 0); - glVertex3f($bar_right, $bar_top, $z_max); - glVertex3f($bar_left, $bar_top, $z_max); - glEnd(); - glBindTexture(GL_TEXTURE_2D, 0); -#============================================================================================================================== - $shader->disable; +# glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $volume->layer_height_texture_width, $volume->layer_height_texture_height, +# 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); +# glTexImage2D_c(GL_TEXTURE_2D, 1, GL_RGBA8, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, +# 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); +# glTexSubImage2D_c(GL_TEXTURE_2D, 0, 0, 0, $volume->layer_height_texture_width, $volume->layer_height_texture_height, +# GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level0); +# glTexSubImage2D_c(GL_TEXTURE_2D, 1, 0, 0, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, +# GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level1); +# +# # Render the color bar. +# glDisable(GL_DEPTH_TEST); +# # The viewport and camera are set to complete view and glOrtho(-$x/2, $x/2, -$y/2, $y/2, -$depth, $depth), +# # where x, y is the window size divided by $self->_zoom. +# glPushMatrix(); +# glLoadIdentity(); +# # Paint the overlay. +# glBegin(GL_QUADS); +# glVertex3f($bar_left, $bar_bottom, 0); +# glVertex3f($bar_right, $bar_bottom, 0); +# glVertex3f($bar_right, $bar_top, $z_max); +# glVertex3f($bar_left, $bar_top, $z_max); +# glEnd(); +# glBindTexture(GL_TEXTURE_2D, 0); # $self->{layer_height_edit_shader}->disable; -#============================================================================================================================== - -#============================================================================================================================== - Slic3r::GUI::_3DScene::render_layer_editing_textures($self, $print_object); - +# # # Paint the tooltip. # if ($self->_variable_layer_thickness_load_overlay_image) # my $gap = 10/$self->_zoom; @@ -1933,13 +1917,11 @@ sub draw_active_object_annotations { # glVertex3f($bar_left + $h * ($bar_right - $bar_left) / $layer_height_max, $bar_bottom + $z * ($bar_top - $bar_bottom) / $max_z, $z); # } # glEnd(); -#============================================================================================================================== - # Revert the matrices. - glPopMatrix(); - glEnable(GL_DEPTH_TEST); -} - -#============================================================================================================================== +# # Revert the matrices. +# glPopMatrix(); +# glEnable(GL_DEPTH_TEST); +#} +# #sub draw_legend { # my ($self) = @_; # diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 8ce23b1e5..147353abd 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -603,7 +603,10 @@ void ModelObject::clear_instances() // Returns the bounding box of the transformed instances. // This bounding box is approximate and not snug. -const BoundingBoxf3& ModelObject::bounding_box() +//======================================================================================================== +const BoundingBoxf3& ModelObject::bounding_box() const +//const BoundingBoxf3& ModelObject::bounding_box() +//======================================================================================================== { if (! m_bounding_box_valid) { BoundingBoxf3 raw_bbox; diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 8b63c3641..b148ec29d 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -103,7 +103,10 @@ public: // Returns the bounding box of the transformed instances. // This bounding box is approximate and not snug. // This bounding box is being cached. - const BoundingBoxf3& bounding_box(); +//======================================================================================================== + const BoundingBoxf3& bounding_box() const; +// const BoundingBoxf3& bounding_box(); +//======================================================================================================== void invalidate_bounding_box() { m_bounding_box_valid = false; } // Returns a snug bounding box of the transformed instances. // This bounding box is not being cached. @@ -145,8 +148,10 @@ private: // Parent object, owning this ModelObject. Model *m_model; // Bounding box, cached. - BoundingBoxf3 m_bounding_box; - bool m_bounding_box_valid; +//======================================================================================================== + mutable BoundingBoxf3 m_bounding_box; + mutable bool m_bounding_box_valid; +//======================================================================================================== }; // An object STL, or a modifier volume, over which a different set of parameters shall be applied. diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 2969f3e8a..87071ce20 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -2010,6 +2010,16 @@ unsigned int _3DScene::get_layers_editing_z_texture_id(wxGLCanvas* canvas) return s_canvas_mgr.get_layers_editing_z_texture_id(canvas); } +float _3DScene::get_layers_editing_band_width(wxGLCanvas* canvas) +{ + return s_canvas_mgr.get_layers_editing_band_width(canvas); +} + +void _3DScene::set_layers_editing_band_width(wxGLCanvas* canvas, float band_width) +{ + s_canvas_mgr.set_layers_editing_band_width(canvas, band_width); +} + GLShader* _3DScene::get_layers_editing_shader(wxGLCanvas* canvas) { return s_canvas_mgr.get_layers_editing_shader(canvas); @@ -2085,10 +2095,10 @@ void _3DScene::render_legend_texture(wxGLCanvas* canvas) s_canvas_mgr.render_legend_texture(canvas); } -void _3DScene::render_layer_editing_textures(wxGLCanvas* canvas, const PrintObject* print_object) +void _3DScene::render_layer_editing_overlay(wxGLCanvas* canvas, const Print* print) { - if (print_object != nullptr) - s_canvas_mgr.render_layer_editing_textures(canvas, *print_object); + if (print != nullptr) + s_canvas_mgr.render_layer_editing_overlay(canvas, *print); } void _3DScene::render_texture(wxGLCanvas* canvas, unsigned int tex_id, float left, float right, float bottom, float top) diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index ab7f1ba7d..153744987 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -617,6 +617,10 @@ public: static void set_hover_volume_id(wxGLCanvas* canvas, int id); static unsigned int get_layers_editing_z_texture_id(wxGLCanvas* canvas); + + static float get_layers_editing_band_width(wxGLCanvas* canvas); + static void set_layers_editing_band_width(wxGLCanvas* canvas, float band_width); + static GLShader* get_layers_editing_shader(wxGLCanvas* canvas); static void zoom_to_bed(wxGLCanvas* canvas); @@ -636,7 +640,7 @@ public: static void render_cutting_plane(wxGLCanvas* canvas); static void render_warning_texture(wxGLCanvas* canvas); static void render_legend_texture(wxGLCanvas* canvas); - static void render_layer_editing_textures(wxGLCanvas* canvas, const PrintObject* print_object); + static void render_layer_editing_overlay(wxGLCanvas* canvas, const Print* print); static void render_texture(wxGLCanvas* canvas, unsigned int tex_id, float left, float right, float bottom, float top); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 31680148e..823a4df0c 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -553,6 +553,12 @@ void GLCanvas3D::Shader::stop_using() const m_shader->disable(); } +void GLCanvas3D::Shader::set_uniform(const std::string& name, float value) const +{ + if (m_shader != nullptr) + m_shader->set_uniform(name.c_str(), value); +} + GLShader* GLCanvas3D::Shader::get_shader() { return m_shader; @@ -586,6 +592,7 @@ GLCanvas3D::LayersEditing::LayersEditing() : m_allowed(false) , m_enabled(false) , m_z_texture_id(0) + , m_band_width(2.0f) { } @@ -652,13 +659,40 @@ unsigned int GLCanvas3D::LayersEditing::get_z_texture_id() const return m_z_texture_id; } -void GLCanvas3D::LayersEditing::render(const GLCanvas3D& canvas, const PrintObject& print_object) const +float GLCanvas3D::LayersEditing::get_band_width() const { + return m_band_width; +} + +void GLCanvas3D::LayersEditing::set_band_width(float band_width) +{ + m_band_width = band_width; +} + +void GLCanvas3D::LayersEditing::render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const +{ + if (!m_enabled) + return; + const Rect& bar_rect = _get_bar_rect_viewport(canvas); const Rect& reset_rect = _get_reset_rect_viewport(canvas); + + ::glDisable(GL_DEPTH_TEST); + + // The viewport and camera are set to complete view and glOrtho(-$x / 2, $x / 2, -$y / 2, $y / 2, -$depth, $depth), + // where x, y is the window size divided by $self->_zoom. + ::glPushMatrix(); + ::glLoadIdentity(); + _render_tooltip_texture(canvas, bar_rect, reset_rect); _render_reset_texture(canvas, reset_rect); + _render_active_object_annotations(canvas, volume, print_object, bar_rect); _render_profile(print_object, bar_rect); + + // Revert the matrices. + glPopMatrix(); + + glEnable(GL_DEPTH_TEST); } GLShader* GLCanvas3D::LayersEditing::get_shader() @@ -754,6 +788,45 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const GLCanvas3D& canvas, canvas.render_texture(m_reset_texture.id, reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); } +void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const +{ + float max_z = print_object.model_object()->bounding_box().max.z; + + m_shader.start_using(); + + m_shader.set_uniform("z_to_texture_row", (float)volume.layer_height_texture_z_to_row_id()); + m_shader.set_uniform("z_texture_row_to_normalized", 1.0f / (float)volume.layer_height_texture_height()); + m_shader.set_uniform("z_cursor", max_z * _cursor_z_relative(canvas)); + m_shader.set_uniform("z_cursor_band_width", get_band_width()); + + GLsizei w = (GLsizei)volume.layer_height_texture_width(); + GLsizei h = (GLsizei)volume.layer_height_texture_height(); + GLsizei half_w = w / 2; + GLsizei half_h = h / 2; + + ::glBindTexture(GL_TEXTURE_2D, m_z_texture_id); + ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + ::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + ::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, volume.layer_height_texture_data_ptr_level0()); + ::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, volume.layer_height_texture_data_ptr_level1()); + + // Render the color bar + float l = bar_rect.get_left(); + float r = bar_rect.get_right(); + float t = bar_rect.get_top(); + float b = bar_rect.get_bottom(); + + ::glBegin(GL_QUADS); + ::glVertex3f(l, b, 0.0f); + ::glVertex3f(r, b, 0.0f); + ::glVertex3f(r, t, max_z); + ::glVertex3f(l, t, max_z); + ::glEnd(); + ::glBindTexture(GL_TEXTURE_2D, 0); + + m_shader.stop_using(); +} + void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object, const Rect& bar_rect) const { // FIXME show some kind of legend. @@ -851,6 +924,21 @@ Rect GLCanvas3D::LayersEditing::_get_reset_rect_viewport(const GLCanvas3D& canva return Rect((half_w - VARIABLE_LAYER_THICKNESS_BAR_WIDTH) * inv_zoom, (-half_h + VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT) * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); } +float GLCanvas3D::LayersEditing::_cursor_z_relative(const GLCanvas3D& canvas) const +{ + const Point& mouse_pos = canvas.get_local_mouse_position(); + const Rect& bar_rect = _get_bar_rect_screen(canvas); + float x = (float)mouse_pos.x; + float y = (float)mouse_pos.y; + float t = bar_rect.get_top(); + float b = bar_rect.get_bottom(); + return ((bar_rect.get_left() <= x) && (x <= bar_rect.get_right()) && (t <= y) && (y <= b)) ? + // Inside the bar. + (b - y - 1.0f) / (b - t - 1.0f) : + // Outside the bar. + - 1000.0f; +} + GLCanvas3D::Mouse::Mouse() : m_dragging(false) { @@ -1456,6 +1544,16 @@ unsigned int GLCanvas3D::get_layers_editing_z_texture_id() const return m_layers_editing.get_z_texture_id(); } +float GLCanvas3D::get_layers_editing_band_width() const +{ + return m_layers_editing.get_band_width(); +} + +void GLCanvas3D::set_layers_editing_band_width(float band_width) +{ + m_layers_editing.set_band_width(band_width); +} + GLShader* GLCanvas3D::get_layers_editing_shader() { return m_layers_editing.get_shader(); @@ -1635,9 +1733,36 @@ void GLCanvas3D::render_legend_texture() const } } -void GLCanvas3D::render_layer_editing_textures(const PrintObject& print_object) const +void GLCanvas3D::render_layer_editing_overlay(const Print& print) const { - m_layers_editing.render(*this, print_object); + if (m_volumes == nullptr) + return; + + GLVolume* volume = nullptr; + + for (GLVolume* vol : m_volumes->volumes) + { + if ((vol != nullptr) && vol->selected && vol->has_layer_height_texture()) + { + volume = vol; + break; + } + } + + if (volume == nullptr) + return; + + // If the active object was not allocated at the Print, go away.This should only be a momentary case between an object addition / deletion + // and an update by Platter::async_apply_config. + int object_idx = int(volume->select_group_id / 1000000); + if ((int)print.objects.size() < object_idx) + return; + + const PrintObject* print_object = print.get_object(object_idx); + if (print_object == nullptr) + return; + + m_layers_editing.render(*this, *print_object, *volume); } void GLCanvas3D::render_texture(unsigned int tex_id, float left, float right, float bottom, float top) const @@ -1741,6 +1866,15 @@ Size GLCanvas3D::get_canvas_size() const return Size(w, h); } +Point GLCanvas3D::get_local_mouse_position() const +{ + if (m_canvas == nullptr) + return Point(); + + wxPoint mouse_pos = m_canvas->ScreenToClient(wxGetMousePosition()); + return Point(mouse_pos.x, mouse_pos.x); +} + void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox) { // Calculate the zoom factor needed to adjust viewport to bounding box. diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index a11780349..e110fee3b 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -14,9 +14,11 @@ class wxKeyEvent; namespace Slic3r { class GLVolumeCollection; +class GLVolume; class DynamicPrintConfig; class GLShader; class ExPolygon; +class Print; class PrintObject; namespace GUI { @@ -189,6 +191,8 @@ public: bool start_using() const; void stop_using() const; + void set_uniform(const std::string& name, float value) const; + GLShader* get_shader(); private: @@ -213,6 +217,7 @@ public: unsigned int m_z_texture_id; mutable GLTextureData m_tooltip_texture; mutable GLTextureData m_reset_texture; + float m_band_width; public: LayersEditing(); @@ -228,7 +233,10 @@ public: unsigned int get_z_texture_id() const; - void render(const GLCanvas3D& canvas, const PrintObject& print_object) const; + float get_band_width() const; + void set_band_width(float band_width); + + void render(const GLCanvas3D& canvas, const PrintObject& print_object, const GLVolume& volume) const; GLShader* get_shader(); @@ -237,11 +245,13 @@ public: GLTextureData _load_texture_from_file(const std::string& filename) const; void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const; void _render_reset_texture(const GLCanvas3D& canvas, const Rect& reset_rect) const; + void _render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const; void _render_profile(const PrintObject& print_object, const Rect& bar_rect) const; Rect _get_bar_rect_screen(const GLCanvas3D& canvas) const; Rect _get_reset_rect_screen(const GLCanvas3D& canvas) const; Rect _get_bar_rect_viewport(const GLCanvas3D& canvas) const; Rect _get_reset_rect_viewport(const GLCanvas3D& canvas) const; + float _cursor_z_relative(const GLCanvas3D& canvas) const; }; class Mouse @@ -369,6 +379,10 @@ public: void set_hover_volume_id(int id); unsigned int get_layers_editing_z_texture_id() const; + + float get_layers_editing_band_width() const; + void set_layers_editing_band_width(float band_width); + GLShader* get_layers_editing_shader(); void zoom_to_bed(); @@ -388,7 +402,7 @@ public: void render_cutting_plane() const; void render_warning_texture() const; void render_legend_texture() const; - void render_layer_editing_textures(const PrintObject& print_object) const; + void render_layer_editing_overlay(const Print& print) const; void render_texture(unsigned int tex_id, float left, float right, float bottom, float top) const; @@ -400,6 +414,7 @@ public: void on_char(wxKeyEvent& evt); Size get_canvas_size() const; + Point get_local_mouse_position() const; private: void _zoom_to_bounding_box(const BoundingBoxf3& bbox); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 66a66307e..730badb87 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -473,6 +473,19 @@ unsigned int GLCanvas3DManager::get_layers_editing_z_texture_id(wxGLCanvas* canv return (it != m_canvases.end()) ? it->second->get_layers_editing_z_texture_id() : 0; } +float GLCanvas3DManager::get_layers_editing_band_width(wxGLCanvas* canvas) const +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->get_layers_editing_band_width() : 0.0f; +} + +void GLCanvas3DManager::set_layers_editing_band_width(wxGLCanvas* canvas, float band_width) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->set_layers_editing_band_width(band_width); +} + GLShader* GLCanvas3DManager::get_layers_editing_shader(wxGLCanvas* canvas) { CanvasesMap::const_iterator it = _get_canvas(canvas); @@ -576,11 +589,11 @@ void GLCanvas3DManager::render_legend_texture(wxGLCanvas* canvas) const it->second->render_legend_texture(); } -void GLCanvas3DManager::render_layer_editing_textures(wxGLCanvas* canvas, const PrintObject& print_object) const +void GLCanvas3DManager::render_layer_editing_overlay(wxGLCanvas* canvas, const Print& print) const { CanvasesMap::const_iterator it = _get_canvas(canvas); if (it != m_canvases.end()) - it->second->render_layer_editing_textures(print_object); + it->second->render_layer_editing_overlay(print); } void GLCanvas3DManager::render_texture(wxGLCanvas* canvas, unsigned int tex_id, float left, float right, float bottom, float top) const diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index 3b3e35c36..cab1be2f5 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -117,6 +117,10 @@ public: void set_hover_volume_id(wxGLCanvas* canvas, int id); unsigned int get_layers_editing_z_texture_id(wxGLCanvas* canvas) const; + + float get_layers_editing_band_width(wxGLCanvas* canvas) const; + void set_layers_editing_band_width(wxGLCanvas* canvas, float band_width); + GLShader* get_layers_editing_shader(wxGLCanvas* canvas); void zoom_to_bed(wxGLCanvas* canvas); @@ -136,7 +140,7 @@ public: void render_cutting_plane(wxGLCanvas* canvas) const; void render_warning_texture(wxGLCanvas* canvas) const; void render_legend_texture(wxGLCanvas* canvas) const; - void render_layer_editing_textures(wxGLCanvas* canvas, const PrintObject& print_object) const; + void render_layer_editing_overlay(wxGLCanvas* canvas, const Print& print) const; void render_texture(wxGLCanvas* canvas, unsigned int tex_id, float left, float right, float bottom, float top) const; diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 0f47454da..53688e8da 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -571,6 +571,21 @@ get_layers_editing_z_texture_id(canvas) OUTPUT: RETVAL +float +get_layers_editing_band_width(canvas) + SV *canvas; + CODE: + RETVAL = _3DScene::get_layers_editing_band_width((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); + OUTPUT: + RETVAL + +void +set_layers_editing_band_width(canvas, band_width) + SV *canvas; + float band_width; + CODE: + _3DScene::set_layers_editing_band_width((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), band_width); + Ref get_layers_editing_shader(canvas) SV *canvas; @@ -669,11 +684,11 @@ render_legend_texture(canvas) _3DScene::render_legend_texture((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); void -render_layer_editing_textures(canvas, print_object) - SV *canvas; - PrintObject *print_object; +render_layer_editing_overlay(canvas, print) + SV *canvas; + Print *print; CODE: - _3DScene::render_layer_editing_textures((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object); + _3DScene::render_layer_editing_overlay((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print); void render_texture(canvas, tex_id, left, right, bottom, top)